]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // (C) Copyright John Maddock 2007. |
2 | // Use, modification and distribution are subject to the | |
3 | // Boost Software License, Version 1.0. (See accompanying file | |
4 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
5 | ||
6 | #ifdef _MSC_VER | |
92f5a8d4 | 7 | #define _SCL_SECURE_NO_WARNINGS |
7c673cae FG |
8 | #endif |
9 | ||
10 | #include <boost/detail/lightweight_test.hpp> | |
11 | #include <boost/math/special_functions/round.hpp> | |
12 | #include <boost/math/special_functions/trunc.hpp> | |
13 | #include <boost/math/special_functions/modf.hpp> | |
14 | #include <boost/math/special_functions/sign.hpp> | |
15 | #include <boost/random/mersenne_twister.hpp> | |
16 | #include "test.hpp" | |
17 | ||
92f5a8d4 TL |
18 | #if !defined(TEST_MPF_50) && !defined(TEST_MPF) && !defined(TEST_BACKEND) && !defined(TEST_CPP_DEC_FLOAT) && !defined(TEST_MPFR) && !defined(TEST_MPFR_50) && !defined(TEST_MPFI_50) && !defined(TEST_FLOAT128) && !defined(TEST_CPP_BIN_FLOAT) |
19 | #define TEST_MPF_50 | |
20 | #define TEST_MPFR_50 | |
21 | #define TEST_MPFI_50 | |
22 | #define TEST_BACKEND | |
23 | #define TEST_CPP_DEC_FLOAT | |
24 | #define TEST_FLOAT128 | |
25 | #define TEST_CPP_BIN_FLOAT | |
7c673cae FG |
26 | |
27 | #ifdef _MSC_VER | |
28 | #pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!") | |
29 | #endif | |
30 | #ifdef __GNUC__ | |
31 | #pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!" | |
32 | #endif | |
33 | ||
34 | #endif | |
35 | ||
36 | #if defined(TEST_MPF_50) | |
37 | #include <boost/multiprecision/gmp.hpp> | |
38 | #endif | |
39 | #ifdef TEST_MPFR_50 | |
40 | #include <boost/multiprecision/mpfr.hpp> | |
41 | #endif | |
42 | #ifdef TEST_MPFI_50 | |
43 | #include <boost/multiprecision/mpfi.hpp> | |
44 | #endif | |
45 | #ifdef TEST_BACKEND | |
46 | #include <boost/multiprecision/concepts/mp_number_archetypes.hpp> | |
47 | #endif | |
48 | #ifdef TEST_CPP_DEC_FLOAT | |
49 | #include <boost/multiprecision/cpp_dec_float.hpp> | |
50 | #endif | |
51 | #ifdef TEST_CPP_BIN_FLOAT | |
52 | #include <boost/multiprecision/cpp_bin_float.hpp> | |
53 | #endif | |
54 | #ifdef TEST_FLOAT128 | |
55 | #include <boost/multiprecision/float128.hpp> | |
56 | #endif | |
57 | ||
58 | #ifdef BOOST_MSVC | |
92f5a8d4 | 59 | #pragma warning(disable : 4127) |
7c673cae FG |
60 | #endif |
61 | ||
62 | boost::mt19937 rng; | |
63 | ||
64 | template <class T> | |
65 | T get_random() | |
66 | { | |
67 | // | |
68 | // Fill all the bits in T with random values, | |
69 | // likewise set the exponent to a random value | |
70 | // that will still fit inside a T, and always | |
71 | // have a remainder as well as an integer part. | |
72 | // | |
92f5a8d4 TL |
73 | int bits = boost::math::tools::digits<T>(); |
74 | int shift = 0; | |
7c673cae | 75 | int exponent = rng() % (bits - 4); |
92f5a8d4 TL |
76 | T result = 0; |
77 | while (bits > 0) | |
7c673cae FG |
78 | { |
79 | result += ldexp(static_cast<T>(rng()), shift); | |
80 | shift += std::numeric_limits<int>::digits; | |
81 | bits -= std::numeric_limits<int>::digits; | |
82 | } | |
83 | return rng() & 1u ? T(-ldexp(frexp(result, &bits), exponent)) : T(ldexp(frexp(result, &bits), exponent)); | |
84 | } | |
85 | ||
86 | template <class T, class U> | |
1e59de90 | 87 | typename std::enable_if<!boost::multiprecision::is_interval_number<T>::value>::type check_within_half(T a, U u) |
7c673cae FG |
88 | { |
89 | BOOST_MATH_STD_USING | |
92f5a8d4 | 90 | if (fabs(a - u) > 0.5f) |
7c673cae FG |
91 | { |
92 | BOOST_ERROR("Rounded result differed by more than 0.5 from the original"); | |
93 | std::cerr << "Values were: " << std::setprecision(35) << std::setw(40) | |
92f5a8d4 | 94 | << std::left << a << u << std::endl; |
7c673cae | 95 | } |
92f5a8d4 | 96 | if ((fabs(a - u) == 0.5f) && (fabs(static_cast<T>(u)) < fabs(a))) |
7c673cae FG |
97 | { |
98 | BOOST_ERROR("Rounded result was towards zero with boost::round"); | |
99 | std::cerr << "Values were: " << std::setprecision(35) << std::setw(40) | |
92f5a8d4 | 100 | << std::left << a << u << std::endl; |
7c673cae FG |
101 | } |
102 | } | |
103 | template <class T, class U> | |
1e59de90 | 104 | typename std::enable_if<boost::multiprecision::is_interval_number<T>::value>::type check_within_half(T a, U u) |
7c673cae FG |
105 | { |
106 | BOOST_MATH_STD_USING | |
92f5a8d4 | 107 | if (upper(T(fabs(a - u))) > 0.5f) |
7c673cae FG |
108 | { |
109 | BOOST_ERROR("Rounded result differed by more than 0.5 from the original"); | |
110 | std::cerr << "Values were: " << std::setprecision(35) << std::setw(40) | |
92f5a8d4 | 111 | << std::left << a << u << std::endl; |
7c673cae | 112 | } |
92f5a8d4 | 113 | if ((upper(T(fabs(a - u))) == 0.5f) && (fabs(static_cast<T>(u)) < fabs(a))) |
7c673cae FG |
114 | { |
115 | BOOST_ERROR("Rounded result was towards zero with boost::round"); | |
116 | std::cerr << "Values were: " << std::setprecision(35) << std::setw(40) | |
92f5a8d4 | 117 | << std::left << a << u << std::endl; |
7c673cae FG |
118 | } |
119 | } | |
120 | ||
121 | // | |
122 | // We may not have an abs overload for long long so provide a fall back: | |
123 | // | |
124 | inline unsigned safe_abs(int const& v) | |
125 | { | |
92f5a8d4 | 126 | return v < 0 ? static_cast<unsigned>(1u) + static_cast<unsigned>(-(v + 1)) : v; |
7c673cae FG |
127 | } |
128 | inline unsigned long safe_abs(long const& v) | |
129 | { | |
92f5a8d4 | 130 | return v < 0 ? static_cast<unsigned long>(1u) + static_cast<unsigned long>(-(v + 1)) : v; |
7c673cae FG |
131 | } |
132 | inline unsigned long long safe_abs(long long const& v) | |
133 | { | |
92f5a8d4 | 134 | return v < 0 ? static_cast<unsigned long long>(1u) + static_cast<unsigned long long>(-(v + 1)) : v; |
7c673cae FG |
135 | } |
136 | template <class T> | |
1e59de90 | 137 | inline typename std::enable_if<!boost::multiprecision::detail::is_integral<T>::value, T>::type safe_abs(T const& v) |
7c673cae FG |
138 | { |
139 | return v < 0 ? -v : v; | |
140 | } | |
141 | ||
142 | template <class T, class U> | |
143 | void check_trunc_result(T a, U u) | |
144 | { | |
145 | BOOST_MATH_STD_USING | |
92f5a8d4 | 146 | if (fabs(a - u) >= 1) |
7c673cae FG |
147 | { |
148 | BOOST_ERROR("Rounded result differed by more than 1 from the original"); | |
149 | std::cerr << "Values were: " << std::setprecision(35) << std::setw(40) | |
92f5a8d4 | 150 | << std::left << a << u << std::endl; |
7c673cae | 151 | } |
92f5a8d4 | 152 | if (abs(a) < safe_abs(u)) |
7c673cae FG |
153 | { |
154 | BOOST_ERROR("Truncated result had larger absolute value than the original"); | |
155 | std::cerr << "Values were: " << std::setprecision(35) << std::setw(40) | |
92f5a8d4 | 156 | << std::left << a << u << std::endl; |
7c673cae | 157 | } |
92f5a8d4 | 158 | if (fabs(static_cast<T>(u)) > fabs(a)) |
7c673cae FG |
159 | { |
160 | BOOST_ERROR("Rounded result was away from zero with boost::trunc"); | |
161 | std::cerr << "Values were: " << std::setprecision(35) << std::setw(40) | |
92f5a8d4 | 162 | << std::left << a << u << std::endl; |
7c673cae FG |
163 | } |
164 | } | |
165 | ||
166 | template <class T, class U> | |
167 | void check_modf_result(T a, T fract, U ipart) | |
168 | { | |
169 | BOOST_MATH_STD_USING | |
92f5a8d4 | 170 | if (fract + ipart != a) |
7c673cae FG |
171 | { |
172 | BOOST_ERROR("Fractional and integer results do not add up to the original value"); | |
173 | std::cerr << "Values were: " << std::setprecision(35) << " " | |
92f5a8d4 | 174 | << std::left << a << ipart << " " << fract << std::endl; |
7c673cae | 175 | } |
92f5a8d4 | 176 | if ((boost::math::sign(a) != boost::math::sign(fract)) && boost::math::sign(fract)) |
7c673cae FG |
177 | { |
178 | BOOST_ERROR("Original and fractional parts have differing signs"); | |
179 | std::cerr << "Values were: " << std::setprecision(35) << " " | |
92f5a8d4 | 180 | << std::left << a << ipart << " " << fract << std::endl; |
7c673cae | 181 | } |
92f5a8d4 | 182 | if ((boost::math::sign(a) != boost::math::sign(ipart)) && boost::math::sign(ipart)) |
7c673cae FG |
183 | { |
184 | BOOST_ERROR("Original and integer parts have differing signs"); | |
185 | std::cerr << "Values were: " << std::setprecision(35) << " " | |
92f5a8d4 | 186 | << std::left << a << ipart << " " << ipart << std::endl; |
7c673cae | 187 | } |
92f5a8d4 | 188 | if (fabs(a - ipart) >= 1) |
7c673cae FG |
189 | { |
190 | BOOST_ERROR("Rounded result differed by more than 1 from the original"); | |
191 | std::cerr << "Values were: " << std::setprecision(35) << std::setw(40) | |
92f5a8d4 | 192 | << std::left << a << ipart << std::endl; |
7c673cae FG |
193 | } |
194 | } | |
195 | ||
196 | template <class T> | |
197 | void test() | |
198 | { | |
199 | BOOST_MATH_STD_USING | |
200 | ||
92f5a8d4 | 201 | for (int i = 0; i < 1000; ++i) |
7c673cae FG |
202 | { |
203 | T arg = get_random<T>(); | |
92f5a8d4 | 204 | T r = round(arg); |
7c673cae FG |
205 | check_within_half(arg, r); |
206 | BOOST_TEST(r == round(arg + 0)); | |
207 | r = trunc(arg); | |
208 | check_trunc_result(arg, r); | |
209 | BOOST_TEST(r == trunc(arg + 0)); | |
210 | T frac = modf(arg, &r); | |
211 | check_modf_result(arg, frac, r); | |
212 | ||
92f5a8d4 | 213 | if (abs(r) < (std::numeric_limits<int>::max)()) |
7c673cae FG |
214 | { |
215 | int i = iround(arg); | |
216 | check_within_half(arg, i); | |
217 | BOOST_TEST(i == iround(arg + 0)); | |
218 | i = itrunc(arg); | |
219 | check_trunc_result(arg, i); | |
220 | BOOST_TEST(i == itrunc(arg + 0)); | |
221 | r = modf(arg, &i); | |
222 | check_modf_result(arg, r, i); | |
223 | } | |
92f5a8d4 | 224 | if (abs(r) < (std::numeric_limits<long>::max)()) |
7c673cae FG |
225 | { |
226 | long l = lround(arg); | |
227 | check_within_half(arg, l); | |
228 | BOOST_TEST(l == lround(arg + 0)); | |
229 | l = ltrunc(arg); | |
230 | check_trunc_result(arg, l); | |
231 | BOOST_TEST(l == ltrunc(arg + 0)); | |
232 | r = modf(arg, &l); | |
233 | check_modf_result(arg, r, l); | |
234 | } | |
235 | ||
236 | #ifdef BOOST_HAS_LONG_LONG | |
1e59de90 | 237 | if (abs(r) < (std::numeric_limits<long long>::max)()) |
7c673cae | 238 | { |
1e59de90 | 239 | long long ll = llround(arg); |
7c673cae FG |
240 | check_within_half(arg, ll); |
241 | BOOST_TEST(ll == llround(arg + 0)); | |
242 | ll = lltrunc(arg); | |
243 | check_trunc_result(arg, ll); | |
244 | BOOST_TEST(ll == lltrunc(arg + 0)); | |
245 | r = modf(arg, &ll); | |
246 | check_modf_result(arg, r, ll); | |
247 | } | |
248 | #endif | |
249 | } | |
250 | // | |
251 | // Test boundary cases: | |
252 | // | |
92f5a8d4 | 253 | if (std::numeric_limits<T>::digits >= std::numeric_limits<int>::digits) |
7c673cae FG |
254 | { |
255 | int si = iround(static_cast<T>((std::numeric_limits<int>::max)())); | |
256 | check_within_half(static_cast<T>((std::numeric_limits<int>::max)()), si); | |
257 | BOOST_TEST(si == iround(static_cast<T>((std::numeric_limits<int>::max)()) + 0)); | |
258 | si = iround(static_cast<T>((std::numeric_limits<int>::min)())); | |
259 | check_within_half(static_cast<T>((std::numeric_limits<int>::min)()), si); | |
260 | BOOST_TEST(si == iround(static_cast<T>((std::numeric_limits<int>::min)()) + 0)); | |
261 | si = itrunc(static_cast<T>((std::numeric_limits<int>::max)())); | |
262 | check_trunc_result(static_cast<T>((std::numeric_limits<int>::max)()), si); | |
263 | BOOST_TEST(si == itrunc(static_cast<T>((std::numeric_limits<int>::max)()) + 0)); | |
264 | si = itrunc(static_cast<T>((std::numeric_limits<int>::min)())); | |
265 | check_trunc_result(static_cast<T>((std::numeric_limits<int>::min)()), si); | |
266 | BOOST_TEST(si == itrunc(static_cast<T>((std::numeric_limits<int>::min)()) + 0)); | |
267 | ||
268 | si = iround(static_cast<T>((std::numeric_limits<int>::max)() - 1)); | |
269 | check_within_half(static_cast<T>((std::numeric_limits<int>::max)() - 1), si); | |
270 | si = iround(static_cast<T>((std::numeric_limits<int>::min)() + 1)); | |
271 | check_within_half(static_cast<T>((std::numeric_limits<int>::min)() + 1), si); | |
272 | si = itrunc(static_cast<T>((std::numeric_limits<int>::max)() - 1)); | |
273 | check_trunc_result(static_cast<T>((std::numeric_limits<int>::max)() - 1), si); | |
274 | si = itrunc(static_cast<T>((std::numeric_limits<int>::min)() + 1)); | |
275 | check_trunc_result(static_cast<T>((std::numeric_limits<int>::min)() + 1), si); | |
276 | } | |
92f5a8d4 | 277 | if (std::numeric_limits<T>::digits >= std::numeric_limits<long>::digits) |
7c673cae FG |
278 | { |
279 | long k = lround(static_cast<T>((std::numeric_limits<long>::max)())); | |
280 | check_within_half(static_cast<T>((std::numeric_limits<long>::max)()), k); | |
281 | BOOST_TEST(k == lround(static_cast<T>((std::numeric_limits<long>::max)()) + 0)); | |
282 | k = lround(static_cast<T>((std::numeric_limits<long>::min)())); | |
283 | check_within_half(static_cast<T>((std::numeric_limits<long>::min)()), k); | |
284 | BOOST_TEST(k == lround(static_cast<T>((std::numeric_limits<long>::min)()) + 0)); | |
285 | k = ltrunc(static_cast<T>((std::numeric_limits<long>::max)())); | |
286 | check_trunc_result(static_cast<T>((std::numeric_limits<long>::max)()), k); | |
287 | BOOST_TEST(k == ltrunc(static_cast<T>((std::numeric_limits<long>::max)()) + 0)); | |
288 | k = ltrunc(static_cast<T>((std::numeric_limits<long>::min)())); | |
289 | check_trunc_result(static_cast<T>((std::numeric_limits<long>::min)()), k); | |
290 | BOOST_TEST(k == ltrunc(static_cast<T>((std::numeric_limits<long>::min)()) + 0)); | |
291 | ||
292 | k = lround(static_cast<T>((std::numeric_limits<long>::max)() - 1)); | |
293 | check_within_half(static_cast<T>((std::numeric_limits<long>::max)() - 1), k); | |
294 | k = lround(static_cast<T>((std::numeric_limits<long>::min)() + 1)); | |
295 | check_within_half(static_cast<T>((std::numeric_limits<long>::min)() + 1), k); | |
296 | k = ltrunc(static_cast<T>((std::numeric_limits<long>::max)() - 1)); | |
297 | check_trunc_result(static_cast<T>((std::numeric_limits<long>::max)() - 1), k); | |
298 | k = ltrunc(static_cast<T>((std::numeric_limits<long>::min)() + 1)); | |
299 | check_trunc_result(static_cast<T>((std::numeric_limits<long>::min)() + 1), k); | |
300 | } | |
301 | #ifndef BOOST_NO_LONG_LONG | |
1e59de90 | 302 | if (std::numeric_limits<T>::digits >= std::numeric_limits<long long>::digits) |
7c673cae | 303 | { |
1e59de90 TL |
304 | long long j = llround(static_cast<T>((std::numeric_limits<long long>::max)())); |
305 | check_within_half(static_cast<T>((std::numeric_limits<long long>::max)()), j); | |
7c673cae | 306 | BOOST_TEST(j == llround(static_cast<T>((std::numeric_limits<long long>::max)()) + 0)); |
1e59de90 TL |
307 | j = llround(static_cast<T>((std::numeric_limits<long long>::min)())); |
308 | check_within_half(static_cast<T>((std::numeric_limits<long long>::min)()), j); | |
7c673cae | 309 | BOOST_TEST(j == llround(static_cast<T>((std::numeric_limits<long long>::min)()) + 0)); |
1e59de90 TL |
310 | j = lltrunc(static_cast<T>((std::numeric_limits<long long>::max)())); |
311 | check_trunc_result(static_cast<T>((std::numeric_limits<long long>::max)()), j); | |
7c673cae | 312 | BOOST_TEST(j == lltrunc(static_cast<T>((std::numeric_limits<long long>::max)()) + 0)); |
1e59de90 TL |
313 | j = lltrunc(static_cast<T>((std::numeric_limits<long long>::min)())); |
314 | check_trunc_result(static_cast<T>((std::numeric_limits<long long>::min)()), j); | |
7c673cae FG |
315 | BOOST_TEST(j == lltrunc(static_cast<T>((std::numeric_limits<long long>::min)()) + 0)); |
316 | ||
1e59de90 TL |
317 | j = llround(static_cast<T>((std::numeric_limits<long long>::max)() - 1)); |
318 | check_within_half(static_cast<T>((std::numeric_limits<long long>::max)() - 1), j); | |
319 | j = llround(static_cast<T>((std::numeric_limits<long long>::min)() + 1)); | |
320 | check_within_half(static_cast<T>((std::numeric_limits<long long>::min)() + 1), j); | |
321 | j = lltrunc(static_cast<T>((std::numeric_limits<long long>::max)() - 1)); | |
322 | check_trunc_result(static_cast<T>((std::numeric_limits<long long>::max)() - 1), j); | |
323 | j = lltrunc(static_cast<T>((std::numeric_limits<long long>::min)() + 1)); | |
324 | check_trunc_result(static_cast<T>((std::numeric_limits<long long>::min)() + 1), j); | |
7c673cae FG |
325 | } |
326 | #endif | |
327 | // | |
328 | // Finish off by testing the error handlers: | |
329 | // | |
b32b8144 | 330 | T result; |
7c673cae | 331 | #ifndef BOOST_NO_EXCEPTIONS |
b32b8144 FG |
332 | BOOST_CHECK_THROW(result = static_cast<T>(iround(static_cast<T>(1e20))), boost::math::rounding_error); |
333 | BOOST_CHECK_THROW(result = static_cast<T>(iround(static_cast<T>(-1e20))), boost::math::rounding_error); | |
334 | BOOST_CHECK_THROW(result = static_cast<T>(lround(static_cast<T>(1e20))), boost::math::rounding_error); | |
335 | BOOST_CHECK_THROW(result = static_cast<T>(lround(static_cast<T>(-1e20))), boost::math::rounding_error); | |
7c673cae | 336 | #ifdef BOOST_HAS_LONG_LONG |
b32b8144 FG |
337 | BOOST_CHECK_THROW(result = static_cast<T>(llround(static_cast<T>(1e20))), boost::math::rounding_error); |
338 | BOOST_CHECK_THROW(result = static_cast<T>(llround(static_cast<T>(-1e20))), boost::math::rounding_error); | |
7c673cae | 339 | #endif |
92f5a8d4 | 340 | if (std::numeric_limits<T>::has_infinity) |
7c673cae | 341 | { |
b32b8144 FG |
342 | BOOST_CHECK_EQUAL(static_cast<T>(round(std::numeric_limits<T>::infinity())), std::numeric_limits<T>::infinity()); // See C99 Annex F. |
343 | BOOST_CHECK_THROW(result = static_cast<T>(iround(std::numeric_limits<T>::infinity())), boost::math::rounding_error); | |
344 | BOOST_CHECK_THROW(result = static_cast<T>(iround(-std::numeric_limits<T>::infinity())), boost::math::rounding_error); | |
345 | BOOST_CHECK_THROW(result = static_cast<T>(lround(std::numeric_limits<T>::infinity())), boost::math::rounding_error); | |
346 | BOOST_CHECK_THROW(result = static_cast<T>(lround(-std::numeric_limits<T>::infinity())), boost::math::rounding_error); | |
92f5a8d4 | 347 | #ifdef BOOST_HAS_LONG_LONG |
b32b8144 FG |
348 | BOOST_CHECK_THROW(result = static_cast<T>(llround(std::numeric_limits<T>::infinity())), boost::math::rounding_error); |
349 | BOOST_CHECK_THROW(result = static_cast<T>(llround(-std::numeric_limits<T>::infinity())), boost::math::rounding_error); | |
92f5a8d4 | 350 | #endif |
7c673cae | 351 | } |
92f5a8d4 | 352 | if (std::numeric_limits<T>::has_quiet_NaN) |
7c673cae | 353 | { |
b32b8144 FG |
354 | BOOST_CHECK((boost::multiprecision::isnan)(round(std::numeric_limits<T>::quiet_NaN()))); |
355 | BOOST_CHECK_THROW(result = static_cast<T>(iround(std::numeric_limits<T>::quiet_NaN())), boost::math::rounding_error); | |
356 | BOOST_CHECK_THROW(result = static_cast<T>(lround(std::numeric_limits<T>::quiet_NaN())), boost::math::rounding_error); | |
92f5a8d4 | 357 | #ifdef BOOST_HAS_LONG_LONG |
b32b8144 | 358 | BOOST_CHECK_THROW(result = static_cast<T>(llround(std::numeric_limits<T>::quiet_NaN())), boost::math::rounding_error); |
92f5a8d4 | 359 | #endif |
7c673cae | 360 | } |
b32b8144 FG |
361 | BOOST_CHECK_THROW(result = static_cast<T>(itrunc(static_cast<T>(1e20))), boost::math::rounding_error); |
362 | BOOST_CHECK_THROW(result = static_cast<T>(itrunc(static_cast<T>(-1e20))), boost::math::rounding_error); | |
363 | BOOST_CHECK_THROW(result = static_cast<T>(ltrunc(static_cast<T>(1e20))), boost::math::rounding_error); | |
364 | BOOST_CHECK_THROW(result = static_cast<T>(ltrunc(static_cast<T>(-1e20))), boost::math::rounding_error); | |
7c673cae | 365 | #ifdef BOOST_HAS_LONG_LONG |
b32b8144 FG |
366 | BOOST_CHECK_THROW(result = static_cast<T>(lltrunc(static_cast<T>(1e20))), boost::math::rounding_error); |
367 | BOOST_CHECK_THROW(result = static_cast<T>(lltrunc(static_cast<T>(-1e20))), boost::math::rounding_error); | |
7c673cae | 368 | #endif |
92f5a8d4 | 369 | if (std::numeric_limits<T>::has_infinity) |
7c673cae | 370 | { |
b32b8144 FG |
371 | BOOST_CHECK_EQUAL(static_cast<T>(trunc(std::numeric_limits<T>::infinity())), std::numeric_limits<T>::infinity()); |
372 | BOOST_CHECK_EQUAL(static_cast<T>(trunc(-std::numeric_limits<T>::infinity())), -std::numeric_limits<T>::infinity()); | |
373 | BOOST_CHECK_THROW(result = static_cast<T>(itrunc(std::numeric_limits<T>::infinity())), boost::math::rounding_error); | |
374 | BOOST_CHECK_THROW(result = static_cast<T>(itrunc(-std::numeric_limits<T>::infinity())), boost::math::rounding_error); | |
375 | BOOST_CHECK_THROW(result = static_cast<T>(ltrunc(std::numeric_limits<T>::infinity())), boost::math::rounding_error); | |
376 | BOOST_CHECK_THROW(result = static_cast<T>(ltrunc(-std::numeric_limits<T>::infinity())), boost::math::rounding_error); | |
92f5a8d4 | 377 | #ifdef BOOST_HAS_LONG_LONG |
b32b8144 FG |
378 | BOOST_CHECK_THROW(result = static_cast<T>(lltrunc(std::numeric_limits<T>::infinity())), boost::math::rounding_error); |
379 | BOOST_CHECK_THROW(result = static_cast<T>(lltrunc(-std::numeric_limits<T>::infinity())), boost::math::rounding_error); | |
92f5a8d4 | 380 | #endif |
7c673cae | 381 | } |
92f5a8d4 | 382 | if (std::numeric_limits<T>::has_quiet_NaN) |
7c673cae | 383 | { |
b32b8144 FG |
384 | BOOST_CHECK((boost::multiprecision::isnan)(trunc(std::numeric_limits<T>::quiet_NaN()))); |
385 | BOOST_CHECK_THROW(result = static_cast<T>(itrunc(std::numeric_limits<T>::quiet_NaN())), boost::math::rounding_error); | |
386 | BOOST_CHECK_THROW(result = static_cast<T>(ltrunc(std::numeric_limits<T>::quiet_NaN())), boost::math::rounding_error); | |
92f5a8d4 | 387 | #ifdef BOOST_HAS_LONG_LONG |
b32b8144 | 388 | BOOST_CHECK_THROW(result = static_cast<T>(lltrunc(std::numeric_limits<T>::quiet_NaN())), boost::math::rounding_error); |
92f5a8d4 | 389 | #endif |
7c673cae | 390 | } |
92f5a8d4 | 391 | if (std::numeric_limits<T>::digits >= std::numeric_limits<int>::digits) |
7c673cae | 392 | { |
b32b8144 FG |
393 | BOOST_CHECK_THROW(result = static_cast<T>(itrunc(static_cast<T>((std::numeric_limits<int>::max)()) + 1)), boost::math::rounding_error); |
394 | BOOST_CHECK_THROW(result = static_cast<T>(itrunc(static_cast<T>((std::numeric_limits<int>::min)()) - 1)), boost::math::rounding_error); | |
7c673cae | 395 | } |
92f5a8d4 | 396 | if (std::numeric_limits<T>::digits >= std::numeric_limits<long>::digits) |
7c673cae | 397 | { |
b32b8144 FG |
398 | BOOST_CHECK_THROW(result = static_cast<T>(ltrunc(static_cast<T>((std::numeric_limits<long>::max)()) + 1)), boost::math::rounding_error); |
399 | BOOST_CHECK_THROW(result = static_cast<T>(ltrunc(static_cast<T>((std::numeric_limits<long>::min)()) - 1)), boost::math::rounding_error); | |
7c673cae FG |
400 | } |
401 | #ifndef BOOST_NO_LONG_LONG | |
1e59de90 | 402 | if (std::numeric_limits<T>::digits >= std::numeric_limits<long long>::digits) |
7c673cae | 403 | { |
1e59de90 TL |
404 | BOOST_CHECK_THROW(result = static_cast<T>(lltrunc(static_cast<T>((std::numeric_limits<long long>::max)()) + 1)), boost::math::rounding_error); |
405 | BOOST_CHECK_THROW(result = static_cast<T>(lltrunc(static_cast<T>((std::numeric_limits<long long>::min)()) - 1)), boost::math::rounding_error); | |
7c673cae FG |
406 | } |
407 | #endif | |
92f5a8d4 | 408 | if (std::numeric_limits<T>::digits >= std::numeric_limits<int>::digits) |
7c673cae | 409 | { |
b32b8144 FG |
410 | BOOST_CHECK_THROW(result = static_cast<T>(iround(static_cast<T>((std::numeric_limits<int>::max)()) + 1)), boost::math::rounding_error); |
411 | BOOST_CHECK_THROW(result = static_cast<T>(iround(static_cast<T>((std::numeric_limits<int>::min)()) - 1)), boost::math::rounding_error); | |
7c673cae | 412 | } |
92f5a8d4 | 413 | if (std::numeric_limits<T>::digits >= std::numeric_limits<long>::digits) |
7c673cae | 414 | { |
b32b8144 FG |
415 | BOOST_CHECK_THROW(result = static_cast<T>(lround(static_cast<T>((std::numeric_limits<long>::max)()) + 1)), boost::math::rounding_error); |
416 | BOOST_CHECK_THROW(result = static_cast<T>(lround(static_cast<T>((std::numeric_limits<long>::min)()) - 1)), boost::math::rounding_error); | |
7c673cae FG |
417 | } |
418 | #ifndef BOOST_NO_LONG_LONG | |
1e59de90 | 419 | if (std::numeric_limits<T>::digits >= std::numeric_limits<long long>::digits) |
7c673cae | 420 | { |
1e59de90 TL |
421 | BOOST_CHECK_THROW(result = static_cast<T>(llround(static_cast<T>((std::numeric_limits<long long>::max)()) + 1)), boost::math::rounding_error); |
422 | BOOST_CHECK_THROW(result = static_cast<T>(llround(static_cast<T>((std::numeric_limits<long long>::min)()) - 1)), boost::math::rounding_error); | |
7c673cae FG |
423 | } |
424 | #endif | |
425 | #endif | |
426 | } | |
427 | ||
428 | int main() | |
429 | { | |
430 | #ifdef TEST_MPF_50 | |
431 | test<boost::multiprecision::mpf_float_50>(); | |
432 | test<boost::multiprecision::mpf_float_100>(); | |
433 | #endif | |
434 | #ifdef TEST_MPFR_50 | |
435 | test<boost::multiprecision::mpfr_float_50>(); | |
436 | test<boost::multiprecision::mpfr_float_100>(); | |
437 | #endif | |
438 | #ifdef TEST_MPFI_50 | |
439 | test<boost::multiprecision::mpfi_float_50>(); | |
440 | test<boost::multiprecision::mpfi_float_100>(); | |
441 | #endif | |
442 | #ifdef TEST_CPP_DEC_FLOAT | |
443 | test<boost::multiprecision::cpp_dec_float_50>(); | |
444 | test<boost::multiprecision::cpp_dec_float_100>(); | |
445 | #ifndef SLOW_COMPLER | |
446 | // Some "peculiar" digit counts which stress our code: | |
447 | test<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<65> > >(); | |
448 | test<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<64> > >(); | |
449 | test<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<63> > >(); | |
450 | test<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<62> > >(); | |
451 | test<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<61, long long> > >(); | |
452 | test<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<60, long long> > >(); | |
11fdf7f2 TL |
453 | test<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<59, long long, std::allocator<char> > > >(); |
454 | test<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<58, long long, std::allocator<char> > > >(); | |
7c673cae FG |
455 | #endif |
456 | #endif | |
457 | #ifdef TEST_CPP_BIN_FLOAT | |
458 | test<boost::multiprecision::cpp_bin_float_50>(); | |
459 | test<boost::multiprecision::cpp_bin_float_100>(); | |
1e59de90 | 460 | test<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<35, boost::multiprecision::digit_base_10, std::allocator<char>, long long> > >(); |
7c673cae FG |
461 | #endif |
462 | #ifdef TEST_BACKEND | |
463 | test<boost::multiprecision::number<boost::multiprecision::concepts::number_backend_float_architype> >(); | |
464 | #endif | |
465 | #ifdef TEST_FLOAT128 | |
466 | test<boost::multiprecision::float128>(); | |
467 | #endif | |
468 | return boost::report_errors(); | |
469 | } |