• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2020 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 
16 #ifndef TENSORFLOW_CORE_KERNELS_MLIR_GENERATED_BASE_OPS_TEST_H_
17 #define TENSORFLOW_CORE_KERNELS_MLIR_GENERATED_BASE_OPS_TEST_H_
18 
19 #include <string>
20 
21 #include "absl/container/inlined_vector.h"
22 #include "absl/strings/string_view.h"
23 #include "llvm/ADT/STLExtras.h"
24 #include "tensorflow/core/framework/tensor_shape.h"
25 
26 namespace tensorflow {
27 namespace test {
28 
29 template <typename T>
30 using is_integer = llvm::is_one_of<T, int8_t, int16_t, int32_t, int64_t,
31                                    uint8_t, uint16_t, uint32_t, uint64_t>;
32 
33 /// Helper functions to create or derive inputs of the right type and size.
34 
35 template <typename T, typename LiteralT>
InputAsVector(std::initializer_list<LiteralT> input)36 absl::InlinedVector<T, 10> InputAsVector(
37     std::initializer_list<LiteralT> input) {
38   absl::InlinedVector<T, 10> result;
39   result.reserve(input.size());
40   for (const LiteralT& value : input) {
41     result.push_back(static_cast<T>(value));
42   }
43   return result;
44 }
45 
46 template <typename T>
RepeatInputToMatchShape(absl::InlinedVector<T,10> input,int size)47 absl::InlinedVector<T, 10> RepeatInputToMatchShape(
48     absl::InlinedVector<T, 10> input, int size) {
49   absl::InlinedVector<T, 10> result;
50   for (int i = 0; i < size; i++) {
51     auto value = input[i % input.size()];
52     result.push_back(value);
53   }
54   return result;
55 }
56 
57 template <typename T>
RepeatElements(absl::InlinedVector<T,10> input,int num_repeats)58 absl::InlinedVector<T, 10> RepeatElements(absl::InlinedVector<T, 10> input,
59                                           int num_repeats) {
60   absl::InlinedVector<T, 10> result;
61   for (T value : input) {
62     for (int i = 0; i < num_repeats; ++i) {
63       result.push_back(value);
64     }
65   }
66   return result;
67 }
68 
69 /// Helper functions to get default input shapes.
70 
71 TensorShape DefaultInputShape();
72 
73 /// Helper functions to configure tests.
74 
75 struct OpsTestConfig {
76   bool add_t = true;
77   bool add_tout = false;
78   // Only used for gpu_unary_ops_test.
79   bool expect_buffer_reuse = true;
80   bool expect_strictly_equal = false;
81   bool supress_tolerance = false;
82   // Negative atol/rtol will make ExpectClose use the default.
83   double atol = -1;
84   double rtol = -1;
85   std::string input_attribute = "T";
86   std::string output_attribute = "Tout";
87   bool jit_compilation = false;
ExpectStrictlyEqualOpsTestConfig88   OpsTestConfig ExpectStrictlyEqual() {
89     OpsTestConfig config = *this;
90     config.expect_strictly_equal = true;
91     return config;
92   }
SuppressToleranceOpsTestConfig93   OpsTestConfig SuppressTolerance() {
94     OpsTestConfig config = *this;
95     config.supress_tolerance = true;
96     return config;
97   }
NoBufferReuseOpsTestConfig98   OpsTestConfig NoBufferReuse() {
99     OpsTestConfig config = *this;
100     config.expect_buffer_reuse = false;
101     return config;
102   }
AddToutOpsTestConfig103   OpsTestConfig AddTout() {
104     OpsTestConfig config = *this;
105     config.add_tout = true;
106     return config;
107   }
NoTOpsTestConfig108   OpsTestConfig NoT() {
109     OpsTestConfig config = *this;
110     config.add_t = false;
111     return config;
112   }
RTolOpsTestConfig113   OpsTestConfig RTol(double new_rtol) {
114     OpsTestConfig config = *this;
115     config.rtol = new_rtol;
116     return config;
117   }
ATolOpsTestConfig118   OpsTestConfig ATol(double new_atol) {
119     OpsTestConfig config = *this;
120     config.atol = new_atol;
121     return config;
122   }
InputAttributeOpsTestConfig123   OpsTestConfig InputAttribute(const std::string& attr) {
124     OpsTestConfig config = *this;
125     config.input_attribute = attr;
126     return config;
127   }
OutputAttributeOpsTestConfig128   OpsTestConfig OutputAttribute(const std::string& attr) {
129     OpsTestConfig config = *this;
130     config.output_attribute = attr;
131     return config;
132   }
JITCompilationOpsTestConfig133   OpsTestConfig JITCompilation() {
134     OpsTestConfig config = *this;
135     config.jit_compilation = true;
136     return config;
137   }
138 };
139 
140 /// Helper functions to get more specific input data.
141 
142 template <typename T, std::enable_if_t<
143                           llvm::is_one_of<T, Eigen::half, float, double>::value,
144                           bool> = true>
NearZeroAndExtremeInput()145 absl::InlinedVector<T, 10> NearZeroAndExtremeInput() {
146   return InputAsVector<T, double>({-std::numeric_limits<double>::infinity(),
147                                    -0.1, -0.0, 0.0, 0.1,
148                                    std::numeric_limits<double>::infinity()});
149 }
150 
151 template <typename T, std::enable_if_t<is_integer<T>::value, bool> = true>
NearZeroAndExtremeInput()152 absl::InlinedVector<T, 10> NearZeroAndExtremeInput() {
153   return InputAsVector<T, T>({std::numeric_limits<T>::min(),
154                               std::numeric_limits<T>::min() + 1, -1, 0, 1,
155                               std::numeric_limits<T>::max()});
156 }
157 
158 template <typename T, std::enable_if_t<
159                           llvm::is_one_of<T, Eigen::half, float, double>::value,
160                           bool> = true>
NearZeroInfAndNanInput()161 absl::InlinedVector<T, 10> NearZeroInfAndNanInput() {
162   return InputAsVector<T, double>({-std::numeric_limits<double>::quiet_NaN(),
163                                    -std::numeric_limits<double>::infinity(),
164                                    -0.1, -0.0, 0.0, 0.1,
165                                    std::numeric_limits<double>::infinity(),
166                                    std::numeric_limits<double>::quiet_NaN()});
167 }
168 
169 template <typename T, std::enable_if_t<
170                           llvm::is_one_of<T, Eigen::half, float, double>::value,
171                           bool> = true>
DefaultInputGreaterEqualOne()172 absl::InlinedVector<T, 10> DefaultInputGreaterEqualOne() {
173   return test::InputAsVector<T, double>(
174       {18.0, 9.0, 1.0, std::numeric_limits<T>::max(), 42.0, 2.0, 1.0,
175        std::sqrt(std::numeric_limits<T>::max()), 9.0, 18.0});
176 }
177 
178 template <typename T, std::enable_if_t<
179                           llvm::is_one_of<T, Eigen::half, float, double>::value,
180                           bool> = true>
DefaultInputGreaterThanZero()181 absl::InlinedVector<T, 10> DefaultInputGreaterThanZero() {
182   return test::InputAsVector<T, double>({18.0, 9.0, 1e-6, 1.0, 0.1, 1e-6, 0.1,
183                                          0.2, 0.3, 0.5, 0.7, 0.9, 9.0, 18.0});
184 }
185 
186 template <typename T, std::enable_if_t<
187                           llvm::is_one_of<T, Eigen::half, float, double>::value,
188                           bool> = true>
DefaultInputGreaterOrEqualToZero()189 absl::InlinedVector<T, 10> DefaultInputGreaterOrEqualToZero() {
190   return test::InputAsVector<T, double>({18.0, 9.0, 1e-6, 0.0, 0.1, 1e-6, 0.1,
191                                          0.2, 0.3, 0.5, 0.7, 0.9, 9.0, 18.0});
192 }
193 
194 template <typename T, std::enable_if_t<
195                           llvm::is_one_of<T, Eigen::half, float, double>::value,
196                           bool> = true>
DefaultInputNonZero()197 absl::InlinedVector<T, 10> DefaultInputNonZero() {
198   return test::InputAsVector<T, double>({18.0, 9.0, 1e-6, -0.1, 0.1, 1e-6, 0.1,
199                                          0.2, 0.3, 0.5, 0.7, 0.9, 9.0, 18.0});
200 }
201 
202 template <typename T, std::enable_if_t<is_integer<T>::value, bool> = true>
DefaultInputNonZero()203 absl::InlinedVector<T, 10> DefaultInputNonZero() {
204   return test::InputAsVector<T, int>({-18, -9, -1, 1, 3, 4, 5, 7, 9, 10, 18});
205 }
206 
207 template <typename T, std::enable_if_t<
208                           llvm::is_one_of<T, Eigen::half, float, double>::value,
209                           bool> = true>
DefaultInputBetweenZeroAndOne()210 absl::InlinedVector<T, 10> DefaultInputBetweenZeroAndOne() {
211   return test::InputAsVector<T, double>({-0.999, -0.9, -0.8, -0.5, -0.1, -0.001,
212                                          -0, 0, 0.001, 0.1, 0.5, 0.8, 0.9,
213                                          0.999});
214 }
215 
216 template <typename T, std::enable_if_t<is_integer<T>::value, bool> = true>
DefaultInputLessThanBitwidth()217 absl::InlinedVector<T, 10> DefaultInputLessThanBitwidth() {
218   auto max_shift = sizeof(T) * 8 - 1;
219   absl::InlinedVector<T, 10> v;
220   for (auto i = 0; i < max_shift; ++i) v.push_back(i);
221   return v;
222 }
223 
224 /// Helper functions to get default input data.
225 
226 template <typename T, std::enable_if_t<is_integer<T>::value, bool> = true>
DefaultInput()227 absl::InlinedVector<T, 10> DefaultInput() {
228   return InputAsVector<T, int>({-18, -9, -1, 0, 0, 1, 1, 2, 3, 5, 7, 9, 9, 18});
229 }
230 
231 template <typename T, std::enable_if_t<
232                           llvm::is_one_of<T, Eigen::half, float, double>::value,
233                           bool> = true>
DefaultInput()234 absl::InlinedVector<T, 10> DefaultInput() {
235   return InputAsVector<T, double>({-18.0, -9.0, -0.7, -0.5, -0.3, -0.2, -0.1,
236                                    -1e-6, -0.0, 0.0, 1e-6, 0.1, 0.2, 0.3, 0.5,
237                                    0.7, 0.9, 18.0});
238 }
239 
240 template <typename T,
241           std::enable_if_t<llvm::is_one_of<T, std::complex<float>,
242                                            std::complex<double>>::value,
243                            bool> = true>
DefaultInput()244 absl::InlinedVector<T, 10> DefaultInput() {
245   using ElementType = typename T::value_type;
246   auto input = test::DefaultInput<ElementType>();
247   absl::InlinedVector<T, 10> complex_input;
248   for (ElementType value : input) {
249     complex_input.emplace_back(value, -value);
250   }
251   return complex_input;
252 }
253 
254 template <typename T,
255           std::enable_if_t<llvm::is_one_of<T, std::complex<float>,
256                                            std::complex<double>>::value,
257                            bool> = true>
ComplexInputFromValues(const absl::InlinedVector<typename T::value_type,10> & real,const absl::InlinedVector<typename T::value_type,10> & imag)258 absl::InlinedVector<T, 10> ComplexInputFromValues(
259     const absl::InlinedVector<typename T::value_type, 10>& real,
260     const absl::InlinedVector<typename T::value_type, 10>& imag) {
261   using ElementType = typename T::value_type;
262   auto input = test::DefaultInput<ElementType>();
263   absl::InlinedVector<T, 10> complex_input;
264   CHECK_EQ(real.size(), imag.size());
265   for (size_t i = 0; i < real.size() && i < imag.size(); ++i) {
266     complex_input.emplace_back(real[i], imag[i]);
267   }
268   return complex_input;
269 }
270 
271 template <typename T,
272           std::enable_if_t<llvm::is_one_of<T, std::complex<float>,
273                                            std::complex<double>>::value,
274                            bool> = true>
DefaultInputNonZero()275 absl::InlinedVector<T, 10> DefaultInputNonZero() {
276   auto real = test::DefaultInputNonZero<typename T::value_type>();
277   auto imag = real;
278   std::reverse(imag.begin(), imag.end());
279   return test::ComplexInputFromValues<T>(real, imag);
280 }
281 
282 template <typename T,
283           std::enable_if_t<llvm::is_one_of<T, std::complex<float>,
284                                            std::complex<double>>::value,
285                            bool> = true>
DefaultInputGreaterOrEqualToZero()286 absl::InlinedVector<T, 10> DefaultInputGreaterOrEqualToZero() {
287   auto real = test::DefaultInputGreaterOrEqualToZero<typename T::value_type>();
288   auto imag = real;
289   std::reverse(imag.begin(), imag.end());
290   return test::ComplexInputFromValues<T>(real, imag);
291 }
292 
293 template <typename T,
294           std::enable_if_t<llvm::is_one_of<T, std::complex<float>,
295                                            std::complex<double>>::value,
296                            bool> = true>
NearZeroInfAndNanInput()297 absl::InlinedVector<T, 10> NearZeroInfAndNanInput() {
298   using ElementType = typename T::value_type;
299   auto input = test::NearZeroInfAndNanInput<ElementType>();
300   absl::InlinedVector<ElementType, 10> real;
301   absl::InlinedVector<ElementType, 10> imag;
302   for (ElementType r : input) {
303     for (ElementType i : input) {
304       real.push_back(r);
305       imag.push_back(i);
306     }
307   }
308   return test::ComplexInputFromValues<T>(real, imag);
309 }
310 
311 template <typename T,
312           std::enable_if_t<llvm::is_one_of<T, bool>::value, bool> = true>
DefaultInput()313 absl::InlinedVector<T, 10> DefaultInput() {
314   return InputAsVector<T, bool>({true, false, true, true, false});
315 }
316 
317 }  // namespace test
318 }  // namespace tensorflow
319 
320 #endif  // TENSORFLOW_CORE_KERNELS_MLIR_GENERATED_BASE_OPS_TEST_H_
321