xref: /aosp_15_r20/external/XNNPACK/test/vlshift-microkernel-tester.h (revision 4bdc94577ba0e567308109d787f7fec7b531ce36)
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