1 // Copyright 2022 Google LLC 2 // 3 // This source code is licensed under the BSD-style license found in the 4 // LICENSE file in the root directory of this source tree. 5 6 #include <array> 7 #include <cstdint> 8 #include <cstddef> 9 #include <limits> 10 #include <memory> 11 #include <numeric> 12 #include <random> 13 14 #include <xnnpack.h> 15 #include <xnnpack/node-type.h> 16 #include <xnnpack/operator.h> 17 #include <xnnpack/requantization.h> 18 #include <xnnpack/subgraph.h> 19 20 #include <gtest/gtest.h> 21 22 template <typename InputType, typename OutputType = InputType, size_t min_dim = 0> class UnaryTest : public ::testing::Test { 23 protected: UnaryTest()24 UnaryTest() 25 { 26 random_device = std::unique_ptr<std::random_device>(new std::random_device()); 27 rng = std::mt19937((*random_device)()); 28 shape_dist = std::uniform_int_distribution<size_t>(min_dim, XNN_MAX_TENSOR_DIMS); 29 dim_dist = std::uniform_int_distribution<size_t>(1, 9); 30 i8dist = 31 std::uniform_int_distribution<int32_t>(std::numeric_limits<int8_t>::min(), std::numeric_limits<int8_t>::max()); 32 u8dist = 33 std::uniform_int_distribution<int32_t>(std::numeric_limits<uint8_t>::min(), std::numeric_limits<uint8_t>::max()); 34 u32dist = std::uniform_int_distribution<uint32_t>(); 35 scale_dist = std::uniform_real_distribution<float>(0.1f, 10.0f); 36 f32dist = std::uniform_real_distribution<float>(0.01f, 1.0f); 37 dims = RandomShape(); 38 channels = dims.empty() ? 1 : dims.back(); 39 xnn_shape shape = { 40 .num_dims = dims.size(), 41 }; 42 memcpy(shape.dim, dims.data(), dims.size() * sizeof(size_t)); 43 batch_size = xnn_shape_multiply_non_channel_dims(&shape); 44 num_output_elements = batch_size * channels; 45 scale = scale_dist(rng); 46 signed_zero_point = i8dist(rng); 47 unsigned_zero_point = u8dist(rng); 48 49 input = std::vector<InputType>(num_output_elements + XNN_EXTRA_BYTES / sizeof(InputType)); 50 operator_output = std::vector<OutputType>(num_output_elements); 51 subgraph_output = std::vector<OutputType>(num_output_elements); 52 } 53 RandomShape()54 std::vector<size_t> RandomShape() { 55 std::vector<size_t> dims(shape_dist(rng)); 56 std::generate(dims.begin(), dims.end(), [&] { return dim_dist(rng); }); 57 return dims; 58 } 59 NumElements(std::vector<size_t> & dims)60 size_t NumElements(std::vector<size_t>& dims) 61 { 62 return std::accumulate(dims.begin(), dims.end(), size_t(1), std::multiplies<size_t>()); 63 } 64 65 std::unique_ptr<std::random_device> random_device; 66 std::mt19937 rng; 67 std::uniform_int_distribution<size_t> shape_dist; 68 std::uniform_int_distribution<size_t> dim_dist; 69 std::uniform_real_distribution<float> scale_dist; 70 std::uniform_int_distribution<int32_t> i8dist; 71 std::uniform_int_distribution<int32_t> u8dist; 72 std::uniform_int_distribution<uint32_t> u32dist; 73 std::uniform_real_distribution<float> f32dist; 74 75 std::vector<size_t> dims; 76 77 uint32_t input_id; 78 uint32_t output_id; 79 80 size_t channels; 81 size_t batch_size; 82 size_t num_output_elements; 83 float scale; 84 int32_t signed_zero_point; 85 int32_t unsigned_zero_point; 86 87 std::vector<InputType> input; 88 std::vector<OutputType> operator_output; 89 std::vector<OutputType> subgraph_output; 90 }; 91