blob: b73b85de3a33f3677cd7b9f7e23d024bd231b965 [file] [log] [blame]
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001// Copyright (c) Facebook, Inc. and its affiliates.
2// All rights reserved.
3//
4// Copyright 2020 Google LLC
5//
6// This source code is licensed under the BSD-style license found in the
7// LICENSE file in the root directory of this source tree.
8
9#include <cmath>
10#include <cstddef>
11#include <cstdlib>
12
13#include <gtest/gtest.h>
14
15#include <xnnpack/common.h>
16
17#include <xnnpack/requantization-stubs.h>
18#include "requantization-tester.h"
19
20
21/*
Marat Dukhan06716242021-05-26 15:56:39 -070022 * Round-to-nearest, ties away from zero, scalar implementation using unsigned 32-bit arithmetics.
Marat Dukhan2e23d2b2020-07-29 16:01:37 -070023 */
24
Marat Dukhan06716242021-05-26 15:56:39 -070025TEST(QS8_RNDNA__SCALAR_UNSIGNED32, exact_divide_by_po2) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -070026 for (uint32_t s = 1; s < 32; s++) {
27 RequantizationTester()
28 .qmin(std::numeric_limits<int8_t>::min())
29 .qmax(std::numeric_limits<int8_t>::max())
30 .s(s)
Marat Dukhan06716242021-05-26 15:56:39 -070031 .TestExactDivideByPO2(xnn_qs8_requantize_rndna__scalar_unsigned32);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -070032 }
33}
34
Marat Dukhan06716242021-05-26 15:56:39 -070035TEST(QS8_RNDNA__SCALAR_UNSIGNED32, exact_divide_by_po2_with_zero_point) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -070036 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
37 zero_point <= std::numeric_limits<int8_t>::max();
38 zero_point++)
39 {
40 for (uint32_t s = 1; s < 32; s++) {
41 RequantizationTester()
42 .zero_point(zero_point)
43 .qmin(std::numeric_limits<int8_t>::min())
44 .qmax(std::numeric_limits<int8_t>::max())
45 .s(s)
Marat Dukhan06716242021-05-26 15:56:39 -070046 .TestExactDivideByPO2(xnn_qs8_requantize_rndna__scalar_unsigned32);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -070047 }
48 }
49}
50
Marat Dukhan06716242021-05-26 15:56:39 -070051TEST(QS8_RNDNA__SCALAR_UNSIGNED32, divide_by_po2_with_rounding_up) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -070052 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
53 zero_point <= std::numeric_limits<int8_t>::max();
54 zero_point++)
55 {
56 for (uint32_t s = 1; s < 32; s++) {
57 RequantizationTester()
58 .zero_point(zero_point)
59 .qmin(std::numeric_limits<int8_t>::min())
60 .qmax(std::numeric_limits<int8_t>::max())
61 .s(s)
Marat Dukhan06716242021-05-26 15:56:39 -070062 .TestDivideByPO2WithRoundingUp(xnn_qs8_requantize_rndna__scalar_unsigned32);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -070063 }
64 }
65}
66
Marat Dukhan06716242021-05-26 15:56:39 -070067TEST(QS8_RNDNA__SCALAR_UNSIGNED32, divide_by_po2_with_rounding_down) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -070068 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
69 zero_point <= std::numeric_limits<int8_t>::max();
70 zero_point++)
71 {
72 for (uint32_t s = 1; s < 32; s++) {
73 RequantizationTester()
74 .zero_point(zero_point)
75 .qmin(std::numeric_limits<int8_t>::min())
76 .qmax(std::numeric_limits<int8_t>::max())
77 .s(s)
Marat Dukhan06716242021-05-26 15:56:39 -070078 .TestDivideByPO2WithRoundingDown(xnn_qs8_requantize_rndna__scalar_unsigned32);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -070079 }
80 }
81}
82
Marat Dukhan06716242021-05-26 15:56:39 -070083TEST(QS8_RNDNA__SCALAR_UNSIGNED32, divide_by_po2_with_rounding_away) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -070084 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
85 zero_point <= std::numeric_limits<int8_t>::max();
86 zero_point++)
87 {
88 for (uint32_t s = 1; s < 32; s++) {
89 RequantizationTester()
90 .zero_point(zero_point)
91 .qmin(std::numeric_limits<int8_t>::min())
92 .qmax(std::numeric_limits<int8_t>::max())
93 .s(s)
Marat Dukhan062bee32021-05-27 20:31:07 -070094 .TestDivideByPO2WithRoundingTiesAway(xnn_qs8_requantize_rndna__scalar_unsigned32);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -070095 }
96 }
97}
98
Marat Dukhan06716242021-05-26 15:56:39 -070099TEST(QS8_RNDNA__SCALAR_UNSIGNED32, special_cases) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700100 RequantizationTester()
101 .qmin(std::numeric_limits<int8_t>::min())
102 .qmax(std::numeric_limits<int8_t>::max())
Marat Dukhan06716242021-05-26 15:56:39 -0700103 .TestSpecialCases(xnn_qs8_requantize_rndna__scalar_unsigned32);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700104}
105
Marat Dukhan06716242021-05-26 15:56:39 -0700106TEST(QS8_RNDNA__SCALAR_UNSIGNED32, random_cases) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700107 RequantizationTester()
108 .qmin(std::numeric_limits<int8_t>::min())
109 .qmax(std::numeric_limits<int8_t>::max())
110 .iterations(100)
Marat Dukhan06716242021-05-26 15:56:39 -0700111 .TestRandomCasesRoundToNearestTiesAway(xnn_qs8_requantize_rndna__scalar_unsigned32);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700112}
113
114
115/*
Marat Dukhan06716242021-05-26 15:56:39 -0700116 * Round-to-nearest, ties away from zero, scalar implementation using unsigned 64-bit arithmetics.
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700117 */
118
Marat Dukhan06716242021-05-26 15:56:39 -0700119TEST(QS8_RNDNA__SCALAR_UNSIGNED64, exact_divide_by_po2) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700120 for (uint32_t s = 1; s < 32; s++) {
121 RequantizationTester()
122 .qmin(std::numeric_limits<int8_t>::min())
123 .qmax(std::numeric_limits<int8_t>::max())
124 .s(s)
Marat Dukhan06716242021-05-26 15:56:39 -0700125 .TestExactDivideByPO2(xnn_qs8_requantize_rndna__scalar_unsigned64);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700126 }
127}
128
Marat Dukhan06716242021-05-26 15:56:39 -0700129TEST(QS8_RNDNA__SCALAR_UNSIGNED64, exact_divide_by_po2_with_zero_point) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700130 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
131 zero_point <= std::numeric_limits<int8_t>::max();
132 zero_point++)
133 {
134 for (uint32_t s = 1; s < 32; s++) {
135 RequantizationTester()
136 .zero_point(zero_point)
137 .qmin(std::numeric_limits<int8_t>::min())
138 .qmax(std::numeric_limits<int8_t>::max())
139 .s(s)
Marat Dukhan06716242021-05-26 15:56:39 -0700140 .TestExactDivideByPO2(xnn_qs8_requantize_rndna__scalar_unsigned64);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700141 }
142 }
143}
144
Marat Dukhan06716242021-05-26 15:56:39 -0700145TEST(QS8_RNDNA__SCALAR_UNSIGNED64, divide_by_po2_with_rounding_up) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700146 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
147 zero_point <= std::numeric_limits<int8_t>::max();
148 zero_point++)
149 {
150 for (uint32_t s = 1; s < 32; s++) {
151 RequantizationTester()
152 .zero_point(zero_point)
153 .qmin(std::numeric_limits<int8_t>::min())
154 .qmax(std::numeric_limits<int8_t>::max())
155 .s(s)
Marat Dukhan06716242021-05-26 15:56:39 -0700156 .TestDivideByPO2WithRoundingUp(xnn_qs8_requantize_rndna__scalar_unsigned64);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700157 }
158 }
159}
160
Marat Dukhan06716242021-05-26 15:56:39 -0700161TEST(QS8_RNDNA__SCALAR_UNSIGNED64, divide_by_po2_with_rounding_down) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700162 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
163 zero_point <= std::numeric_limits<int8_t>::max();
164 zero_point++)
165 {
166 for (uint32_t s = 1; s < 32; s++) {
167 RequantizationTester()
168 .zero_point(zero_point)
169 .qmin(std::numeric_limits<int8_t>::min())
170 .qmax(std::numeric_limits<int8_t>::max())
171 .s(s)
Marat Dukhan06716242021-05-26 15:56:39 -0700172 .TestDivideByPO2WithRoundingDown(xnn_qs8_requantize_rndna__scalar_unsigned64);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700173 }
174 }
175}
176
Marat Dukhan06716242021-05-26 15:56:39 -0700177TEST(QS8_RNDNA__SCALAR_UNSIGNED64, divide_by_po2_with_rounding_away) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700178 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
179 zero_point <= std::numeric_limits<int8_t>::max();
180 zero_point++)
181 {
182 for (uint32_t s = 1; s < 32; s++) {
183 RequantizationTester()
184 .zero_point(zero_point)
185 .qmin(std::numeric_limits<int8_t>::min())
186 .qmax(std::numeric_limits<int8_t>::max())
187 .s(s)
Marat Dukhan062bee32021-05-27 20:31:07 -0700188 .TestDivideByPO2WithRoundingTiesAway(xnn_qs8_requantize_rndna__scalar_unsigned64);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700189 }
190 }
191}
192
Marat Dukhan06716242021-05-26 15:56:39 -0700193TEST(QS8_RNDNA__SCALAR_UNSIGNED64, special_cases) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700194 RequantizationTester()
195 .qmin(std::numeric_limits<int8_t>::min())
196 .qmax(std::numeric_limits<int8_t>::max())
Marat Dukhan06716242021-05-26 15:56:39 -0700197 .TestSpecialCases(xnn_qs8_requantize_rndna__scalar_unsigned64);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700198}
199
Marat Dukhan06716242021-05-26 15:56:39 -0700200TEST(QS8_RNDNA__SCALAR_UNSIGNED64, random_cases) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700201 RequantizationTester()
202 .qmin(std::numeric_limits<int8_t>::min())
203 .qmax(std::numeric_limits<int8_t>::max())
204 .iterations(100)
Marat Dukhan06716242021-05-26 15:56:39 -0700205 .TestRandomCasesRoundToNearestTiesAway(xnn_qs8_requantize_rndna__scalar_unsigned64);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700206}
207
208
209/*
Marat Dukhan06716242021-05-26 15:56:39 -0700210 * Round-to-nearest, ties away from zero, scalar implementation using signed 64-bit arithmetics.
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700211 */
212
Marat Dukhan06716242021-05-26 15:56:39 -0700213TEST(QS8_RNDNA__SCALAR_SIGNED64, exact_divide_by_po2) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700214 for (uint32_t s = 1; s < 32; s++) {
215 RequantizationTester()
216 .qmin(std::numeric_limits<int8_t>::min())
217 .qmax(std::numeric_limits<int8_t>::max())
218 .s(s)
Marat Dukhan06716242021-05-26 15:56:39 -0700219 .TestExactDivideByPO2(xnn_qs8_requantize_rndna__scalar_signed64);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700220 }
221}
222
Marat Dukhan06716242021-05-26 15:56:39 -0700223TEST(QS8_RNDNA__SCALAR_SIGNED64, exact_divide_by_po2_with_zero_point) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700224 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
225 zero_point <= std::numeric_limits<int8_t>::max();
226 zero_point++)
227 {
228 for (uint32_t s = 1; s < 32; s++) {
229 RequantizationTester()
230 .zero_point(zero_point)
231 .qmin(std::numeric_limits<int8_t>::min())
232 .qmax(std::numeric_limits<int8_t>::max())
233 .s(s)
Marat Dukhan06716242021-05-26 15:56:39 -0700234 .TestExactDivideByPO2(xnn_qs8_requantize_rndna__scalar_signed64);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700235 }
236 }
237}
238
Marat Dukhan06716242021-05-26 15:56:39 -0700239TEST(QS8_RNDNA__SCALAR_SIGNED64, divide_by_po2_with_rounding_up) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700240 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
241 zero_point <= std::numeric_limits<int8_t>::max();
242 zero_point++)
243 {
244 for (uint32_t s = 1; s < 32; s++) {
245 RequantizationTester()
246 .zero_point(zero_point)
247 .qmin(std::numeric_limits<int8_t>::min())
248 .qmax(std::numeric_limits<int8_t>::max())
249 .s(s)
Marat Dukhan06716242021-05-26 15:56:39 -0700250 .TestDivideByPO2WithRoundingUp(xnn_qs8_requantize_rndna__scalar_signed64);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700251 }
252 }
253}
254
Marat Dukhan06716242021-05-26 15:56:39 -0700255TEST(QS8_RNDNA__SCALAR_SIGNED64, divide_by_po2_with_rounding_down) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700256 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
257 zero_point <= std::numeric_limits<int8_t>::max();
258 zero_point++)
259 {
260 for (uint32_t s = 1; s < 32; s++) {
261 RequantizationTester()
262 .zero_point(zero_point)
263 .qmin(std::numeric_limits<int8_t>::min())
264 .qmax(std::numeric_limits<int8_t>::max())
265 .s(s)
Marat Dukhan06716242021-05-26 15:56:39 -0700266 .TestDivideByPO2WithRoundingDown(xnn_qs8_requantize_rndna__scalar_signed64);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700267 }
268 }
269}
270
Marat Dukhan06716242021-05-26 15:56:39 -0700271TEST(QS8_RNDNA__SCALAR_SIGNED64, divide_by_po2_with_rounding_away) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700272 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
273 zero_point <= std::numeric_limits<int8_t>::max();
274 zero_point++)
275 {
276 for (uint32_t s = 1; s < 32; s++) {
277 RequantizationTester()
278 .zero_point(zero_point)
279 .qmin(std::numeric_limits<int8_t>::min())
280 .qmax(std::numeric_limits<int8_t>::max())
281 .s(s)
Marat Dukhan062bee32021-05-27 20:31:07 -0700282 .TestDivideByPO2WithRoundingTiesAway(xnn_qs8_requantize_rndna__scalar_signed64);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700283 }
284 }
285}
286
Marat Dukhan06716242021-05-26 15:56:39 -0700287TEST(QS8_RNDNA__SCALAR_SIGNED64, special_cases) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700288 RequantizationTester()
289 .qmin(std::numeric_limits<int8_t>::min())
290 .qmax(std::numeric_limits<int8_t>::max())
Marat Dukhan06716242021-05-26 15:56:39 -0700291 .TestSpecialCases(xnn_qs8_requantize_rndna__scalar_signed64);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700292}
293
Marat Dukhan06716242021-05-26 15:56:39 -0700294TEST(QS8_RNDNA__SCALAR_SIGNED64, random_cases) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700295 RequantizationTester()
296 .qmin(std::numeric_limits<int8_t>::min())
297 .qmax(std::numeric_limits<int8_t>::max())
298 .iterations(100)
Marat Dukhan06716242021-05-26 15:56:39 -0700299 .TestRandomCasesRoundToNearestTiesAway(xnn_qs8_requantize_rndna__scalar_signed64);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700300}
301
302
303/*
Marat Dukhan062bee32021-05-27 20:31:07 -0700304 * Round-to-nearest, ties up, scalar implementation using signed 64-bit arithmetics.
305 */
306
307TEST(QS8_RNDNU__SCALAR, exact_divide_by_po2) {
308 for (uint32_t s = 1; s < 32; s++) {
309 RequantizationTester()
310 .qmin(std::numeric_limits<int8_t>::min())
311 .qmax(std::numeric_limits<int8_t>::max())
312 .s(s)
313 .TestExactDivideByPO2(xnn_qs8_requantize_rndnu__scalar);
314 }
315}
316
317TEST(QS8_RNDNU__SCALAR, exact_divide_by_po2_with_zero_point) {
318 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
319 zero_point <= std::numeric_limits<int8_t>::max();
320 zero_point++)
321 {
322 for (uint32_t s = 1; s < 32; s++) {
323 RequantizationTester()
324 .zero_point(zero_point)
325 .qmin(std::numeric_limits<int8_t>::min())
326 .qmax(std::numeric_limits<int8_t>::max())
327 .s(s)
328 .TestExactDivideByPO2(xnn_qs8_requantize_rndnu__scalar);
329 }
330 }
331}
332
333TEST(QS8_RNDNU__SCALAR, divide_by_po2_with_rounding_up) {
334 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
335 zero_point <= std::numeric_limits<int8_t>::max();
336 zero_point++)
337 {
338 for (uint32_t s = 1; s < 32; s++) {
339 RequantizationTester()
340 .zero_point(zero_point)
341 .qmin(std::numeric_limits<int8_t>::min())
342 .qmax(std::numeric_limits<int8_t>::max())
343 .s(s)
344 .TestDivideByPO2WithRoundingUp(xnn_qs8_requantize_rndnu__scalar);
345 }
346 }
347}
348
349TEST(QS8_RNDNU__SCALAR, divide_by_po2_with_rounding_down) {
350 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
351 zero_point <= std::numeric_limits<int8_t>::max();
352 zero_point++)
353 {
354 for (uint32_t s = 1; s < 32; s++) {
355 RequantizationTester()
356 .zero_point(zero_point)
357 .qmin(std::numeric_limits<int8_t>::min())
358 .qmax(std::numeric_limits<int8_t>::max())
359 .s(s)
360 .TestDivideByPO2WithRoundingDown(xnn_qs8_requantize_rndnu__scalar);
361 }
362 }
363}
364
365TEST(QS8_RNDNU__SCALAR, divide_by_po2_with_rounding_away) {
366 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
367 zero_point <= std::numeric_limits<int8_t>::max();
368 zero_point++)
369 {
370 for (uint32_t s = 1; s < 32; s++) {
371 RequantizationTester()
372 .zero_point(zero_point)
373 .qmin(std::numeric_limits<int8_t>::min())
374 .qmax(std::numeric_limits<int8_t>::max())
375 .s(s)
376 .TestDivideByPO2WithRoundingTiesUp(xnn_qs8_requantize_rndnu__scalar);
377 }
378 }
379}
380
381TEST(QS8_RNDNU__SCALAR, random_cases) {
382 RequantizationTester()
383 .qmin(std::numeric_limits<int8_t>::min())
384 .qmax(std::numeric_limits<int8_t>::max())
385 .iterations(100)
Marat Dukhanc6e6ee02021-05-27 22:27:18 -0700386 .TestRandomCasesRoundToNearestTiesUp(xnn_qs8_requantize_rndnu__scalar);
Marat Dukhan062bee32021-05-27 20:31:07 -0700387}
388
389
390/*
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700391 * FP32-based scalar implementation using lrintf function.
392 */
393
394TEST(QS8_FP32__SCALAR_LRINTF, random_cases) {
395 RequantizationTester()
396 .qmin(std::numeric_limits<int8_t>::min())
397 .qmax(std::numeric_limits<int8_t>::max())
398 .iterations(1000)
399 .TestRandomCasesApproximate(xnn_qs8_requantize_fp32__scalar_lrintf);
400}
401
402
403/*
404 * FP32-based scalar implementation using magic trick for FP32->INT32 conversion.
405 */
406
407TEST(QS8_FP32__SCALAR_MAGIC, random_cases) {
408 RequantizationTester()
409 .qmin(std::numeric_limits<int8_t>::min())
410 .qmax(std::numeric_limits<int8_t>::max())
411 .iterations(1000)
412 .TestRandomCasesApproximate(xnn_qs8_requantize_fp32__scalar_magic);
413}
414
415
416/*
Marat Dukhan9976cd82021-05-24 23:15:45 -0700417 * GEMMLOWP-equivalent scalar implementation.
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700418 */
419
Marat Dukhan9976cd82021-05-24 23:15:45 -0700420TEST(QS8_GEMMLOWP__SCALAR, exact_divide_by_po2) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700421 for (uint32_t s = 1; s < 32; s++) {
422 RequantizationTester()
423 .qmin(std::numeric_limits<int8_t>::min())
424 .qmax(std::numeric_limits<int8_t>::max())
425 .s(s)
Marat Dukhan9976cd82021-05-24 23:15:45 -0700426 .TestExactDivideByPO2(xnn_qs8_requantize_gemmlowp__scalar);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700427 }
428}
429
Marat Dukhan9976cd82021-05-24 23:15:45 -0700430TEST(QS8_GEMMLOWP__SCALAR, exact_divide_by_po2_with_zero_point) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700431 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
432 zero_point <= std::numeric_limits<int8_t>::max();
433 zero_point++)
434 {
435 for (uint32_t s = 1; s < 32; s++) {
436 RequantizationTester()
437 .zero_point(zero_point)
438 .qmin(std::numeric_limits<int8_t>::min())
439 .qmax(std::numeric_limits<int8_t>::max())
440 .s(s)
Marat Dukhan9976cd82021-05-24 23:15:45 -0700441 .TestExactDivideByPO2(xnn_qs8_requantize_gemmlowp__scalar);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700442 }
443 }
444}
445
Marat Dukhan9976cd82021-05-24 23:15:45 -0700446TEST(QS8_GEMMLOWP__SCALAR, divide_by_po2_with_rounding_up) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700447 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
448 zero_point <= std::numeric_limits<int8_t>::max();
449 zero_point++)
450 {
451 for (uint32_t s = 1; s < 32; s++) {
452 RequantizationTester()
453 .zero_point(zero_point)
454 .qmin(std::numeric_limits<int8_t>::min())
455 .qmax(std::numeric_limits<int8_t>::max())
456 .s(s)
Marat Dukhan9976cd82021-05-24 23:15:45 -0700457 .TestDivideByPO2WithRoundingUp(xnn_qs8_requantize_gemmlowp__scalar);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700458 }
459 }
460}
461
462/* No rounding down test - it fails because of upward bias in multiplication */
463/* No rounding away test - it fails because of upward bias in multiplication */
464
Marat Dukhan9976cd82021-05-24 23:15:45 -0700465TEST(QS8_GEMMLOWP__SCALAR, special_cases) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700466 RequantizationTester()
467 .qmin(std::numeric_limits<int8_t>::min())
468 .qmax(std::numeric_limits<int8_t>::max())
Marat Dukhan9976cd82021-05-24 23:15:45 -0700469 .TestSpecialCases(xnn_qs8_requantize_gemmlowp__scalar);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700470}
471
Marat Dukhan9976cd82021-05-24 23:15:45 -0700472TEST(QS8_GEMMLOWP__SCALAR, random_cases) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700473 RequantizationTester()
474 .qmin(std::numeric_limits<int8_t>::min())
475 .qmax(std::numeric_limits<int8_t>::max())
476 .iterations(100)
Marat Dukhan9976cd82021-05-24 23:15:45 -0700477 .TestRandomCasesApproximate(xnn_qs8_requantize_gemmlowp__scalar);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700478}
479
480
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700481#if XNN_ARCH_X86 || XNN_ARCH_X86_64
482 /*
Marat Dukhan06716242021-05-26 15:56:39 -0700483 * Round-to-nearest, ties away from zero, SSE2 implementation using floating-point shuffle.
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700484 */
485
Marat Dukhan06716242021-05-26 15:56:39 -0700486 TEST(QS8_RNDNA__SSE2, exact_divide_by_po2) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700487 for (uint32_t s = 1; s < 32; s++) {
488 RequantizationTester()
489 .qmin(std::numeric_limits<int8_t>::min())
490 .qmax(std::numeric_limits<int8_t>::max())
491 .s(s)
Marat Dukhan06716242021-05-26 15:56:39 -0700492 .TestExactDivideByPO2(xnn_qs8_requantize_rndna__sse2);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700493 }
494 }
495
Marat Dukhan06716242021-05-26 15:56:39 -0700496 TEST(QS8_RNDNA__SSE2, exact_divide_by_po2_with_zero_point) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700497 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
498 zero_point <= std::numeric_limits<int8_t>::max();
499 zero_point++)
500 {
501 for (uint32_t s = 1; s < 32; s++) {
502 RequantizationTester()
503 .zero_point(zero_point)
504 .qmin(std::numeric_limits<int8_t>::min())
505 .qmax(std::numeric_limits<int8_t>::max())
506 .s(s)
Marat Dukhan06716242021-05-26 15:56:39 -0700507 .TestExactDivideByPO2(xnn_qs8_requantize_rndna__sse2);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700508 }
509 }
510 }
511
Marat Dukhan06716242021-05-26 15:56:39 -0700512 TEST(QS8_RNDNA__SSE2, divide_by_po2_with_rounding_up) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700513 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
514 zero_point <= std::numeric_limits<int8_t>::max();
515 zero_point++)
516 {
517 for (uint32_t s = 1; s < 32; s++) {
518 RequantizationTester()
519 .zero_point(zero_point)
520 .qmin(std::numeric_limits<int8_t>::min())
521 .qmax(std::numeric_limits<int8_t>::max())
522 .s(s)
Marat Dukhan06716242021-05-26 15:56:39 -0700523 .TestDivideByPO2WithRoundingUp(xnn_qs8_requantize_rndna__sse2);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700524 }
525 }
526 }
527
Marat Dukhan06716242021-05-26 15:56:39 -0700528 TEST(QS8_RNDNA__SSE2, divide_by_po2_with_rounding_down) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700529 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
530 zero_point <= std::numeric_limits<int8_t>::max();
531 zero_point++)
532 {
533 for (uint32_t s = 1; s < 32; s++) {
534 RequantizationTester()
535 .zero_point(zero_point)
536 .qmin(std::numeric_limits<int8_t>::min())
537 .qmax(std::numeric_limits<int8_t>::max())
538 .s(s)
Marat Dukhan06716242021-05-26 15:56:39 -0700539 .TestDivideByPO2WithRoundingDown(xnn_qs8_requantize_rndna__sse2);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700540 }
541 }
542 }
543
Marat Dukhan06716242021-05-26 15:56:39 -0700544 TEST(QS8_RNDNA__SSE2, divide_by_po2_with_rounding_away) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700545 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
546 zero_point <= std::numeric_limits<int8_t>::max();
547 zero_point++)
548 {
549 for (uint32_t s = 1; s < 32; s++) {
550 RequantizationTester()
551 .zero_point(zero_point)
552 .qmin(std::numeric_limits<int8_t>::min())
553 .qmax(std::numeric_limits<int8_t>::max())
554 .s(s)
Marat Dukhan062bee32021-05-27 20:31:07 -0700555 .TestDivideByPO2WithRoundingTiesAway(xnn_qs8_requantize_rndna__sse2);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700556 }
557 }
558 }
559
Marat Dukhan06716242021-05-26 15:56:39 -0700560 TEST(QS8_RNDNA__SSE2, special_cases) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700561 RequantizationTester()
562 .qmin(std::numeric_limits<int8_t>::min())
563 .qmax(std::numeric_limits<int8_t>::max())
Marat Dukhan06716242021-05-26 15:56:39 -0700564 .TestSpecialCases(xnn_qs8_requantize_rndna__sse2);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700565 }
566
Marat Dukhan06716242021-05-26 15:56:39 -0700567 TEST(QS8_RNDNA__SSE2, random_cases) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700568 RequantizationTester()
569 .qmin(std::numeric_limits<int8_t>::min())
570 .qmax(std::numeric_limits<int8_t>::max())
571 .iterations(100)
Marat Dukhan06716242021-05-26 15:56:39 -0700572 .TestRandomCasesRoundToNearestTiesAway(xnn_qs8_requantize_rndna__sse2);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700573 }
574
575
576 /*
Marat Dukhan06716242021-05-26 15:56:39 -0700577 * Round-to-nearest, ties away from zero, SSSE3 implementation using floating-point shuffle.
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700578 */
579
Marat Dukhan06716242021-05-26 15:56:39 -0700580 TEST(QS8_RNDNA__SSSE3, exact_divide_by_po2) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700581 for (uint32_t s = 1; s < 32; s++) {
582 RequantizationTester()
583 .qmin(std::numeric_limits<int8_t>::min())
584 .qmax(std::numeric_limits<int8_t>::max())
585 .s(s)
Marat Dukhan06716242021-05-26 15:56:39 -0700586 .TestExactDivideByPO2(xnn_qs8_requantize_rndna__ssse3);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700587 }
588 }
589
Marat Dukhan06716242021-05-26 15:56:39 -0700590 TEST(QS8_RNDNA__SSSE3, exact_divide_by_po2_with_zero_point) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700591 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
592 zero_point <= std::numeric_limits<int8_t>::max();
593 zero_point++)
594 {
595 for (uint32_t s = 1; s < 32; s++) {
596 RequantizationTester()
597 .zero_point(zero_point)
598 .qmin(std::numeric_limits<int8_t>::min())
599 .qmax(std::numeric_limits<int8_t>::max())
600 .s(s)
Marat Dukhan06716242021-05-26 15:56:39 -0700601 .TestExactDivideByPO2(xnn_qs8_requantize_rndna__ssse3);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700602 }
603 }
604 }
605
Marat Dukhan06716242021-05-26 15:56:39 -0700606 TEST(QS8_RNDNA__SSSE3, divide_by_po2_with_rounding_up) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700607 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
608 zero_point <= std::numeric_limits<int8_t>::max();
609 zero_point++)
610 {
611 for (uint32_t s = 1; s < 32; s++) {
612 RequantizationTester()
613 .zero_point(zero_point)
614 .qmin(std::numeric_limits<int8_t>::min())
615 .qmax(std::numeric_limits<int8_t>::max())
616 .s(s)
Marat Dukhan06716242021-05-26 15:56:39 -0700617 .TestDivideByPO2WithRoundingUp(xnn_qs8_requantize_rndna__ssse3);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700618 }
619 }
620 }
621
Marat Dukhan06716242021-05-26 15:56:39 -0700622 TEST(QS8_RNDNA__SSSE3, divide_by_po2_with_rounding_down) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700623 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
624 zero_point <= std::numeric_limits<int8_t>::max();
625 zero_point++)
626 {
627 for (uint32_t s = 1; s < 32; s++) {
628 RequantizationTester()
629 .zero_point(zero_point)
630 .qmin(std::numeric_limits<int8_t>::min())
631 .qmax(std::numeric_limits<int8_t>::max())
632 .s(s)
Marat Dukhan06716242021-05-26 15:56:39 -0700633 .TestDivideByPO2WithRoundingDown(xnn_qs8_requantize_rndna__ssse3);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700634 }
635 }
636 }
637
Marat Dukhan06716242021-05-26 15:56:39 -0700638 TEST(QS8_RNDNA__SSSE3, divide_by_po2_with_rounding_away) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700639 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
640 zero_point <= std::numeric_limits<int8_t>::max();
641 zero_point++)
642 {
643 for (uint32_t s = 1; s < 32; s++) {
644 RequantizationTester()
645 .zero_point(zero_point)
646 .qmin(std::numeric_limits<int8_t>::min())
647 .qmax(std::numeric_limits<int8_t>::max())
648 .s(s)
Marat Dukhan062bee32021-05-27 20:31:07 -0700649 .TestDivideByPO2WithRoundingTiesAway(xnn_qs8_requantize_rndna__ssse3);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700650 }
651 }
652 }
653
Marat Dukhan06716242021-05-26 15:56:39 -0700654 TEST(QS8_RNDNA__SSSE3, special_cases) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700655 RequantizationTester()
656 .qmin(std::numeric_limits<int8_t>::min())
657 .qmax(std::numeric_limits<int8_t>::max())
Marat Dukhan06716242021-05-26 15:56:39 -0700658 .TestSpecialCases(xnn_qs8_requantize_rndna__ssse3);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700659 }
660
Marat Dukhan06716242021-05-26 15:56:39 -0700661 TEST(QS8_RNDNA__SSSE3, random_cases) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700662 RequantizationTester()
663 .qmin(std::numeric_limits<int8_t>::min())
664 .qmax(std::numeric_limits<int8_t>::max())
665 .iterations(100)
Marat Dukhan06716242021-05-26 15:56:39 -0700666 .TestRandomCasesRoundToNearestTiesAway(xnn_qs8_requantize_rndna__ssse3);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700667 }
668
669
670 /*
Marat Dukhan06716242021-05-26 15:56:39 -0700671 * Round-to-nearest, ties away from zero, SSE4.1 implementation using static blend instruction.
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700672 */
673
Marat Dukhan06716242021-05-26 15:56:39 -0700674 TEST(QS8_RNDNA__SSE4, exact_divide_by_po2) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700675 for (uint32_t s = 1; s < 32; s++) {
676 RequantizationTester()
677 .qmin(std::numeric_limits<int8_t>::min())
678 .qmax(std::numeric_limits<int8_t>::max())
679 .s(s)
Marat Dukhan06716242021-05-26 15:56:39 -0700680 .TestExactDivideByPO2(xnn_qs8_requantize_rndna__sse4);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700681 }
682 }
683
Marat Dukhan06716242021-05-26 15:56:39 -0700684 TEST(QS8_RNDNA__SSE4, exact_divide_by_po2_with_zero_point) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700685 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
686 zero_point <= std::numeric_limits<int8_t>::max();
687 zero_point++)
688 {
689 for (uint32_t s = 1; s < 32; s++) {
690 RequantizationTester()
691 .zero_point(zero_point)
692 .qmin(std::numeric_limits<int8_t>::min())
693 .qmax(std::numeric_limits<int8_t>::max())
694 .s(s)
Marat Dukhan06716242021-05-26 15:56:39 -0700695 .TestExactDivideByPO2(xnn_qs8_requantize_rndna__sse4);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700696 }
697 }
698 }
699
Marat Dukhan06716242021-05-26 15:56:39 -0700700 TEST(QS8_RNDNA__SSE4, divide_by_po2_with_rounding_up) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700701 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
702 zero_point <= std::numeric_limits<int8_t>::max();
703 zero_point++)
704 {
705 for (uint32_t s = 1; s < 32; s++) {
706 RequantizationTester()
707 .zero_point(zero_point)
708 .qmin(std::numeric_limits<int8_t>::min())
709 .qmax(std::numeric_limits<int8_t>::max())
710 .s(s)
Marat Dukhan06716242021-05-26 15:56:39 -0700711 .TestDivideByPO2WithRoundingUp(xnn_qs8_requantize_rndna__sse4);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700712 }
713 }
714 }
715
Marat Dukhan06716242021-05-26 15:56:39 -0700716 TEST(QS8_RNDNA__SSE4, divide_by_po2_with_rounding_down) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700717 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
718 zero_point <= std::numeric_limits<int8_t>::max();
719 zero_point++)
720 {
721 for (uint32_t s = 1; s < 32; s++) {
722 RequantizationTester()
723 .zero_point(zero_point)
724 .qmin(std::numeric_limits<int8_t>::min())
725 .qmax(std::numeric_limits<int8_t>::max())
726 .s(s)
Marat Dukhan06716242021-05-26 15:56:39 -0700727 .TestDivideByPO2WithRoundingDown(xnn_qs8_requantize_rndna__sse4);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700728 }
729 }
730 }
731
Marat Dukhan06716242021-05-26 15:56:39 -0700732 TEST(QS8_RNDNA__SSE4, divide_by_po2_with_rounding_away) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700733 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
734 zero_point <= std::numeric_limits<int8_t>::max();
735 zero_point++)
736 {
737 for (uint32_t s = 1; s < 32; s++) {
738 RequantizationTester()
739 .zero_point(zero_point)
740 .qmin(std::numeric_limits<int8_t>::min())
741 .qmax(std::numeric_limits<int8_t>::max())
742 .s(s)
Marat Dukhan062bee32021-05-27 20:31:07 -0700743 .TestDivideByPO2WithRoundingTiesAway(xnn_qs8_requantize_rndna__sse4);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700744 }
745 }
746 }
747
Marat Dukhan06716242021-05-26 15:56:39 -0700748 TEST(QS8_RNDNA__SSE4, special_cases) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700749 RequantizationTester()
750 .qmin(std::numeric_limits<int8_t>::min())
751 .qmax(std::numeric_limits<int8_t>::max())
Marat Dukhan06716242021-05-26 15:56:39 -0700752 .TestSpecialCases(xnn_qs8_requantize_rndna__sse4);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700753 }
754
Marat Dukhan06716242021-05-26 15:56:39 -0700755 TEST(QS8_RNDNA__SSE4, random_cases) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700756 RequantizationTester()
757 .qmin(std::numeric_limits<int8_t>::min())
758 .qmax(std::numeric_limits<int8_t>::max())
759 .iterations(100)
Marat Dukhan06716242021-05-26 15:56:39 -0700760 .TestRandomCasesRoundToNearestTiesAway(xnn_qs8_requantize_rndna__sse4);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700761 }
762
763
764 /*
Marat Dukhan0d979d52021-06-09 13:21:18 -0700765 * Round-to-nearest, ties up, SSE4.1 implementation using arithmetic shift right.
Marat Dukhan062bee32021-05-27 20:31:07 -0700766 */
767
Marat Dukhan0d979d52021-06-09 13:21:18 -0700768 TEST(QS8_RNDNU__SSE4_SRA, exact_divide_by_po2) {
Marat Dukhan062bee32021-05-27 20:31:07 -0700769 for (uint32_t s = 1; s < 32; s++) {
770 RequantizationTester()
771 .qmin(std::numeric_limits<int8_t>::min())
772 .qmax(std::numeric_limits<int8_t>::max())
773 .s(s)
Marat Dukhan0d979d52021-06-09 13:21:18 -0700774 .TestExactDivideByPO2(xnn_qs8_requantize_rndnu__sse4_sra);
Marat Dukhan062bee32021-05-27 20:31:07 -0700775 }
776 }
777
Marat Dukhan0d979d52021-06-09 13:21:18 -0700778 TEST(QS8_RNDNU__SSE4_SRA, exact_divide_by_po2_with_zero_point) {
Marat Dukhan062bee32021-05-27 20:31:07 -0700779 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
780 zero_point <= std::numeric_limits<int8_t>::max();
781 zero_point++)
782 {
783 for (uint32_t s = 1; s < 32; s++) {
784 RequantizationTester()
785 .zero_point(zero_point)
786 .qmin(std::numeric_limits<int8_t>::min())
787 .qmax(std::numeric_limits<int8_t>::max())
788 .s(s)
Marat Dukhan0d979d52021-06-09 13:21:18 -0700789 .TestExactDivideByPO2(xnn_qs8_requantize_rndnu__sse4_sra);
Marat Dukhan062bee32021-05-27 20:31:07 -0700790 }
791 }
792 }
793
Marat Dukhan0d979d52021-06-09 13:21:18 -0700794 TEST(QS8_RNDNU__SSE4_SRA, divide_by_po2_with_rounding_up) {
Marat Dukhan062bee32021-05-27 20:31:07 -0700795 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
796 zero_point <= std::numeric_limits<int8_t>::max();
797 zero_point++)
798 {
799 for (uint32_t s = 1; s < 32; s++) {
800 RequantizationTester()
801 .zero_point(zero_point)
802 .qmin(std::numeric_limits<int8_t>::min())
803 .qmax(std::numeric_limits<int8_t>::max())
804 .s(s)
Marat Dukhan0d979d52021-06-09 13:21:18 -0700805 .TestDivideByPO2WithRoundingUp(xnn_qs8_requantize_rndnu__sse4_sra);
Marat Dukhan062bee32021-05-27 20:31:07 -0700806 }
807 }
808 }
809
Marat Dukhan0d979d52021-06-09 13:21:18 -0700810 TEST(QS8_RNDNU__SSE4_SRA, divide_by_po2_with_rounding_down) {
Marat Dukhan062bee32021-05-27 20:31:07 -0700811 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
812 zero_point <= std::numeric_limits<int8_t>::max();
813 zero_point++)
814 {
815 for (uint32_t s = 1; s < 32; s++) {
816 RequantizationTester()
817 .zero_point(zero_point)
818 .qmin(std::numeric_limits<int8_t>::min())
819 .qmax(std::numeric_limits<int8_t>::max())
820 .s(s)
Marat Dukhan0d979d52021-06-09 13:21:18 -0700821 .TestDivideByPO2WithRoundingDown(xnn_qs8_requantize_rndnu__sse4_sra);
Marat Dukhan062bee32021-05-27 20:31:07 -0700822 }
823 }
824 }
825
Marat Dukhan0d979d52021-06-09 13:21:18 -0700826 TEST(QS8_RNDNU__SSE4_SRA, divide_by_po2_with_rounding_away) {
Marat Dukhan062bee32021-05-27 20:31:07 -0700827 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
828 zero_point <= std::numeric_limits<int8_t>::max();
829 zero_point++)
830 {
831 for (uint32_t s = 1; s < 32; s++) {
832 RequantizationTester()
833 .zero_point(zero_point)
834 .qmin(std::numeric_limits<int8_t>::min())
835 .qmax(std::numeric_limits<int8_t>::max())
836 .s(s)
Marat Dukhan0d979d52021-06-09 13:21:18 -0700837 .TestDivideByPO2WithRoundingTiesUp(xnn_qs8_requantize_rndnu__sse4_sra);
Marat Dukhan062bee32021-05-27 20:31:07 -0700838 }
839 }
840 }
841
Marat Dukhan0d979d52021-06-09 13:21:18 -0700842 TEST(QS8_RNDNU__SSE4_SRA, random_cases) {
Marat Dukhan062bee32021-05-27 20:31:07 -0700843 RequantizationTester()
844 .qmin(std::numeric_limits<int8_t>::min())
845 .qmax(std::numeric_limits<int8_t>::max())
846 .iterations(100)
Marat Dukhan0d979d52021-06-09 13:21:18 -0700847 .TestRandomCasesRoundToNearestTiesUp(xnn_qs8_requantize_rndnu__sse4_sra);
848 }
849
850
851 /*
852 * Round-to-nearest, ties up, SSE4.1 implementation using logical shift right.
853 */
854
855 TEST(QS8_RNDNU__SSE4_SRL, exact_divide_by_po2) {
856 for (uint32_t s = 1; s < 32; s++) {
857 RequantizationTester()
858 .qmin(std::numeric_limits<int8_t>::min())
859 .qmax(std::numeric_limits<int8_t>::max())
860 .s(s)
861 .TestExactDivideByPO2(xnn_qs8_requantize_rndnu__sse4_srl);
862 }
863 }
864
865 TEST(QS8_RNDNU__SSE4_SRL, exact_divide_by_po2_with_zero_point) {
866 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
867 zero_point <= std::numeric_limits<int8_t>::max();
868 zero_point++)
869 {
870 for (uint32_t s = 1; s < 32; s++) {
871 RequantizationTester()
872 .zero_point(zero_point)
873 .qmin(std::numeric_limits<int8_t>::min())
874 .qmax(std::numeric_limits<int8_t>::max())
875 .s(s)
876 .TestExactDivideByPO2(xnn_qs8_requantize_rndnu__sse4_srl);
877 }
878 }
879 }
880
881 TEST(QS8_RNDNU__SSE4_SRL, divide_by_po2_with_rounding_up) {
882 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
883 zero_point <= std::numeric_limits<int8_t>::max();
884 zero_point++)
885 {
886 for (uint32_t s = 1; s < 32; s++) {
887 RequantizationTester()
888 .zero_point(zero_point)
889 .qmin(std::numeric_limits<int8_t>::min())
890 .qmax(std::numeric_limits<int8_t>::max())
891 .s(s)
892 .TestDivideByPO2WithRoundingUp(xnn_qs8_requantize_rndnu__sse4_srl);
893 }
894 }
895 }
896
897 TEST(QS8_RNDNU__SSE4_SRL, divide_by_po2_with_rounding_down) {
898 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
899 zero_point <= std::numeric_limits<int8_t>::max();
900 zero_point++)
901 {
902 for (uint32_t s = 1; s < 32; s++) {
903 RequantizationTester()
904 .zero_point(zero_point)
905 .qmin(std::numeric_limits<int8_t>::min())
906 .qmax(std::numeric_limits<int8_t>::max())
907 .s(s)
908 .TestDivideByPO2WithRoundingDown(xnn_qs8_requantize_rndnu__sse4_srl);
909 }
910 }
911 }
912
913 TEST(QS8_RNDNU__SSE4_SRL, divide_by_po2_with_rounding_away) {
914 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
915 zero_point <= std::numeric_limits<int8_t>::max();
916 zero_point++)
917 {
918 for (uint32_t s = 1; s < 32; s++) {
919 RequantizationTester()
920 .zero_point(zero_point)
921 .qmin(std::numeric_limits<int8_t>::min())
922 .qmax(std::numeric_limits<int8_t>::max())
923 .s(s)
924 .TestDivideByPO2WithRoundingTiesUp(xnn_qs8_requantize_rndnu__sse4_srl);
925 }
926 }
927 }
928
929 TEST(QS8_RNDNU__SSE4_SRL, random_cases) {
930 RequantizationTester()
931 .qmin(std::numeric_limits<int8_t>::min())
932 .qmax(std::numeric_limits<int8_t>::max())
933 .iterations(100)
934 .TestRandomCasesRoundToNearestTiesUp(xnn_qs8_requantize_rndnu__sse4_srl);
Marat Dukhan062bee32021-05-27 20:31:07 -0700935 }
936
937
938 /*
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700939 * FP32-based x86 SSE2 implementation.
940 */
941
942 TEST(QS8_FP32__SSE2, random_cases) {
943 RequantizationTester()
944 .qmin(std::numeric_limits<int8_t>::min())
945 .qmax(std::numeric_limits<int8_t>::max())
946 .iterations(1000)
947 .TestRandomCasesApproximate(xnn_qs8_requantize_fp32__sse2);
948 }
949
950
951 /*
952 * FP32-based x86 SSE4 implementation.
953 */
954
955 TEST(QS8_FP32__SSE4, random_cases) {
956 RequantizationTester()
957 .qmin(std::numeric_limits<int8_t>::min())
958 .qmax(std::numeric_limits<int8_t>::max())
959 .iterations(1000)
960 .TestRandomCasesApproximate(xnn_qs8_requantize_fp32__sse4);
961 }
962
963
964 /*
Marat Dukhan9976cd82021-05-24 23:15:45 -0700965 * GEMMLOWP-equivalent x86 SSE2 implementation.
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700966 */
967
Marat Dukhan9976cd82021-05-24 23:15:45 -0700968 TEST(QS8_GEMMLOWP__SSE2, exact_divide_by_po2) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700969 for (uint32_t s = 1; s < 32; s++) {
970 RequantizationTester()
971 .qmin(std::numeric_limits<int8_t>::min())
972 .qmax(std::numeric_limits<int8_t>::max())
973 .s(s)
Marat Dukhan9976cd82021-05-24 23:15:45 -0700974 .TestExactDivideByPO2(xnn_qs8_requantize_gemmlowp__sse2);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700975 }
976 }
977
Marat Dukhan9976cd82021-05-24 23:15:45 -0700978 TEST(QS8_GEMMLOWP__SSE2, exact_divide_by_po2_with_zero_point) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700979 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
980 zero_point <= std::numeric_limits<int8_t>::max();
981 zero_point++)
982 {
983 for (uint32_t s = 1; s < 32; s++) {
984 RequantizationTester()
985 .zero_point(zero_point)
986 .qmin(std::numeric_limits<int8_t>::min())
987 .qmax(std::numeric_limits<int8_t>::max())
988 .s(s)
Marat Dukhan9976cd82021-05-24 23:15:45 -0700989 .TestExactDivideByPO2(xnn_qs8_requantize_gemmlowp__sse2);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700990 }
991 }
992 }
993
Marat Dukhan9976cd82021-05-24 23:15:45 -0700994 TEST(QS8_GEMMLOWP__SSE2, divide_by_po2_with_rounding_up) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700995 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
996 zero_point <= std::numeric_limits<int8_t>::max();
997 zero_point++)
998 {
999 for (uint32_t s = 1; s < 32; s++) {
1000 RequantizationTester()
1001 .zero_point(zero_point)
1002 .qmin(std::numeric_limits<int8_t>::min())
1003 .qmax(std::numeric_limits<int8_t>::max())
1004 .s(s)
Marat Dukhan9976cd82021-05-24 23:15:45 -07001005 .TestDivideByPO2WithRoundingUp(xnn_qs8_requantize_gemmlowp__sse2);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001006 }
1007 }
1008 }
1009
1010 /* No rounding down test - it fails because of upward bias in multiplication */
1011 /* No rounding away test - it fails because of upward bias in multiplication */
1012
Marat Dukhan9976cd82021-05-24 23:15:45 -07001013 TEST(QS8_GEMMLOWP__SSE2, special_cases) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001014 RequantizationTester()
1015 .qmin(std::numeric_limits<int8_t>::min())
1016 .qmax(std::numeric_limits<int8_t>::max())
Marat Dukhan9976cd82021-05-24 23:15:45 -07001017 .TestSpecialCases(xnn_qs8_requantize_gemmlowp__sse2);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001018 }
1019
Marat Dukhan9976cd82021-05-24 23:15:45 -07001020 TEST(QS8_GEMMLOWP__SSE2, random_cases) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001021 RequantizationTester()
1022 .qmin(std::numeric_limits<int8_t>::min())
1023 .qmax(std::numeric_limits<int8_t>::max())
1024 .iterations(100)
Marat Dukhan9976cd82021-05-24 23:15:45 -07001025 .TestRandomCasesApproximate(xnn_qs8_requantize_gemmlowp__sse2);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001026 }
1027
1028
1029 /*
Marat Dukhan9976cd82021-05-24 23:15:45 -07001030 * GEMMLOWP-equivalent x86 SSSE3 implementation.
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001031 */
1032
Marat Dukhan9976cd82021-05-24 23:15:45 -07001033 TEST(QS8_GEMMLOWP__SSSE3, exact_divide_by_po2) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001034 for (uint32_t s = 1; s < 32; s++) {
1035 RequantizationTester()
1036 .qmin(std::numeric_limits<int8_t>::min())
1037 .qmax(std::numeric_limits<int8_t>::max())
1038 .s(s)
Marat Dukhan9976cd82021-05-24 23:15:45 -07001039 .TestExactDivideByPO2(xnn_qs8_requantize_gemmlowp__ssse3);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001040 }
1041 }
1042
Marat Dukhan9976cd82021-05-24 23:15:45 -07001043 TEST(QS8_GEMMLOWP__SSSE3, exact_divide_by_po2_with_zero_point) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001044 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
1045 zero_point <= std::numeric_limits<int8_t>::max();
1046 zero_point++)
1047 {
1048 for (uint32_t s = 1; s < 32; s++) {
1049 RequantizationTester()
1050 .zero_point(zero_point)
1051 .qmin(std::numeric_limits<int8_t>::min())
1052 .qmax(std::numeric_limits<int8_t>::max())
1053 .s(s)
Marat Dukhan9976cd82021-05-24 23:15:45 -07001054 .TestExactDivideByPO2(xnn_qs8_requantize_gemmlowp__ssse3);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001055 }
1056 }
1057 }
1058
Marat Dukhan9976cd82021-05-24 23:15:45 -07001059 TEST(QS8_GEMMLOWP__SSSE3, divide_by_po2_with_rounding_up) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001060 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
1061 zero_point <= std::numeric_limits<int8_t>::max();
1062 zero_point++)
1063 {
1064 for (uint32_t s = 1; s < 32; s++) {
1065 RequantizationTester()
1066 .zero_point(zero_point)
1067 .qmin(std::numeric_limits<int8_t>::min())
1068 .qmax(std::numeric_limits<int8_t>::max())
1069 .s(s)
Marat Dukhan9976cd82021-05-24 23:15:45 -07001070 .TestDivideByPO2WithRoundingUp(xnn_qs8_requantize_gemmlowp__ssse3);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001071 }
1072 }
1073 }
1074
1075 /* No rounding down test - it fails because of upward bias in multiplication */
1076 /* No rounding away test - it fails because of upward bias in multiplication */
1077
Marat Dukhan9976cd82021-05-24 23:15:45 -07001078 TEST(QS8_GEMMLOWP__SSSE3, special_cases) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001079 RequantizationTester()
1080 .qmin(std::numeric_limits<int8_t>::min())
1081 .qmax(std::numeric_limits<int8_t>::max())
Marat Dukhan9976cd82021-05-24 23:15:45 -07001082 .TestSpecialCases(xnn_qs8_requantize_gemmlowp__ssse3);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001083 }
1084
Marat Dukhan9976cd82021-05-24 23:15:45 -07001085 TEST(QS8_GEMMLOWP__SSSE3, random_cases) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001086 RequantizationTester()
1087 .qmin(std::numeric_limits<int8_t>::min())
1088 .qmax(std::numeric_limits<int8_t>::max())
1089 .iterations(100)
Marat Dukhan9976cd82021-05-24 23:15:45 -07001090 .TestRandomCasesApproximate(xnn_qs8_requantize_gemmlowp__ssse3);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001091 }
1092
1093
1094 /*
Marat Dukhan9976cd82021-05-24 23:15:45 -07001095 * GEMMLOWP-equivalent x86 SSE4 implementation.
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001096 */
1097
Marat Dukhan9976cd82021-05-24 23:15:45 -07001098 TEST(QS8_GEMMLOWP__SSE4, exact_divide_by_po2) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001099 for (uint32_t s = 1; s < 32; s++) {
1100 RequantizationTester()
1101 .qmin(std::numeric_limits<int8_t>::min())
1102 .qmax(std::numeric_limits<int8_t>::max())
1103 .s(s)
Marat Dukhan9976cd82021-05-24 23:15:45 -07001104 .TestExactDivideByPO2(xnn_qs8_requantize_gemmlowp__sse4);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001105 }
1106 }
1107
Marat Dukhan9976cd82021-05-24 23:15:45 -07001108 TEST(QS8_GEMMLOWP__SSE4, exact_divide_by_po2_with_zero_point) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001109 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
1110 zero_point <= std::numeric_limits<int8_t>::max();
1111 zero_point++)
1112 {
1113 for (uint32_t s = 1; s < 32; s++) {
1114 RequantizationTester()
1115 .zero_point(zero_point)
1116 .qmin(std::numeric_limits<int8_t>::min())
1117 .qmax(std::numeric_limits<int8_t>::max())
1118 .s(s)
Marat Dukhan9976cd82021-05-24 23:15:45 -07001119 .TestExactDivideByPO2(xnn_qs8_requantize_gemmlowp__sse4);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001120 }
1121 }
1122 }
1123
Marat Dukhan9976cd82021-05-24 23:15:45 -07001124 TEST(QS8_GEMMLOWP__SSE4, divide_by_po2_with_rounding_up) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001125 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
1126 zero_point <= std::numeric_limits<int8_t>::max();
1127 zero_point++)
1128 {
1129 for (uint32_t s = 1; s < 32; s++) {
1130 RequantizationTester()
1131 .zero_point(zero_point)
1132 .qmin(std::numeric_limits<int8_t>::min())
1133 .qmax(std::numeric_limits<int8_t>::max())
1134 .s(s)
Marat Dukhan9976cd82021-05-24 23:15:45 -07001135 .TestDivideByPO2WithRoundingUp(xnn_qs8_requantize_gemmlowp__sse4);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001136 }
1137 }
1138 }
1139
1140 /* No rounding down test - it fails because of upward bias in multiplication */
1141 /* No rounding away test - it fails because of upward bias in multiplication */
1142
Marat Dukhan9976cd82021-05-24 23:15:45 -07001143 TEST(QS8_GEMMLOWP__SSE4, special_cases) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001144 RequantizationTester()
1145 .qmin(std::numeric_limits<int8_t>::min())
1146 .qmax(std::numeric_limits<int8_t>::max())
Marat Dukhan9976cd82021-05-24 23:15:45 -07001147 .TestSpecialCases(xnn_qs8_requantize_gemmlowp__sse4);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001148 }
1149
Marat Dukhan9976cd82021-05-24 23:15:45 -07001150 TEST(QS8_GEMMLOWP__SSE4, random_cases) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001151 RequantizationTester()
1152 .qmin(std::numeric_limits<int8_t>::min())
1153 .qmax(std::numeric_limits<int8_t>::max())
1154 .iterations(100)
Marat Dukhan9976cd82021-05-24 23:15:45 -07001155 .TestRandomCasesApproximate(xnn_qs8_requantize_gemmlowp__sse4);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001156 }
1157#endif // XNN_ARCH_X86 || XNN_ARCH_X86_64
1158
1159#if XNN_ARCH_ARM || XNN_ARCH_ARM64
1160 /*
Marat Dukhan06716242021-05-26 15:56:39 -07001161 * Round-to-nearest, ties away from zero, ARM NEON implementation.
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001162 */
1163
Marat Dukhan06716242021-05-26 15:56:39 -07001164 TEST(QS8_RNDNA__NEON, exact_divide_by_po2) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001165 for (uint32_t s = 1; s < 32; s++) {
1166 RequantizationTester()
1167 .s(s)
1168 .qmin(std::numeric_limits<int8_t>::min())
1169 .qmax(std::numeric_limits<int8_t>::max())
Marat Dukhan06716242021-05-26 15:56:39 -07001170 .TestExactDivideByPO2(xnn_qs8_requantize_rndna__neon);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001171 }
1172 }
1173
Marat Dukhan06716242021-05-26 15:56:39 -07001174 TEST(QS8_RNDNA__NEON, exact_divide_by_po2_with_zero_point) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001175 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
1176 zero_point <= std::numeric_limits<int8_t>::max();
1177 zero_point++)
1178 {
1179 for (uint32_t s = 1; s < 32; s++) {
1180 RequantizationTester()
1181 .zero_point(zero_point)
1182 .qmin(std::numeric_limits<int8_t>::min())
1183 .qmax(std::numeric_limits<int8_t>::max())
1184 .s(s)
Marat Dukhan06716242021-05-26 15:56:39 -07001185 .TestExactDivideByPO2(xnn_qs8_requantize_rndna__neon);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001186 }
1187 }
1188 }
1189
Marat Dukhan06716242021-05-26 15:56:39 -07001190 TEST(QS8_RNDNA__NEON, divide_by_po2_with_rounding_up) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001191 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
1192 zero_point <= std::numeric_limits<int8_t>::max();
1193 zero_point++)
1194 {
1195 for (uint32_t s = 1; s < 32; s++) {
1196 RequantizationTester()
1197 .zero_point(zero_point)
1198 .qmin(std::numeric_limits<int8_t>::min())
1199 .qmax(std::numeric_limits<int8_t>::max())
1200 .s(s)
Marat Dukhan06716242021-05-26 15:56:39 -07001201 .TestDivideByPO2WithRoundingUp(xnn_qs8_requantize_rndna__neon);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001202 }
1203 }
1204 }
1205
Marat Dukhan06716242021-05-26 15:56:39 -07001206 TEST(QS8_RNDNA__NEON, divide_by_po2_with_rounding_down) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001207 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
1208 zero_point <= std::numeric_limits<int8_t>::max();
1209 zero_point++)
1210 {
1211 for (uint32_t s = 1; s < 32; s++) {
1212 RequantizationTester()
1213 .zero_point(zero_point)
1214 .qmin(std::numeric_limits<int8_t>::min())
1215 .qmax(std::numeric_limits<int8_t>::max())
1216 .s(s)
Marat Dukhan06716242021-05-26 15:56:39 -07001217 .TestDivideByPO2WithRoundingDown(xnn_qs8_requantize_rndna__neon);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001218 }
1219 }
1220 }
1221
Marat Dukhan06716242021-05-26 15:56:39 -07001222 TEST(QS8_RNDNA__NEON, divide_by_po2_with_rounding_away) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001223 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
1224 zero_point <= std::numeric_limits<int8_t>::max();
1225 zero_point++)
1226 {
1227 for (uint32_t s = 1; s < 32; s++) {
1228 RequantizationTester()
1229 .zero_point(zero_point)
1230 .qmin(std::numeric_limits<int8_t>::min())
1231 .qmax(std::numeric_limits<int8_t>::max())
1232 .s(s)
Marat Dukhan062bee32021-05-27 20:31:07 -07001233 .TestDivideByPO2WithRoundingTiesAway(xnn_qs8_requantize_rndna__neon);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001234 }
1235 }
1236 }
1237
Marat Dukhan06716242021-05-26 15:56:39 -07001238 TEST(QS8_RNDNA__NEON, special_cases) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001239 RequantizationTester()
1240 .qmin(std::numeric_limits<int8_t>::min())
1241 .qmax(std::numeric_limits<int8_t>::max())
Marat Dukhan06716242021-05-26 15:56:39 -07001242 .TestSpecialCases(xnn_qs8_requantize_rndna__neon);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001243 }
1244
Marat Dukhan06716242021-05-26 15:56:39 -07001245 TEST(QS8_RNDNA__NEON, random_cases) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001246 RequantizationTester()
1247 .qmin(std::numeric_limits<int8_t>::min())
1248 .qmax(std::numeric_limits<int8_t>::max())
1249 .iterations(100)
Marat Dukhan06716242021-05-26 15:56:39 -07001250 .TestRandomCasesRoundToNearestTiesAway(xnn_qs8_requantize_rndna__neon);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001251 }
1252
1253
1254 /*
Marat Dukhan062bee32021-05-27 20:31:07 -07001255 * Round-to-nearest, ties up, ARM NEON implementation.
1256 */
1257
1258 TEST(QS8_RNDNU__NEON, exact_divide_by_po2) {
1259 for (uint32_t s = 1; s < 32; s++) {
1260 RequantizationTester()
1261 .qmin(std::numeric_limits<int8_t>::min())
1262 .qmax(std::numeric_limits<int8_t>::max())
1263 .s(s)
1264 .TestExactDivideByPO2(xnn_qs8_requantize_rndnu__neon);
1265 }
1266 }
1267
1268 TEST(QS8_RNDNU__NEON, exact_divide_by_po2_with_zero_point) {
1269 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
1270 zero_point <= std::numeric_limits<int8_t>::max();
1271 zero_point++)
1272 {
1273 for (uint32_t s = 1; s < 32; s++) {
1274 RequantizationTester()
1275 .zero_point(zero_point)
1276 .qmin(std::numeric_limits<int8_t>::min())
1277 .qmax(std::numeric_limits<int8_t>::max())
1278 .s(s)
1279 .TestExactDivideByPO2(xnn_qs8_requantize_rndnu__neon);
1280 }
1281 }
1282 }
1283
1284 TEST(QS8_RNDNU__NEON, divide_by_po2_with_rounding_up) {
1285 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
1286 zero_point <= std::numeric_limits<int8_t>::max();
1287 zero_point++)
1288 {
1289 for (uint32_t s = 1; s < 32; s++) {
1290 RequantizationTester()
1291 .zero_point(zero_point)
1292 .qmin(std::numeric_limits<int8_t>::min())
1293 .qmax(std::numeric_limits<int8_t>::max())
1294 .s(s)
1295 .TestDivideByPO2WithRoundingUp(xnn_qs8_requantize_rndnu__neon);
1296 }
1297 }
1298 }
1299
1300 TEST(QS8_RNDNU__NEON, divide_by_po2_with_rounding_down) {
1301 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
1302 zero_point <= std::numeric_limits<int8_t>::max();
1303 zero_point++)
1304 {
1305 for (uint32_t s = 1; s < 32; s++) {
1306 RequantizationTester()
1307 .zero_point(zero_point)
1308 .qmin(std::numeric_limits<int8_t>::min())
1309 .qmax(std::numeric_limits<int8_t>::max())
1310 .s(s)
1311 .TestDivideByPO2WithRoundingDown(xnn_qs8_requantize_rndnu__neon);
1312 }
1313 }
1314 }
1315
1316 TEST(QS8_RNDNU__NEON, divide_by_po2_with_rounding_away) {
1317 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
1318 zero_point <= std::numeric_limits<int8_t>::max();
1319 zero_point++)
1320 {
1321 for (uint32_t s = 1; s < 32; s++) {
1322 RequantizationTester()
1323 .zero_point(zero_point)
1324 .qmin(std::numeric_limits<int8_t>::min())
1325 .qmax(std::numeric_limits<int8_t>::max())
1326 .s(s)
1327 .TestDivideByPO2WithRoundingTiesUp(xnn_qs8_requantize_rndnu__neon);
1328 }
1329 }
1330 }
1331
1332 TEST(QS8_RNDNU__NEON, random_cases) {
1333 RequantizationTester()
1334 .qmin(std::numeric_limits<int8_t>::min())
1335 .qmax(std::numeric_limits<int8_t>::max())
1336 .iterations(100)
Marat Dukhanc6e6ee02021-05-27 22:27:18 -07001337 .TestRandomCasesRoundToNearestTiesUp(xnn_qs8_requantize_rndnu__neon);
Marat Dukhan062bee32021-05-27 20:31:07 -07001338 }
1339
1340
1341 /*
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001342 * FP32-based ARM NEON implementation.
1343 */
1344
1345 TEST(QS8_FP32__NEON, random_cases) {
1346 RequantizationTester()
1347 .qmin(std::numeric_limits<int8_t>::min())
1348 .qmax(std::numeric_limits<int8_t>::max())
1349 .iterations(1000)
1350 .TestRandomCasesApproximate(xnn_qs8_requantize_fp32__neon);
1351 }
1352
1353
1354 /*
Marat Dukhan9976cd82021-05-24 23:15:45 -07001355 * GEMMLOWP-equivalent ARM NEON implementation.
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001356 */
1357
Marat Dukhan9976cd82021-05-24 23:15:45 -07001358 TEST(QS8_GEMMLOWP__NEON, exact_divide_by_po2) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001359 for (uint32_t s = 1; s < 32; s++) {
1360 RequantizationTester()
1361 .qmin(std::numeric_limits<int8_t>::min())
1362 .qmax(std::numeric_limits<int8_t>::max())
1363 .s(s)
Marat Dukhan9976cd82021-05-24 23:15:45 -07001364 .TestExactDivideByPO2(xnn_qs8_requantize_gemmlowp__neon);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001365 }
1366 }
1367
Marat Dukhan9976cd82021-05-24 23:15:45 -07001368 TEST(QS8_GEMMLOWP__NEON, exact_divide_by_po2_with_zero_point) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001369 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
1370 zero_point <= std::numeric_limits<int8_t>::max();
1371 zero_point++)
1372 {
1373 for (uint32_t s = 1; s < 32; s++) {
1374 RequantizationTester()
1375 .zero_point(zero_point)
1376 .qmin(std::numeric_limits<int8_t>::min())
1377 .qmax(std::numeric_limits<int8_t>::max())
1378 .s(s)
Marat Dukhan9976cd82021-05-24 23:15:45 -07001379 .TestExactDivideByPO2(xnn_qs8_requantize_gemmlowp__neon);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001380 }
1381 }
1382 }
1383
Marat Dukhan9976cd82021-05-24 23:15:45 -07001384 TEST(QS8_GEMMLOWP__NEON, divide_by_po2_with_rounding_up) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001385 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
1386 zero_point <= std::numeric_limits<int8_t>::max();
1387 zero_point++)
1388 {
1389 for (uint32_t s = 1; s < 32; s++) {
1390 RequantizationTester()
1391 .zero_point(zero_point)
1392 .qmin(std::numeric_limits<int8_t>::min())
1393 .qmax(std::numeric_limits<int8_t>::max())
1394 .s(s)
Marat Dukhan9976cd82021-05-24 23:15:45 -07001395 .TestDivideByPO2WithRoundingUp(xnn_qs8_requantize_gemmlowp__neon);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001396 }
1397 }
1398 }
1399
1400 /* No rounding down test - it fails because of upward bias in multiplication */
1401 /* No rounding away test - it fails because of upward bias in multiplication */
1402
Marat Dukhan9976cd82021-05-24 23:15:45 -07001403 TEST(QS8_GEMMLOWP__NEON, special_cases) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001404 RequantizationTester()
1405 .qmin(std::numeric_limits<int8_t>::min())
1406 .qmax(std::numeric_limits<int8_t>::max())
Marat Dukhan9976cd82021-05-24 23:15:45 -07001407 .TestSpecialCases(xnn_qs8_requantize_gemmlowp__neon);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001408 }
1409
Marat Dukhan9976cd82021-05-24 23:15:45 -07001410 TEST(QS8_GEMMLOWP__NEON, random_cases) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001411 RequantizationTester()
1412 .qmin(std::numeric_limits<int8_t>::min())
1413 .qmax(std::numeric_limits<int8_t>::max())
1414 .iterations(100)
Marat Dukhan9976cd82021-05-24 23:15:45 -07001415 .TestRandomCasesApproximate(xnn_qs8_requantize_gemmlowp__neon);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001416 }
1417#endif // XNN_ARCH_ARM || XNN_ARCH_ARM64
1418
1419#if XNN_ARCH_WASMSIMD
1420 /*
Marat Dukhan138560c2020-08-03 18:57:34 -07001421 * FP32-based WAsm SIMD implementation.
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001422 */
1423
1424 TEST(QS8_FP32__WASMSIMD, random_cases) {
1425 RequantizationTester()
1426 .qmin(std::numeric_limits<int8_t>::min())
1427 .qmax(std::numeric_limits<int8_t>::max())
1428 .iterations(1000)
1429 .TestRandomCasesApproximate(xnn_qs8_requantize_fp32__wasmsimd);
1430 }
Marat Dukhan138560c2020-08-03 18:57:34 -07001431
1432 /*
Marat Dukhan9976cd82021-05-24 23:15:45 -07001433 * GEMMLOWP-equivalent WAsm SIMD implementation.
Marat Dukhan138560c2020-08-03 18:57:34 -07001434 */
1435
Marat Dukhan9976cd82021-05-24 23:15:45 -07001436 TEST(QS8_GEMMLOWP__WASMSIMD, exact_divide_by_po2) {
Marat Dukhan138560c2020-08-03 18:57:34 -07001437 for (uint32_t s = 1; s < 32; s++) {
1438 RequantizationTester()
1439 .qmin(std::numeric_limits<int8_t>::min())
1440 .qmax(std::numeric_limits<int8_t>::max())
1441 .s(s)
Marat Dukhan9976cd82021-05-24 23:15:45 -07001442 .TestExactDivideByPO2(xnn_qs8_requantize_gemmlowp__wasmsimd);
Marat Dukhan138560c2020-08-03 18:57:34 -07001443 }
1444 }
1445
Marat Dukhan9976cd82021-05-24 23:15:45 -07001446 TEST(QS8_GEMMLOWP__WASMSIMD, exact_divide_by_po2_with_zero_point) {
Marat Dukhan138560c2020-08-03 18:57:34 -07001447 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
1448 zero_point <= std::numeric_limits<int8_t>::max();
1449 zero_point++)
1450 {
1451 for (uint32_t s = 1; s < 32; s++) {
1452 RequantizationTester()
1453 .zero_point(zero_point)
1454 .qmin(std::numeric_limits<int8_t>::min())
1455 .qmax(std::numeric_limits<int8_t>::max())
1456 .s(s)
Marat Dukhan9976cd82021-05-24 23:15:45 -07001457 .TestExactDivideByPO2(xnn_qs8_requantize_gemmlowp__wasmsimd);
Marat Dukhan138560c2020-08-03 18:57:34 -07001458 }
1459 }
1460 }
1461
Marat Dukhan9976cd82021-05-24 23:15:45 -07001462 TEST(QS8_GEMMLOWP__WASMSIMD, divide_by_po2_with_rounding_up) {
Marat Dukhan138560c2020-08-03 18:57:34 -07001463 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
1464 zero_point <= std::numeric_limits<int8_t>::max();
1465 zero_point++)
1466 {
1467 for (uint32_t s = 1; s < 32; s++) {
1468 RequantizationTester()
1469 .zero_point(zero_point)
1470 .qmin(std::numeric_limits<int8_t>::min())
1471 .qmax(std::numeric_limits<int8_t>::max())
1472 .s(s)
Marat Dukhan9976cd82021-05-24 23:15:45 -07001473 .TestDivideByPO2WithRoundingUp(xnn_qs8_requantize_gemmlowp__wasmsimd);
Marat Dukhan138560c2020-08-03 18:57:34 -07001474 }
1475 }
1476 }
1477
1478 /* No rounding down test - it fails because of upward bias in multiplication */
1479 /* No rounding away test - it fails because of upward bias in multiplication */
1480
Marat Dukhan9976cd82021-05-24 23:15:45 -07001481 TEST(QS8_GEMMLOWP__WASMSIMD, special_cases) {
Marat Dukhan138560c2020-08-03 18:57:34 -07001482 RequantizationTester()
1483 .qmin(std::numeric_limits<int8_t>::min())
1484 .qmax(std::numeric_limits<int8_t>::max())
Marat Dukhan9976cd82021-05-24 23:15:45 -07001485 .TestSpecialCases(xnn_qs8_requantize_gemmlowp__wasmsimd);
Marat Dukhan138560c2020-08-03 18:57:34 -07001486 }
1487
Marat Dukhan9976cd82021-05-24 23:15:45 -07001488 TEST(QS8_GEMMLOWP__WASMSIMD, random_cases) {
Marat Dukhan138560c2020-08-03 18:57:34 -07001489 RequantizationTester()
1490 .qmin(std::numeric_limits<int8_t>::min())
1491 .qmax(std::numeric_limits<int8_t>::max())
1492 .iterations(100)
Marat Dukhan9976cd82021-05-24 23:15:45 -07001493 .TestRandomCasesApproximate(xnn_qs8_requantize_gemmlowp__wasmsimd);
Marat Dukhan138560c2020-08-03 18:57:34 -07001494 }
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001495#endif // XNN_ARCH_WASMSIMD