1*4bdc9457SAndroid Build Coastguard Worker // Copyright (c) Facebook, Inc. and its affiliates. 2*4bdc9457SAndroid Build Coastguard Worker // All rights reserved. 3*4bdc9457SAndroid Build Coastguard Worker // 4*4bdc9457SAndroid Build Coastguard Worker // Copyright 2019 Google LLC 5*4bdc9457SAndroid Build Coastguard Worker // 6*4bdc9457SAndroid Build Coastguard Worker // This source code is licensed under the BSD-style license found in the 7*4bdc9457SAndroid Build Coastguard Worker // LICENSE file in the root directory of this source tree. 8*4bdc9457SAndroid Build Coastguard Worker 9*4bdc9457SAndroid Build Coastguard Worker #pragma once 10*4bdc9457SAndroid Build Coastguard Worker 11*4bdc9457SAndroid Build Coastguard Worker #include <gtest/gtest.h> 12*4bdc9457SAndroid Build Coastguard Worker 13*4bdc9457SAndroid Build Coastguard Worker #include <algorithm> 14*4bdc9457SAndroid Build Coastguard Worker #include <cassert> 15*4bdc9457SAndroid Build Coastguard Worker #include <cstddef> 16*4bdc9457SAndroid Build Coastguard Worker #include <cstdlib> 17*4bdc9457SAndroid Build Coastguard Worker #include <functional> 18*4bdc9457SAndroid Build Coastguard Worker #include <limits> 19*4bdc9457SAndroid Build Coastguard Worker #include <random> 20*4bdc9457SAndroid Build Coastguard Worker #include <vector> 21*4bdc9457SAndroid Build Coastguard Worker 22*4bdc9457SAndroid Build Coastguard Worker #include <xnnpack.h> 23*4bdc9457SAndroid Build Coastguard Worker #include <xnnpack/microfnptr.h> 24*4bdc9457SAndroid Build Coastguard Worker #include <xnnpack/microparams-init.h> 25*4bdc9457SAndroid Build Coastguard Worker #include <xnnpack/requantization.h> 26*4bdc9457SAndroid Build Coastguard Worker 27*4bdc9457SAndroid Build Coastguard Worker 28*4bdc9457SAndroid Build Coastguard Worker class VAddMicrokernelTester { 29*4bdc9457SAndroid Build Coastguard Worker public: batch_size(size_t batch_size)30*4bdc9457SAndroid Build Coastguard Worker inline VAddMicrokernelTester& batch_size(size_t batch_size) { 31*4bdc9457SAndroid Build Coastguard Worker assert(batch_size != 0); 32*4bdc9457SAndroid Build Coastguard Worker this->batch_size_ = batch_size; 33*4bdc9457SAndroid Build Coastguard Worker return *this; 34*4bdc9457SAndroid Build Coastguard Worker } 35*4bdc9457SAndroid Build Coastguard Worker batch_size()36*4bdc9457SAndroid Build Coastguard Worker inline size_t batch_size() const { 37*4bdc9457SAndroid Build Coastguard Worker return this->batch_size_; 38*4bdc9457SAndroid Build Coastguard Worker } 39*4bdc9457SAndroid Build Coastguard Worker inplace_a(bool inplace_a)40*4bdc9457SAndroid Build Coastguard Worker inline VAddMicrokernelTester& inplace_a(bool inplace_a) { 41*4bdc9457SAndroid Build Coastguard Worker this->inplace_a_ = inplace_a; 42*4bdc9457SAndroid Build Coastguard Worker return *this; 43*4bdc9457SAndroid Build Coastguard Worker } 44*4bdc9457SAndroid Build Coastguard Worker inplace_a()45*4bdc9457SAndroid Build Coastguard Worker inline bool inplace_a() const { 46*4bdc9457SAndroid Build Coastguard Worker return this->inplace_a_; 47*4bdc9457SAndroid Build Coastguard Worker } 48*4bdc9457SAndroid Build Coastguard Worker inplace_b(bool inplace_b)49*4bdc9457SAndroid Build Coastguard Worker inline VAddMicrokernelTester& inplace_b(bool inplace_b) { 50*4bdc9457SAndroid Build Coastguard Worker this->inplace_b_ = inplace_b; 51*4bdc9457SAndroid Build Coastguard Worker return *this; 52*4bdc9457SAndroid Build Coastguard Worker } 53*4bdc9457SAndroid Build Coastguard Worker inplace_b()54*4bdc9457SAndroid Build Coastguard Worker inline bool inplace_b() const { 55*4bdc9457SAndroid Build Coastguard Worker return this->inplace_b_; 56*4bdc9457SAndroid Build Coastguard Worker } 57*4bdc9457SAndroid Build Coastguard Worker a_scale(float a_scale)58*4bdc9457SAndroid Build Coastguard Worker inline VAddMicrokernelTester& a_scale(float a_scale) { 59*4bdc9457SAndroid Build Coastguard Worker assert(a_scale > 0.0f); 60*4bdc9457SAndroid Build Coastguard Worker assert(std::isnormal(a_scale)); 61*4bdc9457SAndroid Build Coastguard Worker this->a_scale_ = a_scale; 62*4bdc9457SAndroid Build Coastguard Worker return *this; 63*4bdc9457SAndroid Build Coastguard Worker } 64*4bdc9457SAndroid Build Coastguard Worker a_scale()65*4bdc9457SAndroid Build Coastguard Worker inline float a_scale() const { 66*4bdc9457SAndroid Build Coastguard Worker return this->a_scale_; 67*4bdc9457SAndroid Build Coastguard Worker } 68*4bdc9457SAndroid Build Coastguard Worker a_zero_point(uint8_t a_zero_point)69*4bdc9457SAndroid Build Coastguard Worker inline VAddMicrokernelTester& a_zero_point(uint8_t a_zero_point) { 70*4bdc9457SAndroid Build Coastguard Worker this->a_zero_point_ = a_zero_point; 71*4bdc9457SAndroid Build Coastguard Worker return *this; 72*4bdc9457SAndroid Build Coastguard Worker } 73*4bdc9457SAndroid Build Coastguard Worker a_zero_point()74*4bdc9457SAndroid Build Coastguard Worker inline uint8_t a_zero_point() const { 75*4bdc9457SAndroid Build Coastguard Worker return this->a_zero_point_; 76*4bdc9457SAndroid Build Coastguard Worker } 77*4bdc9457SAndroid Build Coastguard Worker b_scale(float b_scale)78*4bdc9457SAndroid Build Coastguard Worker inline VAddMicrokernelTester& b_scale(float b_scale) { 79*4bdc9457SAndroid Build Coastguard Worker assert(b_scale > 0.0f); 80*4bdc9457SAndroid Build Coastguard Worker assert(std::isnormal(b_scale)); 81*4bdc9457SAndroid Build Coastguard Worker this->b_scale_ = b_scale; 82*4bdc9457SAndroid Build Coastguard Worker return *this; 83*4bdc9457SAndroid Build Coastguard Worker } 84*4bdc9457SAndroid Build Coastguard Worker b_scale()85*4bdc9457SAndroid Build Coastguard Worker inline float b_scale() const { 86*4bdc9457SAndroid Build Coastguard Worker return this->b_scale_; 87*4bdc9457SAndroid Build Coastguard Worker } 88*4bdc9457SAndroid Build Coastguard Worker b_zero_point(uint8_t b_zero_point)89*4bdc9457SAndroid Build Coastguard Worker inline VAddMicrokernelTester& b_zero_point(uint8_t b_zero_point) { 90*4bdc9457SAndroid Build Coastguard Worker this->b_zero_point_ = b_zero_point; 91*4bdc9457SAndroid Build Coastguard Worker return *this; 92*4bdc9457SAndroid Build Coastguard Worker } 93*4bdc9457SAndroid Build Coastguard Worker b_zero_point()94*4bdc9457SAndroid Build Coastguard Worker inline uint8_t b_zero_point() const { 95*4bdc9457SAndroid Build Coastguard Worker return this->b_zero_point_; 96*4bdc9457SAndroid Build Coastguard Worker } 97*4bdc9457SAndroid Build Coastguard Worker y_scale(float y_scale)98*4bdc9457SAndroid Build Coastguard Worker inline VAddMicrokernelTester& y_scale(float y_scale) { 99*4bdc9457SAndroid Build Coastguard Worker assert(y_scale > 0.0f); 100*4bdc9457SAndroid Build Coastguard Worker assert(std::isnormal(y_scale)); 101*4bdc9457SAndroid Build Coastguard Worker this->y_scale_ = y_scale; 102*4bdc9457SAndroid Build Coastguard Worker return *this; 103*4bdc9457SAndroid Build Coastguard Worker } 104*4bdc9457SAndroid Build Coastguard Worker y_scale()105*4bdc9457SAndroid Build Coastguard Worker inline float y_scale() const { 106*4bdc9457SAndroid Build Coastguard Worker return this->y_scale_; 107*4bdc9457SAndroid Build Coastguard Worker } 108*4bdc9457SAndroid Build Coastguard Worker y_zero_point(uint8_t y_zero_point)109*4bdc9457SAndroid Build Coastguard Worker inline VAddMicrokernelTester& y_zero_point(uint8_t y_zero_point) { 110*4bdc9457SAndroid Build Coastguard Worker this->y_zero_point_ = y_zero_point; 111*4bdc9457SAndroid Build Coastguard Worker return *this; 112*4bdc9457SAndroid Build Coastguard Worker } 113*4bdc9457SAndroid Build Coastguard Worker y_zero_point()114*4bdc9457SAndroid Build Coastguard Worker inline uint8_t y_zero_point() const { 115*4bdc9457SAndroid Build Coastguard Worker return this->y_zero_point_; 116*4bdc9457SAndroid Build Coastguard Worker } 117*4bdc9457SAndroid Build Coastguard Worker qmin(uint8_t qmin)118*4bdc9457SAndroid Build Coastguard Worker inline VAddMicrokernelTester& qmin(uint8_t qmin) { 119*4bdc9457SAndroid Build Coastguard Worker this->qmin_ = qmin; 120*4bdc9457SAndroid Build Coastguard Worker return *this; 121*4bdc9457SAndroid Build Coastguard Worker } 122*4bdc9457SAndroid Build Coastguard Worker qmin()123*4bdc9457SAndroid Build Coastguard Worker inline uint8_t qmin() const { 124*4bdc9457SAndroid Build Coastguard Worker return this->qmin_; 125*4bdc9457SAndroid Build Coastguard Worker } 126*4bdc9457SAndroid Build Coastguard Worker qmax(uint8_t qmax)127*4bdc9457SAndroid Build Coastguard Worker inline VAddMicrokernelTester& qmax(uint8_t qmax) { 128*4bdc9457SAndroid Build Coastguard Worker this->qmax_ = qmax; 129*4bdc9457SAndroid Build Coastguard Worker return *this; 130*4bdc9457SAndroid Build Coastguard Worker } 131*4bdc9457SAndroid Build Coastguard Worker qmax()132*4bdc9457SAndroid Build Coastguard Worker inline uint8_t qmax() const { 133*4bdc9457SAndroid Build Coastguard Worker return this->qmax_; 134*4bdc9457SAndroid Build Coastguard Worker } 135*4bdc9457SAndroid Build Coastguard Worker iterations(size_t iterations)136*4bdc9457SAndroid Build Coastguard Worker inline VAddMicrokernelTester& iterations(size_t iterations) { 137*4bdc9457SAndroid Build Coastguard Worker this->iterations_ = iterations; 138*4bdc9457SAndroid Build Coastguard Worker return *this; 139*4bdc9457SAndroid Build Coastguard Worker } 140*4bdc9457SAndroid Build Coastguard Worker iterations()141*4bdc9457SAndroid Build Coastguard Worker inline size_t iterations() const { 142*4bdc9457SAndroid Build Coastguard Worker return this->iterations_; 143*4bdc9457SAndroid Build Coastguard Worker } 144*4bdc9457SAndroid Build Coastguard Worker Test(xnn_qu8_vadd_minmax_ukernel_function vadd_minmax,xnn_init_qu8_add_minmax_params_fn init_params)145*4bdc9457SAndroid Build Coastguard Worker void Test(xnn_qu8_vadd_minmax_ukernel_function vadd_minmax, xnn_init_qu8_add_minmax_params_fn init_params) const { 146*4bdc9457SAndroid Build Coastguard Worker std::random_device random_device; 147*4bdc9457SAndroid Build Coastguard Worker auto rng = std::mt19937(random_device()); 148*4bdc9457SAndroid Build Coastguard Worker auto u8rng = std::bind(std::uniform_int_distribution<uint32_t>(0, std::numeric_limits<uint8_t>::max()), rng); 149*4bdc9457SAndroid Build Coastguard Worker 150*4bdc9457SAndroid Build Coastguard Worker std::vector<uint8_t> a(batch_size() + XNN_EXTRA_BYTES / sizeof(uint8_t)); 151*4bdc9457SAndroid Build Coastguard Worker std::vector<uint8_t> b(batch_size() + XNN_EXTRA_BYTES / sizeof(uint8_t)); 152*4bdc9457SAndroid Build Coastguard Worker std::vector<uint8_t> y(batch_size() + (inplace_a() || inplace_b() ? XNN_EXTRA_BYTES / sizeof(uint8_t) : 0)); 153*4bdc9457SAndroid Build Coastguard Worker std::vector<float> y_fp(batch_size()); 154*4bdc9457SAndroid Build Coastguard Worker std::vector<uint8_t> y_ref(batch_size()); 155*4bdc9457SAndroid Build Coastguard Worker for (size_t iteration = 0; iteration < iterations(); iteration++) { 156*4bdc9457SAndroid Build Coastguard Worker std::generate(a.begin(), a.end(), std::ref(u8rng)); 157*4bdc9457SAndroid Build Coastguard Worker std::generate(b.begin(), b.end(), std::ref(u8rng)); 158*4bdc9457SAndroid Build Coastguard Worker if (inplace_a() || inplace_b()) { 159*4bdc9457SAndroid Build Coastguard Worker std::generate(y.begin(), y.end(), std::ref(u8rng)); 160*4bdc9457SAndroid Build Coastguard Worker } else { 161*4bdc9457SAndroid Build Coastguard Worker std::fill(y.begin(), y.end(), 0xA5); 162*4bdc9457SAndroid Build Coastguard Worker } 163*4bdc9457SAndroid Build Coastguard Worker const uint8_t* a_data = inplace_a() ? y.data() : a.data(); 164*4bdc9457SAndroid Build Coastguard Worker const uint8_t* b_data = inplace_b() ? y.data() : b.data(); 165*4bdc9457SAndroid Build Coastguard Worker 166*4bdc9457SAndroid Build Coastguard Worker // Prepare parameters. 167*4bdc9457SAndroid Build Coastguard Worker xnn_qu8_add_minmax_params quantization_params; 168*4bdc9457SAndroid Build Coastguard Worker init_params( 169*4bdc9457SAndroid Build Coastguard Worker &quantization_params, 170*4bdc9457SAndroid Build Coastguard Worker a_zero_point(), b_zero_point(), y_zero_point(), 171*4bdc9457SAndroid Build Coastguard Worker a_scale() / y_scale(), b_scale() / y_scale(), 172*4bdc9457SAndroid Build Coastguard Worker qmin(), qmax()); 173*4bdc9457SAndroid Build Coastguard Worker xnn_qu8_add_minmax_params scalar_quantization_params; 174*4bdc9457SAndroid Build Coastguard Worker xnn_init_qu8_add_minmax_scalar_params( 175*4bdc9457SAndroid Build Coastguard Worker &scalar_quantization_params, 176*4bdc9457SAndroid Build Coastguard Worker a_zero_point(), b_zero_point(), y_zero_point(), 177*4bdc9457SAndroid Build Coastguard Worker a_scale() / y_scale(), b_scale() / y_scale(), 178*4bdc9457SAndroid Build Coastguard Worker qmin(), qmax()); 179*4bdc9457SAndroid Build Coastguard Worker 180*4bdc9457SAndroid Build Coastguard Worker // Compute reference results. 181*4bdc9457SAndroid Build Coastguard Worker for (size_t i = 0; i < batch_size(); i++) { 182*4bdc9457SAndroid Build Coastguard Worker y_fp[i] = float(y_zero_point()) + 183*4bdc9457SAndroid Build Coastguard Worker float(int32_t(a_data[i]) - int32_t(a_zero_point())) * (a_scale() / y_scale()) + 184*4bdc9457SAndroid Build Coastguard Worker float(int32_t(b_data[i]) - int32_t(b_zero_point())) * (b_scale() / y_scale()); 185*4bdc9457SAndroid Build Coastguard Worker y_fp[i] = std::min<float>(y_fp[i], float(qmax())); 186*4bdc9457SAndroid Build Coastguard Worker y_fp[i] = std::max<float>(y_fp[i], float(qmin())); 187*4bdc9457SAndroid Build Coastguard Worker y_ref[i] = xnn_qu8_quantize_add(a_data[i], b_data[i], scalar_quantization_params); 188*4bdc9457SAndroid Build Coastguard Worker } 189*4bdc9457SAndroid Build Coastguard Worker 190*4bdc9457SAndroid Build Coastguard Worker // Call optimized micro-kernel. 191*4bdc9457SAndroid Build Coastguard Worker vadd_minmax(batch_size(), a_data, b_data, y.data(), &quantization_params); 192*4bdc9457SAndroid Build Coastguard Worker 193*4bdc9457SAndroid Build Coastguard Worker // Verify results. 194*4bdc9457SAndroid Build Coastguard Worker for (size_t i = 0; i < batch_size(); i++) { 195*4bdc9457SAndroid Build Coastguard Worker ASSERT_LE(uint32_t(y[i]), uint32_t(qmax())) 196*4bdc9457SAndroid Build Coastguard Worker << "at element " << i << " / " << batch_size(); 197*4bdc9457SAndroid Build Coastguard Worker ASSERT_GE(uint32_t(y[i]), uint32_t(qmin())) 198*4bdc9457SAndroid Build Coastguard Worker << "at element " << i << " / " << batch_size(); 199*4bdc9457SAndroid Build Coastguard Worker ASSERT_NEAR(float(int32_t(y[i])), y_fp[i], 0.6f) 200*4bdc9457SAndroid Build Coastguard Worker << "at element " << i << " / " << batch_size(); 201*4bdc9457SAndroid Build Coastguard Worker ASSERT_EQ(uint32_t(y_ref[i]), uint32_t(y[i])) 202*4bdc9457SAndroid Build Coastguard Worker << "at element " << i << " / " << batch_size(); 203*4bdc9457SAndroid Build Coastguard Worker } 204*4bdc9457SAndroid Build Coastguard Worker } 205*4bdc9457SAndroid Build Coastguard Worker } 206*4bdc9457SAndroid Build Coastguard Worker Test(xnn_qs8_vadd_minmax_ukernel_function vadd_minmax,xnn_init_qs8_add_minmax_params_fn init_params)207*4bdc9457SAndroid Build Coastguard Worker void Test(xnn_qs8_vadd_minmax_ukernel_function vadd_minmax, xnn_init_qs8_add_minmax_params_fn init_params) const { 208*4bdc9457SAndroid Build Coastguard Worker std::random_device random_device; 209*4bdc9457SAndroid Build Coastguard Worker auto rng = std::mt19937(random_device()); 210*4bdc9457SAndroid Build Coastguard Worker auto i8rng = std::bind( 211*4bdc9457SAndroid Build Coastguard Worker std::uniform_int_distribution<int32_t>(std::numeric_limits<int8_t>::min(), std::numeric_limits<int8_t>::max()), rng); 212*4bdc9457SAndroid Build Coastguard Worker 213*4bdc9457SAndroid Build Coastguard Worker std::vector<int8_t> a(batch_size() + XNN_EXTRA_BYTES / sizeof(int8_t)); 214*4bdc9457SAndroid Build Coastguard Worker std::vector<int8_t> b(batch_size() + XNN_EXTRA_BYTES / sizeof(int8_t)); 215*4bdc9457SAndroid Build Coastguard Worker std::vector<int8_t> y(batch_size() + (inplace_a() || inplace_b() ? XNN_EXTRA_BYTES / sizeof(int8_t) : 0)); 216*4bdc9457SAndroid Build Coastguard Worker std::vector<float> y_fp(batch_size()); 217*4bdc9457SAndroid Build Coastguard Worker std::vector<int8_t> y_ref(batch_size()); 218*4bdc9457SAndroid Build Coastguard Worker for (size_t iteration = 0; iteration < iterations(); iteration++) { 219*4bdc9457SAndroid Build Coastguard Worker std::generate(a.begin(), a.end(), std::ref(i8rng)); 220*4bdc9457SAndroid Build Coastguard Worker std::generate(b.begin(), b.end(), std::ref(i8rng)); 221*4bdc9457SAndroid Build Coastguard Worker if (inplace_a() || inplace_b()) { 222*4bdc9457SAndroid Build Coastguard Worker std::generate(y.begin(), y.end(), std::ref(i8rng)); 223*4bdc9457SAndroid Build Coastguard Worker } else { 224*4bdc9457SAndroid Build Coastguard Worker std::fill(y.begin(), y.end(), 0xA5); 225*4bdc9457SAndroid Build Coastguard Worker } 226*4bdc9457SAndroid Build Coastguard Worker const int8_t* a_data = inplace_a() ? y.data() : a.data(); 227*4bdc9457SAndroid Build Coastguard Worker const int8_t* b_data = inplace_b() ? y.data() : b.data(); 228*4bdc9457SAndroid Build Coastguard Worker 229*4bdc9457SAndroid Build Coastguard Worker // Prepare parameters. 230*4bdc9457SAndroid Build Coastguard Worker xnn_qs8_add_minmax_params quantization_params; 231*4bdc9457SAndroid Build Coastguard Worker init_params( 232*4bdc9457SAndroid Build Coastguard Worker &quantization_params, 233*4bdc9457SAndroid Build Coastguard Worker int8_t(a_zero_point() - 0x80), int8_t(b_zero_point() - 0x80), int8_t(y_zero_point() - 0x80), 234*4bdc9457SAndroid Build Coastguard Worker a_scale() / y_scale(), b_scale() / y_scale(), 235*4bdc9457SAndroid Build Coastguard Worker int8_t(qmin() - 0x80), int8_t(qmax() - 0x80)); 236*4bdc9457SAndroid Build Coastguard Worker xnn_qs8_add_minmax_params scalar_quantization_params; 237*4bdc9457SAndroid Build Coastguard Worker xnn_init_qs8_add_minmax_scalar_params( 238*4bdc9457SAndroid Build Coastguard Worker &scalar_quantization_params, 239*4bdc9457SAndroid Build Coastguard Worker int8_t(a_zero_point() - 0x80), int8_t(b_zero_point() - 0x80), int8_t(y_zero_point() - 0x80), 240*4bdc9457SAndroid Build Coastguard Worker a_scale() / y_scale(), b_scale() / y_scale(), 241*4bdc9457SAndroid Build Coastguard Worker int8_t(qmin() - 0x80), int8_t(qmax() - 0x80)); 242*4bdc9457SAndroid Build Coastguard Worker 243*4bdc9457SAndroid Build Coastguard Worker // Compute reference results. 244*4bdc9457SAndroid Build Coastguard Worker for (size_t i = 0; i < batch_size(); i++) { 245*4bdc9457SAndroid Build Coastguard Worker y_fp[i] = float(int32_t(y_zero_point() - 0x80)) + 246*4bdc9457SAndroid Build Coastguard Worker float(int32_t(a_data[i]) - int32_t(a_zero_point() - 0x80)) * (a_scale() / y_scale()) + 247*4bdc9457SAndroid Build Coastguard Worker float(int32_t(b_data[i]) - int32_t(b_zero_point() - 0x80)) * (b_scale() / y_scale()); 248*4bdc9457SAndroid Build Coastguard Worker y_fp[i] = std::min<float>(y_fp[i], float(int32_t(qmax() - 0x80))); 249*4bdc9457SAndroid Build Coastguard Worker y_fp[i] = std::max<float>(y_fp[i], float(int32_t(qmin() - 0x80))); 250*4bdc9457SAndroid Build Coastguard Worker y_ref[i] = xnn_qs8_quantize_add(a_data[i], b_data[i], scalar_quantization_params); 251*4bdc9457SAndroid Build Coastguard Worker } 252*4bdc9457SAndroid Build Coastguard Worker 253*4bdc9457SAndroid Build Coastguard Worker // Call optimized micro-kernel. 254*4bdc9457SAndroid Build Coastguard Worker vadd_minmax(batch_size(), a_data, b_data, y.data(), &quantization_params); 255*4bdc9457SAndroid Build Coastguard Worker 256*4bdc9457SAndroid Build Coastguard Worker // Verify results. 257*4bdc9457SAndroid Build Coastguard Worker for (size_t i = 0; i < batch_size(); i++) { 258*4bdc9457SAndroid Build Coastguard Worker ASSERT_LE(int32_t(y[i]), int32_t(qmax() - 0x80)) 259*4bdc9457SAndroid Build Coastguard Worker << "at element " << i << " / " << batch_size(); 260*4bdc9457SAndroid Build Coastguard Worker ASSERT_GE(int32_t(y[i]), int32_t(qmin() - 0x80)) 261*4bdc9457SAndroid Build Coastguard Worker << "at element " << i << " / " << batch_size(); 262*4bdc9457SAndroid Build Coastguard Worker ASSERT_EQ(int32_t(y_ref[i]), int32_t(y[i])) 263*4bdc9457SAndroid Build Coastguard Worker << "at element " << i << " / " << batch_size(); 264*4bdc9457SAndroid Build Coastguard Worker ASSERT_NEAR(float(int32_t(y[i])), y_fp[i], 0.6f) 265*4bdc9457SAndroid Build Coastguard Worker << "at element " << i << " / " << batch_size(); 266*4bdc9457SAndroid Build Coastguard Worker } 267*4bdc9457SAndroid Build Coastguard Worker } 268*4bdc9457SAndroid Build Coastguard Worker } 269*4bdc9457SAndroid Build Coastguard Worker 270*4bdc9457SAndroid Build Coastguard Worker private: 271*4bdc9457SAndroid Build Coastguard Worker size_t batch_size_{1}; 272*4bdc9457SAndroid Build Coastguard Worker bool inplace_a_{false}; 273*4bdc9457SAndroid Build Coastguard Worker bool inplace_b_{false}; 274*4bdc9457SAndroid Build Coastguard Worker float a_scale_{0.75f}; 275*4bdc9457SAndroid Build Coastguard Worker float b_scale_{1.25f}; 276*4bdc9457SAndroid Build Coastguard Worker float y_scale_{0.96875f}; 277*4bdc9457SAndroid Build Coastguard Worker uint8_t a_zero_point_{121}; 278*4bdc9457SAndroid Build Coastguard Worker uint8_t b_zero_point_{127}; 279*4bdc9457SAndroid Build Coastguard Worker uint8_t y_zero_point_{133}; 280*4bdc9457SAndroid Build Coastguard Worker uint8_t qmin_{0}; 281*4bdc9457SAndroid Build Coastguard Worker uint8_t qmax_{255}; 282*4bdc9457SAndroid Build Coastguard Worker size_t iterations_{15}; 283*4bdc9457SAndroid Build Coastguard Worker }; 284