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