1 /* Copyright 2017 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
TestMaxMinFloat(const TfLiteRegistration & registration,const int * input1_dims_data,const float * input1_data,const int * input2_dims_data,const float * input2_data,const float * expected_output_data,const int * output_dims_data,float * output_data)27 void TestMaxMinFloat(const TfLiteRegistration& registration,
28 const int* input1_dims_data, const float* input1_data,
29 const int* input2_dims_data, const float* input2_data,
30 const float* expected_output_data,
31 const int* output_dims_data, float* output_data) {
32 TfLiteIntArray* input1_dims = IntArrayFromInts(input1_dims_data);
33 TfLiteIntArray* input2_dims = IntArrayFromInts(input2_dims_data);
34 TfLiteIntArray* output_dims = IntArrayFromInts(output_dims_data);
35 const int output_dims_count = ElementCount(*output_dims);
36
37 constexpr int inputs_size = 2;
38 constexpr int outputs_size = 1;
39 constexpr int tensors_size = inputs_size + outputs_size;
40 TfLiteTensor tensors[tensors_size] = {
41 CreateTensor(input1_data, input1_dims),
42 CreateTensor(input2_data, input2_dims),
43 CreateTensor(output_data, output_dims),
44 };
45
46 int inputs_array_data[] = {2, 0, 1};
47 TfLiteIntArray* inputs_array = IntArrayFromInts(inputs_array_data);
48 int outputs_array_data[] = {1, 2};
49 TfLiteIntArray* outputs_array = IntArrayFromInts(outputs_array_data);
50
51 micro::KernelRunner runner(registration, tensors, tensors_size, inputs_array,
52 outputs_array,
53 /*builtin_data=*/nullptr);
54
55 TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, runner.InitAndPrepare());
56 TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, runner.Invoke());
57
58 for (int i = 0; i < output_dims_count; ++i) {
59 TF_LITE_MICRO_EXPECT_NEAR(expected_output_data[i], output_data[i], 1e-5f);
60 }
61 }
62
TestMaxMinQuantized(const TfLiteRegistration & registration,const int * input1_dims_data,const uint8_t * input1_data,float const input1_scale,const int input1_zero_point,const int * input2_dims_data,const uint8_t * input2_data,const float input2_scale,const int input2_zero_point,const uint8_t * expected_output_data,const float output_scale,const int output_zero_point,const int * output_dims_data,uint8_t * output_data)63 void TestMaxMinQuantized(const TfLiteRegistration& registration,
64 const int* input1_dims_data,
65 const uint8_t* input1_data, float const input1_scale,
66 const int input1_zero_point,
67 const int* input2_dims_data,
68 const uint8_t* input2_data, const float input2_scale,
69 const int input2_zero_point,
70 const uint8_t* expected_output_data,
71 const float output_scale, const int output_zero_point,
72 const int* output_dims_data, uint8_t* output_data) {
73 TfLiteIntArray* input1_dims = IntArrayFromInts(input1_dims_data);
74 TfLiteIntArray* input2_dims = IntArrayFromInts(input2_dims_data);
75 TfLiteIntArray* output_dims = IntArrayFromInts(output_dims_data);
76 const int output_dims_count = ElementCount(*output_dims);
77
78 constexpr int inputs_size = 2;
79 constexpr int outputs_size = 1;
80 constexpr int tensors_size = inputs_size + outputs_size;
81 TfLiteTensor tensors[tensors_size] = {
82 CreateQuantizedTensor(input1_data, input1_dims, input1_scale,
83 input1_zero_point),
84 CreateQuantizedTensor(input2_data, input2_dims, input2_scale,
85 input2_zero_point),
86 CreateQuantizedTensor(output_data, output_dims, output_scale,
87 output_zero_point),
88 };
89
90 int inputs_array_data[] = {2, 0, 1};
91 TfLiteIntArray* inputs_array = IntArrayFromInts(inputs_array_data);
92 int outputs_array_data[] = {1, 2};
93 TfLiteIntArray* outputs_array = IntArrayFromInts(outputs_array_data);
94
95 micro::KernelRunner runner(registration, tensors, tensors_size, inputs_array,
96 outputs_array,
97 /*builtin_data=*/nullptr);
98
99 TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, runner.InitAndPrepare());
100 TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, runner.Invoke());
101
102 for (int i = 0; i < output_dims_count; ++i) {
103 TF_LITE_MICRO_EXPECT_EQ(expected_output_data[i], output_data[i]);
104 }
105 }
106
TestMaxMinQuantizedInt32(const TfLiteRegistration & registration,const int * input1_dims_data,const int32_t * input1_data,const int * input2_dims_data,const int32_t * input2_data,const int32_t * expected_output_data,const int * output_dims_data,int32_t * output_data)107 void TestMaxMinQuantizedInt32(
108 const TfLiteRegistration& registration, const int* input1_dims_data,
109 const int32_t* input1_data, const int* input2_dims_data,
110 const int32_t* input2_data, const int32_t* expected_output_data,
111 const int* output_dims_data, int32_t* output_data) {
112 TfLiteIntArray* input1_dims = IntArrayFromInts(input1_dims_data);
113 TfLiteIntArray* input2_dims = IntArrayFromInts(input2_dims_data);
114 TfLiteIntArray* output_dims = IntArrayFromInts(output_dims_data);
115 const int output_dims_count = ElementCount(*output_dims);
116
117 constexpr int inputs_size = 2;
118 constexpr int outputs_size = 1;
119 constexpr int tensors_size = inputs_size + outputs_size;
120 TfLiteTensor tensors[tensors_size] = {
121 CreateTensor(input1_data, input1_dims),
122 CreateTensor(input2_data, input2_dims),
123 CreateTensor(output_data, output_dims),
124 };
125
126 int inputs_array_data[] = {2, 0, 1};
127 TfLiteIntArray* inputs_array = IntArrayFromInts(inputs_array_data);
128 int outputs_array_data[] = {1, 2};
129 TfLiteIntArray* outputs_array = IntArrayFromInts(outputs_array_data);
130
131 micro::KernelRunner runner(registration, tensors, tensors_size, inputs_array,
132 outputs_array,
133 /*builtin_data=*/nullptr);
134
135 TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, runner.InitAndPrepare());
136 TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, runner.Invoke());
137
138 for (int i = 0; i < output_dims_count; ++i) {
139 TF_LITE_MICRO_EXPECT_EQ(expected_output_data[i], output_data[i]);
140 }
141 }
142
143 } // namespace
144 } // namespace testing
145 } // namespace tflite
146
147 TF_LITE_MICRO_TESTS_BEGIN
148
TF_LITE_MICRO_TEST(FloatTest)149 TF_LITE_MICRO_TEST(FloatTest) {
150 const int dims[] = {3, 3, 1, 2};
151 const float data1[] = {1.0, 0.0, -1.0, 11.0, -2.0, -1.44};
152 const float data2[] = {-1.0, 0.0, 1.0, 12.0, -3.0, -1.43};
153 const float golden_max[] = {1.0, 0.0, 1.0, 12.0, -2.0, -1.43};
154 const float golden_min[] = {-1.0, 0.0, -1.0, 11.0, -3.0, -1.44};
155 float output_data[6];
156
157 tflite::testing::TestMaxMinFloat(tflite::ops::micro::Register_MAXIMUM(), dims,
158 data1, dims, data2, golden_max, dims,
159 output_data);
160
161 tflite::testing::TestMaxMinFloat(tflite::ops::micro::Register_MINIMUM(), dims,
162 data1, dims, data2, golden_min, dims,
163 output_data);
164 }
165
TF_LITE_MICRO_TEST(Uint8Test)166 TF_LITE_MICRO_TEST(Uint8Test) {
167 const int dims[] = {3, 3, 1, 2};
168 const uint8_t data1[] = {1, 0, 2, 11, 2, 23};
169 const uint8_t data2[] = {0, 0, 1, 12, 255, 1};
170 const uint8_t golden_max[] = {1, 0, 2, 12, 255, 23};
171 const uint8_t golden_min[] = {0, 0, 1, 11, 2, 1};
172
173 const float input_scale = 1.0;
174 const int input_zero_point = 0;
175 const float output_scale = 1.0;
176 const int output_zero_point = 0;
177
178 uint8_t output_data[6];
179
180 tflite::testing::TestMaxMinQuantized(
181 tflite::ops::micro::Register_MAXIMUM(), dims, data1, input_scale,
182 input_zero_point, dims, data2, input_scale, input_zero_point, golden_max,
183 output_scale, output_zero_point, dims, output_data);
184
185 tflite::testing::TestMaxMinQuantized(
186 tflite::ops::micro::Register_MINIMUM(), dims, data1, input_scale,
187 input_zero_point, dims, data2, input_scale, input_zero_point, golden_min,
188 output_scale, output_zero_point, dims, output_data);
189 }
190
TF_LITE_MICRO_TEST(FloatWithBroadcastTest)191 TF_LITE_MICRO_TEST(FloatWithBroadcastTest) {
192 const int dims[] = {3, 3, 1, 2};
193 const int dims_scalar[] = {1, 2};
194 const float data1[] = {1.0, 0.0, -1.0, -2.0, -1.44, 11.0};
195 const float data2[] = {0.5, 2.0};
196 const float golden_max[] = {1.0, 2.0, 0.5, 2.0, 0.5, 11.0};
197 const float golden_min[] = {0.5, 0.0, -1.0, -2.0, -1.44, 2.0};
198 float output_data[6];
199
200 tflite::testing::TestMaxMinFloat(tflite::ops::micro::Register_MAXIMUM(), dims,
201 data1, dims_scalar, data2, golden_max, dims,
202 output_data);
203
204 tflite::testing::TestMaxMinFloat(tflite::ops::micro::Register_MINIMUM(), dims,
205 data1, dims_scalar, data2, golden_min, dims,
206 output_data);
207 }
208
TF_LITE_MICRO_TEST(Int32WithBroadcastTest)209 TF_LITE_MICRO_TEST(Int32WithBroadcastTest) {
210 const int dims[] = {3, 3, 1, 2};
211 const int dims_scalar[] = {1, 1};
212 const int32_t data1[] = {1, 0, -1, -2, 3, 11};
213 const int32_t data2[] = {2};
214 const int32_t golden_max[] = {2, 2, 2, 2, 3, 11};
215 const int32_t golden_min[] = {1, 0, -1, -2, 2, 2};
216 int32_t output_data[6];
217
218 tflite::testing::TestMaxMinQuantizedInt32(
219 tflite::ops::micro::Register_MAXIMUM(), dims, data1, dims_scalar, data2,
220 golden_max, dims, output_data);
221
222 tflite::testing::TestMaxMinQuantizedInt32(
223 tflite::ops::micro::Register_MINIMUM(), dims, data1, dims_scalar, data2,
224 golden_min, dims, output_data);
225 }
226
227 TF_LITE_MICRO_TESTS_END
228