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