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