xref: /aosp_15_r20/external/tensorflow/tensorflow/lite/kernels/internal/test_util.cc (revision b6fb3261f9314811a0f4371741dbb8839866f948)
1 /* Copyright 2018 The TensorFlow Authors. All Rights Reserved.
2 
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6 
7     http://www.apache.org/licenses/LICENSE-2.0
8 
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15 #include "tensorflow/lite/kernels/internal/test_util.h"
16 
17 #include <algorithm>
18 #include <cmath>
19 #include <functional>
20 #include <iterator>
21 #include <random>
22 
23 namespace tflite {
24 
25 // this is a copied from an internal function in propagate_fixed_sizes.cc
ComputeConvSizes(const RuntimeShape & input_shape,int output_depth,int filter_width,int filter_height,int stride,int dilation_width_factor,int dilation_height_factor,PaddingType padding_type,RuntimeShape * output_shape,int * pad_width,int * pad_height)26 bool ComputeConvSizes(const RuntimeShape& input_shape, int output_depth,
27                       int filter_width, int filter_height, int stride,
28                       int dilation_width_factor, int dilation_height_factor,
29                       PaddingType padding_type, RuntimeShape* output_shape,
30                       int* pad_width, int* pad_height) {
31   const int input_width = input_shape.Dims(2);
32   const int input_height = input_shape.Dims(1);
33   const int batch = input_shape.Dims(0);
34 
35   int dilated_filter_width = dilation_width_factor * (filter_width - 1) + 1;
36   int dilated_filter_height = dilation_height_factor * (filter_height - 1) + 1;
37 
38   int output_height = 0;
39   int output_width = 0;
40   if (padding_type == PaddingType::kValid) {
41     // Official TF is
42     // ceil((input_height - (dilated_filter_height - 1)) / stride),
43     // implemented as
44     // floor(
45     //   (input_height - (dilated_filter_height - 1) + (stride - 1)) / stride).
46     output_height = (input_height + stride - dilated_filter_height) / stride;
47     output_width = (input_width + stride - dilated_filter_width) / stride;
48   } else if (padding_type == PaddingType::kSame) {
49     output_height = (input_height + stride - 1) / stride;
50     output_width = (input_width + stride - 1) / stride;
51   } else {
52     return false;
53   }
54 
55   if (output_width <= 0 || output_height <= 0) {
56     return false;
57   }
58 
59   *pad_height = std::max(
60       0, ((output_height - 1) * stride + dilated_filter_height - input_height) /
61              2);
62   *pad_width = std::max(
63       0,
64       ((output_width - 1) * stride + dilated_filter_width - input_width) / 2);
65 
66   output_shape->BuildFrom({batch, output_height, output_width, output_depth});
67   return true;
68 }
69 
RandomEngine()70 std::mt19937& RandomEngine() {
71   static std::mt19937 engine;
72   return engine;
73 }
74 
UniformRandomInt(int min,int max)75 int UniformRandomInt(int min, int max) {
76   std::uniform_int_distribution<int> dist(min, max);
77   return dist(RandomEngine());
78 }
79 
UniformRandomFloat(float min,float max)80 float UniformRandomFloat(float min, float max) {
81   std::uniform_real_distribution<float> dist(min, max);
82   return dist(RandomEngine());
83 }
84 
ExponentialRandomPositiveInt(float percentile,int percentile_val,int max_val)85 int ExponentialRandomPositiveInt(float percentile, int percentile_val,
86                                  int max_val) {
87   const float lambda =
88       -std::log(1.f - percentile) / static_cast<float>(percentile_val);
89   std::exponential_distribution<float> dist(lambda);
90   float val;
91   do {
92     val = dist(RandomEngine());
93   } while (!val || !std::isfinite(val) || val > max_val);
94   return static_cast<int>(std::ceil(val));
95 }
96 
ExponentialRandomPositiveFloat(float percentile,float percentile_val,float max_val)97 float ExponentialRandomPositiveFloat(float percentile, float percentile_val,
98                                      float max_val) {
99   const float lambda =
100       -std::log(1.f - percentile) / static_cast<float>(percentile_val);
101   std::exponential_distribution<float> dist(lambda);
102   float val;
103   do {
104     val = dist(RandomEngine());
105   } while (!std::isfinite(val) || val > max_val);
106   return val;
107 }
108 
FillRandomFloat(std::vector<float> * vec,float min,float max)109 void FillRandomFloat(std::vector<float>* vec, float min, float max) {
110   std::uniform_real_distribution<float> dist(min, max);
111   // TODO(b/154540105): use std::ref to avoid copying the random engine.
112   auto gen = std::bind(dist, RandomEngine());
113   std::generate(std::begin(*vec), std::end(*vec), gen);
114 }
115 
116 }  // namespace tflite
117