• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) Facebook, Inc. and its affiliates.
2 // All rights reserved.
3 //
4 // Copyright 2019 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 #pragma once
10 
11 #include <gtest/gtest.h>
12 
13 #include <cstddef>
14 #include <cstdlib>
15 
16 #include <algorithm>
17 #include <cfloat>
18 #include <cmath>
19 #include <functional>
20 #include <limits>
21 #include <random>
22 #include <vector>
23 
24 #include <xnnpack/params.h>
25 
26 
27 class ZipMicrokernelTester {
28  public:
n(size_t n)29   inline ZipMicrokernelTester& n(size_t n) {
30     assert(n != 0);
31     this->n_ = n;
32     return *this;
33   }
34 
n()35   inline size_t n() const {
36     return this->n_;
37   }
38 
g(size_t g)39   inline ZipMicrokernelTester& g(size_t g) {
40     assert(g != 0);
41     this->g_ = g;
42     return *this;
43   }
44 
g()45   inline size_t g() const {
46     return this->g_;
47   }
48 
iterations(size_t iterations)49   inline ZipMicrokernelTester& iterations(size_t iterations) {
50     this->iterations_ = iterations;
51     return *this;
52   }
53 
iterations()54   inline size_t iterations() const {
55     return this->iterations_;
56   }
57 
Test(xnn_x8_zipc_ukernel_function zip)58   void Test(xnn_x8_zipc_ukernel_function zip) const {
59     std::random_device random_device;
60     auto rng = std::mt19937(random_device());
61     auto u8rng = std::bind(std::uniform_int_distribution<uint32_t>(0, std::numeric_limits<uint8_t>::max()), rng);
62 
63     std::vector<uint8_t> x(n() * g());
64     std::vector<uint8_t> y(g() * n());
65 
66     for (size_t iteration = 0; iteration < iterations(); iteration++) {
67       std::generate(x.begin(), x.end(), std::ref(u8rng));
68       std::fill(y.begin(), y.end(), 0xA5);
69 
70       // Call optimized micro-kernel.
71       zip(n() * sizeof(uint8_t), x.data(), y.data());
72 
73       // Verify results.
74       for (size_t i = 0; i < n(); i++) {
75         for (size_t j = 0; j < g(); j++) {
76           ASSERT_EQ(uint32_t(y[i * g() + j]), uint32_t(x[j * n() + i]))
77             << "at element " << i << ", group " << j;
78         }
79       }
80     }
81   }
82 
Test(xnn_x8_zipv_ukernel_function zip)83   void Test(xnn_x8_zipv_ukernel_function zip) const {
84     std::random_device random_device;
85     auto rng = std::mt19937(random_device());
86     auto u8rng = std::bind(std::uniform_int_distribution<uint32_t>(0, std::numeric_limits<uint8_t>::max()), rng);
87 
88     std::vector<uint8_t> x(n() * g());
89     std::vector<uint8_t> y(g() * n());
90 
91     for (size_t iteration = 0; iteration < iterations(); iteration++) {
92       std::generate(x.begin(), x.end(), std::ref(u8rng));
93       std::fill(y.begin(), y.end(), 0xA5);
94 
95       // Call optimized micro-kernel.
96       zip(n() * sizeof(uint8_t), g(), x.data(), y.data());
97 
98       // Verify results.
99       for (size_t i = 0; i < n(); i++) {
100         for (size_t j = 0; j < g(); j++) {
101           ASSERT_EQ(uint32_t(y[i * g() + j]), uint32_t(x[j * n() + i]))
102             << "at element " << i << ", group " << j;
103         }
104       }
105     }
106   }
107 
Test(xnn_x32_zipc_ukernel_function zip)108   void Test(xnn_x32_zipc_ukernel_function zip) const {
109     std::random_device random_device;
110     auto rng = std::mt19937(random_device());
111     auto u32rng = std::bind(std::uniform_int_distribution<uint32_t>(), rng);
112 
113     std::vector<uint32_t> x(n() * g());
114     std::vector<uint32_t> y(g() * n());
115 
116     for (size_t iteration = 0; iteration < iterations(); iteration++) {
117       std::generate(x.begin(), x.end(), std::ref(u32rng));
118       std::fill(y.begin(), y.end(), 0xA55A5AA5);
119 
120       // Call optimized micro-kernel.
121       zip(n() * sizeof(uint32_t), x.data(), y.data());
122 
123       // Verify results.
124       for (size_t i = 0; i < n(); i++) {
125         for (size_t j = 0; j < g(); j++) {
126           ASSERT_EQ(y[i * g() + j], x[j * n() + i])
127             << "at element " << i << ", group " << j;
128         }
129       }
130     }
131   }
132 
Test(xnn_x32_zipv_ukernel_function zip)133   void Test(xnn_x32_zipv_ukernel_function zip) const {
134     std::random_device random_device;
135     auto rng = std::mt19937(random_device());
136     auto u32rng = std::bind(std::uniform_int_distribution<uint32_t>(), rng);
137 
138     std::vector<uint32_t> x(n() * g());
139     std::vector<uint32_t> y(g() * n());
140 
141     for (size_t iteration = 0; iteration < iterations(); iteration++) {
142       std::generate(x.begin(), x.end(), std::ref(u32rng));
143       std::fill(y.begin(), y.end(), 0xA55A5AA5);
144 
145       // Call optimized micro-kernel.
146       zip(n() * sizeof(uint32_t), g(), x.data(), y.data());
147 
148       // Verify results.
149       for (size_t i = 0; i < n(); i++) {
150         for (size_t j = 0; j < g(); j++) {
151           ASSERT_EQ(y[i * g() + j], x[j * n() + i])
152             << "at element " << i << ", group " << j;
153         }
154       }
155     }
156   }
157 
158  private:
159   size_t n_{1};
160   size_t g_{1};
161   size_t iterations_{3};
162 };
163