xref: /aosp_15_r20/external/llvm-libc/test/src/math/smoke/SubTest.h (revision 71db0c75aadcf003ffe3238005f61d7618a3fead)
1 //===-- Utility class to test different flavors of float sub ----*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLVM_LIBC_TEST_SRC_MATH_SMOKE_SUBTEST_H
10 #define LLVM_LIBC_TEST_SRC_MATH_SMOKE_SUBTEST_H
11 
12 #include "hdr/errno_macros.h"
13 #include "hdr/fenv_macros.h"
14 #include "src/__support/macros/properties/os.h"
15 #include "test/UnitTest/FEnvSafeTest.h"
16 #include "test/UnitTest/FPMatcher.h"
17 #include "test/UnitTest/Test.h"
18 
19 using LIBC_NAMESPACE::Sign;
20 
21 template <typename OutType, typename InType>
22 class SubTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
23 
24   DECLARE_SPECIAL_CONSTANTS(OutType)
25 
26   struct InConstants {
27     DECLARE_SPECIAL_CONSTANTS(InType)
28   };
29 
30   using InFPBits = typename InConstants::FPBits;
31   using InStorageType = typename InConstants::StorageType;
32 
33   InConstants in;
34 
35 public:
36   using SubFunc = OutType (*)(InType, InType);
37 
test_special_numbers(SubFunc func)38   void test_special_numbers(SubFunc func) {
39     EXPECT_FP_IS_NAN(func(in.aNaN, in.aNaN));
40     EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.sNaN, in.sNaN), FE_INVALID);
41 
42     InType qnan_42 = InFPBits::quiet_nan(Sign::POS, 0x42).get_val();
43     EXPECT_FP_IS_NAN(func(qnan_42, in.zero));
44     EXPECT_FP_IS_NAN(func(in.zero, qnan_42));
45 
46     EXPECT_FP_EQ(inf, func(in.inf, in.zero));
47     EXPECT_FP_EQ(neg_inf, func(in.neg_inf, in.zero));
48     EXPECT_FP_EQ(inf, func(in.inf, in.neg_zero));
49     EXPECT_FP_EQ(neg_inf, func(in.neg_inf, in.neg_zero));
50   }
51 
test_invalid_operations(SubFunc func)52   void test_invalid_operations(SubFunc func) {
53     EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.inf, in.inf), FE_INVALID);
54     EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(in.neg_inf, in.neg_inf), FE_INVALID);
55   }
56 
test_range_errors(SubFunc func)57   void test_range_errors(SubFunc func) {
58 #ifndef LIBC_TARGET_OS_IS_WINDOWS
59     using namespace LIBC_NAMESPACE::fputil::testing;
60 
61     if (ForceRoundingMode r(RoundingMode::Nearest); r.success) {
62       EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(in.max_normal, in.neg_max_normal),
63                                   FE_OVERFLOW | FE_INEXACT);
64       EXPECT_MATH_ERRNO(ERANGE);
65       EXPECT_FP_EQ_WITH_EXCEPTION(-inf, func(in.neg_max_normal, in.max_normal),
66                                   FE_OVERFLOW | FE_INEXACT);
67       EXPECT_MATH_ERRNO(ERANGE);
68 
69       EXPECT_FP_EQ_WITH_EXCEPTION(zero,
70                                   func(in.min_denormal, in.neg_min_denormal),
71                                   FE_UNDERFLOW | FE_INEXACT);
72       EXPECT_MATH_ERRNO(ERANGE);
73       EXPECT_FP_EQ_WITH_EXCEPTION(neg_zero,
74                                   func(in.neg_min_denormal, in.min_denormal),
75                                   FE_UNDERFLOW | FE_INEXACT);
76       EXPECT_MATH_ERRNO(ERANGE);
77     }
78 
79     if (ForceRoundingMode r(RoundingMode::TowardZero); r.success) {
80       EXPECT_FP_EQ_WITH_EXCEPTION(max_normal,
81                                   func(in.max_normal, in.neg_max_normal),
82                                   FE_OVERFLOW | FE_INEXACT);
83       EXPECT_FP_EQ_WITH_EXCEPTION(neg_max_normal,
84                                   func(in.neg_max_normal, in.max_normal),
85                                   FE_OVERFLOW | FE_INEXACT);
86 
87       EXPECT_FP_EQ_WITH_EXCEPTION(zero,
88                                   func(in.min_denormal, in.neg_min_denormal),
89                                   FE_UNDERFLOW | FE_INEXACT);
90       EXPECT_MATH_ERRNO(ERANGE);
91       EXPECT_FP_EQ_WITH_EXCEPTION(neg_zero,
92                                   func(in.neg_min_denormal, in.min_denormal),
93                                   FE_UNDERFLOW | FE_INEXACT);
94       EXPECT_MATH_ERRNO(ERANGE);
95     }
96 
97     if (ForceRoundingMode r(RoundingMode::Downward); r.success) {
98       EXPECT_FP_EQ_WITH_EXCEPTION(max_normal,
99                                   func(in.max_normal, in.neg_max_normal),
100                                   FE_OVERFLOW | FE_INEXACT);
101       EXPECT_FP_EQ_WITH_EXCEPTION(-inf, func(in.neg_max_normal, in.max_normal),
102                                   FE_OVERFLOW | FE_INEXACT);
103       EXPECT_MATH_ERRNO(ERANGE);
104 
105       EXPECT_FP_EQ_WITH_EXCEPTION(zero,
106                                   func(in.min_denormal, in.neg_min_denormal),
107                                   FE_UNDERFLOW | FE_INEXACT);
108       EXPECT_MATH_ERRNO(ERANGE);
109       EXPECT_FP_EQ_WITH_EXCEPTION(neg_min_denormal,
110                                   func(in.neg_min_denormal, in.min_denormal),
111                                   FE_UNDERFLOW | FE_INEXACT);
112       EXPECT_MATH_ERRNO(ERANGE);
113     }
114 
115     if (ForceRoundingMode r(RoundingMode::Upward); r.success) {
116       EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(in.max_normal, in.neg_max_normal),
117                                   FE_OVERFLOW | FE_INEXACT);
118       EXPECT_MATH_ERRNO(ERANGE);
119       EXPECT_FP_EQ_WITH_EXCEPTION(neg_max_normal,
120                                   func(in.neg_max_normal, in.max_normal),
121                                   FE_OVERFLOW | FE_INEXACT);
122 
123       EXPECT_FP_EQ_WITH_EXCEPTION(min_denormal,
124                                   func(in.min_denormal, in.neg_min_denormal),
125                                   FE_UNDERFLOW | FE_INEXACT);
126       EXPECT_MATH_ERRNO(ERANGE);
127       EXPECT_FP_EQ_WITH_EXCEPTION(neg_zero,
128                                   func(in.neg_min_denormal, in.min_denormal),
129                                   FE_UNDERFLOW | FE_INEXACT);
130       EXPECT_MATH_ERRNO(ERANGE);
131     }
132 #endif
133   }
134 
test_inexact_results(SubFunc func)135   void test_inexact_results(SubFunc func) {
136     func(InType(1.0), in.min_denormal);
137     EXPECT_FP_EXCEPTION(FE_INEXACT);
138   }
139 };
140 
141 #define LIST_SUB_TESTS(OutType, InType, func)                                  \
142   using LlvmLibcSubTest = SubTest<OutType, InType>;                            \
143   TEST_F(LlvmLibcSubTest, SpecialNumbers) { test_special_numbers(&func); }     \
144   TEST_F(LlvmLibcSubTest, InvalidOperations) {                                 \
145     test_invalid_operations(&func);                                            \
146   }                                                                            \
147   TEST_F(LlvmLibcSubTest, RangeErrors) { test_range_errors(&func); }           \
148   TEST_F(LlvmLibcSubTest, InexactResults) { test_inexact_results(&func); }
149 
150 #endif // LLVM_LIBC_TEST_SRC_MATH_SMOKE_SUBTEST_H
151