xref: /aosp_15_r20/external/tensorflow/tensorflow/lite/kernels/internal/resize_nearest_neighbor_test.cc (revision b6fb3261f9314811a0f4371741dbb8839866f948)
1 /* Copyright 2018 The TensorFlow Authors. All Rights Reserved.
2 
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6 
7     http://www.apache.org/licenses/LICENSE-2.0
8 
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15 #include <algorithm>
16 #include <cmath>
17 #include <vector>
18 
19 #include <gtest/gtest.h>
20 #include "tensorflow/lite/kernels/internal/optimized/optimized_ops.h"
21 #include "tensorflow/lite/kernels/internal/reference/reference_ops.h"
22 #include "tensorflow/lite/kernels/internal/test_util.h"
23 #include "tensorflow/lite/kernels/internal/types.h"
24 
25 namespace tflite {
26 namespace {
27 
28 template <typename T>
TestReferenceResizeNearestNeighbor(const RuntimeShape & input_shape,const std::vector<T> & input_data,const std::vector<int32> & output_size_data,const RuntimeShape & output_shape,const std::vector<T> & expected_output_data,bool align_corners=false,bool half_pixel_centers=false)29 void TestReferenceResizeNearestNeighbor(
30     const RuntimeShape& input_shape, const std::vector<T>& input_data,
31     const std::vector<int32>& output_size_data,
32     const RuntimeShape& output_shape,
33     const std::vector<T>& expected_output_data, bool align_corners = false,
34     bool half_pixel_centers = false) {
35   ResizeNearestNeighborParams op_params{align_corners, half_pixel_centers};
36   RuntimeShape output_size_shape({1, 1, 1, 2});
37 
38   std::vector<T> output_data(expected_output_data.size());
39   reference_ops::ResizeNearestNeighbor(
40       op_params, input_shape, input_data.data(), output_size_shape,
41       output_size_data.data(), output_shape, output_data.data());
42   ASSERT_EQ(expected_output_data, output_data);
43 }
44 
45 // Consistency test values are from
46 // third_party/tensorflow/core/kernels/resize_nearest_neighbor_op_test.cc.
47 
TEST(ResizeNearestNeighborReference,Test2x2To1x1)48 TEST(ResizeNearestNeighborReference, Test2x2To1x1) {
49   RuntimeShape input_shape = {1, 2, 2, 1};
50   std::vector<float> input_data = {1, 2, 3, 4};
51   std::vector<int32> output_size_data = {1, 1};
52   RuntimeShape output_shape = {1, 1, 1, 1};
53   std::vector<float> output_data = {1};
54 
55   TestReferenceResizeNearestNeighbor(input_shape, input_data, output_size_data,
56                                      output_shape, output_data);
57 }
58 
TEST(ResizeNearestNeighborReference,Test2x2To1x1_AlignCorners)59 TEST(ResizeNearestNeighborReference, Test2x2To1x1_AlignCorners) {
60   RuntimeShape input_shape = {1, 2, 2, 1};
61   std::vector<float> input_data = {1, 2, 3, 4};
62   std::vector<int32> output_size_data = {1, 1};
63   RuntimeShape output_shape = {1, 1, 1, 1};
64   std::vector<float> output_data = {1};
65 
66   TestReferenceResizeNearestNeighbor(input_shape, input_data, output_size_data,
67                                      output_shape, output_data,
68                                      /*align_corners=*/true);
69 }
70 
TEST(ResizeNearestNeighborReference,Test2x2To1x1_HalfPixelCenters)71 TEST(ResizeNearestNeighborReference, Test2x2To1x1_HalfPixelCenters) {
72   RuntimeShape input_shape = {1, 2, 2, 1};
73   std::vector<float> input_data = {1, 2, 3, 4};
74   std::vector<int32> output_size_data = {1, 1};
75   RuntimeShape output_shape = {1, 1, 1, 1};
76   std::vector<float> output_data = {4};
77 
78   TestReferenceResizeNearestNeighbor(
79       input_shape, input_data, output_size_data, output_shape, output_data,
80       /*align_corners=*/false, /*half_pixel_centers=*/true);
81 }
82 
TEST(ResizeNearestNeighborReference,Test2x2To3x3)83 TEST(ResizeNearestNeighborReference, Test2x2To3x3) {
84   RuntimeShape input_shape = {1, 2, 2, 1};
85   std::vector<uint8> input_data = {1, 2, 3, 4};
86   std::vector<int32> output_size_data = {3, 3};
87   RuntimeShape output_shape = {1, 3, 3, 1};
88   std::vector<uint8> output_data = {1, 1, 2, 1, 1, 2, 3, 3, 4};
89 
90   TestReferenceResizeNearestNeighbor(input_shape, input_data, output_size_data,
91                                      output_shape, output_data);
92 }
93 
TEST(ResizeNearestNeighborReference,Test2x2To3x3Int16)94 TEST(ResizeNearestNeighborReference, Test2x2To3x3Int16) {
95   RuntimeShape input_shape = {1, 2, 2, 1};
96   std::vector<int16_t> input_data = {1, 2, 3, 4};
97   std::vector<int32> output_size_data = {3, 3};
98   RuntimeShape output_shape = {1, 3, 3, 1};
99   std::vector<int16_t> output_data = {1, 1, 2, 1, 1, 2, 3, 3, 4};
100 
101   TestReferenceResizeNearestNeighbor(input_shape, input_data, output_size_data,
102                                      output_shape, output_data);
103 }
104 
TEST(ResizeNearestNeighborReference,Test2x2To3x3_AlignCorners)105 TEST(ResizeNearestNeighborReference, Test2x2To3x3_AlignCorners) {
106   RuntimeShape input_shape = {1, 2, 2, 1};
107   std::vector<uint8> input_data = {1, 2, 3, 4};
108   std::vector<int32> output_size_data = {3, 3};
109   RuntimeShape output_shape = {1, 3, 3, 1};
110   std::vector<uint8> output_data = {1, 2, 2, 3, 4, 4, 3, 4, 4};
111 
112   TestReferenceResizeNearestNeighbor(input_shape, input_data, output_size_data,
113                                      output_shape, output_data,
114                                      /*align_corners=*/true);
115 }
116 
TEST(ResizeNearestNeighborReference,Test2x2To3x3_HalfPixelCenters)117 TEST(ResizeNearestNeighborReference, Test2x2To3x3_HalfPixelCenters) {
118   RuntimeShape input_shape = {1, 2, 2, 1};
119   std::vector<uint8> input_data = {1, 2, 3, 4};
120   std::vector<int32> output_size_data = {3, 3};
121   RuntimeShape output_shape = {1, 3, 3, 1};
122   std::vector<uint8> output_data = {1, 2, 2, 3, 4, 4, 3, 4, 4};
123 
124   TestReferenceResizeNearestNeighbor(
125       input_shape, input_data, output_size_data, output_shape, output_data,
126       /*align_corners=*/false, /*half_pixel_centers=*/true);
127 }
128 
TEST(ResizeNearestNeighborReference,Test3x3To2x2)129 TEST(ResizeNearestNeighborReference, Test3x3To2x2) {
130   RuntimeShape input_shape = {1, 3, 3, 1};
131   std::vector<float> input_data = {1, 2, 3, 4, 5, 6, 7, 8, 9};
132   std::vector<int32> output_size_data = {2, 2};
133   RuntimeShape output_shape = {1, 2, 2, 1};
134   std::vector<float> output_data = {1, 2, 4, 5};
135 
136   TestReferenceResizeNearestNeighbor(input_shape, input_data, output_size_data,
137                                      output_shape, output_data);
138 }
139 
TEST(ResizeNearestNeighborReference,Test3x3To2x2_AlignCorners)140 TEST(ResizeNearestNeighborReference, Test3x3To2x2_AlignCorners) {
141   RuntimeShape input_shape = {1, 3, 3, 1};
142   std::vector<float> input_data = {1, 2, 3, 4, 5, 6, 7, 8, 9};
143   std::vector<int32> output_size_data = {2, 2};
144   RuntimeShape output_shape = {1, 2, 2, 1};
145   std::vector<float> output_data = {1, 3, 7, 9};
146 
147   TestReferenceResizeNearestNeighbor(input_shape, input_data, output_size_data,
148                                      output_shape, output_data,
149                                      /*align_corners=*/true);
150 }
151 
TEST(ResizeNearestNeighborReference,Test3x3To2x2_HalfPixelCenters)152 TEST(ResizeNearestNeighborReference, Test3x3To2x2_HalfPixelCenters) {
153   RuntimeShape input_shape = {1, 3, 3, 1};
154   std::vector<float> input_data = {1, 2, 3, 4, 5, 6, 7, 8, 9};
155   std::vector<int32> output_size_data = {2, 2};
156   RuntimeShape output_shape = {1, 2, 2, 1};
157   std::vector<float> output_data = {1, 3, 7, 9};
158 
159   TestReferenceResizeNearestNeighbor(
160       input_shape, input_data, output_size_data, output_shape, output_data,
161       /*align_corners=*/false, /*half_pixel_centers=*/true);
162 }
163 
TEST(ResizeNearestNeighborReference,Test2x2To2x5)164 TEST(ResizeNearestNeighborReference, Test2x2To2x5) {
165   RuntimeShape input_shape = {1, 2, 2, 1};
166   std::vector<uint8> input_data = {1, 2, 3, 4};
167   std::vector<int32> output_size_data = {2, 5};
168   RuntimeShape output_shape = {1, 2, 5, 1};
169   std::vector<uint8> output_data = {1, 1, 1, 2, 2, 3, 3, 3, 4, 4};
170 
171   TestReferenceResizeNearestNeighbor(input_shape, input_data, output_size_data,
172                                      output_shape, output_data);
173 }
174 
TEST(ResizeNearestNeighborReference,Test2x2To2x5_HalfPixelCenters)175 TEST(ResizeNearestNeighborReference, Test2x2To2x5_HalfPixelCenters) {
176   RuntimeShape input_shape = {1, 2, 2, 1};
177   std::vector<uint8> input_data = {1, 2, 3, 4};
178   std::vector<int32> output_size_data = {2, 5};
179   RuntimeShape output_shape = {1, 2, 5, 1};
180   std::vector<uint8> output_data = {1, 1, 2, 2, 2, 3, 3, 4, 4, 4};
181 
182   TestReferenceResizeNearestNeighbor(
183       input_shape, input_data, output_size_data, output_shape, output_data,
184       /*align_corners=*/false, /*half_pixel_centers=*/true);
185 }
186 
TEST(ResizeNearestNeighborReference,Test4x4To3x3)187 TEST(ResizeNearestNeighborReference, Test4x4To3x3) {
188   RuntimeShape input_shape = {1, 4, 4, 1};
189   std::vector<uint8> input_data = {1, 2,  3,  4,  5,  6,  7,  8,
190                                    9, 10, 11, 12, 13, 14, 15, 16};
191   std::vector<int32> output_size_data = {3, 3};
192   RuntimeShape output_shape = {1, 3, 3, 1};
193   std::vector<uint8> output_data = {1, 2, 3, 5, 6, 7, 9, 10, 11};
194 
195   TestReferenceResizeNearestNeighbor(input_shape, input_data, output_size_data,
196                                      output_shape, output_data);
197 }
198 
TEST(ResizeNearestNeighborReference,Test4x4To3x3_AlignCorners)199 TEST(ResizeNearestNeighborReference, Test4x4To3x3_AlignCorners) {
200   RuntimeShape input_shape = {1, 4, 4, 1};
201   std::vector<uint8> input_data = {1, 2,  3,  4,  5,  6,  7,  8,
202                                    9, 10, 11, 12, 13, 14, 15, 16};
203   std::vector<int32> output_size_data = {3, 3};
204   RuntimeShape output_shape = {1, 3, 3, 1};
205   std::vector<uint8> output_data = {1, 3, 4, 9, 11, 12, 13, 15, 16};
206 
207   TestReferenceResizeNearestNeighbor(input_shape, input_data, output_size_data,
208                                      output_shape, output_data,
209                                      /*align_corners=*/true);
210 }
211 
TEST(ResizeNearestNeighborReference,Test4x4To3x3_HalfPixelCenters)212 TEST(ResizeNearestNeighborReference, Test4x4To3x3_HalfPixelCenters) {
213   RuntimeShape input_shape = {1, 4, 4, 1};
214   std::vector<uint8> input_data = {1, 2,  3,  4,  5,  6,  7,  8,
215                                    9, 10, 11, 12, 13, 14, 15, 16};
216   std::vector<int32> output_size_data = {3, 3};
217   RuntimeShape output_shape = {1, 3, 3, 1};
218   std::vector<uint8> output_data = {1, 3, 4, 9, 11, 12, 13, 15, 16};
219 
220   TestReferenceResizeNearestNeighbor(
221       input_shape, input_data, output_size_data, output_shape, output_data,
222       /*align_corners=*/false, /*half_pixel_centers=*/true);
223 }
224 
TEST(ResizeNearestNeighborReference,Test2x2To5x2)225 TEST(ResizeNearestNeighborReference, Test2x2To5x2) {
226   RuntimeShape input_shape = {1, 2, 2, 1};
227   std::vector<float> input_data = {1, 2, 3, 4};
228   std::vector<int32> output_size_data = {5, 2};
229   RuntimeShape output_shape = {1, 5, 2, 1};
230   std::vector<float> output_data = {1, 2, 1, 2, 1, 2, 3, 4, 3, 4};
231 
232   TestReferenceResizeNearestNeighbor(input_shape, input_data, output_size_data,
233                                      output_shape, output_data);
234 }
235 
TEST(ResizeNearestNeighborReference,Test2x2To5x2_HalfPixelCenters)236 TEST(ResizeNearestNeighborReference, Test2x2To5x2_HalfPixelCenters) {
237   RuntimeShape input_shape = {1, 2, 2, 1};
238   std::vector<float> input_data = {1, 2, 3, 4};
239   std::vector<int32> output_size_data = {5, 2};
240   RuntimeShape output_shape = {1, 5, 2, 1};
241   std::vector<float> output_data = {1, 2, 1, 2, 3, 4, 3, 4, 3, 4};
242 
243   TestReferenceResizeNearestNeighbor(
244       input_shape, input_data, output_size_data, output_shape, output_data,
245       /*align_corners=*/false, /*half_pixel_centers=*/true);
246 }
247 
TEST(ResizeNearestNeighborReference,Test2x2To5x2_HalfPixelCenters_AlignCorners)248 TEST(ResizeNearestNeighborReference,
249      Test2x2To5x2_HalfPixelCenters_AlignCorners) {
250   RuntimeShape input_shape = {1, 2, 2, 1};
251   std::vector<float> input_data = {1, 2, 3, 4};
252   std::vector<int32> output_size_data = {5, 2};
253   RuntimeShape output_shape = {1, 5, 2, 1};
254   std::vector<float> output_data = {2, 2, 2, 2, 4, 4, 4, 4, 4, 4};
255 
256   TestReferenceResizeNearestNeighbor(
257       input_shape, input_data, output_size_data, output_shape, output_data,
258       /*align_corners=*/true, /*half_pixel_centers=*/true);
259 }
260 
TEST(ResizeNearestNeighborReference,Test2x2To4x4)261 TEST(ResizeNearestNeighborReference, Test2x2To4x4) {
262   RuntimeShape input_shape = {1, 2, 2, 1};
263   std::vector<uint8> input_data = {1, 2, 3, 4};
264   std::vector<int32> output_size_data = {4, 4};
265   RuntimeShape output_shape = {1, 4, 4, 1};
266   std::vector<uint8> output_data = {1, 1, 2, 2, 1, 1, 2, 2,
267                                     3, 3, 4, 4, 3, 3, 4, 4};
268 
269   TestReferenceResizeNearestNeighbor(input_shape, input_data, output_size_data,
270                                      output_shape, output_data);
271 }
272 
TEST(ResizeNearestNeighborReference,Test2x2x2x2To2x3x3x2)273 TEST(ResizeNearestNeighborReference, Test2x2x2x2To2x3x3x2) {
274   // Input:
275   //  [ [ 1, 1 ], [ 2, 2 ],
276   //    [ 3, 3 ], [ 4, 4 ] ],
277   //  [ [ 5, 5 ], [ 6, 6 ],
278   //    [ 7, 7 ], [ 8, 8 ] ]
279   RuntimeShape input_shape = {2, 2, 2, 2};
280   std::vector<float> input_data = {1, 1, 2, 2, 3, 3, 4, 4,
281                                    5, 5, 6, 6, 7, 7, 8, 8};
282   std::vector<int32> output_size_data = {3, 3};
283   RuntimeShape output_shape = {2, 3, 3, 2};
284   // Output:
285   //  [ [ 1, 1 ], [ 1, 1 ], [ 2, 2 ],
286   //    [ 1, 1 ], [ 1, 1 ], [ 2, 2 ],
287   //    [ 3, 3 ], [ 3, 3 ], [ 4, 4 ] ],
288   //  [ [ 5, 5 ], [ 5, 5 ], [ 6, 6 ],
289   //    [ 5, 5 ], [ 5, 5 ], [ 6, 6 ],
290   //    [ 7, 7 ], [ 7, 7 ], [ 8, 8 ] ]
291   std::vector<float> output_data = {1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 2, 2,
292                                     3, 3, 3, 3, 4, 4, 5, 5, 5, 5, 6, 6,
293                                     5, 5, 5, 5, 6, 6, 7, 7, 7, 7, 8, 8};
294 
295   TestReferenceResizeNearestNeighbor(input_shape, input_data, output_size_data,
296                                      output_shape, output_data);
297 }
298 
TEST(ResizeNearestNeighborReference,Test2x2x2x2To2x3x3x2_AlignCorners)299 TEST(ResizeNearestNeighborReference, Test2x2x2x2To2x3x3x2_AlignCorners) {
300   RuntimeShape input_shape = {2, 2, 2, 2};
301   std::vector<float> input_data = {1, 2, 3, 4, 5, 6, 7, 8,
302                                    1, 2, 3, 4, 5, 6, 7, 8};
303   std::vector<int32> output_size_data = {3, 3};
304   RuntimeShape output_shape = {2, 3, 3, 2};
305   std::vector<float> output_data = {
306       1, 2, 3, 4, 3, 4, 5, 6, 7, 8, 7, 8, 5, 6, 7, 8, 7, 8,
307       1, 2, 3, 4, 3, 4, 5, 6, 7, 8, 7, 8, 5, 6, 7, 8, 7, 8,
308   };
309 
310   TestReferenceResizeNearestNeighbor(
311       input_shape, input_data, output_size_data, output_shape, output_data,
312       /*align_corners=*/true, /*half_pixel_centers=*/false);
313 }
314 
TEST(ResizeNearestNeighborReference,Test2x2x2x2To2x3x3x2_HalfPixelCenters)315 TEST(ResizeNearestNeighborReference, Test2x2x2x2To2x3x3x2_HalfPixelCenters) {
316   RuntimeShape input_shape = {2, 2, 2, 2};
317   std::vector<float> input_data = {1, 1, 2, 2, 3, 3, 4, 4,
318                                    5, 5, 6, 6, 7, 7, 8, 8};
319   std::vector<int32> output_size_data = {3, 3};
320   RuntimeShape output_shape = {2, 3, 3, 2};
321   std::vector<float> output_data = {1, 1, 2, 2, 2, 2, 3, 3, 4, 4, 4, 4,
322                                     3, 3, 4, 4, 4, 4, 5, 5, 6, 6, 6, 6,
323                                     7, 7, 8, 8, 8, 8, 7, 7, 8, 8, 8, 8};
324 
325   TestReferenceResizeNearestNeighbor(
326       input_shape, input_data, output_size_data, output_shape, output_data,
327       /*align_corners=*/false, /*half_pixel_centers=*/true);
328 }
329 
TEST(ResizeNearestNeighborReference,Test2x2x2x2To2x3x3x2_HalfPixelCenters_AlignCorners)330 TEST(ResizeNearestNeighborReference,
331      Test2x2x2x2To2x3x3x2_HalfPixelCenters_AlignCorners) {
332   RuntimeShape input_shape = {2, 2, 2, 2};
333   std::vector<float> input_data = {1, 2, 3, 4, 5, 6, 7, 8,
334                                    1, 2, 3, 4, 5, 6, 7, 8};
335   std::vector<int32> output_size_data = {3, 3};
336   RuntimeShape output_shape = {2, 3, 3, 2};
337   std::vector<float> output_data = {1, 2, 3, 4, 3, 4, 5, 6, 7, 8, 7, 8,
338                                     5, 6, 7, 8, 7, 8, 1, 2, 3, 4, 3, 4,
339                                     5, 6, 7, 8, 7, 8, 5, 6, 7, 8, 7, 8};
340 
341   TestReferenceResizeNearestNeighbor(
342       input_shape, input_data, output_size_data, output_shape, output_data,
343       /*align_corners=*/true, /*half_pixel_centers=*/true);
344 }
345 
TestOptimizedResizeNearestNeighbor(int batch,int depth,int input_width,int input_height,int output_width,int output_height)346 void TestOptimizedResizeNearestNeighbor(int batch, int depth, int input_width,
347                                         int input_height, int output_width,
348                                         int output_height) {
349   RuntimeShape output_size_shape({1, 1, 1, 2});
350 
351   RuntimeShape input_shape({batch, input_height, input_width, depth});
352   RuntimeShape output_shape({batch, output_height, output_width, depth});
353 
354   std::vector<uint8> input_data(input_shape.FlatSize(), 0);
355   FillRandom(&input_data, static_cast<uint8>(0), static_cast<uint8>(255));
356 
357   std::vector<uint8> reference_output_data(output_shape.FlatSize(), 0);
358   // Initialize the output data with something other than zero, so we can catch
359   // issue with kernels failing to initialize the output.
360   std::vector<uint8> output_data(output_shape.FlatSize(), 3);
361   std::vector<int32> output_size_data = {output_height, output_width};
362 
363   ResizeNearestNeighborParams op_params{/*align_corners=*/false,
364                                         /*half_pixel_centers=*/false};
365 
366   // Test the optimized version against the reference version.
367   reference_ops::ResizeNearestNeighbor(
368       op_params, input_shape, input_data.data(), output_size_shape,
369       output_size_data.data(), output_shape, reference_output_data.data());
370   optimized_ops::ResizeNearestNeighbor(
371       op_params, input_shape, input_data.data(), output_size_shape,
372       output_size_data.data(), output_shape, output_data.data());
373   ASSERT_EQ(reference_output_data, output_data);
374 
375   op_params.align_corners = true;
376   reference_ops::ResizeNearestNeighbor(
377       op_params, input_shape, input_data.data(), output_size_shape,
378       output_size_data.data(), output_shape, reference_output_data.data());
379   optimized_ops::ResizeNearestNeighbor(
380       op_params, input_shape, input_data.data(), output_size_shape,
381       output_size_data.data(), output_shape, output_data.data());
382   ASSERT_EQ(reference_output_data, output_data);
383 
384   op_params.align_corners = false;
385   op_params.half_pixel_centers = true;
386   reference_ops::ResizeNearestNeighbor(
387       op_params, input_shape, input_data.data(), output_size_shape,
388       output_size_data.data(), output_shape, reference_output_data.data());
389   optimized_ops::ResizeNearestNeighbor(
390       op_params, input_shape, input_data.data(), output_size_shape,
391       output_size_data.data(), output_shape, output_data.data());
392   ASSERT_EQ(reference_output_data, output_data);
393 
394   op_params.align_corners = true;
395   op_params.half_pixel_centers = true;
396   reference_ops::ResizeNearestNeighbor(
397       op_params, input_shape, input_data.data(), output_size_shape,
398       output_size_data.data(), output_shape, reference_output_data.data());
399   optimized_ops::ResizeNearestNeighbor(
400       op_params, input_shape, input_data.data(), output_size_shape,
401       output_size_data.data(), output_shape, output_data.data());
402   ASSERT_EQ(reference_output_data, output_data);
403 }
404 
405 // Since the optimized version uses fixed-point and the reference version uses
406 // float, offsets may differ. Test if the input/output image combination results
407 // in the same offsets before running parity tests.
is_valid_scale(int input_width,int input_height,int output_width,int output_height)408 bool is_valid_scale(int input_width, int input_height, int output_width,
409                     int output_height) {
410   const float height_scale_float =
411       static_cast<float>(input_height) / output_height;
412   const float width_scale_float =
413       static_cast<float>(input_width) / output_width;
414 
415   int32 height_scale_int = (input_height << 16) / output_height + 1;
416   int32 width_scale_int = (input_width << 16) / output_width + 1;
417 
418   for (int y = 0; y < output_height; ++y) {
419     int32 in_y_float =
420         std::min(static_cast<int32>(std::floor(y * height_scale_float)),
421                  input_height - 1);
422     int32 in_y_int = std::min((y * height_scale_int) >> 16, input_height - 1);
423     if (in_y_int != in_y_float) {
424       return false;
425     }
426     for (int x = 0; x < output_width; ++x) {
427       int32 in_x_float =
428           std::min(static_cast<int32>(std::floor(x * width_scale_float)),
429                    input_width - 1);
430       int32 in_x_int = std::min((x * width_scale_int) >> 16, input_width - 1);
431       if (in_x_int != in_x_float) {
432         return false;
433       }
434     }
435   }
436   return true;
437 }
438 
TEST(ResizeNearestNeighborOptimized,TestReferenceParity)439 TEST(ResizeNearestNeighborOptimized, TestReferenceParity) {
440   int invalid_count = 0;
441   const int kTestsToRun = 10000;
442   for (int i = 0; i < kTestsToRun; i++) {
443     const int batch = ExponentialRandomPositiveInt(0.9f, 3, 20);
444     const int depth = ExponentialRandomPositiveInt(0.9f, 6, 50);
445     const int input_width = ExponentialRandomPositiveInt(0.9f, 20, 200);
446     const int input_height = ExponentialRandomPositiveInt(0.9f, 20, 200);
447     const int output_width = ExponentialRandomPositiveInt(0.9f, 20, 200);
448     const int output_height = ExponentialRandomPositiveInt(0.9f, 20, 200);
449 
450     if (is_valid_scale(input_width, input_height, output_width,
451                        output_height)) {
452       TestOptimizedResizeNearestNeighbor(
453           batch, depth, input_width, input_height, output_width, output_height);
454     } else {
455       invalid_count++;
456     }
457   }
458   // Test that the total number of invalid tests are a small percentage.
459   ASSERT_LT(static_cast<float>(invalid_count) / kTestsToRun, 0.001f);
460 }
461 
462 }  // namespace
463 }  // namespace tflite
464