1 /* Copyright 2021 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 
TestReluFloat(int * input_dims_data,const float * input_data,int * output_dims_data,const float * golden,float * output_data)27 void TestReluFloat(int* input_dims_data, const float* input_data,
28                    int* output_dims_data, const float* golden,
29                    float* output_data) {
30   TfLiteIntArray* input_dims = IntArrayFromInts(input_dims_data);
31   TfLiteIntArray* output_dims = IntArrayFromInts(output_dims_data);
32   const int output_elements_count = ElementCount(*output_dims);
33 
34   constexpr int inputs_size = 1;
35   constexpr int outputs_size = 1;
36   constexpr int tensors_size = inputs_size + outputs_size;
37   TfLiteTensor tensors[tensors_size] = {
38       CreateTensor(input_data, input_dims),
39       CreateTensor(output_data, output_dims),
40   };
41 
42   int inputs_array_data[] = {1, 0};
43   TfLiteIntArray* inputs_array = IntArrayFromInts(inputs_array_data);
44   int outputs_array_data[] = {1, 1};
45   TfLiteIntArray* outputs_array = IntArrayFromInts(outputs_array_data);
46 
47   const TfLiteRegistration registration = Register_RELU();
48   micro::KernelRunner runner(registration, tensors, tensors_size, inputs_array,
49                              outputs_array,
50                              /*builtin_data=*/nullptr);
51 
52   TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, runner.InitAndPrepare());
53   TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, runner.Invoke());
54 
55   for (int i = 0; i < output_elements_count; ++i) {
56     TF_LITE_MICRO_EXPECT_NEAR(golden[i], output_data[i], 1e-5f);
57   }
58 }
59 
TestRelu6Float(int * input_dims_data,const float * input_data,int * output_dims_data,const float * golden,float * output_data)60 void TestRelu6Float(int* input_dims_data, const float* input_data,
61                     int* output_dims_data, const float* golden,
62                     float* output_data) {
63   TfLiteIntArray* input_dims = IntArrayFromInts(input_dims_data);
64   TfLiteIntArray* output_dims = IntArrayFromInts(output_dims_data);
65   const int output_elements_count = ElementCount(*output_dims);
66 
67   constexpr int inputs_size = 1;
68   constexpr int outputs_size = 1;
69   constexpr int tensors_size = inputs_size + outputs_size;
70   TfLiteTensor tensors[tensors_size] = {
71       CreateTensor(input_data, input_dims),
72       CreateTensor(output_data, output_dims),
73   };
74 
75   int inputs_array_data[] = {1, 0};
76   TfLiteIntArray* inputs_array = IntArrayFromInts(inputs_array_data);
77   int outputs_array_data[] = {1, 1};
78   TfLiteIntArray* outputs_array = IntArrayFromInts(outputs_array_data);
79 
80   const TfLiteRegistration registration = Register_RELU6();
81   micro::KernelRunner runner(registration, tensors, tensors_size, inputs_array,
82                              outputs_array,
83                              /*builtin_data=*/nullptr);
84 
85   TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, runner.InitAndPrepare());
86   TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, runner.Invoke());
87 
88   for (int i = 0; i < output_elements_count; ++i) {
89     TF_LITE_MICRO_EXPECT_NEAR(golden[i], output_data[i], 1e-5f);
90   }
91 }
92 
TestReluInt8(int * input_dims_data,const float * input_data,int8_t * input_data_quantized,const float input_scale,const int input_zero_point,const float * golden,int8_t * golden_quantized,int * output_dims_data,const float output_scale,const int output_zero_point,int8_t * output_data)93 void TestReluInt8(int* input_dims_data, const float* input_data,
94                   int8_t* input_data_quantized, const float input_scale,
95                   const int input_zero_point, const float* golden,
96                   int8_t* golden_quantized, int* output_dims_data,
97                   const float output_scale, const int output_zero_point,
98                   int8_t* output_data) {
99   TfLiteIntArray* input_dims = IntArrayFromInts(input_dims_data);
100   TfLiteIntArray* output_dims = IntArrayFromInts(output_dims_data);
101   const int output_elements_count = ElementCount(*output_dims);
102   constexpr int inputs_size = 1;
103   constexpr int outputs_size = 1;
104   constexpr int tensors_size = inputs_size + outputs_size;
105   TfLiteTensor tensors[tensors_size] = {
106       CreateQuantizedTensor(input_data, input_data_quantized, input_dims,
107                             input_scale, input_zero_point),
108       CreateQuantizedTensor(output_data, output_dims, output_scale,
109                             output_zero_point),
110   };
111 
112   int inputs_array_data[] = {1, 0};
113   TfLiteIntArray* inputs_array = IntArrayFromInts(inputs_array_data);
114   int outputs_array_data[] = {1, 1};
115   TfLiteIntArray* outputs_array = IntArrayFromInts(outputs_array_data);
116 
117   const TfLiteRegistration registration = Register_RELU();
118   micro::KernelRunner runner(registration, tensors, tensors_size, inputs_array,
119                              outputs_array,
120                              /*builtin_data=*/nullptr);
121 
122   TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, runner.InitAndPrepare());
123   TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, runner.Invoke());
124 
125   Quantize(golden, golden_quantized, output_elements_count, output_scale,
126            output_zero_point);
127 
128   for (int i = 0; i < output_elements_count; ++i) {
129     TF_LITE_MICRO_EXPECT_EQ(golden_quantized[i], output_data[i]);
130   }
131 }
132 
TestRelu6Int8(int * input_dims_data,const float * input_data,int8_t * input_data_quantized,const float input_scale,const int input_zero_point,const float * golden,int8_t * golden_quantized,int * output_dims_data,const float output_scale,const int output_zero_point,int8_t * output_data)133 void TestRelu6Int8(int* input_dims_data, const float* input_data,
134                    int8_t* input_data_quantized, const float input_scale,
135                    const int input_zero_point, const float* golden,
136                    int8_t* golden_quantized, int* output_dims_data,
137                    const float output_scale, const int output_zero_point,
138                    int8_t* output_data) {
139   TfLiteIntArray* input_dims = IntArrayFromInts(input_dims_data);
140   TfLiteIntArray* output_dims = IntArrayFromInts(output_dims_data);
141   const int output_elements_count = ElementCount(*output_dims);
142   constexpr int inputs_size = 1;
143   constexpr int outputs_size = 1;
144   constexpr int tensors_size = inputs_size + outputs_size;
145   TfLiteTensor tensors[tensors_size] = {
146       CreateQuantizedTensor(input_data, input_data_quantized, input_dims,
147                             input_scale, input_zero_point),
148       CreateQuantizedTensor(output_data, output_dims, output_scale,
149                             output_zero_point),
150   };
151 
152   int inputs_array_data[] = {1, 0};
153   TfLiteIntArray* inputs_array = IntArrayFromInts(inputs_array_data);
154   int outputs_array_data[] = {1, 1};
155   TfLiteIntArray* outputs_array = IntArrayFromInts(outputs_array_data);
156 
157   const TfLiteRegistration registration = Register_RELU6();
158   micro::KernelRunner runner(registration, tensors, tensors_size, inputs_array,
159                              outputs_array,
160                              /*builtin_data=*/nullptr);
161 
162   TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, runner.InitAndPrepare());
163   TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, runner.Invoke());
164 
165   Quantize(golden, golden_quantized, output_elements_count, output_scale,
166            output_zero_point);
167 
168   for (int i = 0; i < output_elements_count; ++i) {
169     TF_LITE_MICRO_EXPECT_EQ(golden_quantized[i], output_data[i]);
170   }
171 }
172 
173 }  // namespace
174 }  // namespace testing
175 }  // namespace tflite
176 
177 TF_LITE_MICRO_TESTS_BEGIN
178 
TF_LITE_MICRO_TEST(SimpleReluTestFloat)179 TF_LITE_MICRO_TEST(SimpleReluTestFloat) {
180   const int output_elements_count = 10;
181   int input_shape[] = {2, 1, 5};
182   const float input_data[] = {
183       1.0, 2.0, 3.0, 4.0, 5.0, -1.0, -2.0, -3.0, -4.0, -5.0,
184   };
185   const float golden[] = {1.0, 2.0, 3.0, 4.0, 5.0, 0, 0, 0, 0, 0};
186   int output_shape[] = {2, 1, 5};
187   float output_data[output_elements_count];
188   tflite::testing::TestReluFloat(input_shape, input_data, output_shape, golden,
189                                  output_data);
190 }
191 
TF_LITE_MICRO_TEST(SimpleRelu6TestFloat)192 TF_LITE_MICRO_TEST(SimpleRelu6TestFloat) {
193   const int output_elements_count = 10;
194   float output_data[output_elements_count];
195   int input_shape[] = {2, 1, 5};
196   const float input_data[] = {4.0,  5.0,  6.0,  7.0,  8.0,
197                               -4.0, -5.0, -6.0, -7.0, -8.0};
198   int output_shape[] = {2, 1, 5};
199   const float golden[] = {
200       4.0, 5.0, 6.0, 6.0, 6.0, 0.0, 0.0, 0.0, 0.0, 0.0,
201   };
202 
203   tflite::testing::TestRelu6Float(input_shape, input_data, output_shape, golden,
204                                   output_data);
205 }
206 
TF_LITE_MICRO_TEST(SimpleReluTestInt8)207 TF_LITE_MICRO_TEST(SimpleReluTestInt8) {
208   const int elements_count = 10;
209 
210   int input_shape[] = {2, 1, 5};
211   const float input_data[] = {1, 2, 3, 4, 5, -1, -2, -3, -4, -5};
212   int8_t input_quantized[elements_count];
213   int output_shape[] = {2, 1, 5};
214   const float golden[] = {1, 2, 3, 4, 5, 0, 0, 0, 0, 0};
215   int8_t golden_quantized[elements_count];
216   int8_t output_data[elements_count];
217 
218   const float input_scale = 0.5f;
219   const int input_zero_point = 0;
220   const float output_scale = 0.5f;
221   const int output_zero_point = 0;
222 
223   tflite::testing::TestReluInt8(input_shape, input_data, input_quantized,
224                                 input_scale, input_zero_point, golden,
225                                 golden_quantized, output_shape, output_scale,
226                                 output_zero_point, output_data);
227 }
228 
TF_LITE_MICRO_TEST(SimpleRelu6TestInt8)229 TF_LITE_MICRO_TEST(SimpleRelu6TestInt8) {
230   const int elements_count = 10;
231 
232   int input_shape[] = {2, 1, 5};
233   const float input_data[] = {4, 5, 6, 7, 8, -1, -2, -3, -4, -5};
234   int8_t input_quantized[elements_count];
235   int output_shape[] = {2, 1, 5};
236   const float golden[] = {4, 5, 6, 6, 6, 0, 0, 0, 0, 0};
237   int8_t golden_quantized[elements_count];
238   int8_t output_data[elements_count];
239 
240   const float input_scale = 0.5f;
241   const int input_zero_point = 127;
242   const float output_scale = 0.5f;
243   const int output_zero_point = 127;
244 
245   tflite::testing::TestRelu6Int8(input_shape, input_data, input_quantized,
246                                  input_scale, input_zero_point, golden,
247                                  golden_quantized, output_shape, output_scale,
248                                  output_zero_point, output_data);
249 }
250 
251 TF_LITE_MICRO_TESTS_END
252