• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/kernels/internal/quantization_util.h"
17 
18 #include "tensorflow/lite/micro/testing/micro_test.h"
19 
20 namespace tflite {
21 namespace {
22 
23 template <class FloatIn, class IntOut>
RunSafeCastTests()24 void RunSafeCastTests() {
25   const IntOut imax = std::numeric_limits<IntOut>::max();
26   TF_LITE_MICRO_EXPECT_GT(imax, 0);
27   const IntOut imin = std::numeric_limits<IntOut>::min();
28   const bool s = std::numeric_limits<IntOut>::is_signed;
29   if (s) {
30     TF_LITE_MICRO_EXPECT_LT(static_cast<IntOut>(imin), 0);
31   } else {
32     TF_LITE_MICRO_EXPECT_EQ(static_cast<IntOut>(0), imin);
33   }
34 
35   // Some basic tests.
36   TF_LITE_MICRO_EXPECT_EQ(SafeCast<IntOut>(static_cast<FloatIn>(0.0)),
37                           static_cast<IntOut>(0));
38   TF_LITE_MICRO_EXPECT_EQ(SafeCast<IntOut>(static_cast<FloatIn>(-0.0)),
39                           static_cast<IntOut>(0));
40   TF_LITE_MICRO_EXPECT_EQ(SafeCast<IntOut>(static_cast<FloatIn>(0.99)),
41                           static_cast<IntOut>(0));
42   TF_LITE_MICRO_EXPECT_EQ(SafeCast<IntOut>(static_cast<FloatIn>(1.0)),
43                           static_cast<IntOut>(1));
44   TF_LITE_MICRO_EXPECT_EQ(SafeCast<IntOut>(static_cast<FloatIn>(1.01)),
45                           static_cast<IntOut>(1));
46   TF_LITE_MICRO_EXPECT_EQ(SafeCast<IntOut>(static_cast<FloatIn>(1.99)),
47                           static_cast<IntOut>(1));
48   TF_LITE_MICRO_EXPECT_EQ(SafeCast<IntOut>(static_cast<FloatIn>(2.0)),
49                           static_cast<IntOut>(2));
50   TF_LITE_MICRO_EXPECT_EQ(SafeCast<IntOut>(static_cast<FloatIn>(2.01)),
51                           static_cast<IntOut>(2));
52   TF_LITE_MICRO_EXPECT_EQ(SafeCast<IntOut>(static_cast<FloatIn>(-0.99)),
53                           static_cast<IntOut>(0));
54   TF_LITE_MICRO_EXPECT_EQ(SafeCast<IntOut>(static_cast<FloatIn>(-1.0)),
55                           s ? static_cast<IntOut>(-1) : static_cast<IntOut>(0));
56   TF_LITE_MICRO_EXPECT_EQ(SafeCast<IntOut>(static_cast<FloatIn>(-1.01)),
57                           s ? static_cast<IntOut>(-1) : static_cast<IntOut>(0));
58   TF_LITE_MICRO_EXPECT_EQ(SafeCast<IntOut>(static_cast<FloatIn>(-1.99)),
59                           s ? static_cast<IntOut>(-1) : static_cast<IntOut>(0));
60   TF_LITE_MICRO_EXPECT_EQ(SafeCast<IntOut>(static_cast<FloatIn>(-2.0)),
61                           s ? static_cast<IntOut>(-2) : static_cast<IntOut>(0));
62   TF_LITE_MICRO_EXPECT_EQ(SafeCast<IntOut>(static_cast<FloatIn>(-2.01)),
63                           s ? static_cast<IntOut>(-2) : static_cast<IntOut>(0));
64   TF_LITE_MICRO_EXPECT_EQ(SafeCast<IntOut>(static_cast<FloatIn>(117.9)),
65                           static_cast<IntOut>(117));
66   TF_LITE_MICRO_EXPECT_EQ(SafeCast<IntOut>(static_cast<FloatIn>(118.0)),
67                           static_cast<IntOut>(118));
68   TF_LITE_MICRO_EXPECT_EQ(SafeCast<IntOut>(static_cast<FloatIn>(118.1)),
69                           static_cast<IntOut>(118));
70   TF_LITE_MICRO_EXPECT_EQ(
71       SafeCast<IntOut>(static_cast<FloatIn>(-117.9)),
72       s ? static_cast<IntOut>(-117) : static_cast<IntOut>(0));
73   TF_LITE_MICRO_EXPECT_EQ(
74       SafeCast<IntOut>(static_cast<FloatIn>(-118.0)),
75       s ? static_cast<IntOut>(-118) : static_cast<IntOut>(0));
76   TF_LITE_MICRO_EXPECT_EQ(
77       SafeCast<IntOut>(static_cast<FloatIn>(-118.1)),
78       s ? static_cast<IntOut>(-118) : static_cast<IntOut>(0));
79 
80   // Some edge cases.
81   TF_LITE_MICRO_EXPECT_EQ(SafeCast<IntOut>(std::numeric_limits<FloatIn>::max()),
82                           imax);
83   TF_LITE_MICRO_EXPECT_EQ(
84       SafeCast<IntOut>(std::numeric_limits<FloatIn>::lowest()), imin);
85   TF_LITE_MICRO_EXPECT_EQ(
86       SafeCast<IntOut>(std::numeric_limits<FloatIn>::infinity()), imax);
87   TF_LITE_MICRO_EXPECT_EQ(
88       SafeCast<IntOut>(-std::numeric_limits<FloatIn>::infinity()), imin);
89   TF_LITE_MICRO_EXPECT_EQ(
90       SafeCast<IntOut>(std::numeric_limits<FloatIn>::quiet_NaN()),
91       static_cast<IntOut>(0));
92 
93   // Some larger numbers.
94   if (sizeof(IntOut) >= static_cast<size_t>(4) &&
95       sizeof(FloatIn) > static_cast<size_t>(4)) {
96     TF_LITE_MICRO_EXPECT_EQ(SafeCast<IntOut>(static_cast<FloatIn>(0x76543210)),
97                             static_cast<IntOut>(0x76543210));
98   }
99 
100   if (sizeof(FloatIn) > sizeof(IntOut)) {
101     // Check values near imax.
102     TF_LITE_MICRO_EXPECT_EQ(
103         SafeCast<IntOut>(static_cast<FloatIn>(static_cast<FloatIn>(imax) +
104                                               static_cast<FloatIn>(0.1))),
105         imax);
106     TF_LITE_MICRO_EXPECT_EQ(
107         SafeCast<IntOut>(static_cast<FloatIn>(static_cast<FloatIn>(imax) +
108                                               static_cast<FloatIn>(0.99))),
109         imax);
110     TF_LITE_MICRO_EXPECT_EQ(
111         SafeCast<IntOut>(static_cast<FloatIn>(static_cast<FloatIn>(imax) +
112                                               static_cast<FloatIn>(1.0))),
113         imax);
114     TF_LITE_MICRO_EXPECT_EQ(
115         SafeCast<IntOut>(static_cast<FloatIn>(static_cast<FloatIn>(imax) +
116                                               static_cast<FloatIn>(1.99))),
117         imax);
118     TF_LITE_MICRO_EXPECT_EQ(
119         SafeCast<IntOut>(static_cast<FloatIn>(static_cast<FloatIn>(imax) +
120                                               static_cast<FloatIn>(2.0))),
121         imax);
122     TF_LITE_MICRO_EXPECT_EQ(
123         SafeCast<IntOut>(static_cast<FloatIn>(static_cast<FloatIn>(imax) -
124                                               static_cast<FloatIn>(0.1))),
125         imax - 1);
126     TF_LITE_MICRO_EXPECT_EQ(
127         SafeCast<IntOut>(static_cast<FloatIn>(static_cast<FloatIn>(imax) -
128                                               static_cast<FloatIn>(0.99))),
129         imax - 1);
130     TF_LITE_MICRO_EXPECT_EQ(
131         SafeCast<IntOut>(static_cast<FloatIn>(static_cast<FloatIn>(imax) -
132                                               static_cast<FloatIn>(1.0))),
133         imax - 1);
134     TF_LITE_MICRO_EXPECT_EQ(
135         SafeCast<IntOut>(static_cast<FloatIn>(static_cast<FloatIn>(imax) -
136                                               static_cast<FloatIn>(1.01))),
137         imax - 2);
138     TF_LITE_MICRO_EXPECT_EQ(
139         SafeCast<IntOut>(static_cast<FloatIn>(static_cast<FloatIn>(imax) -
140                                               static_cast<FloatIn>(1.99))),
141         imax - 2);
142     TF_LITE_MICRO_EXPECT_EQ(
143         SafeCast<IntOut>(static_cast<FloatIn>(static_cast<FloatIn>(imax) -
144                                               static_cast<FloatIn>(2.0))),
145         imax - 2);
146     TF_LITE_MICRO_EXPECT_EQ(
147         SafeCast<IntOut>(static_cast<FloatIn>(static_cast<FloatIn>(imax) -
148                                               static_cast<FloatIn>(2.01))),
149         imax - 3);
150   }
151 
152   // Check values considerably larger in magnitude than imin and imax
153   TF_LITE_MICRO_EXPECT_EQ(
154       SafeCast<IntOut>(static_cast<FloatIn>(static_cast<FloatIn>(imax) * 2)),
155       imax);
156   TF_LITE_MICRO_EXPECT_EQ(
157       SafeCast<IntOut>(static_cast<FloatIn>(static_cast<FloatIn>(imax) * 20)),
158       imax);
159   TF_LITE_MICRO_EXPECT_EQ(
160       SafeCast<IntOut>(static_cast<FloatIn>(static_cast<FloatIn>(imax) * 100)),
161       imax);
162   TF_LITE_MICRO_EXPECT_EQ(
163       SafeCast<IntOut>(static_cast<FloatIn>(static_cast<FloatIn>(imin) * 2)),
164       imin);
165   TF_LITE_MICRO_EXPECT_EQ(
166       SafeCast<IntOut>(static_cast<FloatIn>(static_cast<FloatIn>(imin) * 20)),
167       imin);
168   TF_LITE_MICRO_EXPECT_EQ(
169       SafeCast<IntOut>(static_cast<FloatIn>(static_cast<FloatIn>(imin) * 100)),
170       imin);
171 }
172 
173 }  // namespace
174 }  // namespace tflite
175 
176 TF_LITE_MICRO_TESTS_BEGIN
177 
TF_LITE_MICRO_TEST(QuantizationUtilTest_SafeCast)178 TF_LITE_MICRO_TEST(QuantizationUtilTest_SafeCast) {
179   tflite::RunSafeCastTests<float, int8_t>();
180   tflite::RunSafeCastTests<double, int8_t>();
181   tflite::RunSafeCastTests<float, int16_t>();
182   tflite::RunSafeCastTests<double, int16_t>();
183   tflite::RunSafeCastTests<float, int32_t>();
184   tflite::RunSafeCastTests<double, int32_t>();
185   tflite::RunSafeCastTests<float, int64_t>();
186   tflite::RunSafeCastTests<double, int64_t>();
187   tflite::RunSafeCastTests<float, uint8_t>();
188   tflite::RunSafeCastTests<double, uint8_t>();
189   tflite::RunSafeCastTests<float, uint16_t>();
190   tflite::RunSafeCastTests<double, uint16_t>();
191   tflite::RunSafeCastTests<float, uint32_t>();
192   tflite::RunSafeCastTests<double, uint32_t>();
193   tflite::RunSafeCastTests<float, uint64_t>();
194   tflite::RunSafeCastTests<double, uint64_t>();
195 }
196 
197 // Example taken from http://www.tensorflow.org/performance/quantization
198 //
199 //  Quantized | Float
200 //  --------- | -----
201 //  0         | -10.0
202 //  255       | 30.0
203 //  128       | 10.0
TF_LITE_MICRO_TEST(QuantizationUtilTest_ChooseQuantizationParams)204 TF_LITE_MICRO_TEST(QuantizationUtilTest_ChooseQuantizationParams) {
205   tflite::QuantizationParams qp =
206       tflite::ChooseQuantizationParams<uint8_t>(-10.0, 30.0);
207   TF_LITE_MICRO_EXPECT_NEAR(qp.scale, 0.156863, 1e-5);
208   TF_LITE_MICRO_EXPECT_EQ(qp.zero_point, 64);
209 }
210 
TF_LITE_MICRO_TEST(QuantizationUtilTest_ChooseQuantizationParamsZeroPointOnMinBoundary)211 TF_LITE_MICRO_TEST(
212     QuantizationUtilTest_ChooseQuantizationParamsZeroPointOnMinBoundary) {
213   tflite::QuantizationParams qp =
214       tflite::ChooseQuantizationParams<uint8_t>(0.0, 30.0);
215   TF_LITE_MICRO_EXPECT_NEAR(qp.scale, 0.117647, 1e-5);
216   TF_LITE_MICRO_EXPECT_EQ(qp.zero_point, 0);
217 }
218 
TF_LITE_MICRO_TEST(QuantizationUtilTest_ChooseQuantizationParamsEmptyRangeZero)219 TF_LITE_MICRO_TEST(
220     QuantizationUtilTest_ChooseQuantizationParamsEmptyRangeZero) {
221   tflite::QuantizationParams qp =
222       tflite::ChooseQuantizationParams<uint8_t>(0.0, 0.0);
223   TF_LITE_MICRO_EXPECT_NEAR(qp.scale, 0.0, 1e-5);
224   TF_LITE_MICRO_EXPECT_EQ(qp.zero_point, 0);
225 }
226 
TF_LITE_MICRO_TEST(QuantizationUtilTest_ChooseQuantizationParamsZeroPointOnMaxBoundary)227 TF_LITE_MICRO_TEST(
228     QuantizationUtilTest_ChooseQuantizationParamsZeroPointOnMaxBoundary) {
229   tflite::QuantizationParams qp =
230       tflite::ChooseQuantizationParams<uint8_t>(-10.0, 0.0);
231   TF_LITE_MICRO_EXPECT_NEAR(qp.scale, 0.039216, 1e-5);
232   TF_LITE_MICRO_EXPECT_EQ(qp.zero_point, 255);
233 }
234 
TF_LITE_MICRO_TEST(QuantizationUtilTest_IntegerFrExp)235 TF_LITE_MICRO_TEST(QuantizationUtilTest_IntegerFrExp) {
236   int shift;
237   int64_t result = tflite::IntegerFrExp(0.0, &shift);
238   TF_LITE_MICRO_EXPECT_EQ(0, result);
239   TF_LITE_MICRO_EXPECT_EQ(0, shift);
240 
241   result = tflite::IntegerFrExp(1.0, &shift);
242   TF_LITE_MICRO_EXPECT_NEAR(0x40000000, result, 1ll);
243   TF_LITE_MICRO_EXPECT_EQ(1, shift);
244 
245   result = tflite::IntegerFrExp(0.25, &shift);
246   TF_LITE_MICRO_EXPECT_NEAR(0x40000000, result, 1ll);
247   TF_LITE_MICRO_EXPECT_EQ(-1, shift);
248 
249   result = tflite::IntegerFrExp(-1.0, &shift);
250   TF_LITE_MICRO_EXPECT_NEAR(-(1 << 30), result, 1ll);
251   TF_LITE_MICRO_EXPECT_EQ(1, shift);
252 
253   result = tflite::IntegerFrExp(123.45, &shift);
254   TF_LITE_MICRO_EXPECT_NEAR(2071147315, result, 1ll);
255   TF_LITE_MICRO_EXPECT_EQ(7, shift);
256 
257   result = tflite::IntegerFrExp(static_cast<double>(NAN), &shift);
258   TF_LITE_MICRO_EXPECT_NEAR(0, result, 1);
259   TF_LITE_MICRO_EXPECT_EQ(0x7fffffff, shift);
260 
261   result = tflite::IntegerFrExp(static_cast<double>(INFINITY), &shift);
262   TF_LITE_MICRO_EXPECT_NEAR(std::numeric_limits<int64_t>::max(), result, 1);
263   TF_LITE_MICRO_EXPECT_EQ(0x7fffffff, shift);
264 
265   result = tflite::IntegerFrExp(-static_cast<double>(INFINITY), &shift);
266   TF_LITE_MICRO_EXPECT_NEAR(std::numeric_limits<int64_t>::min(), result, 1);
267   TF_LITE_MICRO_EXPECT_EQ(0x7fffffff, shift);
268 }
269 
TF_LITE_MICRO_TEST(QuantizationUtilTest_IntegerFrExpVersusDouble)270 TF_LITE_MICRO_TEST(QuantizationUtilTest_IntegerFrExpVersusDouble) {
271   int shift;
272   int32_t result = tflite::IntegerFrExp(0.0, &shift);
273   TF_LITE_MICRO_EXPECT_EQ(result, 0);
274   TF_LITE_MICRO_EXPECT_EQ(shift, 0);
275 
276   int double_shift;
277   double double_result = std::frexp(0.0, &double_shift);
278   TF_LITE_MICRO_EXPECT_EQ(double_result, 0);
279   TF_LITE_MICRO_EXPECT_EQ(double_shift, 0);
280 
281   result = tflite::IntegerFrExp(1.0, &shift);
282   TF_LITE_MICRO_EXPECT_NEAR(result, 0x40000000, 1);
283   TF_LITE_MICRO_EXPECT_EQ(shift, 1);
284   double_result = std::frexp(1.0, &double_shift);
285   TF_LITE_MICRO_EXPECT_NEAR(double_result, 0.5, 1e-5);
286   TF_LITE_MICRO_EXPECT_EQ(double_shift, 1);
287 
288   result = tflite::IntegerFrExp(0.25, &shift);
289   TF_LITE_MICRO_EXPECT_NEAR(result, 0x40000000, 1);
290   TF_LITE_MICRO_EXPECT_EQ(shift, -1);
291   double_result = std::frexp(0.25, &double_shift);
292   TF_LITE_MICRO_EXPECT_NEAR(double_result, 0.5, 1e-5);
293   TF_LITE_MICRO_EXPECT_EQ(double_shift, -1);
294 
295   result = tflite::IntegerFrExp(-1.0, &shift);
296   TF_LITE_MICRO_EXPECT_NEAR(result, -(1 << 30), 1);
297   TF_LITE_MICRO_EXPECT_EQ(shift, 1);
298   double_result = std::frexp(-1.0, &double_shift);
299   TF_LITE_MICRO_EXPECT_NEAR(double_result, -0.5, 1e-5);
300   TF_LITE_MICRO_EXPECT_EQ(double_shift, 1);
301 
302   result = tflite::IntegerFrExp(123.45, &shift);
303   TF_LITE_MICRO_EXPECT_NEAR(result, (0.964453 * (1LL << 31)), 1000);
304   TF_LITE_MICRO_EXPECT_EQ(shift, 7);
305   double_result = std::frexp(123.45, &double_shift);
306   TF_LITE_MICRO_EXPECT_NEAR(double_result, 0.964453, 1e-5);
307   TF_LITE_MICRO_EXPECT_EQ(double_shift, 7);
308 }
309 
TF_LITE_MICRO_TEST(QuantizationUtilTest_DoubleFromFractionAndShift)310 TF_LITE_MICRO_TEST(QuantizationUtilTest_DoubleFromFractionAndShift) {
311   double result = tflite::DoubleFromFractionAndShift(0, 0);
312   TF_LITE_MICRO_EXPECT_EQ(0, result);
313 
314   result = tflite::DoubleFromFractionAndShift(0x40000000, 1);
315   TF_LITE_MICRO_EXPECT_NEAR(1.0, result, 1e-5);
316 
317   result = tflite::DoubleFromFractionAndShift(0x40000000, 2);
318   TF_LITE_MICRO_EXPECT_NEAR(2.0, result, 1e-5);
319 
320   int shift;
321   int64_t fraction = tflite::IntegerFrExp(3.0, &shift);
322   result = tflite::DoubleFromFractionAndShift(fraction, shift);
323   TF_LITE_MICRO_EXPECT_NEAR(3.0, result, 1e-5);
324 
325   fraction = tflite::IntegerFrExp(123.45, &shift);
326   result = tflite::DoubleFromFractionAndShift(fraction, shift);
327   TF_LITE_MICRO_EXPECT_NEAR(123.45, result, 1e-5);
328 
329   fraction = tflite::IntegerFrExp(-23.232323, &shift);
330   result = tflite::DoubleFromFractionAndShift(fraction, shift);
331   TF_LITE_MICRO_EXPECT_NEAR(-23.232323, result, 1e-5);
332 
333   fraction = tflite::IntegerFrExp(static_cast<double>(NAN), &shift);
334   result = tflite::DoubleFromFractionAndShift(fraction, shift);
335   TF_LITE_MICRO_EXPECT_TRUE(std::isnan(result));
336 
337   fraction = tflite::IntegerFrExp(static_cast<double>(INFINITY), &shift);
338   result = tflite::DoubleFromFractionAndShift(fraction, shift);
339   TF_LITE_MICRO_EXPECT_FALSE(std::isfinite(result));
340 }
341 
TF_LITE_MICRO_TEST(QuantizationUtilTest_IntegerDoubleMultiply)342 TF_LITE_MICRO_TEST(QuantizationUtilTest_IntegerDoubleMultiply) {
343   TF_LITE_MICRO_EXPECT_NEAR(1.0, tflite::IntegerDoubleMultiply(1.0, 1.0), 1e-5);
344   TF_LITE_MICRO_EXPECT_NEAR(2.0, tflite::IntegerDoubleMultiply(1.0, 2.0), 1e-5);
345   TF_LITE_MICRO_EXPECT_NEAR(2.0, tflite::IntegerDoubleMultiply(2.0, 1.0), 1e-5);
346   TF_LITE_MICRO_EXPECT_NEAR(4.0, tflite::IntegerDoubleMultiply(2.0, 2.0), 1e-5);
347   TF_LITE_MICRO_EXPECT_NEAR(0.5, tflite::IntegerDoubleMultiply(1.0, 0.5), 1e-5);
348   TF_LITE_MICRO_EXPECT_NEAR(0.25, tflite::IntegerDoubleMultiply(0.5, 0.5),
349                             1e-5);
350   TF_LITE_MICRO_EXPECT_NEAR(-1.0, tflite::IntegerDoubleMultiply(1.0, -1.0),
351                             1e-5);
352   TF_LITE_MICRO_EXPECT_NEAR(-1.0, tflite::IntegerDoubleMultiply(-1.0, 1.0),
353                             1e-5);
354   TF_LITE_MICRO_EXPECT_NEAR(1.0, tflite::IntegerDoubleMultiply(-1.0, -1.0),
355                             1e-5);
356   TF_LITE_MICRO_EXPECT_NEAR(
357       15000000.0, tflite::IntegerDoubleMultiply(3000.0, 5000.0), 1e-5);
358   TF_LITE_MICRO_EXPECT_TRUE(std::isnan(
359       tflite::IntegerDoubleMultiply(static_cast<double>(NAN), 5000.0)));
360   TF_LITE_MICRO_EXPECT_TRUE(std::isnan(
361       tflite::IntegerDoubleMultiply(3000.0, static_cast<double>(NAN))));
362 }
363 
TF_LITE_MICRO_TEST(QuantizationUtilTest_IntegerDoubleCompare)364 TF_LITE_MICRO_TEST(QuantizationUtilTest_IntegerDoubleCompare) {
365   TF_LITE_MICRO_EXPECT_EQ(-1, tflite::IntegerDoubleCompare(0.0, 1.0));
366   TF_LITE_MICRO_EXPECT_EQ(1, tflite::IntegerDoubleCompare(1.0, 0.0));
367   TF_LITE_MICRO_EXPECT_EQ(0, tflite::IntegerDoubleCompare(1.0, 1.0));
368   TF_LITE_MICRO_EXPECT_EQ(0, tflite::IntegerDoubleCompare(0.0, 0.0));
369   TF_LITE_MICRO_EXPECT_EQ(-1, tflite::IntegerDoubleCompare(-10.0, 10.0));
370   TF_LITE_MICRO_EXPECT_EQ(1, tflite::IntegerDoubleCompare(123.45, 10.0));
371   TF_LITE_MICRO_EXPECT_EQ(
372       1, tflite::IntegerDoubleCompare(static_cast<double>(NAN),
373                                       static_cast<double>(INFINITY)));
374   TF_LITE_MICRO_EXPECT_EQ(
375       1, tflite::IntegerDoubleCompare(static_cast<double>(INFINITY),
376                                       static_cast<double>(NAN)));
377 }
378 
TF_LITE_MICRO_TEST(QuantizationUtilTest_PreprocessSoftmaxScaling)379 TF_LITE_MICRO_TEST(QuantizationUtilTest_PreprocessSoftmaxScaling) {
380   auto quantize = [](double beta, double scale, int integer_bits) {
381     int32_t q;
382     int s;
383     tflite::PreprocessSoftmaxScaling(beta, scale, integer_bits, &q, &s);
384     return std::pair<int32_t, int>{q, s};
385   };
386 
387   // If beta * scale is greater than fits in the number of integer bits, the
388   // result is move near the maximum. Otherwise they quantize as expected.
389   // With 4 integer bits we can represent up to 16.0.
390 
391   auto r = quantize(1.0, 16.0, 4);
392   TF_LITE_MICRO_EXPECT_EQ(r.first, 2147483647);
393   TF_LITE_MICRO_EXPECT_EQ(r.second, 31);
394 
395   r = quantize(1.0, 8.0, 4);
396   TF_LITE_MICRO_EXPECT_EQ(r.first, 1073741824);
397   TF_LITE_MICRO_EXPECT_EQ(r.second, 31);
398 
399   // But with 5 bits we can go further.
400   r = quantize(2.0, 16.0, 5);
401   TF_LITE_MICRO_EXPECT_EQ(r.first, 2147483647);
402   TF_LITE_MICRO_EXPECT_EQ(r.second, 31);
403 
404   r = quantize(2.0, 8.0, 5);
405   TF_LITE_MICRO_EXPECT_EQ(r.first, 1073741824);
406   TF_LITE_MICRO_EXPECT_EQ(r.second, 31);
407 }
408 
TF_LITE_MICRO_TEST(QuantizationUtilTest_CalculateInputRadius)409 TF_LITE_MICRO_TEST(QuantizationUtilTest_CalculateInputRadius) {
410   TF_LITE_MICRO_EXPECT_EQ(tflite::CalculateInputRadius(4, 27), 15);
411   TF_LITE_MICRO_EXPECT_EQ(tflite::CalculateInputRadius(3, 27), 14);
412   TF_LITE_MICRO_EXPECT_EQ(tflite::CalculateInputRadius(3, 28), 7);
413   TF_LITE_MICRO_EXPECT_EQ(tflite::CalculateInputRadius(4, 2), 503316480);
414 }
415 
TF_LITE_MICRO_TEST(QuantizationUtilTest_QuantizeMultiplierArray)416 TF_LITE_MICRO_TEST(QuantizationUtilTest_QuantizeMultiplierArray) {
417   const double weights[] = {-4,    -2,   -1,  -0.5, -0.25, -0.125, 0,
418                             0.125, 0.25, 0.5, 1,    2,     4};
419 
420   const int size = 13;
421   int32_t effective_scale_significand[size];
422   int effective_scale_shift[size];
423   tflite::QuantizeMultiplierArray(weights, size, effective_scale_significand,
424                                   effective_scale_shift);
425   const int32_t expected_effective_scale_significand[] = {
426       -1073741824,  // float scale = -4
427       -1073741824,  // float scale = -2
428       -1073741824,  // float scale = -1
429       -1073741824,  // float scale = -0.5
430       -1073741824,  // float scale = -0.25
431       -1073741824,  // float scale = -0.125
432       0,            // float scale = 0
433       1073741824,   // float scale = 0.125
434       1073741824,   // float scale = 0.25
435       1073741824,   // float scale = 0.5
436       1073741824,   // float scale = 1
437       1073741824,   // float scale = 2
438       1073741824,   // float scale = 4
439   };
440 
441   const int expected_effective_scale_shift[] = {
442       3,   // float scale = -4
443       2,   // float scale = -2
444       1,   // float scale = -1
445       0,   // float scale = -0.5
446       -1,  // float scale = -0.25
447       -2,  // float scale = -0.125
448       0,   // float scale = 0
449       -2,  // float scale = 0.125
450       -1,  // float scale = 0.25
451       0,   // float scale = 0.5
452       1,   // float scale = 1
453       2,   // float scale = 2
454       3,   // float scale = 4
455   };
456 
457   for (int i = 0; i < size; i++) {
458     TF_LITE_MICRO_EXPECT_EQ(effective_scale_significand[i],
459                             expected_effective_scale_significand[i]);
460     TF_LITE_MICRO_EXPECT_EQ(effective_scale_shift[i],
461                             expected_effective_scale_shift[i]);
462   }
463 }
464 
465 TF_LITE_MICRO_TESTS_END
466