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 <random> 21 #include <vector> 22 23 #include <xnnpack/params.h> 24 25 26 class ZipMicrokernelTester { 27 public: n(size_t n)28 inline ZipMicrokernelTester& n(size_t n) { 29 assert(n != 0); 30 this->n_ = n; 31 return *this; 32 } 33 n()34 inline size_t n() const { 35 return this->n_; 36 } 37 g(size_t g)38 inline ZipMicrokernelTester& g(size_t g) { 39 assert(g != 0); 40 this->g_ = g; 41 return *this; 42 } 43 g()44 inline size_t g() const { 45 return this->g_; 46 } 47 iterations(size_t iterations)48 inline ZipMicrokernelTester& iterations(size_t iterations) { 49 this->iterations_ = iterations; 50 return *this; 51 } 52 iterations()53 inline size_t iterations() const { 54 return this->iterations_; 55 } 56 Test(xnn_x8_zipc_ukernel_function zip)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 Test(xnn_x8_zipv_ukernel_function zip)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 Test(xnn_x32_zipc_ukernel_function zip)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 Test(xnn_x32_zipv_ukernel_function zip)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 }; 162