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