• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2019 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/debug_log.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 
26 template <typename T>
ValidatePackGoldens(TfLiteTensor * tensors,int tensors_size,TfLitePackParams params,TfLiteIntArray * inputs_array,TfLiteIntArray * outputs_array,const T * golden,int output_len,float tolerance,T * output)27 void ValidatePackGoldens(TfLiteTensor* tensors, int tensors_size,
28                          TfLitePackParams params, TfLiteIntArray* inputs_array,
29                          TfLiteIntArray* outputs_array, const T* golden,
30                          int output_len, float tolerance, T* output) {
31   // Place a unique value in the uninitialized output buffer.
32   for (int i = 0; i < output_len; ++i) {
33     output[i] = 23;
34   }
35 
36   const TfLiteRegistration registration = tflite::ops::micro::Register_PACK();
37   micro::KernelRunner runner(registration, tensors, tensors_size, inputs_array,
38                              outputs_array, reinterpret_cast<void*>(&params));
39 
40   TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, runner.InitAndPrepare());
41   TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, runner.Invoke());
42 
43   for (int i = 0; i < output_len; ++i) {
44     TF_LITE_MICRO_EXPECT_NEAR(golden[i], output[i], tolerance);
45   }
46 }
47 
TestPackTwoInputsFloat(const int * input1_dims_data,const float * input1_data,const int * input2_dims_data,const float * input2_data,int axis,const int * output_dims_data,const float * expected_output_data,float * output_data)48 void TestPackTwoInputsFloat(const int* input1_dims_data,
49                             const float* input1_data,
50                             const int* input2_dims_data,
51                             const float* input2_data, int axis,
52                             const int* output_dims_data,
53                             const float* expected_output_data,
54                             float* output_data) {
55   TfLiteIntArray* input1_dims = IntArrayFromInts(input1_dims_data);
56   TfLiteIntArray* input2_dims = IntArrayFromInts(input2_dims_data);
57   TfLiteIntArray* output_dims = IntArrayFromInts(output_dims_data);
58   const int output_dims_count = ElementCount(*output_dims);
59 
60   constexpr int input_size = 2;
61   constexpr int output_size = 1;
62   constexpr int tensors_size = input_size + output_size;
63   TfLiteTensor tensors[tensors_size] = {CreateTensor(input1_data, input1_dims),
64                                         CreateTensor(input2_data, input2_dims),
65                                         CreateTensor(output_data, output_dims)};
66 
67   TfLitePackParams builtin_data = {
68       .values_count = 2,
69       .axis = axis,
70   };
71   int inputs_array_data[] = {2, 0, 1};
72   TfLiteIntArray* inputs_array = IntArrayFromInts(inputs_array_data);
73   int outputs_array_data[] = {1, 2};
74   TfLiteIntArray* outputs_array = IntArrayFromInts(outputs_array_data);
75 
76   ValidatePackGoldens(tensors, tensors_size, builtin_data, inputs_array,
77                       outputs_array, expected_output_data, output_dims_count,
78                       1e-5f, output_data);
79 }
80 
TestPackThreeInputsFloat(const int * input1_dims_data,const float * input1_data,const int * input2_dims_data,const float * input2_data,const int * input3_dims_data,const float * input3_data,int axis,const int * output_dims_data,const float * expected_output_data,float * output_data)81 void TestPackThreeInputsFloat(
82     const int* input1_dims_data, const float* input1_data,
83     const int* input2_dims_data, const float* input2_data,
84     const int* input3_dims_data, const float* input3_data, int axis,
85     const int* output_dims_data, const float* expected_output_data,
86     float* output_data) {
87   TfLiteIntArray* input1_dims = IntArrayFromInts(input1_dims_data);
88   TfLiteIntArray* input2_dims = IntArrayFromInts(input2_dims_data);
89   TfLiteIntArray* input3_dims = IntArrayFromInts(input3_dims_data);
90   TfLiteIntArray* output_dims = IntArrayFromInts(output_dims_data);
91   const int output_dims_count = ElementCount(*output_dims);
92 
93   constexpr int input_size = 3;
94   constexpr int output_size = 1;
95   constexpr int tensors_size = input_size + output_size;
96   TfLiteTensor tensors[tensors_size] = {CreateTensor(input1_data, input1_dims),
97                                         CreateTensor(input2_data, input2_dims),
98                                         CreateTensor(input3_data, input3_dims),
99                                         CreateTensor(output_data, output_dims)};
100 
101   TfLitePackParams builtin_data = {
102       .values_count = 3,
103       .axis = axis,
104   };
105   int inputs_array_data[] = {3, 0, 1, 2};
106   TfLiteIntArray* inputs_array = IntArrayFromInts(inputs_array_data);
107   int outputs_array_data[] = {1, 3};
108   TfLiteIntArray* outputs_array = IntArrayFromInts(outputs_array_data);
109 
110   ValidatePackGoldens(tensors, tensors_size, builtin_data, inputs_array,
111                       outputs_array, expected_output_data, output_dims_count,
112                       1e-5f, output_data);
113 }
114 
TestPackTwoInputsQuantized(const int * input1_dims_data,const uint8_t * input1_data,const int * input2_dims_data,const uint8_t * input2_data,int axis,const int * output_dims_data,const uint8_t * expected_output_data,uint8_t * output_data)115 void TestPackTwoInputsQuantized(const int* input1_dims_data,
116                                 const uint8_t* input1_data,
117                                 const int* input2_dims_data,
118                                 const uint8_t* input2_data, int axis,
119                                 const int* output_dims_data,
120                                 const uint8_t* expected_output_data,
121                                 uint8_t* output_data) {
122   TfLiteIntArray* input1_dims = IntArrayFromInts(input1_dims_data);
123   TfLiteIntArray* input2_dims = IntArrayFromInts(input2_dims_data);
124   TfLiteIntArray* output_dims = IntArrayFromInts(output_dims_data);
125   const int output_dims_count = ElementCount(*output_dims);
126 
127   constexpr int input_size = 2;
128   constexpr int output_size = 1;
129   constexpr int tensors_size = input_size + output_size;
130   TfLiteTensor tensors[tensors_size] = {
131       // CreateQuantizedTensor needs scale/zero_point values as input, but these
132       // values don't matter as to the functionality of PACK, so just set as 1.0
133       // and 128.
134       CreateQuantizedTensor(input1_data, input1_dims, 1.0, 128),
135       CreateQuantizedTensor(input2_data, input2_dims, 1.0, 128),
136       CreateQuantizedTensor(output_data, output_dims, 1.0, 128)};
137 
138   TfLitePackParams builtin_data = {
139       .values_count = 2,
140       .axis = axis,
141   };
142   int inputs_array_data[] = {2, 0, 1};
143   TfLiteIntArray* inputs_array = IntArrayFromInts(inputs_array_data);
144   int outputs_array_data[] = {1, 2};
145   TfLiteIntArray* outputs_array = IntArrayFromInts(outputs_array_data);
146 
147   ValidatePackGoldens(tensors, tensors_size, builtin_data, inputs_array,
148                       outputs_array, expected_output_data, output_dims_count,
149                       1e-5f, output_data);
150 }
151 
TestPackTwoInputsQuantized32(const int * input1_dims_data,const int32_t * input1_data,const int * input2_dims_data,const int32_t * input2_data,int axis,const int * output_dims_data,const int32_t * expected_output_data,int32_t * output_data)152 void TestPackTwoInputsQuantized32(const int* input1_dims_data,
153                                   const int32_t* input1_data,
154                                   const int* input2_dims_data,
155                                   const int32_t* input2_data, int axis,
156                                   const int* output_dims_data,
157                                   const int32_t* expected_output_data,
158                                   int32_t* output_data) {
159   TfLiteIntArray* input1_dims = IntArrayFromInts(input1_dims_data);
160   TfLiteIntArray* input2_dims = IntArrayFromInts(input2_dims_data);
161   TfLiteIntArray* output_dims = IntArrayFromInts(output_dims_data);
162   const int output_dims_count = ElementCount(*output_dims);
163 
164   constexpr int input_size = 2;
165   constexpr int output_size = 1;
166   constexpr int tensors_size = input_size + output_size;
167   TfLiteTensor tensors[tensors_size] = {CreateTensor(input1_data, input1_dims),
168                                         CreateTensor(input2_data, input2_dims),
169                                         CreateTensor(output_data, output_dims)};
170 
171   TfLitePackParams builtin_data = {
172       .values_count = 2,
173       .axis = axis,
174   };
175   int inputs_array_data[] = {2, 0, 1};
176   TfLiteIntArray* inputs_array = IntArrayFromInts(inputs_array_data);
177   int outputs_array_data[] = {1, 2};
178   TfLiteIntArray* outputs_array = IntArrayFromInts(outputs_array_data);
179 
180   ValidatePackGoldens(tensors, tensors_size, builtin_data, inputs_array,
181                       outputs_array, expected_output_data, output_dims_count,
182                       1e-5f, output_data);
183 }
184 
185 }  // namespace testing
186 }  // namespace tflite
187 
188 TF_LITE_MICRO_TESTS_BEGIN
189 
TF_LITE_MICRO_TEST(PackFloatThreeInputs)190 TF_LITE_MICRO_TEST(PackFloatThreeInputs) {
191   const int input_shape[] = {1, 2};
192   const int output_shape[] = {2, 3, 2};
193   const float input1_values[] = {1, 4};
194   const float input2_values[] = {2, 5};
195   const float input3_values[] = {3, 6};
196   const float golden[] = {1, 4, 2, 5, 3, 6};
197   const int axis = 0;
198   constexpr int output_dims_count = 6;
199   float output_data[output_dims_count];
200 
201   tflite::testing::TestPackThreeInputsFloat(
202       input_shape, input1_values, input_shape, input2_values, input_shape,
203       input3_values, axis, output_shape, golden, output_data);
204 }
205 
TF_LITE_MICRO_TEST(PackFloatThreeInputsDifferentAxis)206 TF_LITE_MICRO_TEST(PackFloatThreeInputsDifferentAxis) {
207   const int input_shape[] = {1, 2};
208   const int output_shape[] = {2, 2, 3};
209   const float input1_values[] = {1, 4};
210   const float input2_values[] = {2, 5};
211   const float input3_values[] = {3, 6};
212   const float golden[] = {1, 2, 3, 4, 5, 6};
213   const int axis = 1;
214   constexpr int output_dims_count = 6;
215   float output_data[output_dims_count];
216 
217   tflite::testing::TestPackThreeInputsFloat(
218       input_shape, input1_values, input_shape, input2_values, input_shape,
219       input3_values, axis, output_shape, golden, output_data);
220 }
221 
TF_LITE_MICRO_TEST(PackFloatThreeInputsNegativeAxis)222 TF_LITE_MICRO_TEST(PackFloatThreeInputsNegativeAxis) {
223   const int input_shape[] = {1, 2};
224   const int output_shape[] = {2, 2, 3};
225   const float input1_values[] = {1, 4};
226   const float input2_values[] = {2, 5};
227   const float input3_values[] = {3, 6};
228   const float golden[] = {1, 2, 3, 4, 5, 6};
229   const int axis = -1;
230   constexpr int output_dims_count = 6;
231   float output_data[output_dims_count];
232 
233   tflite::testing::TestPackThreeInputsFloat(
234       input_shape, input1_values, input_shape, input2_values, input_shape,
235       input3_values, axis, output_shape, golden, output_data);
236 }
237 
TF_LITE_MICRO_TEST(PackFloatMultilDimensions)238 TF_LITE_MICRO_TEST(PackFloatMultilDimensions) {
239   const int input_shape[] = {2, 2, 3};
240   const int output_shape[] = {3, 2, 2, 3};
241   const float input1_values[] = {1, 2, 3, 4, 5, 6};
242   const float input2_values[] = {7, 8, 9, 10, 11, 12};
243   const float golden[] = {1, 2, 3, 7, 8, 9, 4, 5, 6, 10, 11, 12};
244   const int axis = 1;
245   constexpr int output_dims_count = 12;
246   float output_data[output_dims_count];
247 
248   tflite::testing::TestPackTwoInputsFloat(input_shape, input1_values,
249                                           input_shape, input2_values, axis,
250                                           output_shape, golden, output_data);
251 }
252 
TF_LITE_MICRO_TEST(PackQuantizedMultilDimensions)253 TF_LITE_MICRO_TEST(PackQuantizedMultilDimensions) {
254   const int input_shape[] = {2, 2, 3};
255   const int output_shape[] = {3, 2, 2, 3};
256   const uint8_t input1_values[] = {1, 2, 3, 4, 5, 6};
257   const uint8_t input2_values[] = {7, 8, 9, 10, 11, 12};
258   const uint8_t golden[] = {1, 2, 3, 7, 8, 9, 4, 5, 6, 10, 11, 12};
259   const int axis = 1;
260   constexpr int output_dims_count = 12;
261   uint8_t output_data[output_dims_count];
262 
263   tflite::testing::TestPackTwoInputsQuantized(
264       input_shape, input1_values, input_shape, input2_values, axis,
265       output_shape, golden, output_data);
266 }
267 
TF_LITE_MICRO_TEST(PackQuantized32MultilDimensions)268 TF_LITE_MICRO_TEST(PackQuantized32MultilDimensions) {
269   const int input_shape[] = {2, 2, 3};
270   const int output_shape[] = {3, 2, 2, 3};
271   const int32_t input1_values[] = {1, 2, 3, 4, 5, 6};
272   const int32_t input2_values[] = {7, 8, 9, 10, 11, 12};
273   const int32_t golden[] = {1, 2, 3, 7, 8, 9, 4, 5, 6, 10, 11, 12};
274   const int axis = 1;
275   constexpr int output_dims_count = 12;
276   int32_t output_data[output_dims_count];
277 
278   tflite::testing::TestPackTwoInputsQuantized32(
279       input_shape, input1_values, input_shape, input2_values, axis,
280       output_shape, golden, output_data);
281 }
282 
283 TF_LITE_MICRO_TESTS_END
284