xref: /aosp_15_r20/external/XNNPACK/test/subgraph-unary-tester.h (revision 4bdc94577ba0e567308109d787f7fec7b531ce36)
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