blob: 97dd14e9393665d41725dbed911e19cc2ea77620 [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>
Marat Dukhan348ed6d2021-08-06 01:19:04 -070016#include <xnnpack/isa-checks.h>
Marat Dukhan2e23d2b2020-07-29 16:01:37 -070017#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
Marat Dukhan2ac722e2022-01-04 01:54:20 -0800407TEST(QS8_FP32__SCALAR_FMAGIC, random_cases) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700408 RequantizationTester()
409 .qmin(std::numeric_limits<int8_t>::min())
410 .qmax(std::numeric_limits<int8_t>::max())
411 .iterations(1000)
Marat Dukhan2ac722e2022-01-04 01:54:20 -0800412 .TestRandomCasesApproximate(xnn_qs8_requantize_fp32__scalar_fmagic);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700413}
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 Dukhan348ed6d2021-08-06 01:19:04 -0700581 TEST_REQUIRES_X86_SSSE3;
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700582 for (uint32_t s = 1; s < 32; s++) {
583 RequantizationTester()
584 .qmin(std::numeric_limits<int8_t>::min())
585 .qmax(std::numeric_limits<int8_t>::max())
586 .s(s)
Marat Dukhan06716242021-05-26 15:56:39 -0700587 .TestExactDivideByPO2(xnn_qs8_requantize_rndna__ssse3);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700588 }
589 }
590
Marat Dukhan06716242021-05-26 15:56:39 -0700591 TEST(QS8_RNDNA__SSSE3, exact_divide_by_po2_with_zero_point) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -0700592 TEST_REQUIRES_X86_SSSE3;
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700593 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
594 zero_point <= std::numeric_limits<int8_t>::max();
595 zero_point++)
596 {
597 for (uint32_t s = 1; s < 32; s++) {
598 RequantizationTester()
599 .zero_point(zero_point)
600 .qmin(std::numeric_limits<int8_t>::min())
601 .qmax(std::numeric_limits<int8_t>::max())
602 .s(s)
Marat Dukhan06716242021-05-26 15:56:39 -0700603 .TestExactDivideByPO2(xnn_qs8_requantize_rndna__ssse3);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700604 }
605 }
606 }
607
Marat Dukhan06716242021-05-26 15:56:39 -0700608 TEST(QS8_RNDNA__SSSE3, divide_by_po2_with_rounding_up) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -0700609 TEST_REQUIRES_X86_SSSE3;
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700610 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
611 zero_point <= std::numeric_limits<int8_t>::max();
612 zero_point++)
613 {
614 for (uint32_t s = 1; s < 32; s++) {
615 RequantizationTester()
616 .zero_point(zero_point)
617 .qmin(std::numeric_limits<int8_t>::min())
618 .qmax(std::numeric_limits<int8_t>::max())
619 .s(s)
Marat Dukhan06716242021-05-26 15:56:39 -0700620 .TestDivideByPO2WithRoundingUp(xnn_qs8_requantize_rndna__ssse3);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700621 }
622 }
623 }
624
Marat Dukhan06716242021-05-26 15:56:39 -0700625 TEST(QS8_RNDNA__SSSE3, divide_by_po2_with_rounding_down) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -0700626 TEST_REQUIRES_X86_SSSE3;
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700627 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
628 zero_point <= std::numeric_limits<int8_t>::max();
629 zero_point++)
630 {
631 for (uint32_t s = 1; s < 32; s++) {
632 RequantizationTester()
633 .zero_point(zero_point)
634 .qmin(std::numeric_limits<int8_t>::min())
635 .qmax(std::numeric_limits<int8_t>::max())
636 .s(s)
Marat Dukhan06716242021-05-26 15:56:39 -0700637 .TestDivideByPO2WithRoundingDown(xnn_qs8_requantize_rndna__ssse3);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700638 }
639 }
640 }
641
Marat Dukhan06716242021-05-26 15:56:39 -0700642 TEST(QS8_RNDNA__SSSE3, divide_by_po2_with_rounding_away) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -0700643 TEST_REQUIRES_X86_SSSE3;
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700644 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
645 zero_point <= std::numeric_limits<int8_t>::max();
646 zero_point++)
647 {
648 for (uint32_t s = 1; s < 32; s++) {
649 RequantizationTester()
650 .zero_point(zero_point)
651 .qmin(std::numeric_limits<int8_t>::min())
652 .qmax(std::numeric_limits<int8_t>::max())
653 .s(s)
Marat Dukhan062bee32021-05-27 20:31:07 -0700654 .TestDivideByPO2WithRoundingTiesAway(xnn_qs8_requantize_rndna__ssse3);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700655 }
656 }
657 }
658
Marat Dukhan06716242021-05-26 15:56:39 -0700659 TEST(QS8_RNDNA__SSSE3, special_cases) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -0700660 TEST_REQUIRES_X86_SSSE3;
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700661 RequantizationTester()
662 .qmin(std::numeric_limits<int8_t>::min())
663 .qmax(std::numeric_limits<int8_t>::max())
Marat Dukhan06716242021-05-26 15:56:39 -0700664 .TestSpecialCases(xnn_qs8_requantize_rndna__ssse3);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700665 }
666
Marat Dukhan06716242021-05-26 15:56:39 -0700667 TEST(QS8_RNDNA__SSSE3, random_cases) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -0700668 TEST_REQUIRES_X86_SSSE3;
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700669 RequantizationTester()
670 .qmin(std::numeric_limits<int8_t>::min())
671 .qmax(std::numeric_limits<int8_t>::max())
672 .iterations(100)
Marat Dukhan06716242021-05-26 15:56:39 -0700673 .TestRandomCasesRoundToNearestTiesAway(xnn_qs8_requantize_rndna__ssse3);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700674 }
675
676
677 /*
Marat Dukhan06716242021-05-26 15:56:39 -0700678 * Round-to-nearest, ties away from zero, SSE4.1 implementation using static blend instruction.
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700679 */
680
Marat Dukhan06716242021-05-26 15:56:39 -0700681 TEST(QS8_RNDNA__SSE4, exact_divide_by_po2) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -0700682 TEST_REQUIRES_X86_SSE41;
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700683 for (uint32_t s = 1; s < 32; s++) {
684 RequantizationTester()
685 .qmin(std::numeric_limits<int8_t>::min())
686 .qmax(std::numeric_limits<int8_t>::max())
687 .s(s)
Marat Dukhan06716242021-05-26 15:56:39 -0700688 .TestExactDivideByPO2(xnn_qs8_requantize_rndna__sse4);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700689 }
690 }
691
Marat Dukhan06716242021-05-26 15:56:39 -0700692 TEST(QS8_RNDNA__SSE4, exact_divide_by_po2_with_zero_point) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -0700693 TEST_REQUIRES_X86_SSE41;
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700694 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
695 zero_point <= std::numeric_limits<int8_t>::max();
696 zero_point++)
697 {
698 for (uint32_t s = 1; s < 32; s++) {
699 RequantizationTester()
700 .zero_point(zero_point)
701 .qmin(std::numeric_limits<int8_t>::min())
702 .qmax(std::numeric_limits<int8_t>::max())
703 .s(s)
Marat Dukhan06716242021-05-26 15:56:39 -0700704 .TestExactDivideByPO2(xnn_qs8_requantize_rndna__sse4);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700705 }
706 }
707 }
708
Marat Dukhan06716242021-05-26 15:56:39 -0700709 TEST(QS8_RNDNA__SSE4, divide_by_po2_with_rounding_up) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -0700710 TEST_REQUIRES_X86_SSE41;
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700711 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
712 zero_point <= std::numeric_limits<int8_t>::max();
713 zero_point++)
714 {
715 for (uint32_t s = 1; s < 32; s++) {
716 RequantizationTester()
717 .zero_point(zero_point)
718 .qmin(std::numeric_limits<int8_t>::min())
719 .qmax(std::numeric_limits<int8_t>::max())
720 .s(s)
Marat Dukhan06716242021-05-26 15:56:39 -0700721 .TestDivideByPO2WithRoundingUp(xnn_qs8_requantize_rndna__sse4);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700722 }
723 }
724 }
725
Marat Dukhan06716242021-05-26 15:56:39 -0700726 TEST(QS8_RNDNA__SSE4, divide_by_po2_with_rounding_down) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -0700727 TEST_REQUIRES_X86_SSE41;
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700728 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
729 zero_point <= std::numeric_limits<int8_t>::max();
730 zero_point++)
731 {
732 for (uint32_t s = 1; s < 32; s++) {
733 RequantizationTester()
734 .zero_point(zero_point)
735 .qmin(std::numeric_limits<int8_t>::min())
736 .qmax(std::numeric_limits<int8_t>::max())
737 .s(s)
Marat Dukhan06716242021-05-26 15:56:39 -0700738 .TestDivideByPO2WithRoundingDown(xnn_qs8_requantize_rndna__sse4);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700739 }
740 }
741 }
742
Marat Dukhan06716242021-05-26 15:56:39 -0700743 TEST(QS8_RNDNA__SSE4, divide_by_po2_with_rounding_away) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -0700744 TEST_REQUIRES_X86_SSE41;
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700745 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
746 zero_point <= std::numeric_limits<int8_t>::max();
747 zero_point++)
748 {
749 for (uint32_t s = 1; s < 32; s++) {
750 RequantizationTester()
751 .zero_point(zero_point)
752 .qmin(std::numeric_limits<int8_t>::min())
753 .qmax(std::numeric_limits<int8_t>::max())
754 .s(s)
Marat Dukhan062bee32021-05-27 20:31:07 -0700755 .TestDivideByPO2WithRoundingTiesAway(xnn_qs8_requantize_rndna__sse4);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700756 }
757 }
758 }
759
Marat Dukhan06716242021-05-26 15:56:39 -0700760 TEST(QS8_RNDNA__SSE4, special_cases) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -0700761 TEST_REQUIRES_X86_SSE41;
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700762 RequantizationTester()
763 .qmin(std::numeric_limits<int8_t>::min())
764 .qmax(std::numeric_limits<int8_t>::max())
Marat Dukhan06716242021-05-26 15:56:39 -0700765 .TestSpecialCases(xnn_qs8_requantize_rndna__sse4);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700766 }
767
Marat Dukhan06716242021-05-26 15:56:39 -0700768 TEST(QS8_RNDNA__SSE4, random_cases) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -0700769 TEST_REQUIRES_X86_SSE41;
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700770 RequantizationTester()
771 .qmin(std::numeric_limits<int8_t>::min())
772 .qmax(std::numeric_limits<int8_t>::max())
773 .iterations(100)
Marat Dukhan06716242021-05-26 15:56:39 -0700774 .TestRandomCasesRoundToNearestTiesAway(xnn_qs8_requantize_rndna__sse4);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700775 }
776
777
778 /*
Marat Dukhan0d979d52021-06-09 13:21:18 -0700779 * Round-to-nearest, ties up, SSE4.1 implementation using arithmetic shift right.
Marat Dukhan062bee32021-05-27 20:31:07 -0700780 */
781
Marat Dukhan0d979d52021-06-09 13:21:18 -0700782 TEST(QS8_RNDNU__SSE4_SRA, exact_divide_by_po2) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -0700783 TEST_REQUIRES_X86_SSE41;
Marat Dukhan062bee32021-05-27 20:31:07 -0700784 for (uint32_t s = 1; s < 32; s++) {
785 RequantizationTester()
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
Marat Dukhan0d979d52021-06-09 13:21:18 -0700793 TEST(QS8_RNDNU__SSE4_SRA, exact_divide_by_po2_with_zero_point) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -0700794 TEST_REQUIRES_X86_SSE41;
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 .TestExactDivideByPO2(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_up) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -0700811 TEST_REQUIRES_X86_SSE41;
Marat Dukhan062bee32021-05-27 20:31:07 -0700812 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
813 zero_point <= std::numeric_limits<int8_t>::max();
814 zero_point++)
815 {
816 for (uint32_t s = 1; s < 32; s++) {
817 RequantizationTester()
818 .zero_point(zero_point)
819 .qmin(std::numeric_limits<int8_t>::min())
820 .qmax(std::numeric_limits<int8_t>::max())
821 .s(s)
Marat Dukhan0d979d52021-06-09 13:21:18 -0700822 .TestDivideByPO2WithRoundingUp(xnn_qs8_requantize_rndnu__sse4_sra);
Marat Dukhan062bee32021-05-27 20:31:07 -0700823 }
824 }
825 }
826
Marat Dukhan0d979d52021-06-09 13:21:18 -0700827 TEST(QS8_RNDNU__SSE4_SRA, divide_by_po2_with_rounding_down) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -0700828 TEST_REQUIRES_X86_SSE41;
Marat Dukhan062bee32021-05-27 20:31:07 -0700829 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
830 zero_point <= std::numeric_limits<int8_t>::max();
831 zero_point++)
832 {
833 for (uint32_t s = 1; s < 32; s++) {
834 RequantizationTester()
835 .zero_point(zero_point)
836 .qmin(std::numeric_limits<int8_t>::min())
837 .qmax(std::numeric_limits<int8_t>::max())
838 .s(s)
Marat Dukhan0d979d52021-06-09 13:21:18 -0700839 .TestDivideByPO2WithRoundingDown(xnn_qs8_requantize_rndnu__sse4_sra);
Marat Dukhan062bee32021-05-27 20:31:07 -0700840 }
841 }
842 }
843
Marat Dukhan0d979d52021-06-09 13:21:18 -0700844 TEST(QS8_RNDNU__SSE4_SRA, divide_by_po2_with_rounding_away) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -0700845 TEST_REQUIRES_X86_SSE41;
Marat Dukhan062bee32021-05-27 20:31:07 -0700846 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
847 zero_point <= std::numeric_limits<int8_t>::max();
848 zero_point++)
849 {
850 for (uint32_t s = 1; s < 32; s++) {
851 RequantizationTester()
852 .zero_point(zero_point)
853 .qmin(std::numeric_limits<int8_t>::min())
854 .qmax(std::numeric_limits<int8_t>::max())
855 .s(s)
Marat Dukhan0d979d52021-06-09 13:21:18 -0700856 .TestDivideByPO2WithRoundingTiesUp(xnn_qs8_requantize_rndnu__sse4_sra);
Marat Dukhan062bee32021-05-27 20:31:07 -0700857 }
858 }
859 }
860
Marat Dukhan0d979d52021-06-09 13:21:18 -0700861 TEST(QS8_RNDNU__SSE4_SRA, random_cases) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -0700862 TEST_REQUIRES_X86_SSE41;
Marat Dukhan062bee32021-05-27 20:31:07 -0700863 RequantizationTester()
864 .qmin(std::numeric_limits<int8_t>::min())
865 .qmax(std::numeric_limits<int8_t>::max())
866 .iterations(100)
Marat Dukhan0d979d52021-06-09 13:21:18 -0700867 .TestRandomCasesRoundToNearestTiesUp(xnn_qs8_requantize_rndnu__sse4_sra);
868 }
869
870
871 /*
872 * Round-to-nearest, ties up, SSE4.1 implementation using logical shift right.
873 */
874
875 TEST(QS8_RNDNU__SSE4_SRL, exact_divide_by_po2) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -0700876 TEST_REQUIRES_X86_SSE41;
Marat Dukhan0d979d52021-06-09 13:21:18 -0700877 for (uint32_t s = 1; s < 32; s++) {
878 RequantizationTester()
879 .qmin(std::numeric_limits<int8_t>::min())
880 .qmax(std::numeric_limits<int8_t>::max())
881 .s(s)
882 .TestExactDivideByPO2(xnn_qs8_requantize_rndnu__sse4_srl);
883 }
884 }
885
886 TEST(QS8_RNDNU__SSE4_SRL, exact_divide_by_po2_with_zero_point) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -0700887 TEST_REQUIRES_X86_SSE41;
Marat Dukhan0d979d52021-06-09 13:21:18 -0700888 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
889 zero_point <= std::numeric_limits<int8_t>::max();
890 zero_point++)
891 {
892 for (uint32_t s = 1; s < 32; s++) {
893 RequantizationTester()
894 .zero_point(zero_point)
895 .qmin(std::numeric_limits<int8_t>::min())
896 .qmax(std::numeric_limits<int8_t>::max())
897 .s(s)
898 .TestExactDivideByPO2(xnn_qs8_requantize_rndnu__sse4_srl);
899 }
900 }
901 }
902
903 TEST(QS8_RNDNU__SSE4_SRL, divide_by_po2_with_rounding_up) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -0700904 TEST_REQUIRES_X86_SSE41;
Marat Dukhan0d979d52021-06-09 13:21:18 -0700905 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
906 zero_point <= std::numeric_limits<int8_t>::max();
907 zero_point++)
908 {
909 for (uint32_t s = 1; s < 32; s++) {
910 RequantizationTester()
911 .zero_point(zero_point)
912 .qmin(std::numeric_limits<int8_t>::min())
913 .qmax(std::numeric_limits<int8_t>::max())
914 .s(s)
915 .TestDivideByPO2WithRoundingUp(xnn_qs8_requantize_rndnu__sse4_srl);
916 }
917 }
918 }
919
920 TEST(QS8_RNDNU__SSE4_SRL, divide_by_po2_with_rounding_down) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -0700921 TEST_REQUIRES_X86_SSE41;
Marat Dukhan0d979d52021-06-09 13:21:18 -0700922 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
923 zero_point <= std::numeric_limits<int8_t>::max();
924 zero_point++)
925 {
926 for (uint32_t s = 1; s < 32; s++) {
927 RequantizationTester()
928 .zero_point(zero_point)
929 .qmin(std::numeric_limits<int8_t>::min())
930 .qmax(std::numeric_limits<int8_t>::max())
931 .s(s)
932 .TestDivideByPO2WithRoundingDown(xnn_qs8_requantize_rndnu__sse4_srl);
933 }
934 }
935 }
936
937 TEST(QS8_RNDNU__SSE4_SRL, divide_by_po2_with_rounding_away) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -0700938 TEST_REQUIRES_X86_SSE41;
Marat Dukhan0d979d52021-06-09 13:21:18 -0700939 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
940 zero_point <= std::numeric_limits<int8_t>::max();
941 zero_point++)
942 {
943 for (uint32_t s = 1; s < 32; s++) {
944 RequantizationTester()
945 .zero_point(zero_point)
946 .qmin(std::numeric_limits<int8_t>::min())
947 .qmax(std::numeric_limits<int8_t>::max())
948 .s(s)
949 .TestDivideByPO2WithRoundingTiesUp(xnn_qs8_requantize_rndnu__sse4_srl);
950 }
951 }
952 }
953
954 TEST(QS8_RNDNU__SSE4_SRL, random_cases) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -0700955 TEST_REQUIRES_X86_SSE41;
Marat Dukhan0d979d52021-06-09 13:21:18 -0700956 RequantizationTester()
957 .qmin(std::numeric_limits<int8_t>::min())
958 .qmax(std::numeric_limits<int8_t>::max())
959 .iterations(100)
960 .TestRandomCasesRoundToNearestTiesUp(xnn_qs8_requantize_rndnu__sse4_srl);
Marat Dukhan062bee32021-05-27 20:31:07 -0700961 }
962
963
964 /*
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700965 * FP32-based x86 SSE2 implementation.
966 */
967
968 TEST(QS8_FP32__SSE2, random_cases) {
969 RequantizationTester()
970 .qmin(std::numeric_limits<int8_t>::min())
971 .qmax(std::numeric_limits<int8_t>::max())
972 .iterations(1000)
973 .TestRandomCasesApproximate(xnn_qs8_requantize_fp32__sse2);
974 }
975
976
977 /*
978 * FP32-based x86 SSE4 implementation.
979 */
980
981 TEST(QS8_FP32__SSE4, random_cases) {
982 RequantizationTester()
983 .qmin(std::numeric_limits<int8_t>::min())
984 .qmax(std::numeric_limits<int8_t>::max())
985 .iterations(1000)
986 .TestRandomCasesApproximate(xnn_qs8_requantize_fp32__sse4);
987 }
988
989
990 /*
Marat Dukhan9976cd82021-05-24 23:15:45 -0700991 * GEMMLOWP-equivalent x86 SSE2 implementation.
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700992 */
993
Marat Dukhan9976cd82021-05-24 23:15:45 -0700994 TEST(QS8_GEMMLOWP__SSE2, exact_divide_by_po2) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -0700995 for (uint32_t s = 1; s < 32; s++) {
996 RequantizationTester()
997 .qmin(std::numeric_limits<int8_t>::min())
998 .qmax(std::numeric_limits<int8_t>::max())
999 .s(s)
Marat Dukhan9976cd82021-05-24 23:15:45 -07001000 .TestExactDivideByPO2(xnn_qs8_requantize_gemmlowp__sse2);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001001 }
1002 }
1003
Marat Dukhan9976cd82021-05-24 23:15:45 -07001004 TEST(QS8_GEMMLOWP__SSE2, exact_divide_by_po2_with_zero_point) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001005 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
1006 zero_point <= std::numeric_limits<int8_t>::max();
1007 zero_point++)
1008 {
1009 for (uint32_t s = 1; s < 32; s++) {
1010 RequantizationTester()
1011 .zero_point(zero_point)
1012 .qmin(std::numeric_limits<int8_t>::min())
1013 .qmax(std::numeric_limits<int8_t>::max())
1014 .s(s)
Marat Dukhan9976cd82021-05-24 23:15:45 -07001015 .TestExactDivideByPO2(xnn_qs8_requantize_gemmlowp__sse2);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001016 }
1017 }
1018 }
1019
Marat Dukhan9976cd82021-05-24 23:15:45 -07001020 TEST(QS8_GEMMLOWP__SSE2, divide_by_po2_with_rounding_up) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001021 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
1022 zero_point <= std::numeric_limits<int8_t>::max();
1023 zero_point++)
1024 {
1025 for (uint32_t s = 1; s < 32; s++) {
1026 RequantizationTester()
1027 .zero_point(zero_point)
1028 .qmin(std::numeric_limits<int8_t>::min())
1029 .qmax(std::numeric_limits<int8_t>::max())
1030 .s(s)
Marat Dukhan9976cd82021-05-24 23:15:45 -07001031 .TestDivideByPO2WithRoundingUp(xnn_qs8_requantize_gemmlowp__sse2);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001032 }
1033 }
1034 }
1035
1036 /* No rounding down test - it fails because of upward bias in multiplication */
1037 /* No rounding away test - it fails because of upward bias in multiplication */
1038
Marat Dukhan9976cd82021-05-24 23:15:45 -07001039 TEST(QS8_GEMMLOWP__SSE2, special_cases) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001040 RequantizationTester()
1041 .qmin(std::numeric_limits<int8_t>::min())
1042 .qmax(std::numeric_limits<int8_t>::max())
Marat Dukhan9976cd82021-05-24 23:15:45 -07001043 .TestSpecialCases(xnn_qs8_requantize_gemmlowp__sse2);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001044 }
1045
Marat Dukhan9976cd82021-05-24 23:15:45 -07001046 TEST(QS8_GEMMLOWP__SSE2, random_cases) {
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001047 RequantizationTester()
1048 .qmin(std::numeric_limits<int8_t>::min())
1049 .qmax(std::numeric_limits<int8_t>::max())
1050 .iterations(100)
Marat Dukhan9976cd82021-05-24 23:15:45 -07001051 .TestRandomCasesApproximate(xnn_qs8_requantize_gemmlowp__sse2);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001052 }
1053
1054
1055 /*
Marat Dukhan9976cd82021-05-24 23:15:45 -07001056 * GEMMLOWP-equivalent x86 SSSE3 implementation.
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001057 */
1058
Marat Dukhan9976cd82021-05-24 23:15:45 -07001059 TEST(QS8_GEMMLOWP__SSSE3, exact_divide_by_po2) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -07001060 TEST_REQUIRES_X86_SSSE3;
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001061 for (uint32_t s = 1; s < 32; s++) {
1062 RequantizationTester()
1063 .qmin(std::numeric_limits<int8_t>::min())
1064 .qmax(std::numeric_limits<int8_t>::max())
1065 .s(s)
Marat Dukhan9976cd82021-05-24 23:15:45 -07001066 .TestExactDivideByPO2(xnn_qs8_requantize_gemmlowp__ssse3);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001067 }
1068 }
1069
Marat Dukhan9976cd82021-05-24 23:15:45 -07001070 TEST(QS8_GEMMLOWP__SSSE3, exact_divide_by_po2_with_zero_point) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -07001071 TEST_REQUIRES_X86_SSSE3;
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001072 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
1073 zero_point <= std::numeric_limits<int8_t>::max();
1074 zero_point++)
1075 {
1076 for (uint32_t s = 1; s < 32; s++) {
1077 RequantizationTester()
1078 .zero_point(zero_point)
1079 .qmin(std::numeric_limits<int8_t>::min())
1080 .qmax(std::numeric_limits<int8_t>::max())
1081 .s(s)
Marat Dukhan9976cd82021-05-24 23:15:45 -07001082 .TestExactDivideByPO2(xnn_qs8_requantize_gemmlowp__ssse3);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001083 }
1084 }
1085 }
1086
Marat Dukhan9976cd82021-05-24 23:15:45 -07001087 TEST(QS8_GEMMLOWP__SSSE3, divide_by_po2_with_rounding_up) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -07001088 TEST_REQUIRES_X86_SSSE3;
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001089 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
1090 zero_point <= std::numeric_limits<int8_t>::max();
1091 zero_point++)
1092 {
1093 for (uint32_t s = 1; s < 32; s++) {
1094 RequantizationTester()
1095 .zero_point(zero_point)
1096 .qmin(std::numeric_limits<int8_t>::min())
1097 .qmax(std::numeric_limits<int8_t>::max())
1098 .s(s)
Marat Dukhan9976cd82021-05-24 23:15:45 -07001099 .TestDivideByPO2WithRoundingUp(xnn_qs8_requantize_gemmlowp__ssse3);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001100 }
1101 }
1102 }
1103
1104 /* No rounding down test - it fails because of upward bias in multiplication */
1105 /* No rounding away test - it fails because of upward bias in multiplication */
1106
Marat Dukhan9976cd82021-05-24 23:15:45 -07001107 TEST(QS8_GEMMLOWP__SSSE3, special_cases) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -07001108 TEST_REQUIRES_X86_SSSE3;
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001109 RequantizationTester()
1110 .qmin(std::numeric_limits<int8_t>::min())
1111 .qmax(std::numeric_limits<int8_t>::max())
Marat Dukhan9976cd82021-05-24 23:15:45 -07001112 .TestSpecialCases(xnn_qs8_requantize_gemmlowp__ssse3);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001113 }
1114
Marat Dukhan9976cd82021-05-24 23:15:45 -07001115 TEST(QS8_GEMMLOWP__SSSE3, random_cases) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -07001116 TEST_REQUIRES_X86_SSSE3;
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001117 RequantizationTester()
1118 .qmin(std::numeric_limits<int8_t>::min())
1119 .qmax(std::numeric_limits<int8_t>::max())
1120 .iterations(100)
Marat Dukhan9976cd82021-05-24 23:15:45 -07001121 .TestRandomCasesApproximate(xnn_qs8_requantize_gemmlowp__ssse3);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001122 }
1123
1124
1125 /*
Marat Dukhan9976cd82021-05-24 23:15:45 -07001126 * GEMMLOWP-equivalent x86 SSE4 implementation.
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001127 */
1128
Marat Dukhan9976cd82021-05-24 23:15:45 -07001129 TEST(QS8_GEMMLOWP__SSE4, exact_divide_by_po2) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -07001130 TEST_REQUIRES_X86_SSE41;
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001131 for (uint32_t s = 1; s < 32; s++) {
1132 RequantizationTester()
1133 .qmin(std::numeric_limits<int8_t>::min())
1134 .qmax(std::numeric_limits<int8_t>::max())
1135 .s(s)
Marat Dukhan9976cd82021-05-24 23:15:45 -07001136 .TestExactDivideByPO2(xnn_qs8_requantize_gemmlowp__sse4);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001137 }
1138 }
1139
Marat Dukhan9976cd82021-05-24 23:15:45 -07001140 TEST(QS8_GEMMLOWP__SSE4, exact_divide_by_po2_with_zero_point) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -07001141 TEST_REQUIRES_X86_SSE41;
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001142 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
1143 zero_point <= std::numeric_limits<int8_t>::max();
1144 zero_point++)
1145 {
1146 for (uint32_t s = 1; s < 32; s++) {
1147 RequantizationTester()
1148 .zero_point(zero_point)
1149 .qmin(std::numeric_limits<int8_t>::min())
1150 .qmax(std::numeric_limits<int8_t>::max())
1151 .s(s)
Marat Dukhan9976cd82021-05-24 23:15:45 -07001152 .TestExactDivideByPO2(xnn_qs8_requantize_gemmlowp__sse4);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001153 }
1154 }
1155 }
1156
Marat Dukhan9976cd82021-05-24 23:15:45 -07001157 TEST(QS8_GEMMLOWP__SSE4, divide_by_po2_with_rounding_up) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -07001158 TEST_REQUIRES_X86_SSE41;
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001159 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
1160 zero_point <= std::numeric_limits<int8_t>::max();
1161 zero_point++)
1162 {
1163 for (uint32_t s = 1; s < 32; s++) {
1164 RequantizationTester()
1165 .zero_point(zero_point)
1166 .qmin(std::numeric_limits<int8_t>::min())
1167 .qmax(std::numeric_limits<int8_t>::max())
1168 .s(s)
Marat Dukhan9976cd82021-05-24 23:15:45 -07001169 .TestDivideByPO2WithRoundingUp(xnn_qs8_requantize_gemmlowp__sse4);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001170 }
1171 }
1172 }
1173
1174 /* No rounding down test - it fails because of upward bias in multiplication */
1175 /* No rounding away test - it fails because of upward bias in multiplication */
1176
Marat Dukhan9976cd82021-05-24 23:15:45 -07001177 TEST(QS8_GEMMLOWP__SSE4, special_cases) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -07001178 TEST_REQUIRES_X86_SSE41;
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001179 RequantizationTester()
1180 .qmin(std::numeric_limits<int8_t>::min())
1181 .qmax(std::numeric_limits<int8_t>::max())
Marat Dukhan9976cd82021-05-24 23:15:45 -07001182 .TestSpecialCases(xnn_qs8_requantize_gemmlowp__sse4);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001183 }
1184
Marat Dukhan9976cd82021-05-24 23:15:45 -07001185 TEST(QS8_GEMMLOWP__SSE4, random_cases) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -07001186 TEST_REQUIRES_X86_SSE41;
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001187 RequantizationTester()
1188 .qmin(std::numeric_limits<int8_t>::min())
1189 .qmax(std::numeric_limits<int8_t>::max())
1190 .iterations(100)
Marat Dukhan9976cd82021-05-24 23:15:45 -07001191 .TestRandomCasesApproximate(xnn_qs8_requantize_gemmlowp__sse4);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001192 }
1193#endif // XNN_ARCH_X86 || XNN_ARCH_X86_64
1194
1195#if XNN_ARCH_ARM || XNN_ARCH_ARM64
1196 /*
Marat Dukhan06716242021-05-26 15:56:39 -07001197 * Round-to-nearest, ties away from zero, ARM NEON implementation.
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001198 */
1199
Marat Dukhan06716242021-05-26 15:56:39 -07001200 TEST(QS8_RNDNA__NEON, exact_divide_by_po2) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -07001201 TEST_REQUIRES_ARM_NEON;
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001202 for (uint32_t s = 1; s < 32; s++) {
1203 RequantizationTester()
1204 .s(s)
1205 .qmin(std::numeric_limits<int8_t>::min())
1206 .qmax(std::numeric_limits<int8_t>::max())
Marat Dukhan06716242021-05-26 15:56:39 -07001207 .TestExactDivideByPO2(xnn_qs8_requantize_rndna__neon);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001208 }
1209 }
1210
Marat Dukhan06716242021-05-26 15:56:39 -07001211 TEST(QS8_RNDNA__NEON, exact_divide_by_po2_with_zero_point) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -07001212 TEST_REQUIRES_ARM_NEON;
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001213 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
1214 zero_point <= std::numeric_limits<int8_t>::max();
1215 zero_point++)
1216 {
1217 for (uint32_t s = 1; s < 32; s++) {
1218 RequantizationTester()
1219 .zero_point(zero_point)
1220 .qmin(std::numeric_limits<int8_t>::min())
1221 .qmax(std::numeric_limits<int8_t>::max())
1222 .s(s)
Marat Dukhan06716242021-05-26 15:56:39 -07001223 .TestExactDivideByPO2(xnn_qs8_requantize_rndna__neon);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001224 }
1225 }
1226 }
1227
Marat Dukhan06716242021-05-26 15:56:39 -07001228 TEST(QS8_RNDNA__NEON, divide_by_po2_with_rounding_up) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -07001229 TEST_REQUIRES_ARM_NEON;
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001230 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
1231 zero_point <= std::numeric_limits<int8_t>::max();
1232 zero_point++)
1233 {
1234 for (uint32_t s = 1; s < 32; s++) {
1235 RequantizationTester()
1236 .zero_point(zero_point)
1237 .qmin(std::numeric_limits<int8_t>::min())
1238 .qmax(std::numeric_limits<int8_t>::max())
1239 .s(s)
Marat Dukhan06716242021-05-26 15:56:39 -07001240 .TestDivideByPO2WithRoundingUp(xnn_qs8_requantize_rndna__neon);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001241 }
1242 }
1243 }
1244
Marat Dukhan06716242021-05-26 15:56:39 -07001245 TEST(QS8_RNDNA__NEON, divide_by_po2_with_rounding_down) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -07001246 TEST_REQUIRES_ARM_NEON;
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001247 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
1248 zero_point <= std::numeric_limits<int8_t>::max();
1249 zero_point++)
1250 {
1251 for (uint32_t s = 1; s < 32; s++) {
1252 RequantizationTester()
1253 .zero_point(zero_point)
1254 .qmin(std::numeric_limits<int8_t>::min())
1255 .qmax(std::numeric_limits<int8_t>::max())
1256 .s(s)
Marat Dukhan06716242021-05-26 15:56:39 -07001257 .TestDivideByPO2WithRoundingDown(xnn_qs8_requantize_rndna__neon);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001258 }
1259 }
1260 }
1261
Marat Dukhan06716242021-05-26 15:56:39 -07001262 TEST(QS8_RNDNA__NEON, divide_by_po2_with_rounding_away) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -07001263 TEST_REQUIRES_ARM_NEON;
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001264 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
1265 zero_point <= std::numeric_limits<int8_t>::max();
1266 zero_point++)
1267 {
1268 for (uint32_t s = 1; s < 32; s++) {
1269 RequantizationTester()
1270 .zero_point(zero_point)
1271 .qmin(std::numeric_limits<int8_t>::min())
1272 .qmax(std::numeric_limits<int8_t>::max())
1273 .s(s)
Marat Dukhan062bee32021-05-27 20:31:07 -07001274 .TestDivideByPO2WithRoundingTiesAway(xnn_qs8_requantize_rndna__neon);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001275 }
1276 }
1277 }
1278
Marat Dukhan06716242021-05-26 15:56:39 -07001279 TEST(QS8_RNDNA__NEON, special_cases) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -07001280 TEST_REQUIRES_ARM_NEON;
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001281 RequantizationTester()
1282 .qmin(std::numeric_limits<int8_t>::min())
1283 .qmax(std::numeric_limits<int8_t>::max())
Marat Dukhan06716242021-05-26 15:56:39 -07001284 .TestSpecialCases(xnn_qs8_requantize_rndna__neon);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001285 }
1286
Marat Dukhan06716242021-05-26 15:56:39 -07001287 TEST(QS8_RNDNA__NEON, random_cases) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -07001288 TEST_REQUIRES_ARM_NEON;
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001289 RequantizationTester()
1290 .qmin(std::numeric_limits<int8_t>::min())
1291 .qmax(std::numeric_limits<int8_t>::max())
1292 .iterations(100)
Marat Dukhan06716242021-05-26 15:56:39 -07001293 .TestRandomCasesRoundToNearestTiesAway(xnn_qs8_requantize_rndna__neon);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001294 }
1295
1296
1297 /*
Marat Dukhand3d818c2021-07-16 17:56:54 -07001298 * Round-to-nearest, ties up, ARM NEON implementation using extended multiplication.
Marat Dukhan062bee32021-05-27 20:31:07 -07001299 */
1300
Marat Dukhand3d818c2021-07-16 17:56:54 -07001301 TEST(QS8_RNDNU__NEON_MULL, exact_divide_by_po2) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -07001302 TEST_REQUIRES_ARM_NEON;
Marat Dukhan062bee32021-05-27 20:31:07 -07001303 for (uint32_t s = 1; s < 32; s++) {
1304 RequantizationTester()
1305 .qmin(std::numeric_limits<int8_t>::min())
1306 .qmax(std::numeric_limits<int8_t>::max())
1307 .s(s)
Marat Dukhand3d818c2021-07-16 17:56:54 -07001308 .TestExactDivideByPO2(xnn_qs8_requantize_rndnu__neon_mull);
Marat Dukhan062bee32021-05-27 20:31:07 -07001309 }
1310 }
1311
Marat Dukhand3d818c2021-07-16 17:56:54 -07001312 TEST(QS8_RNDNU__NEON_MULL, exact_divide_by_po2_with_zero_point) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -07001313 TEST_REQUIRES_ARM_NEON;
Marat Dukhan062bee32021-05-27 20:31:07 -07001314 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
1315 zero_point <= std::numeric_limits<int8_t>::max();
1316 zero_point++)
1317 {
1318 for (uint32_t s = 1; s < 32; s++) {
1319 RequantizationTester()
1320 .zero_point(zero_point)
1321 .qmin(std::numeric_limits<int8_t>::min())
1322 .qmax(std::numeric_limits<int8_t>::max())
1323 .s(s)
Marat Dukhand3d818c2021-07-16 17:56:54 -07001324 .TestExactDivideByPO2(xnn_qs8_requantize_rndnu__neon_mull);
Marat Dukhan062bee32021-05-27 20:31:07 -07001325 }
1326 }
1327 }
1328
Marat Dukhand3d818c2021-07-16 17:56:54 -07001329 TEST(QS8_RNDNU__NEON_MULL, divide_by_po2_with_rounding_up) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -07001330 TEST_REQUIRES_ARM_NEON;
Marat Dukhan062bee32021-05-27 20:31:07 -07001331 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
1332 zero_point <= std::numeric_limits<int8_t>::max();
1333 zero_point++)
1334 {
1335 for (uint32_t s = 1; s < 32; s++) {
1336 RequantizationTester()
1337 .zero_point(zero_point)
1338 .qmin(std::numeric_limits<int8_t>::min())
1339 .qmax(std::numeric_limits<int8_t>::max())
1340 .s(s)
Marat Dukhand3d818c2021-07-16 17:56:54 -07001341 .TestDivideByPO2WithRoundingUp(xnn_qs8_requantize_rndnu__neon_mull);
Marat Dukhan062bee32021-05-27 20:31:07 -07001342 }
1343 }
1344 }
1345
Marat Dukhand3d818c2021-07-16 17:56:54 -07001346 TEST(QS8_RNDNU__NEON_MULL, divide_by_po2_with_rounding_down) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -07001347 TEST_REQUIRES_ARM_NEON;
Marat Dukhan062bee32021-05-27 20:31:07 -07001348 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
1349 zero_point <= std::numeric_limits<int8_t>::max();
1350 zero_point++)
1351 {
1352 for (uint32_t s = 1; s < 32; s++) {
1353 RequantizationTester()
1354 .zero_point(zero_point)
1355 .qmin(std::numeric_limits<int8_t>::min())
1356 .qmax(std::numeric_limits<int8_t>::max())
1357 .s(s)
Marat Dukhand3d818c2021-07-16 17:56:54 -07001358 .TestDivideByPO2WithRoundingDown(xnn_qs8_requantize_rndnu__neon_mull);
Marat Dukhan062bee32021-05-27 20:31:07 -07001359 }
1360 }
1361 }
1362
Marat Dukhand3d818c2021-07-16 17:56:54 -07001363 TEST(QS8_RNDNU__NEON_MULL, divide_by_po2_with_rounding_away) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -07001364 TEST_REQUIRES_ARM_NEON;
Marat Dukhan062bee32021-05-27 20:31:07 -07001365 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
1366 zero_point <= std::numeric_limits<int8_t>::max();
1367 zero_point++)
1368 {
1369 for (uint32_t s = 1; s < 32; s++) {
1370 RequantizationTester()
1371 .zero_point(zero_point)
1372 .qmin(std::numeric_limits<int8_t>::min())
1373 .qmax(std::numeric_limits<int8_t>::max())
1374 .s(s)
Marat Dukhand3d818c2021-07-16 17:56:54 -07001375 .TestDivideByPO2WithRoundingTiesUp(xnn_qs8_requantize_rndnu__neon_mull);
Marat Dukhan062bee32021-05-27 20:31:07 -07001376 }
1377 }
1378 }
1379
Marat Dukhand3d818c2021-07-16 17:56:54 -07001380 TEST(QS8_RNDNU__NEON_MULL, random_cases) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -07001381 TEST_REQUIRES_ARM_NEON;
Marat Dukhan062bee32021-05-27 20:31:07 -07001382 RequantizationTester()
1383 .qmin(std::numeric_limits<int8_t>::min())
1384 .qmax(std::numeric_limits<int8_t>::max())
1385 .iterations(100)
Marat Dukhand3d818c2021-07-16 17:56:54 -07001386 .TestRandomCasesRoundToNearestTiesUp(xnn_qs8_requantize_rndnu__neon_mull);
1387 }
1388
1389
1390 /*
1391 * Round-to-nearest, ties up, ARM NEON implementation using Q31 multiplication.
1392 */
1393
1394 TEST(QS8_RNDNU__NEON_QDMULH, exact_divide_by_po2) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -07001395 TEST_REQUIRES_ARM_NEON;
Marat Dukhand3d818c2021-07-16 17:56:54 -07001396 for (uint32_t s = 1; s < 32; s++) {
1397 RequantizationTester()
1398 .qmin(std::numeric_limits<int8_t>::min())
1399 .qmax(std::numeric_limits<int8_t>::max())
1400 .s(s)
1401 .TestExactDivideByPO2(xnn_qs8_requantize_rndnu__neon_qdmulh);
1402 }
1403 }
1404
1405 TEST(QS8_RNDNU__NEON_QDMULH, exact_divide_by_po2_with_zero_point) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -07001406 TEST_REQUIRES_ARM_NEON;
Marat Dukhand3d818c2021-07-16 17:56:54 -07001407 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
1408 zero_point <= std::numeric_limits<int8_t>::max();
1409 zero_point++)
1410 {
1411 for (uint32_t s = 1; s < 32; s++) {
1412 RequantizationTester()
1413 .zero_point(zero_point)
1414 .qmin(std::numeric_limits<int8_t>::min())
1415 .qmax(std::numeric_limits<int8_t>::max())
1416 .s(s)
1417 .TestExactDivideByPO2(xnn_qs8_requantize_rndnu__neon_qdmulh);
1418 }
1419 }
1420 }
1421
1422 TEST(QS8_RNDNU__NEON_QDMULH, divide_by_po2_with_rounding_up) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -07001423 TEST_REQUIRES_ARM_NEON;
Marat Dukhand3d818c2021-07-16 17:56:54 -07001424 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
1425 zero_point <= std::numeric_limits<int8_t>::max();
1426 zero_point++)
1427 {
1428 for (uint32_t s = 1; s < 32; s++) {
1429 RequantizationTester()
1430 .zero_point(zero_point)
1431 .qmin(std::numeric_limits<int8_t>::min())
1432 .qmax(std::numeric_limits<int8_t>::max())
1433 .s(s)
1434 .TestDivideByPO2WithRoundingUp(xnn_qs8_requantize_rndnu__neon_qdmulh);
1435 }
1436 }
1437 }
1438
1439 TEST(QS8_RNDNU__NEON_QDMULH, divide_by_po2_with_rounding_down) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -07001440 TEST_REQUIRES_ARM_NEON;
Marat Dukhand3d818c2021-07-16 17:56:54 -07001441 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
1442 zero_point <= std::numeric_limits<int8_t>::max();
1443 zero_point++)
1444 {
1445 for (uint32_t s = 1; s < 32; s++) {
1446 RequantizationTester()
1447 .zero_point(zero_point)
1448 .qmin(std::numeric_limits<int8_t>::min())
1449 .qmax(std::numeric_limits<int8_t>::max())
1450 .s(s)
1451 .TestDivideByPO2WithRoundingDown(xnn_qs8_requantize_rndnu__neon_qdmulh);
1452 }
1453 }
1454 }
1455
1456 TEST(QS8_RNDNU__NEON_QDMULH, divide_by_po2_with_rounding_away) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -07001457 TEST_REQUIRES_ARM_NEON;
Marat Dukhand3d818c2021-07-16 17:56:54 -07001458 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
1459 zero_point <= std::numeric_limits<int8_t>::max();
1460 zero_point++)
1461 {
1462 for (uint32_t s = 1; s < 32; s++) {
1463 RequantizationTester()
1464 .zero_point(zero_point)
1465 .qmin(std::numeric_limits<int8_t>::min())
1466 .qmax(std::numeric_limits<int8_t>::max())
1467 .s(s)
1468 .TestDivideByPO2WithRoundingTiesUp(xnn_qs8_requantize_rndnu__neon_qdmulh);
1469 }
1470 }
1471 }
1472
1473 TEST(QS8_RNDNU__NEON_QDMULH, random_cases) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -07001474 TEST_REQUIRES_ARM_NEON;
Marat Dukhand3d818c2021-07-16 17:56:54 -07001475 RequantizationTester()
1476 .qmin(std::numeric_limits<int8_t>::min())
1477 .qmax(std::numeric_limits<int8_t>::max())
1478 .iterations(100)
1479 .TestRandomCasesRoundToNearestTiesUp(xnn_qs8_requantize_rndnu__neon_qdmulh);
Marat Dukhan062bee32021-05-27 20:31:07 -07001480 }
1481
1482
1483 /*
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001484 * FP32-based ARM NEON implementation.
1485 */
1486
1487 TEST(QS8_FP32__NEON, random_cases) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -07001488 TEST_REQUIRES_ARM_NEON;
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001489 RequantizationTester()
1490 .qmin(std::numeric_limits<int8_t>::min())
1491 .qmax(std::numeric_limits<int8_t>::max())
1492 .iterations(1000)
1493 .TestRandomCasesApproximate(xnn_qs8_requantize_fp32__neon);
1494 }
1495
1496
1497 /*
Marat Dukhan9976cd82021-05-24 23:15:45 -07001498 * GEMMLOWP-equivalent ARM NEON implementation.
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001499 */
1500
Marat Dukhan9976cd82021-05-24 23:15:45 -07001501 TEST(QS8_GEMMLOWP__NEON, exact_divide_by_po2) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -07001502 TEST_REQUIRES_ARM_NEON;
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001503 for (uint32_t s = 1; s < 32; s++) {
1504 RequantizationTester()
1505 .qmin(std::numeric_limits<int8_t>::min())
1506 .qmax(std::numeric_limits<int8_t>::max())
1507 .s(s)
Marat Dukhan9976cd82021-05-24 23:15:45 -07001508 .TestExactDivideByPO2(xnn_qs8_requantize_gemmlowp__neon);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001509 }
1510 }
1511
Marat Dukhan9976cd82021-05-24 23:15:45 -07001512 TEST(QS8_GEMMLOWP__NEON, exact_divide_by_po2_with_zero_point) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -07001513 TEST_REQUIRES_ARM_NEON;
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001514 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
1515 zero_point <= std::numeric_limits<int8_t>::max();
1516 zero_point++)
1517 {
1518 for (uint32_t s = 1; s < 32; s++) {
1519 RequantizationTester()
1520 .zero_point(zero_point)
1521 .qmin(std::numeric_limits<int8_t>::min())
1522 .qmax(std::numeric_limits<int8_t>::max())
1523 .s(s)
Marat Dukhan9976cd82021-05-24 23:15:45 -07001524 .TestExactDivideByPO2(xnn_qs8_requantize_gemmlowp__neon);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001525 }
1526 }
1527 }
1528
Marat Dukhan9976cd82021-05-24 23:15:45 -07001529 TEST(QS8_GEMMLOWP__NEON, divide_by_po2_with_rounding_up) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -07001530 TEST_REQUIRES_ARM_NEON;
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001531 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
1532 zero_point <= std::numeric_limits<int8_t>::max();
1533 zero_point++)
1534 {
1535 for (uint32_t s = 1; s < 32; s++) {
1536 RequantizationTester()
1537 .zero_point(zero_point)
1538 .qmin(std::numeric_limits<int8_t>::min())
1539 .qmax(std::numeric_limits<int8_t>::max())
1540 .s(s)
Marat Dukhan9976cd82021-05-24 23:15:45 -07001541 .TestDivideByPO2WithRoundingUp(xnn_qs8_requantize_gemmlowp__neon);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001542 }
1543 }
1544 }
1545
1546 /* No rounding down test - it fails because of upward bias in multiplication */
1547 /* No rounding away test - it fails because of upward bias in multiplication */
1548
Marat Dukhan9976cd82021-05-24 23:15:45 -07001549 TEST(QS8_GEMMLOWP__NEON, special_cases) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -07001550 TEST_REQUIRES_ARM_NEON;
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001551 RequantizationTester()
1552 .qmin(std::numeric_limits<int8_t>::min())
1553 .qmax(std::numeric_limits<int8_t>::max())
Marat Dukhan9976cd82021-05-24 23:15:45 -07001554 .TestSpecialCases(xnn_qs8_requantize_gemmlowp__neon);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001555 }
1556
Marat Dukhan9976cd82021-05-24 23:15:45 -07001557 TEST(QS8_GEMMLOWP__NEON, random_cases) {
Marat Dukhan348ed6d2021-08-06 01:19:04 -07001558 TEST_REQUIRES_ARM_NEON;
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001559 RequantizationTester()
1560 .qmin(std::numeric_limits<int8_t>::min())
1561 .qmax(std::numeric_limits<int8_t>::max())
1562 .iterations(100)
Marat Dukhan9976cd82021-05-24 23:15:45 -07001563 .TestRandomCasesApproximate(xnn_qs8_requantize_gemmlowp__neon);
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001564 }
1565#endif // XNN_ARCH_ARM || XNN_ARCH_ARM64
1566
1567#if XNN_ARCH_WASMSIMD
1568 /*
Marat Dukhan138560c2020-08-03 18:57:34 -07001569 * FP32-based WAsm SIMD implementation.
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001570 */
1571
1572 TEST(QS8_FP32__WASMSIMD, random_cases) {
1573 RequantizationTester()
1574 .qmin(std::numeric_limits<int8_t>::min())
1575 .qmax(std::numeric_limits<int8_t>::max())
1576 .iterations(1000)
1577 .TestRandomCasesApproximate(xnn_qs8_requantize_fp32__wasmsimd);
1578 }
Marat Dukhan138560c2020-08-03 18:57:34 -07001579
1580 /*
Marat Dukhan9976cd82021-05-24 23:15:45 -07001581 * GEMMLOWP-equivalent WAsm SIMD implementation.
Marat Dukhan138560c2020-08-03 18:57:34 -07001582 */
1583
Marat Dukhan9976cd82021-05-24 23:15:45 -07001584 TEST(QS8_GEMMLOWP__WASMSIMD, exact_divide_by_po2) {
Marat Dukhan138560c2020-08-03 18:57:34 -07001585 for (uint32_t s = 1; s < 32; s++) {
1586 RequantizationTester()
1587 .qmin(std::numeric_limits<int8_t>::min())
1588 .qmax(std::numeric_limits<int8_t>::max())
1589 .s(s)
Marat Dukhan9976cd82021-05-24 23:15:45 -07001590 .TestExactDivideByPO2(xnn_qs8_requantize_gemmlowp__wasmsimd);
Marat Dukhan138560c2020-08-03 18:57:34 -07001591 }
1592 }
1593
Marat Dukhan9976cd82021-05-24 23:15:45 -07001594 TEST(QS8_GEMMLOWP__WASMSIMD, exact_divide_by_po2_with_zero_point) {
Marat Dukhan138560c2020-08-03 18:57:34 -07001595 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
1596 zero_point <= std::numeric_limits<int8_t>::max();
1597 zero_point++)
1598 {
1599 for (uint32_t s = 1; s < 32; s++) {
1600 RequantizationTester()
1601 .zero_point(zero_point)
1602 .qmin(std::numeric_limits<int8_t>::min())
1603 .qmax(std::numeric_limits<int8_t>::max())
1604 .s(s)
Marat Dukhan9976cd82021-05-24 23:15:45 -07001605 .TestExactDivideByPO2(xnn_qs8_requantize_gemmlowp__wasmsimd);
Marat Dukhan138560c2020-08-03 18:57:34 -07001606 }
1607 }
1608 }
1609
Marat Dukhan9976cd82021-05-24 23:15:45 -07001610 TEST(QS8_GEMMLOWP__WASMSIMD, divide_by_po2_with_rounding_up) {
Marat Dukhan138560c2020-08-03 18:57:34 -07001611 for (int32_t zero_point = std::numeric_limits<int8_t>::min();
1612 zero_point <= std::numeric_limits<int8_t>::max();
1613 zero_point++)
1614 {
1615 for (uint32_t s = 1; s < 32; s++) {
1616 RequantizationTester()
1617 .zero_point(zero_point)
1618 .qmin(std::numeric_limits<int8_t>::min())
1619 .qmax(std::numeric_limits<int8_t>::max())
1620 .s(s)
Marat Dukhan9976cd82021-05-24 23:15:45 -07001621 .TestDivideByPO2WithRoundingUp(xnn_qs8_requantize_gemmlowp__wasmsimd);
Marat Dukhan138560c2020-08-03 18:57:34 -07001622 }
1623 }
1624 }
1625
1626 /* No rounding down test - it fails because of upward bias in multiplication */
1627 /* No rounding away test - it fails because of upward bias in multiplication */
1628
Marat Dukhan9976cd82021-05-24 23:15:45 -07001629 TEST(QS8_GEMMLOWP__WASMSIMD, special_cases) {
Marat Dukhan138560c2020-08-03 18:57:34 -07001630 RequantizationTester()
1631 .qmin(std::numeric_limits<int8_t>::min())
1632 .qmax(std::numeric_limits<int8_t>::max())
Marat Dukhan9976cd82021-05-24 23:15:45 -07001633 .TestSpecialCases(xnn_qs8_requantize_gemmlowp__wasmsimd);
Marat Dukhan138560c2020-08-03 18:57:34 -07001634 }
1635
Marat Dukhan9976cd82021-05-24 23:15:45 -07001636 TEST(QS8_GEMMLOWP__WASMSIMD, random_cases) {
Marat Dukhan138560c2020-08-03 18:57:34 -07001637 RequantizationTester()
1638 .qmin(std::numeric_limits<int8_t>::min())
1639 .qmax(std::numeric_limits<int8_t>::max())
1640 .iterations(100)
Marat Dukhan9976cd82021-05-24 23:15:45 -07001641 .TestRandomCasesApproximate(xnn_qs8_requantize_gemmlowp__wasmsimd);
Marat Dukhan138560c2020-08-03 18:57:34 -07001642 }
Marat Dukhan2e23d2b2020-07-29 16:01:37 -07001643#endif // XNN_ARCH_WASMSIMD