• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Meta Platforms, Inc. and affiliates.
3  * All rights reserved.
4  *
5  * This source code is licensed under the BSD-style license found in the
6  * LICENSE file in the root directory of this source tree.
7  */
8 
9 #include <executorch/kernels/portable/NativeFunctions.h> // Declares the operator
10 #include <executorch/kernels/test/TestUtil.h>
11 #include <executorch/runtime/core/exec_aten/exec_aten.h>
12 #include <executorch/runtime/core/exec_aten/testing_util/tensor_factory.h>
13 #include <executorch/runtime/core/exec_aten/testing_util/tensor_util.h>
14 #include <executorch/test/utils/DeathTest.h>
15 
16 #include <gtest/gtest.h>
17 #include <cmath>
18 
19 using namespace ::testing;
20 using exec_aten::ScalarType;
21 using exec_aten::Tensor;
22 using torch::executor::native::allclose_out;
23 using torch::executor::testing::IsCloseTo;
24 using torch::executor::testing::TensorFactory;
25 
26 const double default_atol{1e-08};
27 const double default_rtol{1e-05};
28 
TEST(OpAllCloseTest,IdenticalFloatTensors)29 TEST(OpAllCloseTest, IdenticalFloatTensors) {
30   TensorFactory<ScalarType::Float> tf_float;
31   Tensor a = tf_float.ones(/*sizes=*/{2, 2});
32   Tensor b = tf_float.ones(/*sizes=*/{2, 2});
33   TensorFactory<ScalarType::Bool> tf_bool;
34   Tensor out = tf_bool.zeros(/*sizes=*/{1});
35 
36   allclose_out(
37       a,
38       b,
39       default_rtol,
40       default_atol,
41       /*equal_nan=*/false,
42       /*dummy_param=*/false,
43       out);
44 
45   auto out_data = out.data_ptr<bool>();
46   EXPECT_EQ(out_data[0], true);
47 }
48 
TEST(OpAllCloseTest,IdenticalDoubleTensors)49 TEST(OpAllCloseTest, IdenticalDoubleTensors) {
50   TensorFactory<ScalarType::Double> tf_double;
51   Tensor a = tf_double.ones(/*sizes=*/{2, 2});
52   Tensor b = tf_double.ones(/*sizes=*/{2, 2});
53   TensorFactory<ScalarType::Bool> tf_bool;
54   Tensor out = tf_bool.zeros(/*sizes=*/{1});
55 
56   allclose_out(
57       a,
58       b,
59       default_rtol,
60       default_atol,
61       /*equal_nan=*/false,
62       /*dummy_param=*/false,
63       out);
64 
65   auto out_data = out.data_ptr<bool>();
66   EXPECT_EQ(out_data[0], true);
67 }
68 
TEST(OpAllCloseTest,NonEqualFloatTensors)69 TEST(OpAllCloseTest, NonEqualFloatTensors) {
70   TensorFactory<ScalarType::Float> tf_float;
71   Tensor a = tf_float.make(/*sizes=*/{2, 2}, /*data=*/{1., 2., 3., 4.});
72   Tensor b = tf_float.make(/*sizes=*/{2, 2}, /*data=*/{5., 6., 7., 8.});
73   TensorFactory<ScalarType::Bool> tf_bool;
74   Tensor out = tf_bool.zeros(/*sizes=*/{1});
75 
76   allclose_out(
77       a,
78       b,
79       default_rtol,
80       default_atol,
81       /*equal_nan=*/false,
82       /*dummy_param=*/false,
83       out);
84 
85   auto out_data = out.data_ptr<bool>();
86   EXPECT_EQ(out_data[0], false);
87 }
88 
TEST(OpAllCloseTest,NonEqualDoubleTensors)89 TEST(OpAllCloseTest, NonEqualDoubleTensors) {
90   TensorFactory<ScalarType::Double> tf_double;
91   Tensor a = tf_double.make(/*sizes=*/{2, 2}, /*data=*/{1., 2., 3., 4.});
92   Tensor b = tf_double.make(/*sizes=*/{2, 2}, /*data=*/{5., 6., 7., 8.});
93   TensorFactory<ScalarType::Bool> tf_bool;
94   Tensor out = tf_bool.zeros(/*sizes=*/{1});
95 
96   allclose_out(
97       a,
98       b,
99       default_rtol,
100       default_atol,
101       /*equal_nan=*/false,
102       /*dummy_param=*/false,
103       out);
104 
105   auto out_data = out.data_ptr<bool>();
106   EXPECT_EQ(out_data[0], false);
107 }
108 
TEST(OpAllCloseTest,IdenticalIntTensors)109 TEST(OpAllCloseTest, IdenticalIntTensors) {
110   TensorFactory<ScalarType::Int> tf_int;
111   Tensor a = tf_int.ones(/*sizes=*/{2, 2});
112   Tensor b = tf_int.ones(/*sizes=*/{2, 2});
113   TensorFactory<ScalarType::Bool> tf_bool;
114   Tensor out = tf_bool.zeros(/*sizes=*/{1});
115   allclose_out(
116       a,
117       b,
118       default_rtol,
119       default_atol,
120       /*equal_nan=*/false,
121       /*dummy_param=*/false,
122       out);
123 
124   auto out_data = out.data_ptr<bool>();
125   EXPECT_EQ(out_data[0], true);
126 }
127 
TEST(OpAllCloseTest,NonEqualIntTensors)128 TEST(OpAllCloseTest, NonEqualIntTensors) {
129   TensorFactory<ScalarType::Int> tf_int;
130   Tensor a = tf_int.make(/*sizes=*/{2, 2}, /*data=*/{1, 2, 3, 4});
131   Tensor b = tf_int.make(/*sizes=*/{2, 2}, /*data=*/{5, 6, 7, 8});
132   TensorFactory<ScalarType::Bool> tf_bool;
133   Tensor out = tf_bool.zeros(/*sizes=*/{1});
134   allclose_out(
135       a,
136       b,
137       default_rtol,
138       default_atol,
139       /*equal_nan=*/false,
140       /*dummy_param=*/false,
141       out);
142 
143   auto out_data = out.data_ptr<bool>();
144   EXPECT_EQ(out_data[0], false);
145 }
146 
TEST(OpAllCloseTest,IdenticalBoolTensors)147 TEST(OpAllCloseTest, IdenticalBoolTensors) {
148   TensorFactory<ScalarType::Bool> tf_bool;
149   Tensor a = tf_bool.ones(/*sizes=*/{2, 2});
150   Tensor b = tf_bool.ones(/*sizes=*/{2, 2});
151   Tensor out = tf_bool.zeros(/*sizes=*/{1});
152 
153   allclose_out(
154       a,
155       b,
156       default_rtol,
157       default_atol,
158       /*equal_nan=*/false,
159       /*dummy_param=*/false,
160       out);
161   auto out_data = out.data_ptr<bool>();
162   EXPECT_EQ(out_data[0], true);
163 }
164 
TEST(OpAllCloseTest,NonEqualBoolTensors)165 TEST(OpAllCloseTest, NonEqualBoolTensors) {
166   TensorFactory<ScalarType::Bool> tf_bool;
167   Tensor a = tf_bool.ones(/*sizes=*/{2, 2});
168   Tensor b = tf_bool.ones(/*sizes=*/{2, 2});
169   auto b_data = b.data_ptr<bool>();
170   b_data[0] = false;
171   Tensor out = tf_bool.zeros(/*sizes=*/{1});
172 
173   allclose_out(
174       a,
175       b,
176       default_rtol,
177       default_atol,
178       /*equal_nan=*/false,
179       /*dummy_param=*/false,
180       out);
181   auto out_data = out.data_ptr<bool>();
182   EXPECT_EQ(out_data[0], false);
183 }
184 
TEST(OpAllCloseTest,MismatchedInputShapesDeath)185 TEST(OpAllCloseTest, MismatchedInputShapesDeath) {
186   TensorFactory<ScalarType::Int> tf_int;
187   Tensor a = tf_int.ones(/*sizes=*/{2, 1});
188   Tensor b = tf_int.ones(/*sizes=*/{2, 2});
189   TensorFactory<ScalarType::Bool> tf_bool;
190   Tensor out = tf_bool.zeros(/*sizes=*/{1});
191 
192   ET_EXPECT_DEATH(
193       allclose_out(
194           a,
195           b,
196           default_rtol,
197           default_atol,
198           /*equal_nan=*/false,
199           /*dummy_param=*/false,
200           out),
201       "");
202 }
203 
TEST(OpAllCloseTest,MismatchedInputDtypesDeath)204 TEST(OpAllCloseTest, MismatchedInputDtypesDeath) {
205   TensorFactory<ScalarType::Float> tf_float;
206   Tensor a = tf_float.ones(/*sizes=*/{2, 2});
207 
208   TensorFactory<ScalarType::Int> tf_int;
209   Tensor b = tf_int.ones(/*sizes=*/{2, 2});
210 
211   TensorFactory<ScalarType::Bool> tf_bool;
212   Tensor out = tf_bool.zeros(/*sizes=*/{1});
213 
214   ET_EXPECT_DEATH(
215       allclose_out(
216           a,
217           b,
218           default_rtol,
219           default_atol,
220           /*equal_nan=*/false,
221           /*dummy_param=*/false,
222           out),
223       "");
224 }
225 
TEST(OpAllCloseTest,IncorrectOutputDtypeDeath)226 TEST(OpAllCloseTest, IncorrectOutputDtypeDeath) {
227   TensorFactory<ScalarType::Float> tf_float;
228   Tensor a = tf_float.ones(/*sizes=*/{2, 2});
229   Tensor b = tf_float.ones(/*sizes=*/{2, 2});
230   Tensor out = tf_float.zeros(/*sizes=*/{1});
231 
232   ET_EXPECT_DEATH(
233       allclose_out(
234           a,
235           b,
236           default_rtol,
237           default_atol,
238           /*equal_nan=*/false,
239           /*dummy_param=*/false,
240           out),
241       "");
242 }
243 
TEST(OpAllCloseTest,IncorrectOutputShapeDeath)244 TEST(OpAllCloseTest, IncorrectOutputShapeDeath) {
245   TensorFactory<ScalarType::Float> tf_float;
246   Tensor a = tf_float.ones(/*sizes=*/{2, 2});
247   Tensor b = tf_float.ones(/*sizes=*/{2, 2});
248   TensorFactory<ScalarType::Bool> tf_bool;
249   Tensor out = tf_bool.zeros(/*sizes=*/{2, 2});
250 
251   ET_EXPECT_DEATH(
252       allclose_out(
253           a,
254           b,
255           default_rtol,
256           default_atol,
257           /*equal_nan=*/false,
258           /*dummy_param=*/false,
259           out),
260       "");
261 }
262 
TEST(OpAllCloseTest,FloatTensorsVaryWithinRelativeTolerance)263 TEST(OpAllCloseTest, FloatTensorsVaryWithinRelativeTolerance) {
264   const double rtol = 1e-05;
265   const double rdiff = 1e-06;
266 
267   TensorFactory<ScalarType::Float> tf_float;
268   Tensor a = tf_float.ones(/*sizes=*/{2, 2});
269   Tensor b = tf_float.ones(/*sizes=*/{2, 2});
270 
271   auto a_data = a.data_ptr<float>();
272   auto b_data = b.data_ptr<float>();
273   b_data[0] = a_data[0] * (1. + rdiff);
274 
275   TensorFactory<ScalarType::Bool> tf_bool;
276   Tensor out = tf_bool.zeros(/*sizes=*/{1});
277 
278   allclose_out(
279       a, b, rtol, /*atol=*/0., /*equal_nan=*/false, /*dummy_param=*/false, out);
280 
281   auto out_data = out.data_ptr<bool>();
282   EXPECT_EQ(out_data[0], true);
283 }
284 
TEST(OpAllCloseTest,DoubleTensorsVaryWithinRelativeTolerance)285 TEST(OpAllCloseTest, DoubleTensorsVaryWithinRelativeTolerance) {
286   const double rtol = 1e-05;
287   const double rdiff = 1e-06;
288 
289   TensorFactory<ScalarType::Double> tf_double;
290   Tensor a = tf_double.ones(/*sizes=*/{2, 2});
291   Tensor b = tf_double.ones(/*sizes=*/{2, 2});
292 
293   auto a_data = a.data_ptr<double>();
294   auto b_data = b.data_ptr<double>();
295   b_data[0] = a_data[0] * (1. + rdiff);
296   TensorFactory<ScalarType::Bool> tf_bool;
297   Tensor out = tf_bool.zeros(/*sizes=*/{1});
298 
299   allclose_out(
300       a, b, rtol, /*atol=*/0., /*equal_nan=*/false, /*dummy_param=*/false, out);
301 
302   auto out_data = out.data_ptr<bool>();
303   EXPECT_EQ(out_data[0], true);
304 }
305 
TEST(OpAllCloseTest,FloatTensorsVaryOutsideRelativeTolerance)306 TEST(OpAllCloseTest, FloatTensorsVaryOutsideRelativeTolerance) {
307   const double rtol = 1e-05;
308   const double rdiff = 1e-04;
309 
310   TensorFactory<ScalarType::Float> tf_float;
311   Tensor a = tf_float.ones(/*sizes=*/{2, 2});
312   Tensor b = tf_float.ones(/*sizes=*/{2, 2});
313 
314   auto a_data = a.data_ptr<float>();
315   auto b_data = b.data_ptr<float>();
316   b_data[0] = a_data[0] * (1. + rdiff);
317   TensorFactory<ScalarType::Bool> tf_bool;
318   Tensor out = tf_bool.zeros(/*sizes=*/{1});
319 
320   allclose_out(
321       a, b, rtol, /*atol=*/0., /*equal_nan=*/false, /*dummy_param=*/false, out);
322 
323   auto out_data = out.data_ptr<bool>();
324   EXPECT_EQ(out_data[0], false);
325 }
326 
TEST(OpAllCloseTest,DoubleTensorsVaryOutsideRelativeTolerance)327 TEST(OpAllCloseTest, DoubleTensorsVaryOutsideRelativeTolerance) {
328   const double rtol = 1e-05;
329   const double rdiff = 1e-04;
330 
331   TensorFactory<ScalarType::Double> tf_double;
332   Tensor a = tf_double.ones(/*sizes=*/{2, 2});
333   Tensor b = tf_double.ones(/*sizes=*/{2, 2});
334 
335   auto a_data = a.data_ptr<double>();
336   auto b_data = b.data_ptr<double>();
337   b_data[0] = a_data[0] * (1. + rdiff);
338   TensorFactory<ScalarType::Bool> tf_bool;
339   Tensor out = tf_bool.zeros(/*sizes=*/{1});
340 
341   allclose_out(
342       a, b, rtol, /*atol=*/0., /*equal_nan=*/false, /*dummy_param=*/false, out);
343 
344   auto out_data = out.data_ptr<bool>();
345   EXPECT_EQ(out_data[0], false);
346 }
347 
TEST(OpAllCloseTest,FloatTensorsVaryWithinAbsoluteTolerance)348 TEST(OpAllCloseTest, FloatTensorsVaryWithinAbsoluteTolerance) {
349   const double atol = 1e-08;
350   const double adiff = 1e-09;
351 
352   TensorFactory<ScalarType::Float> tf_float;
353   Tensor a = tf_float.ones(/*sizes=*/{2, 2});
354   Tensor b = tf_float.ones(/*sizes=*/{2, 2});
355 
356   auto a_data = a.data_ptr<float>();
357   auto b_data = b.data_ptr<float>();
358   b_data[0] = a_data[0] + adiff;
359   TensorFactory<ScalarType::Bool> tf_bool;
360   Tensor out = tf_bool.zeros(/*sizes=*/{1});
361 
362   allclose_out(
363       a, b, /*rtol=*/0., atol, /*equal_nan=*/false, /*dummy_param=*/false, out);
364 
365   auto out_data = out.data_ptr<bool>();
366   EXPECT_EQ(out_data[0], true);
367 }
368 
TEST(OpAllCloseTest,DoubleTensorsVaryWithinAbsoluteTolerance)369 TEST(OpAllCloseTest, DoubleTensorsVaryWithinAbsoluteTolerance) {
370   const double atol = 1e-08;
371   const double adiff = 1e-09;
372 
373   TensorFactory<ScalarType::Double> tf_double;
374   Tensor a = tf_double.ones(/*sizes=*/{2, 2});
375   Tensor b = tf_double.ones(/*sizes=*/{2, 2});
376 
377   auto a_data = a.data_ptr<double>();
378   auto b_data = b.data_ptr<double>();
379   b_data[0] = a_data[0] + adiff;
380   TensorFactory<ScalarType::Bool> tf_bool;
381   Tensor out = tf_bool.zeros(/*sizes=*/{1});
382 
383   allclose_out(
384       a, b, /*rtol=*/0., atol, /*equal_nan=*/false, /*dummy_param=*/false, out);
385 
386   auto out_data = out.data_ptr<bool>();
387   EXPECT_EQ(out_data[0], true);
388 }
389 
TEST(OpAllCloseTest,FloatTensorsVaryOutsideAbsoluteTolerance)390 TEST(OpAllCloseTest, FloatTensorsVaryOutsideAbsoluteTolerance) {
391   const double atol = 1e-08;
392   const double adiff = 1e-07;
393 
394   TensorFactory<ScalarType::Float> tf_float;
395   Tensor a = tf_float.ones(/*sizes=*/{2, 2});
396   Tensor b = tf_float.ones(/*sizes=*/{2, 2});
397 
398   auto a_data = a.data_ptr<float>();
399   auto b_data = b.data_ptr<float>();
400   b_data[0] = a_data[0] + adiff;
401   TensorFactory<ScalarType::Bool> tf_bool;
402   Tensor out = tf_bool.zeros(/*sizes=*/{1});
403 
404   allclose_out(
405       a, b, /*rtol=*/0., atol, /*equal_nan=*/false, /*dummy_param=*/false, out);
406 
407   auto out_data = out.data_ptr<bool>();
408   EXPECT_EQ(out_data[0], false);
409 }
410 
TEST(OpAllCloseTest,DoubleTensorsVaryOutsideAbsoluteTolerance)411 TEST(OpAllCloseTest, DoubleTensorsVaryOutsideAbsoluteTolerance) {
412   const double atol = 1e-08;
413   const double adiff = 1e-07;
414 
415   TensorFactory<ScalarType::Float> tf_double;
416   Tensor a = tf_double.ones(/*sizes=*/{2, 2});
417   Tensor b = tf_double.ones(/*sizes=*/{2, 2});
418 
419   auto a_data = a.data_ptr<double>();
420   auto b_data = b.data_ptr<double>();
421   b_data[0] = a_data[0] + adiff;
422   TensorFactory<ScalarType::Bool> tf_bool;
423   Tensor out = tf_bool.zeros(/*sizes=*/{1});
424 
425   allclose_out(
426       a, b, /*rtol=*/0., atol, /*equal_nan=*/false, /*dummy_param=*/false, out);
427 
428   auto out_data = out.data_ptr<bool>();
429   EXPECT_EQ(out_data[0], false);
430 }
431 
TEST(OpAllCloseTest,FloatTensorsVaryWithZeroTolerance)432 TEST(OpAllCloseTest, FloatTensorsVaryWithZeroTolerance) {
433   TensorFactory<ScalarType::Float> tf_float;
434   Tensor a = tf_float.ones(/*sizes=*/{2, 2});
435   Tensor b = tf_float.ones(/*sizes=*/{2, 2});
436 
437   auto a_data = a.data_ptr<float>();
438   auto b_data = b.data_ptr<float>();
439   b_data[0] = a_data[0] + 1e-07;
440   TensorFactory<ScalarType::Bool> tf_bool;
441   Tensor out = tf_bool.zeros(/*sizes=*/{1});
442 
443   allclose_out(
444       a,
445       b,
446       /*rtol=*/0.,
447       /*atol=*/0,
448       /*equal_nan=*/false,
449       /*dummy_param=*/false,
450       out);
451 
452   auto out_data = out.data_ptr<bool>();
453   EXPECT_EQ(out_data[0], false);
454 }
455 
TEST(OpAllCloseTest,DoubleTensorsVaryWithZeroTolerance)456 TEST(OpAllCloseTest, DoubleTensorsVaryWithZeroTolerance) {
457   TensorFactory<ScalarType::Double> tf_double;
458   Tensor a = tf_double.ones(/*sizes=*/{2, 2});
459   Tensor b = tf_double.ones(/*sizes=*/{2, 2});
460 
461   auto a_data = a.data_ptr<double>();
462   auto b_data = b.data_ptr<double>();
463   b_data[0] = a_data[0] + 1e-09;
464   TensorFactory<ScalarType::Bool> tf_bool;
465   Tensor out = tf_bool.zeros(/*sizes=*/{1});
466 
467   allclose_out(
468       a,
469       b,
470       /*rtol=*/0.,
471       /*atol=*/0.,
472       /*equal_nan=*/false,
473       /*dummy_param=*/false,
474       out);
475 
476   auto out_data = out.data_ptr<bool>();
477   EXPECT_EQ(out_data[0], false);
478 }
479