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