• 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 
TestUnpackThreeOutputsFloat(const int * input_dims_data,const float * input_data,int axis,const int * output1_dims_data,const float * expected_output1_data,const int * output2_dims_data,const float * expected_output2_data,const int * output3_dims_data,const float * expected_output3_data,float * output1_data,float * output2_data,float * output3_data)26 void TestUnpackThreeOutputsFloat(
27     const int* input_dims_data, const float* input_data, int axis,
28     const int* output1_dims_data, const float* expected_output1_data,
29     const int* output2_dims_data, const float* expected_output2_data,
30     const int* output3_dims_data, const float* expected_output3_data,
31     float* output1_data, float* output2_data, float* output3_data) {
32   TfLiteIntArray* input_dims = IntArrayFromInts(input_dims_data);
33   TfLiteIntArray* output1_dims = IntArrayFromInts(output1_dims_data);
34   TfLiteIntArray* output2_dims = IntArrayFromInts(output2_dims_data);
35   TfLiteIntArray* output3_dims = IntArrayFromInts(output3_dims_data);
36   const int output1_dims_count = ElementCount(*output1_dims);
37   const int output2_dims_count = ElementCount(*output2_dims);
38   const int output3_dims_count = ElementCount(*output3_dims);
39 
40   constexpr int input_size = 1;
41   constexpr int output_size = 3;
42   constexpr int tensors_size = input_size + output_size;
43   TfLiteTensor tensors[tensors_size] = {
44       CreateTensor(input_data, input_dims),
45       CreateTensor(output1_data, output1_dims),
46       CreateTensor(output2_data, output2_dims),
47       CreateTensor(output3_data, output3_dims)};
48 
49   // Place a unique value in the uninitialized output buffer.
50   for (int i = 0; i < output1_dims_count; ++i) {
51     output1_data[i] = 23;
52   }
53 
54   for (int i = 0; i < output2_dims_count; ++i) {
55     output2_data[i] = 23;
56   }
57 
58   for (int i = 0; i < output3_dims_count; ++i) {
59     output3_data[i] = 23;
60   }
61 
62   TfLiteUnpackParams builtin_data = {
63       .num = 3,
64       .axis = axis,
65   };
66 
67   int inputs_array_data[] = {1, 0};
68   TfLiteIntArray* inputs_array = IntArrayFromInts(inputs_array_data);
69   int outputs_array_data[] = {3, 1, 2, 3};
70   TfLiteIntArray* outputs_array = IntArrayFromInts(outputs_array_data);
71 
72   const TfLiteRegistration registration = tflite::ops::micro::Register_UNPACK();
73   micro::KernelRunner runner(registration, tensors, tensors_size, inputs_array,
74                              outputs_array,
75                              reinterpret_cast<void*>(&builtin_data));
76 
77   TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, runner.InitAndPrepare());
78   TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, runner.Invoke());
79 
80   for (int i = 0; i < output1_dims_count; ++i) {
81     TF_LITE_MICRO_EXPECT_NEAR(expected_output1_data[i], output1_data[i], 1e-5f);
82   }
83 
84   for (int i = 0; i < output2_dims_count; ++i) {
85     TF_LITE_MICRO_EXPECT_NEAR(expected_output2_data[i], output2_data[i], 1e-5f);
86   }
87 
88   for (int i = 0; i < output3_dims_count; ++i) {
89     TF_LITE_MICRO_EXPECT_NEAR(expected_output3_data[i], output3_data[i], 1e-5f);
90   }
91 }
92 
TestUnpackOneOutputFloat(const int * input_dims_data,const float * input_data,int axis,const int * output_dims_data,const float * expected_output_data,float * output_data)93 void TestUnpackOneOutputFloat(const int* input_dims_data,
94                               const float* input_data, int axis,
95                               const int* output_dims_data,
96                               const float* expected_output_data,
97                               float* output_data) {
98   TfLiteIntArray* input_dims = IntArrayFromInts(input_dims_data);
99   TfLiteIntArray* output_dims = IntArrayFromInts(output_dims_data);
100   const int output_dims_count = ElementCount(*output_dims);
101 
102   constexpr int input_size = 1;
103   constexpr int output_size = 1;
104   constexpr int tensors_size = input_size + output_size;
105   TfLiteTensor tensors[tensors_size] = {CreateTensor(input_data, input_dims),
106                                         CreateTensor(output_data, output_dims)};
107 
108   // Place a unique value in the uninitialized output buffer.
109   for (int i = 0; i < output_dims_count; ++i) {
110     output_data[i] = 23;
111   }
112 
113   TfLiteUnpackParams builtin_data = {
114       .num = 1,
115       .axis = axis,
116   };
117 
118   int inputs_array_data[] = {1, 0};
119   TfLiteIntArray* inputs_array = IntArrayFromInts(inputs_array_data);
120   int outputs_array_data[] = {1, 1};
121   TfLiteIntArray* outputs_array = IntArrayFromInts(outputs_array_data);
122 
123   const TfLiteRegistration registration = tflite::ops::micro::Register_UNPACK();
124   micro::KernelRunner runner(registration, tensors, tensors_size, inputs_array,
125                              outputs_array,
126                              reinterpret_cast<void*>(&builtin_data));
127 
128   TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, runner.InitAndPrepare());
129   TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, runner.Invoke());
130 
131   for (int i = 0; i < output_dims_count; ++i) {
132     TF_LITE_MICRO_EXPECT_NEAR(expected_output_data[i], output_data[i], 1e-5f);
133   }
134 }
135 
TestUnpackThreeOutputsQuantized(const int * input_dims_data,const uint8_t * input_data,int axis,const int * output1_dims_data,const uint8_t * expected_output1_data,const int * output2_dims_data,const uint8_t * expected_output2_data,const int * output3_dims_data,const uint8_t * expected_output3_data,uint8_t * output1_data,uint8_t * output2_data,uint8_t * output3_data)136 void TestUnpackThreeOutputsQuantized(
137     const int* input_dims_data, const uint8_t* input_data, int axis,
138     const int* output1_dims_data, const uint8_t* expected_output1_data,
139     const int* output2_dims_data, const uint8_t* expected_output2_data,
140     const int* output3_dims_data, const uint8_t* expected_output3_data,
141     uint8_t* output1_data, uint8_t* output2_data, uint8_t* output3_data) {
142   TfLiteIntArray* input_dims = IntArrayFromInts(input_dims_data);
143   TfLiteIntArray* output1_dims = IntArrayFromInts(output1_dims_data);
144   TfLiteIntArray* output2_dims = IntArrayFromInts(output2_dims_data);
145   TfLiteIntArray* output3_dims = IntArrayFromInts(output3_dims_data);
146   const int output1_dims_count = ElementCount(*output1_dims);
147   const int output2_dims_count = ElementCount(*output2_dims);
148   const int output3_dims_count = ElementCount(*output3_dims);
149 
150   constexpr int input_size = 1;
151   constexpr int output_size = 3;
152   constexpr int tensors_size = input_size + output_size;
153   TfLiteTensor tensors[tensors_size] = {
154       // CreateQuantizedTensor needs min/max values as input, but these values
155       // don't matter as to the functionality of UNPACK, so just set as 0
156       // and 10.
157       CreateQuantizedTensor(input_data, input_dims, 0, 10),
158       CreateQuantizedTensor(output1_data, output1_dims, 0, 10),
159       CreateQuantizedTensor(output2_data, output2_dims, 0, 10),
160       CreateQuantizedTensor(output3_data, output3_dims, 0, 10)};
161 
162   // Place a unique value in the uninitialized output buffer.
163   for (int i = 0; i < output1_dims_count; ++i) {
164     output1_data[i] = 23;
165   }
166 
167   for (int i = 0; i < output2_dims_count; ++i) {
168     output2_data[i] = 23;
169   }
170 
171   for (int i = 0; i < output3_dims_count; ++i) {
172     output3_data[i] = 23;
173   }
174 
175   TfLiteUnpackParams builtin_data = {
176       .num = 3,
177       .axis = axis,
178   };
179 
180   int inputs_array_data[] = {1, 0};
181   TfLiteIntArray* inputs_array = IntArrayFromInts(inputs_array_data);
182   int outputs_array_data[] = {3, 1, 2, 3};
183   TfLiteIntArray* outputs_array = IntArrayFromInts(outputs_array_data);
184 
185   const TfLiteRegistration registration = tflite::ops::micro::Register_UNPACK();
186   micro::KernelRunner runner(registration, tensors, tensors_size, inputs_array,
187                              outputs_array,
188                              reinterpret_cast<void*>(&builtin_data));
189 
190   TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, runner.InitAndPrepare());
191   TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, runner.Invoke());
192 
193   for (int i = 0; i < output1_dims_count; ++i) {
194     TF_LITE_MICRO_EXPECT_EQ(expected_output1_data[i], output1_data[i]);
195   }
196 
197   for (int i = 0; i < output2_dims_count; ++i) {
198     TF_LITE_MICRO_EXPECT_EQ(expected_output2_data[i], output2_data[i]);
199   }
200 
201   for (int i = 0; i < output3_dims_count; ++i) {
202     TF_LITE_MICRO_EXPECT_EQ(expected_output3_data[i], output3_data[i]);
203   }
204 }
205 
TestUnpackThreeOutputsQuantized32(const int * input_dims_data,const int32_t * input_data,int axis,const int * output1_dims_data,const int32_t * expected_output1_data,const int * output2_dims_data,const int32_t * expected_output2_data,const int * output3_dims_data,const int32_t * expected_output3_data,int32_t * output1_data,int32_t * output2_data,int32_t * output3_data)206 void TestUnpackThreeOutputsQuantized32(
207     const int* input_dims_data, const int32_t* input_data, int axis,
208     const int* output1_dims_data, const int32_t* expected_output1_data,
209     const int* output2_dims_data, const int32_t* expected_output2_data,
210     const int* output3_dims_data, const int32_t* expected_output3_data,
211     int32_t* output1_data, int32_t* output2_data, int32_t* output3_data) {
212   TfLiteIntArray* input_dims = IntArrayFromInts(input_dims_data);
213   TfLiteIntArray* output1_dims = IntArrayFromInts(output1_dims_data);
214   TfLiteIntArray* output2_dims = IntArrayFromInts(output2_dims_data);
215   TfLiteIntArray* output3_dims = IntArrayFromInts(output3_dims_data);
216   const int output1_dims_count = ElementCount(*output1_dims);
217   const int output2_dims_count = ElementCount(*output2_dims);
218   const int output3_dims_count = ElementCount(*output3_dims);
219 
220   constexpr int input_size = 1;
221   constexpr int output_size = 3;
222   constexpr int tensors_size = input_size + output_size;
223   TfLiteTensor tensors[tensors_size] = {
224       CreateTensor(input_data, input_dims),
225       CreateTensor(output1_data, output1_dims),
226       CreateTensor(output2_data, output2_dims),
227       CreateTensor(output3_data, output3_dims)};
228 
229   // Place a unique value in the uninitialized output buffer.
230   for (int i = 0; i < output1_dims_count; ++i) {
231     output1_data[i] = 23;
232   }
233 
234   for (int i = 0; i < output2_dims_count; ++i) {
235     output2_data[i] = 23;
236   }
237 
238   for (int i = 0; i < output3_dims_count; ++i) {
239     output3_data[i] = 23;
240   }
241 
242   TfLiteUnpackParams builtin_data = {
243       .num = 3,
244       .axis = axis,
245   };
246 
247   int inputs_array_data[] = {1, 0};
248   TfLiteIntArray* inputs_array = IntArrayFromInts(inputs_array_data);
249   int outputs_array_data[] = {3, 1, 2, 3};
250   TfLiteIntArray* outputs_array = IntArrayFromInts(outputs_array_data);
251 
252   const TfLiteRegistration registration = tflite::ops::micro::Register_UNPACK();
253   micro::KernelRunner runner(registration, tensors, tensors_size, inputs_array,
254                              outputs_array,
255                              reinterpret_cast<void*>(&builtin_data));
256 
257   TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, runner.InitAndPrepare());
258   TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, runner.Invoke());
259 
260   for (int i = 0; i < output1_dims_count; ++i) {
261     TF_LITE_MICRO_EXPECT_EQ(expected_output1_data[i], output1_data[i]);
262   }
263 
264   for (int i = 0; i < output2_dims_count; ++i) {
265     TF_LITE_MICRO_EXPECT_EQ(expected_output2_data[i], output2_data[i]);
266   }
267 
268   for (int i = 0; i < output3_dims_count; ++i) {
269     TF_LITE_MICRO_EXPECT_EQ(expected_output3_data[i], output3_data[i]);
270   }
271 }
272 
273 }  // namespace testing
274 }  // namespace tflite
275 
276 TF_LITE_MICRO_TESTS_BEGIN
277 
TF_LITE_MICRO_TEST(UnpackFloatThreeOutputs)278 TF_LITE_MICRO_TEST(UnpackFloatThreeOutputs) {
279   const int input_shape[] = {2, 3, 2};
280   const float input_values[] = {1, 2, 3, 4, 5, 6};
281   const int output1_shape[] = {1, 2};
282   const float output1_golden[] = {1, 2};
283   const int output2_shape[] = {1, 2};
284   const float output2_golden[] = {3, 4};
285   const int output3_shape[] = {1, 2};
286   const float output3_golden[] = {5, 6};
287   constexpr int output1_dims_count = 2;
288   constexpr int output2_dims_count = 2;
289   constexpr int output3_dims_count = 2;
290   float output1_data[output1_dims_count];
291   float output2_data[output2_dims_count];
292   float output3_data[output3_dims_count];
293   tflite::testing::TestUnpackThreeOutputsFloat(
294       input_shape, input_values, 0, output1_shape, output1_golden,
295       output2_shape, output2_golden, output3_shape, output3_golden,
296       output1_data, output2_data, output3_data);
297 }
298 
TF_LITE_MICRO_TEST(UnpackFloatThreeOutputsNegativeAxisTwo)299 TF_LITE_MICRO_TEST(UnpackFloatThreeOutputsNegativeAxisTwo) {
300   const int input_shape[] = {2, 3, 2};
301   const float input_values[] = {1, 2, 3, 4, 5, 6};
302   const int output1_shape[] = {1, 2};
303   const float output1_golden[] = {1, 2};
304   const int output2_shape[] = {1, 2};
305   const float output2_golden[] = {3, 4};
306   const int output3_shape[] = {1, 2};
307   const float output3_golden[] = {5, 6};
308   constexpr int output1_dims_count = 2;
309   constexpr int output2_dims_count = 2;
310   constexpr int output3_dims_count = 2;
311   float output1_data[output1_dims_count];
312   float output2_data[output2_dims_count];
313   float output3_data[output3_dims_count];
314   tflite::testing::TestUnpackThreeOutputsFloat(
315       input_shape, input_values, -2, output1_shape, output1_golden,
316       output2_shape, output2_golden, output3_shape, output3_golden,
317       output1_data, output2_data, output3_data);
318 }
319 
TF_LITE_MICRO_TEST(UnpackFloatOneOutput)320 TF_LITE_MICRO_TEST(UnpackFloatOneOutput) {
321   const int input_shape[] = {2, 1, 6};
322   const float input_values[] = {1, 2, 3, 4, 5, 6};
323   const int output_shape[] = {1, 6};
324   const float golden[] = {1, 2, 3, 4, 5, 6};
325   constexpr int output_dims_count = 6;
326   float output_data[output_dims_count];
327   tflite::testing::TestUnpackOneOutputFloat(input_shape, input_values, 0,
328                                             output_shape, golden, output_data);
329 }
330 
TF_LITE_MICRO_TEST(UnpackQuantizedThreeOutputs)331 TF_LITE_MICRO_TEST(UnpackQuantizedThreeOutputs) {
332   const int input_shape[] = {2, 3, 2};
333   const uint8_t input_values[] = {1, 2, 3, 4, 5, 6};
334   const int output1_shape[] = {1, 2};
335   const uint8_t output1_golden[] = {1, 2};
336   const int output2_shape[] = {1, 2};
337   const uint8_t output2_golden[] = {3, 4};
338   const int output3_shape[] = {1, 2};
339   const uint8_t output3_golden[] = {5, 6};
340   constexpr int output1_dims_count = 2;
341   constexpr int output2_dims_count = 2;
342   constexpr int output3_dims_count = 2;
343   uint8_t output1_data[output1_dims_count];
344   uint8_t output2_data[output2_dims_count];
345   uint8_t output3_data[output3_dims_count];
346   tflite::testing::TestUnpackThreeOutputsQuantized(
347       input_shape, input_values, 0, output1_shape, output1_golden,
348       output2_shape, output2_golden, output3_shape, output3_golden,
349       output1_data, output2_data, output3_data);
350 }
351 
TF_LITE_MICRO_TEST(UnpackQuantized32ThreeOutputs)352 TF_LITE_MICRO_TEST(UnpackQuantized32ThreeOutputs) {
353   const int input_shape[] = {2, 3, 2};
354   const int32_t input_values[] = {1, 2, 3, 4, 5, 6};
355   const int output1_shape[] = {1, 2};
356   const int32_t output1_golden[] = {1, 2};
357   const int output2_shape[] = {1, 2};
358   const int32_t output2_golden[] = {3, 4};
359   const int output3_shape[] = {1, 2};
360   const int32_t output3_golden[] = {5, 6};
361   constexpr int output1_dims_count = 2;
362   constexpr int output2_dims_count = 2;
363   constexpr int output3_dims_count = 2;
364   int32_t output1_data[output1_dims_count];
365   int32_t output2_data[output2_dims_count];
366   int32_t output3_data[output3_dims_count];
367   tflite::testing::TestUnpackThreeOutputsQuantized32(
368       input_shape, input_values, 0, output1_shape, output1_golden,
369       output2_shape, output2_golden, output3_shape, output3_golden,
370       output1_data, output2_data, output3_data);
371 }
372 
373 TF_LITE_MICRO_TESTS_END
374