@@ -30,17 +30,19 @@ inline T bilinear_aa_filter(T x) {
3030 : static_cast <T>(0.0 );
3131}
3232
33- // Compute anti-aliasing weights exactly matching PyTorch's algorithm
3433template <typename T>
35- void compute_aa_weights_for_pixel (
36- int64_t output_idx,
37- T scale,
38- int64_t input_size,
39- int64_t * indices,
40- T* weights,
41- int64_t * num_contributors) {
42- // Use the provided scale directly instead of recalculating
34+ struct AAKernelParams {
35+ int64_t xmin;
36+ int64_t xmax;
37+ int64_t fallback_index;
38+ T center;
39+ T invscale;
40+ T total_weight;
41+ };
4342
43+ template <typename T>
44+ AAKernelParams<T>
45+ compute_aa_kernel_params (int64_t output_idx, T scale, int64_t input_size) {
4446 // PyTorch's center calculation for anti-aliasing
4547 // Always uses scale * (i + 0.5) for anti-aliasing, regardless of
4648 // align_corners
@@ -58,58 +60,58 @@ void compute_aa_weights_for_pixel(
5860 static_cast <int64_t >(0 ));
5961 const int64_t xmax = std::min (
6062 static_cast <int64_t >(center + support + static_cast <T>(0.5 )), input_size);
61-
62- *num_contributors = std::min (xmax - xmin, static_cast <int64_t >(4 ));
63+ const T invscale = (scale >= static_cast <T>(1.0 ))
64+ ? (static_cast <T>(1.0 ) / scale)
65+ : static_cast <T>(1.0 );
6366
6467 // Ensure we have at least one contributor
65- if (*num_contributors <= 0 ) {
66- *num_contributors = 1 ;
67- indices[0 ] = std::max (
68+ if (xmax <= xmin) {
69+ const int64_t fallback_index = std::max (
6870 static_cast <int64_t >(0 ),
6971 std::min (static_cast <int64_t >(center), input_size - 1 ));
70- weights[0 ] = static_cast <T>(1.0 );
71- // Clear unused weight slots
72- for (int64_t j = 1 ; j < 4 ; ++j) {
73- weights[j] = static_cast <T>(0.0 );
74- }
75- return ;
72+ return {
73+ fallback_index,
74+ fallback_index + 1 ,
75+ fallback_index,
76+ center,
77+ invscale,
78+ static_cast <T>(1.0 )};
7679 }
7780
78- // PyTorch's weight computation
7981 T total_weight = static_cast <T>(0.0 );
80- const T invscale = (scale >= static_cast <T>(1.0 ))
81- ? (static_cast <T>(1.0 ) / scale)
82- : static_cast <T>(1.0 );
83-
84- for (int64_t j = 0 ; j < *num_contributors; ++j) {
85- int64_t x = xmin + j;
86- // PyTorch's exact weight formula: (j + xmin - center + 0.5) * invscale
87- T arg = (static_cast <T>(j) + static_cast <T>(xmin) - center +
88- static_cast <T>(0.5 )) *
89- invscale;
90- T weight = bilinear_aa_filter<T>(arg);
91- indices[j] = x;
92- weights[j] = weight;
93- total_weight += weight;
82+ for (int64_t x = xmin; x < xmax; ++x) {
83+ total_weight += bilinear_aa_filter<T>(
84+ (static_cast <T>(x) - center + static_cast <T>(0.5 )) * invscale);
9485 }
9586
96- // Normalize weights to sum to 1 (PyTorch does this)
97- if (total_weight > static_cast <T>( 0.0 )) {
98- for ( int64_t j = 0 ; j < *num_contributors; ++j) {
99- weights[j] /= total_weight ;
100- }
101- } else {
102- // Fallback: if total weight is 0, set equal weights
103- T equal_weight = static_cast <T>( 1.0 ) / static_cast <T>(*num_contributors);
104- for ( int64_t j = 0 ; j < *num_contributors; ++j) {
105- weights[j] = equal_weight;
106- }
87+ if (total_weight <= static_cast <T>( 0.0 )) {
88+ const int64_t fallback_index = std::max (
89+ static_cast < int64_t >( 0 ),
90+ std::min ( static_cast < int64_t >(center), input_size - 1 )) ;
91+ return {
92+ fallback_index,
93+ fallback_index + 1 ,
94+ fallback_index,
95+ center,
96+ invscale,
97+ static_cast <T>( 1.0 )};
10798 }
10899
109- // Clear unused weight slots
110- for (int64_t j = *num_contributors; j < 4 ; ++j) {
111- weights[j] = static_cast <T>(0.0 );
100+ return {xmin, xmax, -1 , center, invscale, total_weight};
101+ }
102+
103+ template <typename T>
104+ inline T compute_normalized_aa_weight (
105+ const AAKernelParams<T>& params,
106+ int64_t input_idx) {
107+ if (params.fallback_index >= 0 ) {
108+ return (input_idx == params.fallback_index ) ? static_cast <T>(1.0 )
109+ : static_cast <T>(0.0 );
112110 }
111+ return bilinear_aa_filter<T>(
112+ (static_cast <T>(input_idx) - params.center + static_cast <T>(0.5 )) *
113+ params.invscale ) /
114+ params.total_weight ;
113115}
114116
115117template <typename CTYPE >
@@ -129,48 +131,28 @@ void upsample_bilinear2d_aa_kernel_impl(
129131 if (is_nchw) {
130132 // NCHW layout
131133 for (int64_t n = 0 ; n < out.size (0 ); ++n) {
132- for (int64_t c = 0 ; c < out.size (1 ); ++c) {
133- const auto in_plane =
134- in_data + (n * in.size (1 ) + c) * in.size (2 ) * in.size (3 );
135- auto out_plane =
136- out_data + (n * out.size (1 ) + c) * out.size (2 ) * out.size (3 );
137-
138- for (int64_t oh = 0 ; oh < out.size (2 ); ++oh) {
139- // Compute height weights for this output row
140- int64_t h_indices[4 ];
141- float h_weights[4 ];
142- int64_t h_num_contributors;
143- compute_aa_weights_for_pixel<float >(
144- oh,
145- scale_h,
146- in.size (2 ),
147- h_indices,
148- h_weights,
149- &h_num_contributors);
150-
151- for (int64_t ow = 0 ; ow < out.size (3 ); ++ow) {
152- // Compute width weights for this output column
153- int64_t w_indices[4 ];
154- float w_weights[4 ];
155- int64_t w_num_contributors;
156- compute_aa_weights_for_pixel<float >(
157- ow,
158- scale_w,
159- in.size (3 ),
160- w_indices,
161- w_weights,
162- &w_num_contributors);
134+ for (int64_t oh = 0 ; oh < out.size (2 ); ++oh) {
135+ const auto h_params =
136+ compute_aa_kernel_params<float >(oh, scale_h, in.size (2 ));
163137
138+ for (int64_t ow = 0 ; ow < out.size (3 ); ++ow) {
139+ const auto w_params =
140+ compute_aa_kernel_params<float >(ow, scale_w, in.size (3 ));
141+
142+ for (int64_t c = 0 ; c < out.size (1 ); ++c) {
143+ const auto in_plane =
144+ in_data + (n * in.size (1 ) + c) * in.size (2 ) * in.size (3 );
145+ auto out_plane =
146+ out_data + (n * out.size (1 ) + c) * out.size (2 ) * out.size (3 );
164147 CTYPE value = 0 ;
165148
166149 // Apply anti-aliased interpolation
167- for (int64_t ih_idx = 0 ; ih_idx < h_num_contributors; ++ih_idx) {
168- int64_t ih = h_indices[ih_idx];
169- float h_weight = h_weights[ih_idx];
150+ for (int64_t ih = h_params.xmin ; ih < h_params.xmax ; ++ih) {
151+ const float h_weight = compute_normalized_aa_weight (h_params, ih);
170152
171- for (int64_t iw_idx = 0 ; iw_idx < w_num_contributors ; ++iw_idx ) {
172- int64_t iw = w_indices[iw_idx];
173- float w_weight = w_weights[iw_idx] ;
153+ for (int64_t iw = w_params. xmin ; iw < w_params. xmax ; ++iw ) {
154+ const float w_weight =
155+ compute_normalized_aa_weight (w_params, iw) ;
174156
175157 value += in_plane[ih * in.size (3 ) + iw] * h_weight * w_weight;
176158 }
@@ -188,37 +170,23 @@ void upsample_bilinear2d_aa_kernel_impl(
188170 auto out_batch = out_data + n * out.size (1 ) * out.size (2 ) * out.size (3 );
189171
190172 for (int64_t oh = 0 ; oh < out.size (2 ); ++oh) {
191- // Compute height weights for this output row
192- int64_t h_indices[4 ];
193- float h_weights[4 ];
194- int64_t h_num_contributors;
195- compute_aa_weights_for_pixel<float >(
196- oh, scale_h, in.size (2 ), h_indices, h_weights, &h_num_contributors);
173+ const auto h_params =
174+ compute_aa_kernel_params<float >(oh, scale_h, in.size (2 ));
197175
198176 for (int64_t ow = 0 ; ow < out.size (3 ); ++ow) {
199- // Compute width weights for this output column
200- int64_t w_indices[4 ];
201- float w_weights[4 ];
202- int64_t w_num_contributors;
203- compute_aa_weights_for_pixel<float >(
204- ow,
205- scale_w,
206- in.size (3 ),
207- w_indices,
208- w_weights,
209- &w_num_contributors);
177+ const auto w_params =
178+ compute_aa_kernel_params<float >(ow, scale_w, in.size (3 ));
210179
211180 for (int64_t c = 0 ; c < out.size (1 ); ++c) {
212181 CTYPE value = 0 ;
213182
214183 // Apply anti-aliased interpolation
215- for (int64_t ih_idx = 0 ; ih_idx < h_num_contributors; ++ih_idx) {
216- int64_t ih = h_indices[ih_idx];
217- float h_weight = h_weights[ih_idx];
184+ for (int64_t ih = h_params.xmin ; ih < h_params.xmax ; ++ih) {
185+ const float h_weight = compute_normalized_aa_weight (h_params, ih);
218186
219- for (int64_t iw_idx = 0 ; iw_idx < w_num_contributors ; ++iw_idx ) {
220- int64_t iw = w_indices[iw_idx];
221- float w_weight = w_weights[iw_idx] ;
187+ for (int64_t iw = w_params. xmin ; iw < w_params. xmax ; ++iw ) {
188+ const float w_weight =
189+ compute_normalized_aa_weight (w_params, iw) ;
222190
223191 value += in_batch[(ih * in.size (3 ) + iw) * in.size (1 ) + c] *
224192 h_weight * w_weight;
0 commit comments