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