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 
16 #include "tensorflow/lite/c/builtin_op_data.h"
17 #include "tensorflow/lite/c/common.h"
18 #include "tensorflow/lite/micro/all_ops_resolver.h"
19 #include "tensorflow/lite/micro/kernels/kernel_runner.h"
20 #include "tensorflow/lite/micro/test_helpers.h"
21 #include "tensorflow/lite/micro/testing/micro_test.h"
22 
23 namespace tflite {
24 namespace testing {
25 namespace {
26 
ValidateArgMinMaxGoldens(TfLiteTensor * tensors,int tensors_size,const int32_t * golden,int32_t * output,int output_size,bool using_min)27 void ValidateArgMinMaxGoldens(TfLiteTensor* tensors, int tensors_size,
28                               const int32_t* golden, int32_t* output,
29                               int output_size, bool using_min) {
30   int inputs_array_data[] = {2, 0, 1};
31   TfLiteIntArray* inputs_array = IntArrayFromInts(inputs_array_data);
32   int outputs_array_data[] = {1, 2};
33   TfLiteIntArray* outputs_array = IntArrayFromInts(outputs_array_data);
34 
35   const TfLiteRegistration registration = using_min
36                                               ? ops::micro::Register_ARG_MIN()
37                                               : ops::micro::Register_ARG_MAX();
38   micro::KernelRunner runner(registration, tensors, tensors_size, inputs_array,
39                              outputs_array,
40                              /*builtin_data=*/nullptr);
41 
42   TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, runner.InitAndPrepare());
43   TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, runner.Invoke());
44 
45   for (int i = 0; i < output_size; ++i) {
46     TF_LITE_MICRO_EXPECT_EQ(golden[i], output[i]);
47   }
48 }
49 
TestArgMinMaxFloat(int * input_dims_data,const float * input_values,int * axis_dims_data,const int32_t * axis_values,int * output_dims_data,int32_t * output,const int32_t * goldens,bool using_min)50 void TestArgMinMaxFloat(int* input_dims_data, const float* input_values,
51                         int* axis_dims_data, const int32_t* axis_values,
52                         int* output_dims_data, int32_t* output,
53                         const int32_t* goldens, bool using_min) {
54   TfLiteIntArray* input_dims = IntArrayFromInts(input_dims_data);
55   TfLiteIntArray* axis_dims = IntArrayFromInts(axis_dims_data);
56   TfLiteIntArray* output_dims = IntArrayFromInts(output_dims_data);
57   const int output_dims_count = ElementCount(*output_dims);
58 
59   constexpr int inputs_size = 2;
60   constexpr int outputs_size = 1;
61   constexpr int tensors_size = inputs_size + outputs_size;
62   TfLiteTensor tensors[tensors_size] = {
63       CreateTensor(input_values, input_dims),
64       CreateTensor(axis_values, axis_dims),
65       CreateTensor(output, output_dims),
66   };
67 
68   ValidateArgMinMaxGoldens(tensors, tensors_size, goldens, output,
69                            output_dims_count, using_min);
70 }
71 
72 template <typename T>
TestArgMinMaxQuantized(int * input_dims_data,const float * input_values,T * input_quantized,float input_scale,int input_zero_point,int * axis_dims_data,const int32_t * axis_values,int * output_dims_data,int32_t * output,const int32_t * goldens,bool using_min)73 void TestArgMinMaxQuantized(int* input_dims_data, const float* input_values,
74                             T* input_quantized, float input_scale,
75                             int input_zero_point, int* axis_dims_data,
76                             const int32_t* axis_values, int* output_dims_data,
77                             int32_t* output, const int32_t* goldens,
78                             bool using_min) {
79   TfLiteIntArray* input_dims = IntArrayFromInts(input_dims_data);
80   TfLiteIntArray* axis_dims = IntArrayFromInts(axis_dims_data);
81   TfLiteIntArray* output_dims = IntArrayFromInts(output_dims_data);
82   const int output_dims_count = ElementCount(*output_dims);
83 
84   constexpr int inputs_size = 2;
85   constexpr int outputs_size = 1;
86   constexpr int tensors_size = inputs_size + outputs_size;
87   TfLiteTensor tensors[tensors_size] = {
88       CreateQuantizedTensor(input_values, input_quantized, input_dims,
89                             input_scale, input_zero_point),
90       CreateTensor(axis_values, axis_dims),
91       CreateTensor(output, output_dims),
92   };
93 
94   ValidateArgMinMaxGoldens(tensors, tensors_size, goldens, output,
95                            output_dims_count, using_min);
96 }
97 
98 }  // namespace
99 }  // namespace testing
100 }  // namespace tflite
101 
102 TF_LITE_MICRO_TESTS_BEGIN
103 
TF_LITE_MICRO_TEST(GetMaxArgFloat)104 TF_LITE_MICRO_TEST(GetMaxArgFloat) {
105   int32_t output_data[1];
106   int input_dims[] = {4, 1, 1, 1, 4};
107   const float input_values[] = {0.1, 0.9, 0.7, 0.3};
108   int axis_dims[] = {3, 1, 1, 1};
109   const int32_t axis_values[] = {3};
110   int output_dims[] = {3, 1, 1, 1};
111   const int32_t goldens[] = {1};
112 
113   tflite::testing::TestArgMinMaxFloat(input_dims, input_values, axis_dims,
114                                       axis_values, output_dims, output_data,
115                                       goldens, false);
116 }
117 
TF_LITE_MICRO_TEST(GetMinArgFloat)118 TF_LITE_MICRO_TEST(GetMinArgFloat) {
119   int32_t output_data[1];
120   int input_dims[] = {4, 1, 1, 1, 4};
121   const float input_values[] = {0.1, 0.9, 0.7, 0.3};
122   int axis_dims[] = {3, 1, 1, 1};
123   const int32_t axis_values[] = {3};
124   int output_dims[] = {3, 1, 1, 1};
125   const int32_t goldens[] = {0};
126 
127   tflite::testing::TestArgMinMaxFloat(input_dims, input_values, axis_dims,
128                                       axis_values, output_dims, output_data,
129                                       goldens, true);
130 }
131 
TF_LITE_MICRO_TEST(GetMaxArgUInt8)132 TF_LITE_MICRO_TEST(GetMaxArgUInt8) {
133   int32_t output_data[1];
134   const int input_size = 4;
135   int input_dims[] = {4, 1, 1, 1, input_size};
136   const float input_values[] = {1, 9, 7, 3};
137   int axis_dims[] = {3, 1, 1, 1};
138   const int32_t axis_values[] = {3};
139   int output_dims[] = {3, 1, 1, 1};
140   const int32_t goldens[] = {1};
141 
142   float input_scale = 0.5;
143   int input_zero_point = 124;
144   uint8_t input_quantized[input_size];
145 
146   tflite::testing::TestArgMinMaxQuantized(
147       input_dims, input_values, input_quantized, input_scale, input_zero_point,
148       axis_dims, axis_values, output_dims, output_data, goldens, false);
149 }
150 
TF_LITE_MICRO_TEST(GetMinArgUInt8)151 TF_LITE_MICRO_TEST(GetMinArgUInt8) {
152   int32_t output_data[1];
153   const int input_size = 4;
154   int input_dims[] = {4, 1, 1, 1, input_size};
155   const float input_values[] = {1, 9, 7, 3};
156   int axis_dims[] = {3, 1, 1, 1};
157   const int32_t axis_values[] = {3};
158   int output_dims[] = {3, 1, 1, 1};
159   const int32_t goldens[] = {0};
160 
161   float input_scale = 0.5;
162   int input_zero_point = 124;
163   uint8_t input_quantized[input_size];
164 
165   tflite::testing::TestArgMinMaxQuantized(
166       input_dims, input_values, input_quantized, input_scale, input_zero_point,
167       axis_dims, axis_values, output_dims, output_data, goldens, true);
168 }
169 
TF_LITE_MICRO_TEST(GetMaxArgInt8)170 TF_LITE_MICRO_TEST(GetMaxArgInt8) {
171   int32_t output_data[1];
172   const int input_size = 4;
173   int input_dims[] = {4, 1, 1, 1, input_size};
174   const float input_values[] = {1, 9, 7, 3};
175   int axis_dims[] = {3, 1, 1, 1};
176   const int32_t axis_values[] = {3};
177   int output_dims[] = {3, 1, 1, 1};
178   const int32_t goldens[] = {1};
179 
180   float input_scale = 0.5;
181   int input_zero_point = -9;
182   int8_t input_quantized[input_size];
183 
184   tflite::testing::TestArgMinMaxQuantized(
185       input_dims, input_values, input_quantized, input_scale, input_zero_point,
186       axis_dims, axis_values, output_dims, output_data, goldens, false);
187 }
188 
TF_LITE_MICRO_TEST(GetMinArgInt8)189 TF_LITE_MICRO_TEST(GetMinArgInt8) {
190   int32_t output_data[1];
191   const int input_size = 4;
192   int input_dims[] = {4, 1, 1, 1, input_size};
193   const float input_values[] = {1, 9, 7, 3};
194   int axis_dims[] = {3, 1, 1, 1};
195   const int32_t axis_values[] = {3};
196   int output_dims[] = {3, 1, 1, 1};
197   const int32_t goldens[] = {0};
198 
199   float input_scale = 0.5;
200   int input_zero_point = -9;
201   int8_t input_quantized[input_size];
202 
203   tflite::testing::TestArgMinMaxQuantized(
204       input_dims, input_values, input_quantized, input_scale, input_zero_point,
205       axis_dims, axis_values, output_dims, output_data, goldens, true);
206 }
207 
TF_LITE_MICRO_TEST(GetMaxArgMulDimensions)208 TF_LITE_MICRO_TEST(GetMaxArgMulDimensions) {
209   int32_t output_data[2];
210   const int input_size = 8;
211   int input_dims[] = {4, 1, 1, 2, 4};
212   const float input_values[] = {1, 2, 7, 8, 1, 9, 7, 3};
213   int axis_dims[] = {3, 1, 1, 1};
214   const int32_t axis_values[] = {3};
215   int output_dims[] = {3, 1, 1, 2};
216   const int32_t goldens[] = {3, 1};
217 
218   float input_scale = 0.5;
219   int input_zero_point = -9;
220   int8_t input_quantized[input_size];
221 
222   tflite::testing::TestArgMinMaxQuantized(
223       input_dims, input_values, input_quantized, input_scale, input_zero_point,
224       axis_dims, axis_values, output_dims, output_data, goldens, false);
225 }
226 
TF_LITE_MICRO_TEST(GetMinArgMulDimensions)227 TF_LITE_MICRO_TEST(GetMinArgMulDimensions) {
228   int32_t output_data[2];
229   const int input_size = 8;
230   int input_dims[] = {4, 1, 1, 2, 4};
231   const float input_values[] = {1, 2, 7, 8, 1, 9, 7, 3};
232   int axis_dims[] = {3, 1, 1, 1};
233   const int32_t axis_values[] = {3};
234   int output_dims[] = {3, 1, 1, 2};
235   const int32_t goldens[] = {0, 0};
236 
237   float input_scale = 0.5;
238   int input_zero_point = -9;
239   int8_t input_quantized[input_size];
240 
241   tflite::testing::TestArgMinMaxQuantized(
242       input_dims, input_values, input_quantized, input_scale, input_zero_point,
243       axis_dims, axis_values, output_dims, output_data, goldens, true);
244 }
245 
TF_LITE_MICRO_TEST(GetMaxArgNegativeAxis)246 TF_LITE_MICRO_TEST(GetMaxArgNegativeAxis) {
247   const int input_size = 8;
248   const int output_size = 4;
249   int input_dims[] = {4, 1, 1, 2, 4};
250   const float input_values[] = {1, 2, 7, 8, 1, 9, 7, 3};
251   int axis_dims[] = {3, 1, 1, 1};
252   const int32_t axis_values[] = {-2};
253   int output_dims[] = {3, 1, 1, 4};
254   const int32_t goldens[] = {0, 1, 0, 0};
255 
256   float input_scale = 0.5;
257   int input_zero_point = -9;
258   int32_t output_data[output_size];
259   int8_t input_quantized[input_size];
260 
261   tflite::testing::TestArgMinMaxQuantized(
262       input_dims, input_values, input_quantized, input_scale, input_zero_point,
263       axis_dims, axis_values, output_dims, output_data, goldens, false);
264 }
265 
266 TF_LITE_MICRO_TESTS_END
267