10
10
#define LLVM_LIBC_TEST_SRC_MATH_SMOKE_DIVTEST_H
11
11
12
12
#include " hdr/fenv_macros.h"
13
+ #include " src/__support/FPUtil/BasicOperations.h"
13
14
#include " test/UnitTest/FEnvSafeTest.h"
14
15
#include " test/UnitTest/FPMatcher.h"
16
+ #include " test/UnitTest/RoundingModeUtils.h"
15
17
#include " test/UnitTest/Test.h"
16
18
17
19
template <typename OutType, typename InType>
18
20
class DivTest : public LIBC_NAMESPACE ::testing::FEnvSafeTest {
19
21
20
22
DECLARE_SPECIAL_CONSTANTS (OutType)
21
23
24
+ struct InConstants {
25
+ DECLARE_SPECIAL_CONSTANTS (InType)
26
+ };
27
+
28
+ using InFPBits = typename InConstants::FPBits;
29
+ using InStorageType = typename InConstants::StorageType;
30
+
22
31
public:
23
- typedef OutType (*DivFunc )(InType, InType);
32
+ using DivFunc = OutType (*)(InType, InType);
24
33
25
34
void test_special_numbers (DivFunc func) {
26
35
EXPECT_FP_IS_NAN (func (aNaN, aNaN));
36
+ EXPECT_FP_IS_NAN_WITH_EXCEPTION (func (sNaN , sNaN ), FE_INVALID);
27
37
28
- EXPECT_FP_EQ (inf, func (inf, zero));
29
- EXPECT_FP_EQ (neg_inf, func (neg_inf, zero));
30
- EXPECT_FP_EQ (neg_inf, func (inf, neg_zero));
31
- EXPECT_FP_EQ (inf, func (neg_inf, neg_zero));
38
+ InType qnan_42 = InFPBits::quiet_nan (Sign::POS, 0x42 ).get_val ();
39
+ EXPECT_FP_EQ (InType (0x42 .0p+0 ),
40
+ LIBC_NAMESPACE::fputil::getpayload (func (qnan_42, zero)));
41
+ EXPECT_FP_EQ (InType (0x42 .0p+0 ),
42
+ LIBC_NAMESPACE::fputil::getpayload (func (zero, qnan_42)));
43
+
44
+ if constexpr (sizeof (OutType) < sizeof (InType)) {
45
+ InStorageType max_payload = InFPBits::FRACTION_MASK >> 1 ;
46
+ InType qnan_max = InFPBits::quiet_nan (Sign::POS, max_payload).get_val ();
47
+ EXPECT_FP_EQ (zero,
48
+ LIBC_NAMESPACE::fputil::getpayload (func (qnan_max, zero)));
49
+ EXPECT_FP_EQ (zero,
50
+ LIBC_NAMESPACE::fputil::getpayload (func (zero, qnan_max)));
51
+ EXPECT_FP_EQ (InType (0x42 .0p+0 ),
52
+ LIBC_NAMESPACE::fputil::getpayload (func (qnan_max, qnan_42)));
53
+ EXPECT_FP_EQ (InType (0x42 .0p+0 ),
54
+ LIBC_NAMESPACE::fputil::getpayload (func (qnan_42, qnan_max)));
55
+ }
32
56
33
57
EXPECT_FP_EQ (inf, func (inf, zero));
34
58
EXPECT_FP_EQ (neg_inf, func (neg_inf, zero));
@@ -52,16 +76,100 @@ class DivTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {
52
76
EXPECT_FP_IS_NAN_WITH_EXCEPTION (func (neg_zero, neg_zero), FE_INVALID);
53
77
54
78
EXPECT_FP_IS_NAN_WITH_EXCEPTION (func (inf, inf), FE_INVALID);
79
+ EXPECT_MATH_ERRNO (EDOM);
55
80
EXPECT_FP_IS_NAN_WITH_EXCEPTION (func (neg_inf, inf), FE_INVALID);
81
+ EXPECT_MATH_ERRNO (EDOM);
56
82
EXPECT_FP_IS_NAN_WITH_EXCEPTION (func (inf, neg_inf), FE_INVALID);
83
+ EXPECT_MATH_ERRNO (EDOM);
57
84
EXPECT_FP_IS_NAN_WITH_EXCEPTION (func (neg_inf, neg_inf), FE_INVALID);
85
+ EXPECT_MATH_ERRNO (EDOM);
86
+ }
87
+
88
+ void test_range_errors (DivFunc func) {
89
+ using namespace LIBC_NAMESPACE ::fputil::testing;
90
+
91
+ if (ForceRoundingMode r (RoundingMode::Nearest); r.success ) {
92
+ EXPECT_FP_EQ_WITH_EXCEPTION (inf, func (max_normal, min_normal),
93
+ FE_OVERFLOW | FE_INEXACT);
94
+ EXPECT_MATH_ERRNO (ERANGE);
95
+ EXPECT_FP_EQ_WITH_EXCEPTION (-inf, func (neg_max_normal, min_denormal),
96
+ FE_OVERFLOW | FE_INEXACT);
97
+ EXPECT_MATH_ERRNO (ERANGE);
98
+
99
+ EXPECT_FP_EQ_WITH_EXCEPTION (zero, func (min_denormal, max_normal),
100
+ FE_UNDERFLOW | FE_INEXACT);
101
+ EXPECT_MATH_ERRNO (ERANGE);
102
+ EXPECT_FP_EQ_WITH_EXCEPTION (neg_zero, func (neg_min_denormal, max_normal),
103
+ FE_UNDERFLOW | FE_INEXACT);
104
+ EXPECT_MATH_ERRNO (ERANGE);
105
+ }
106
+
107
+ if (ForceRoundingMode r (RoundingMode::TowardZero); r.success ) {
108
+ EXPECT_FP_EQ_WITH_EXCEPTION (max_normal, func (max_normal, min_normal),
109
+ FE_OVERFLOW | FE_INEXACT);
110
+ EXPECT_MATH_ERRNO (ERANGE);
111
+ EXPECT_FP_EQ_WITH_EXCEPTION (neg_max_normal,
112
+ func (neg_max_normal, min_denormal),
113
+ FE_OVERFLOW | FE_INEXACT);
114
+ EXPECT_MATH_ERRNO (ERANGE);
115
+
116
+ EXPECT_FP_EQ_WITH_EXCEPTION (zero, func (min_denormal, max_normal),
117
+ FE_UNDERFLOW | FE_INEXACT);
118
+ EXPECT_MATH_ERRNO (ERANGE);
119
+ EXPECT_FP_EQ_WITH_EXCEPTION (neg_zero, func (neg_min_denormal, max_normal),
120
+ FE_UNDERFLOW | FE_INEXACT);
121
+ EXPECT_MATH_ERRNO (ERANGE);
122
+ }
123
+
124
+ if (ForceRoundingMode r (RoundingMode::Downward); r.success ) {
125
+ EXPECT_FP_EQ_WITH_EXCEPTION (max_normal, func (max_normal, min_normal),
126
+ FE_OVERFLOW | FE_INEXACT);
127
+ EXPECT_MATH_ERRNO (ERANGE);
128
+ EXPECT_FP_EQ_WITH_EXCEPTION (-inf, func (neg_max_normal, min_denormal),
129
+ FE_OVERFLOW | FE_INEXACT);
130
+ EXPECT_MATH_ERRNO (ERANGE);
131
+
132
+ EXPECT_FP_EQ_WITH_EXCEPTION (zero, func (min_denormal, max_normal),
133
+ FE_UNDERFLOW | FE_INEXACT);
134
+ EXPECT_MATH_ERRNO (ERANGE);
135
+ EXPECT_FP_EQ_WITH_EXCEPTION (neg_min_denormal,
136
+ func (neg_min_denormal, max_normal),
137
+ FE_UNDERFLOW | FE_INEXACT);
138
+ EXPECT_MATH_ERRNO (ERANGE);
139
+ }
140
+
141
+ if (ForceRoundingMode r (RoundingMode::Upward); r.success ) {
142
+ EXPECT_FP_EQ_WITH_EXCEPTION (inf, func (max_normal, min_normal),
143
+ FE_OVERFLOW | FE_INEXACT);
144
+ EXPECT_MATH_ERRNO (ERANGE);
145
+ EXPECT_FP_EQ_WITH_EXCEPTION (neg_max_normal,
146
+ func (neg_max_normal, min_denormal),
147
+ FE_OVERFLOW | FE_INEXACT);
148
+ EXPECT_MATH_ERRNO (ERANGE);
149
+
150
+ EXPECT_FP_EQ_WITH_EXCEPTION (min_denormal, func (min_denormal, max_normal),
151
+ FE_UNDERFLOW | FE_INEXACT);
152
+ EXPECT_MATH_ERRNO (ERANGE);
153
+ EXPECT_FP_EQ_WITH_EXCEPTION (neg_zero, func (neg_min_denormal, max_normal),
154
+ FE_UNDERFLOW | FE_INEXACT);
155
+ EXPECT_MATH_ERRNO (ERANGE);
156
+ }
157
+ }
158
+
159
+ void test_inexact_results (DivFunc func) {
160
+ func (InType (1.0 ), InType (3.0 ));
161
+ EXPECT_FP_EXCEPTION (FE_INEXACT);
58
162
}
59
163
};
60
164
61
165
#define LIST_DIV_TESTS (OutType, InType, func ) \
62
166
using LlvmLibcDivTest = DivTest<OutType, InType>; \
63
167
TEST_F (LlvmLibcDivTest, SpecialNumbers) { test_special_numbers (&func); } \
64
168
TEST_F (LlvmLibcDivTest, DivisionByZero) { test_division_by_zero (&func); } \
65
- TEST_F (LlvmLibcDivTest, InvalidOperations) { test_invalid_operations (&func); }
169
+ TEST_F (LlvmLibcDivTest, InvalidOperations) { \
170
+ test_invalid_operations (&func); \
171
+ } \
172
+ TEST_F (LlvmLibcDivTest, RangeErrors) { test_range_errors (&func); } \
173
+ TEST_F (LlvmLibcDivTest, InexactResults) { test_inexact_results (&func); }
66
174
67
175
#endif // LLVM_LIBC_TEST_SRC_MATH_SMOKE_DIVTEST_H
0 commit comments