8
8
9
9
#include " src/__support/CPP/type_traits.h"
10
10
#include " src/__support/FPUtil/FPBits.h"
11
+ #include " src/__support/macros/properties/types.h"
11
12
#include " test/UnitTest/FPMatcher.h"
12
13
#include " test/UnitTest/Test.h"
13
14
#include " utils/MPFRWrapper/MPFRUtils.h"
@@ -68,22 +69,82 @@ struct UnaryOpChecker : public virtual LIBC_NAMESPACE::testing::Test {
68
69
}
69
70
};
70
71
72
+ template <typename OutType, typename InType = OutType>
73
+ using BinaryOp = OutType(InType, InType);
74
+
75
+ template <typename OutType, typename InType, mpfr::Operation Op,
76
+ BinaryOp<OutType, InType> Func>
77
+ struct BinaryOpChecker : public virtual LIBC_NAMESPACE::testing::Test {
78
+ using FloatType = InType;
79
+ using FPBits = LIBC_NAMESPACE::fputil::FPBits<FloatType>;
80
+ using StorageType = typename FPBits::StorageType;
81
+
82
+ // Check in a range, return the number of failures.
83
+ uint64_t check (StorageType x_start, StorageType x_stop, StorageType y_start,
84
+ StorageType y_stop, mpfr::RoundingMode rounding) {
85
+ mpfr::ForceRoundingMode r (rounding);
86
+ if (!r.success )
87
+ return x_stop > x_start || y_stop > y_start;
88
+ StorageType xbits = x_start;
89
+ uint64_t failed = 0 ;
90
+ do {
91
+ FloatType x = FPBits (xbits).get_val ();
92
+ StorageType ybits = y_start;
93
+ do {
94
+ FloatType y = FPBits (ybits).get_val ();
95
+ mpfr::BinaryInput<FloatType> input{x, y};
96
+ bool correct = TEST_MPFR_MATCH_ROUNDING_SILENTLY (Op, input, Func (x, y),
97
+ 0.5 , rounding);
98
+ failed += (!correct);
99
+ // Uncomment to print out failed values.
100
+ // if (!correct) {
101
+ // EXPECT_MPFR_MATCH_ROUNDING(Op, input, Func(x, y), 0.5, rounding);
102
+ // }
103
+ } while (ybits++ < y_stop);
104
+ } while (xbits++ < x_stop);
105
+ return failed;
106
+ }
107
+ };
108
+
71
109
// Checker class needs inherit from LIBC_NAMESPACE::testing::Test and provide
72
110
// StorageType and check method.
73
- template <typename Checker>
111
+ template <typename Checker, size_t Increment = 1 << 20 >
74
112
struct LlvmLibcExhaustiveMathTest
75
113
: public virtual LIBC_NAMESPACE::testing::Test,
76
114
public Checker {
77
115
using FloatType = typename Checker::FloatType;
78
116
using FPBits = typename Checker::FPBits;
79
117
using StorageType = typename Checker::StorageType;
80
118
81
- static constexpr StorageType INCREMENT = (1 << 20 );
119
+ void explain_failed_range (std::stringstream &msg, StorageType x_begin,
120
+ StorageType x_end) {
121
+ #ifdef LIBC_TYPES_HAS_FLOAT16
122
+ using T = LIBC_NAMESPACE::cpp::conditional_t <
123
+ LIBC_NAMESPACE::cpp::is_same_v<FloatType, float16>, float , FloatType>;
124
+ #else
125
+ using T = FloatType;
126
+ #endif
127
+
128
+ msg << x_begin << " to " << x_end << " [0x" << std::hex << x_begin << " , 0x"
129
+ << x_end << " ), [" << std::hexfloat
130
+ << static_cast <T>(FPBits (x_begin).get_val ()) << " , "
131
+ << static_cast <T>(FPBits (x_end).get_val ()) << " )" ;
132
+ }
133
+
134
+ void explain_failed_range (std::stringstream &msg, StorageType x_begin,
135
+ StorageType x_end, StorageType y_begin,
136
+ StorageType y_end) {
137
+ msg << " x " ;
138
+ explain_failed_range (msg, x_begin, x_end);
139
+ msg << " , y " ;
140
+ explain_failed_range (msg, y_begin, y_end);
141
+ }
82
142
83
143
// Break [start, stop) into `nthreads` subintervals and apply *check to each
84
144
// subinterval in parallel.
85
- void test_full_range (StorageType start, StorageType stop,
86
- mpfr::RoundingMode rounding) {
145
+ template <typename ... T>
146
+ void test_full_range (mpfr::RoundingMode rounding, StorageType start,
147
+ StorageType stop, T... extra_range_bounds) {
87
148
int n_threads = std::thread::hardware_concurrency ();
88
149
std::vector<std::thread> thread_list;
89
150
std::mutex mx_cur_val;
@@ -102,8 +163,8 @@ struct LlvmLibcExhaustiveMathTest
102
163
return ;
103
164
104
165
range_begin = current_value;
105
- if (stop >= INCREMENT && stop - INCREMENT >= current_value) {
106
- range_end = current_value + INCREMENT ;
166
+ if (stop >= Increment && stop - Increment >= current_value) {
167
+ range_end = current_value + Increment ;
107
168
} else {
108
169
range_end = stop;
109
170
}
@@ -120,15 +181,14 @@ struct LlvmLibcExhaustiveMathTest
120
181
std::cout << msg.str () << std::flush;
121
182
}
122
183
123
- uint64_t failed_in_range =
124
- Checker::check ( range_begin, range_end, rounding);
184
+ uint64_t failed_in_range = Checker::check (
185
+ range_begin, range_end, extra_range_bounds... , rounding);
125
186
if (failed_in_range > 0 ) {
126
187
std::stringstream msg;
127
188
msg << " Test failed for " << std::dec << failed_in_range
128
- << " inputs in range: " << range_begin << " to " << range_end
129
- << " [0x" << std::hex << range_begin << " , 0x" << range_end
130
- << " ), [" << std::hexfloat << FPBits (range_begin).get_val ()
131
- << " , " << FPBits (range_end).get_val () << " )\n " ;
189
+ << " inputs in range: " ;
190
+ explain_failed_range (msg, start, stop, extra_range_bounds...);
191
+ msg << " \n " ;
132
192
std::cerr << msg.str () << std::flush;
133
193
134
194
failed.fetch_add (failed_in_range);
@@ -151,19 +211,46 @@ struct LlvmLibcExhaustiveMathTest
151
211
void test_full_range_all_roundings (StorageType start, StorageType stop) {
152
212
std::cout << " -- Testing for FE_TONEAREST in range [0x" << std::hex << start
153
213
<< " , 0x" << stop << " ) --" << std::dec << std::endl;
154
- test_full_range (start, stop, mpfr::RoundingMode::Nearest);
214
+ test_full_range (mpfr::RoundingMode::Nearest, start, stop );
155
215
156
216
std::cout << " -- Testing for FE_UPWARD in range [0x" << std::hex << start
157
217
<< " , 0x" << stop << " ) --" << std::dec << std::endl;
158
- test_full_range (start, stop, mpfr::RoundingMode::Upward);
218
+ test_full_range (mpfr::RoundingMode::Upward, start, stop );
159
219
160
220
std::cout << " -- Testing for FE_DOWNWARD in range [0x" << std::hex << start
161
221
<< " , 0x" << stop << " ) --" << std::dec << std::endl;
162
- test_full_range (start, stop, mpfr::RoundingMode::Downward);
222
+ test_full_range (mpfr::RoundingMode::Downward, start, stop );
163
223
164
224
std::cout << " -- Testing for FE_TOWARDZERO in range [0x" << std::hex
165
225
<< start << " , 0x" << stop << " ) --" << std::dec << std::endl;
166
- test_full_range (start, stop, mpfr::RoundingMode::TowardZero);
226
+ test_full_range (mpfr::RoundingMode::TowardZero, start, stop);
227
+ };
228
+
229
+ void test_full_range_all_roundings (StorageType x_start, StorageType x_stop,
230
+ StorageType y_start, StorageType y_stop) {
231
+ std::cout << " -- Testing for FE_TONEAREST in x range [0x" << std::hex
232
+ << x_start << " , 0x" << x_stop << " ), y range [0x" << y_start
233
+ << " , 0x" << y_stop << " ) --" << std::dec << std::endl;
234
+ test_full_range (mpfr::RoundingMode::Nearest, x_start, x_stop, y_start,
235
+ y_stop);
236
+
237
+ std::cout << " -- Testing for FE_UPWARD in x range [0x" << std::hex
238
+ << x_start << " , 0x" << x_stop << " ), y range [0x" << y_start
239
+ << " , 0x" << y_stop << " ) --" << std::dec << std::endl;
240
+ test_full_range (mpfr::RoundingMode::Upward, x_start, x_stop, y_start,
241
+ y_stop);
242
+
243
+ std::cout << " -- Testing for FE_DOWNWARD in x range [0x" << std::hex
244
+ << x_start << " , 0x" << x_stop << " ), y range [0x" << y_start
245
+ << " , 0x" << y_stop << " ) --" << std::dec << std::endl;
246
+ test_full_range (mpfr::RoundingMode::Downward, x_start, x_stop, y_start,
247
+ y_stop);
248
+
249
+ std::cout << " -- Testing for FE_TOWARDZERO in x range [0x" << std::hex
250
+ << x_start << " , 0x" << x_stop << " ), y range [0x" << y_start
251
+ << " , 0x" << y_stop << " ) --" << std::dec << std::endl;
252
+ test_full_range (mpfr::RoundingMode::TowardZero, x_start, x_stop, y_start,
253
+ y_stop);
167
254
};
168
255
};
169
256
@@ -175,3 +262,8 @@ template <typename OutType, typename InType, mpfr::Operation Op,
175
262
UnaryOp<OutType, InType> Func>
176
263
using LlvmLibcUnaryNarrowingOpExhaustiveMathTest =
177
264
LlvmLibcExhaustiveMathTest<UnaryOpChecker<OutType, InType, Op, Func>>;
265
+
266
+ template <typename FloatType, mpfr::Operation Op, BinaryOp<FloatType> Func>
267
+ using LlvmLibcBinaryOpExhaustiveMathTest =
268
+ LlvmLibcExhaustiveMathTest<BinaryOpChecker<FloatType, FloatType, Op, Func>,
269
+ 1 << 2 >;
0 commit comments