31 const std::vector<int>& filter_dims,
34 const TReal* out_positions,
36 const TReal* inp_positions,
37 const TFeat* inp_features,
38 const TFeat* inp_importance,
39 size_t neighbors_index_size,
40 const TIndex* neighbors_index,
41 const TFeat* neighbors_importance,
42 const int64_t* neighbors_row_splits,
46 const bool NEIGHBORS_IMPORTANCE = neighbors_importance !=
nullptr;
48 typedef Eigen::Array<TReal, VECSIZE, 1> Vec_t;
50 InterpolationVec_t interpolation;
52 const int in_channels = filter_dims[filter_dims.size() - 2];
53 const int out_channels = filter_dims[filter_dims.size() - 1];
55 int spatial_filter_size = 1;
56 for (
int i = 0; i < 3; ++i) spatial_filter_size *= filter_dims[i];
57 Eigen::Array<int, 3, 1> filter_size_xyz(filter_dims[2], filter_dims[1],
60 memset(out_features, 0,
sizeof(TOut) * num_out * out_channels);
63 tbb::blocked_range<size_t>(0, num_out, 32),
64 [&](
const tbb::blocked_range<size_t>& r) {
65 int range_length = r.end() - r.begin();
67 Eigen::Matrix<TOut, Eigen::Dynamic, 1> normalizers(range_length,
69 normalizers.setZero();
71 Eigen::Matrix<TFeat, Eigen::Dynamic, Eigen::Dynamic>
B(
72 in_channels * spatial_filter_size, range_length);
75 typedef Eigen::Array<TFeat, VECSIZE, Eigen::Dynamic> Matrix;
76 Matrix infeat(
VECSIZE, in_channels);
78 Eigen::Array<TReal, 3, 1> offsets_(offsets[0], offsets[1],
81 Eigen::Array<TReal, VECSIZE, 3> inv_extents;
82 if (INDIVIDUAL_EXTENT ==
false) {
83 if (ISOTROPIC_EXTENT) {
84 inv_extents = 1 / extents[0];
86 inv_extents.col(0) = 1 / extents[0];
87 inv_extents.col(1) = 1 / extents[1];
88 inv_extents.col(2) = 1 / extents[2];
92 for (
size_t out_idx = r.begin(); out_idx != r.end();
94 const int out_col = out_idx - r.begin();
95 const size_t neighbor_start = neighbors_row_splits[out_idx];
96 const size_t neighbor_end =
97 neighbors_row_splits[out_idx + 1];
99 if (INDIVIDUAL_EXTENT) {
100 if (ISOTROPIC_EXTENT) {
101 inv_extents = 1 / extents[out_idx];
103 inv_extents.col(0) = 1 / extents[3 * out_idx + 0];
104 inv_extents.col(1) = 1 / extents[3 * out_idx + 1];
105 inv_extents.col(2) = 1 / extents[3 * out_idx + 2];
109 typename InterpolationVec_t::Weight_t interp_weights;
110 typename InterpolationVec_t::Idx_t interp_indices;
112 int vec_valid_count = 0;
120 for (
size_t n = neighbor_start; n < neighbor_end; ++n) {
121 const size_t inp_idx = neighbors_index[n];
122 const int i = vec_valid_count;
123 x(i) = inp_positions[inp_idx * 3 + 0] -
124 out_positions[out_idx * 3 + 0];
125 y(i) = inp_positions[inp_idx * 3 + 1] -
126 out_positions[out_idx * 3 + 1];
127 z(i) = inp_positions[inp_idx * 3 + 2] -
128 out_positions[out_idx * 3 + 2];
130 const TFeat n_importance =
131 (NEIGHBORS_IMPORTANCE ? neighbors_importance[n]
133 normalizers(out_col) += TOut(n_importance);
135 for (
int ic = 0; ic < in_channels; ++ic)
137 inp_features[inp_idx * in_channels + ic];
139 TFeat importance(1.0);
140 if (POINT_IMPORTANCE)
141 importance = inp_importance[inp_idx];
142 if (NEIGHBORS_IMPORTANCE) importance *= n_importance;
144 if (POINT_IMPORTANCE || NEIGHBORS_IMPORTANCE) {
145 for (
int ic = 0; ic < in_channels; ++ic)
146 infeat(i, ic) *= importance;
150 if (vec_valid_count ==
VECSIZE) {
151 ComputeFilterCoordinates<ALIGN_CORNERS, MAPPING>(
152 x, y, z, filter_size_xyz, inv_extents,
154 interpolation.Interpolate(
155 interp_weights, interp_indices, x, y, z,
156 filter_size_xyz, in_channels);
157 for (
int k = 0; k <
VECSIZE; ++k)
158 for (
int j = 0; j < InterpolationVec_t::Size();
160 for (
int ic = 0; ic < in_channels; ++ic)
161 B(interp_indices(j, k) + ic, out_col) +=
162 TFeat(interp_weights(j, k)) *
168 if (vec_valid_count) {
169 ComputeFilterCoordinates<ALIGN_CORNERS, MAPPING>(
170 x, y, z, filter_size_xyz, inv_extents,
172 interpolation.Interpolate(interp_weights,
173 interp_indices, x, y, z,
174 filter_size_xyz, in_channels);
175 for (
int k = 0; k < vec_valid_count; ++k)
176 for (
int j = 0; j < InterpolationVec_t::Size();
178 for (
int ic = 0; ic < in_channels; ++ic)
179 B(interp_indices(j, k) + ic, out_col) +=
180 TFeat(interp_weights(j, k)) *
187 Eigen::Map<
const Eigen::Matrix<TFeat, Eigen::Dynamic,
189 A(filter, out_channels,
190 spatial_filter_size * in_channels);
191 Eigen::Map<Eigen::Matrix<TOut, Eigen::Dynamic, Eigen::Dynamic>>
192 C(out_features + (r.begin() * out_channels),
193 out_channels, range_length);
195 C = (A *
B).
template cast<TOut>();
197 for (
int i = 0; i < range_length; ++i) {
198 if (normalizers(i) != TOut(0))
199 C.col(i) /= normalizers(i);