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