1 // Copyright 2022 Google LLC 2 // 3 // This source code is licensed under the BSD-style license found in the 4 // LICENSE file in the root directory of this source tree. 5 6 #pragma once 7 8 #include <gtest/gtest.h> 9 10 #include <algorithm> 11 #include <cassert> 12 #include <cmath> 13 #include <cstddef> 14 #include <cstdlib> 15 #include <random> 16 #include <vector> 17 18 #include <xnnpack.h> 19 #include <xnnpack/microfnptr.h> 20 21 22 class VLShiftMicrokernelTester { 23 public: batch(size_t batch)24 inline VLShiftMicrokernelTester& batch(size_t batch) { 25 assert(batch != 0); 26 this->batch_ = batch; 27 return *this; 28 } 29 batch()30 inline size_t batch() const { 31 return this->batch_; 32 } 33 shift(uint32_t shift)34 inline VLShiftMicrokernelTester& shift(uint32_t shift) { 35 assert(shift < 32); 36 this->shift_ = shift; 37 return *this; 38 } 39 shift()40 inline uint32_t shift() const { 41 return this->shift_; 42 } 43 inplace(bool inplace)44 inline VLShiftMicrokernelTester& inplace(bool inplace) { 45 this->inplace_ = inplace; 46 return *this; 47 } 48 inplace()49 inline bool inplace() const { 50 return this->inplace_; 51 } 52 iterations(size_t iterations)53 inline VLShiftMicrokernelTester& iterations(size_t iterations) { 54 this->iterations_ = iterations; 55 return *this; 56 } 57 iterations()58 inline size_t iterations() const { 59 return this->iterations_; 60 } 61 Test(xnn_s16_vlshift_ukernel_function vlshift)62 void Test(xnn_s16_vlshift_ukernel_function vlshift) const { 63 std::random_device random_device; 64 auto rng = std::mt19937(random_device()); 65 auto i16rng = std::bind(std::uniform_int_distribution<int16_t>(), std::ref(rng)); 66 67 std::vector<int16_t> x(batch() + XNN_EXTRA_BYTES / sizeof(int16_t)); 68 std::vector<int16_t> y(batch() + (inplace() ? XNN_EXTRA_BYTES / sizeof(int16_t) : 0)); 69 std::vector<int16_t> y_ref(batch()); 70 const int16_t* x_data = inplace() ? y.data() : x.data(); 71 72 for (size_t iteration = 0; iteration < iterations(); iteration++) { 73 std::generate(x.begin(), x.end(), std::ref(i16rng)); 74 std::generate(y.begin(), y.end(), std::ref(i16rng)); 75 std::generate(y_ref.begin(), y_ref.end(), std::ref(i16rng)); 76 77 // Compute reference results. 78 for (size_t n = 0; n < batch(); n++) { 79 const uint16_t i = static_cast<uint16_t>(x_data[n]); 80 uint16_t value = i << shift(); 81 y_ref[n] = reinterpret_cast<uint16_t>(value); 82 } 83 84 // Call optimized micro-kernel. 85 vlshift(batch(), x_data, y.data(), shift()); 86 87 // Verify results. 88 for (size_t n = 0; n < batch(); n++) { 89 ASSERT_EQ(y[n], y_ref[n]) 90 << ", shift " << shift() 91 << ", batch " << n << " / " << batch(); 92 } 93 } 94 } 95 96 private: 97 size_t batch_{1}; 98 uint32_t shift_{12}; 99 bool inplace_{false}; 100 size_t iterations_{15}; 101 }; 102