Imported Upstream version 1.72.0
[platform/upstream/boost.git] / libs / math / test / test_round.cpp
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 #include <pch.hpp>
7
8 #include <boost/math/concepts/real_concept.hpp>
9 #define BOOST_TEST_MAIN
10 #include <boost/test/unit_test.hpp>
11 #include <boost/math/tools/test.hpp>
12 #include <boost/test/tools/floating_point_comparison.hpp>
13 #include <boost/math/special_functions/round.hpp>
14 #include <boost/math/special_functions/next.hpp>
15 #include <boost/math/special_functions/trunc.hpp>
16 #include <boost/math/special_functions/modf.hpp>
17 #include <boost/math/special_functions/sign.hpp>
18 #include <boost/random/mersenne_twister.hpp>
19 #include <iostream>
20 #include <iomanip>
21
22 boost::mt19937 rng;
23
24 template <class T>
25 T get_random()
26 {
27    //
28    // Fill all the bits in T with random values,
29    // likewise set the exponent to a random value
30    // that will still fit inside a T, and always
31    // have a remainder as well as an integer part.
32    //
33    int bits = boost::math::tools::digits<T>();
34    int shift = 0;
35    int exponent = rng() % (bits - 4);
36    T result = 0;
37    while(bits > 0)
38    {
39       result += ldexp(static_cast<T>(rng()), shift);
40       shift += std::numeric_limits<int>::digits;
41       bits -= std::numeric_limits<int>::digits;
42    }
43    return rng() & 1u ? -ldexp(frexp(result, &bits), exponent) : ldexp(frexp(result, &bits), exponent);
44 }
45
46 template <class T, class U>
47 void check_within_half(T a, U u)
48 {
49    BOOST_MATH_STD_USING
50    if(fabs(a-u) > 0.5f)
51    {
52       BOOST_ERROR("Rounded result differed by more than 0.5 from the original");
53       std::cerr << "Values were: " << std::setprecision(35) << std::setw(40)
54          << std::left << a << u << std::endl;
55    }
56    if((fabs(a - u) == 0.5f) && (fabs(static_cast<T>(u)) < fabs(a)))
57    {
58       BOOST_ERROR("Rounded result was towards zero with boost::round");
59       std::cerr << "Values were: " << std::setprecision(35) << std::setw(40)
60          << std::left << a << u << std::endl;
61    }
62 }
63
64 //
65 // We may not have an abs overload for long long so provide a fall back:
66 //
67 template <class T>
68 inline T safe_abs(T const& v ...)
69 {
70    return v < 0 ? -v : v;
71 }
72
73 template <class T, class U>
74 void check_trunc_result(T a, U u)
75 {
76    BOOST_MATH_STD_USING
77    if(fabs(a-u) >= 1)
78    {
79       BOOST_ERROR("Rounded result differed by more than 1 from the original");
80       std::cerr << "Values were: " << std::setprecision(35) << std::setw(40)
81          << std::left << a << u << std::endl;
82    }
83    if(abs(a) < safe_abs(u))
84    {
85       BOOST_ERROR("Truncated result had larger absolute value than the original");
86       std::cerr << "Values were: " << std::setprecision(35) << std::setw(40)
87          << std::left << a << u << std::endl;
88    }
89    if(fabs(static_cast<T>(u)) > fabs(a))
90    {
91       BOOST_ERROR("Rounded result was away from zero with boost::trunc");
92       std::cerr << "Values were: " << std::setprecision(35) << std::setw(40)
93          << std::left << a << u << std::endl;
94    }
95 }
96
97 template <class T, class U>
98 void check_modf_result(T a, T fract, U ipart)
99 {
100    BOOST_MATH_STD_USING
101    if(fract + ipart != a)
102    {
103       BOOST_ERROR("Fractional and integer results do not add up to the original value");
104       std::cerr << "Values were: " << std::setprecision(35) << " "
105          << std::left << a << ipart << " " << fract << std::endl;
106    }
107    if((boost::math::sign(a) != boost::math::sign(fract)) && boost::math::sign(fract))
108    {
109       BOOST_ERROR("Original and fractional parts have differing signs");
110       std::cerr << "Values were: " << std::setprecision(35) << " "
111          << std::left << a << ipart << " " << fract << std::endl;
112    }
113    if((boost::math::sign(a) != boost::math::sign(ipart)) && boost::math::sign(ipart))
114    {
115       BOOST_ERROR("Original and integer parts have differing signs");
116       std::cerr << "Values were: " << std::setprecision(35) << " "
117          << std::left << a << ipart << " " << ipart << std::endl;
118    }
119    if(fabs(a-ipart) >= 1)
120    {
121       BOOST_ERROR("Rounded result differed by more than 1 from the original");
122       std::cerr << "Values were: " << std::setprecision(35) << std::setw(40)
123          << std::left << a << ipart << std::endl;
124    }
125 }
126
127 template <class T>
128 void test_round_number(T arg)
129 {
130    BOOST_MATH_STD_USING
131 #ifdef BOOST_HAS_LONG_LONG
132    using boost::math::llround;  using boost::math::lltrunc;
133 #endif
134
135    T r = round(arg);
136    check_within_half(arg, r);
137    r = trunc(arg);
138    check_trunc_result(arg, r);
139    T frac = boost::math::modf(arg, &r);
140    check_modf_result(arg, frac, r);
141
142    if(abs(r) < (std::numeric_limits<int>::max)())
143    {
144       int i = iround(arg);
145       check_within_half(arg, i);
146       i = itrunc(arg);
147       check_trunc_result(arg, T(i));
148       r = boost::math::modf(arg, &i);
149       check_modf_result(arg, r, i);
150    }
151    if(std::numeric_limits<T>::digits >= std::numeric_limits<int>::digits)
152    {
153       int si = iround(static_cast<T>((std::numeric_limits<int>::max)()));
154       check_within_half(static_cast<T>((std::numeric_limits<int>::max)()), si);
155       si = iround(static_cast<T>((std::numeric_limits<int>::min)()));
156       check_within_half(static_cast<T>((std::numeric_limits<int>::min)()), si);
157       si = itrunc(static_cast<T>((std::numeric_limits<int>::max)()));
158       check_trunc_result(static_cast<T>((std::numeric_limits<int>::max)()), T(si));
159       si = itrunc(static_cast<T>((std::numeric_limits<int>::min)()));
160       check_trunc_result(static_cast<T>((std::numeric_limits<int>::min)()), T(si));
161    }
162    if(abs(r) < (std::numeric_limits<long>::max)())
163    {
164       long l = lround(arg);
165       check_within_half(arg, l);
166       l = ltrunc(arg);
167       check_trunc_result(arg, T(l));
168       r = boost::math::modf(arg, &l);
169       check_modf_result(arg, r, l);
170    }
171    if(std::numeric_limits<T>::digits >= std::numeric_limits<long>::digits)
172    {
173       long k = lround(static_cast<T>((std::numeric_limits<long>::max)()));
174       check_within_half(static_cast<T>((std::numeric_limits<long>::max)()), k);
175       k = lround(static_cast<T>((std::numeric_limits<long>::min)()));
176       check_within_half(static_cast<T>((std::numeric_limits<long>::min)()), k);
177       k = ltrunc(static_cast<T>((std::numeric_limits<long>::max)()));
178       check_trunc_result(static_cast<T>((std::numeric_limits<long>::max)()), T(k));
179       k = ltrunc(static_cast<T>((std::numeric_limits<long>::min)()));
180       check_trunc_result(static_cast<T>((std::numeric_limits<long>::min)()), T(k));
181    }
182
183 #ifdef BOOST_HAS_LONG_LONG
184    if(abs(r) < (std::numeric_limits<boost::long_long_type>::max)())
185    {
186       boost::long_long_type ll = llround(arg);
187       check_within_half(arg, ll);
188       ll = lltrunc(arg);
189       check_trunc_result(arg, T(ll));
190       r = boost::math::modf(arg, &ll);
191       check_modf_result(arg, r, ll);
192    }
193    if(std::numeric_limits<T>::digits >= std::numeric_limits<boost::long_long_type>::digits)
194    {
195       boost::long_long_type j = llround(static_cast<T>((std::numeric_limits<boost::long_long_type>::max)()));
196       check_within_half(static_cast<T>((std::numeric_limits<boost::long_long_type>::max)()), j);
197       j = llround(static_cast<T>((std::numeric_limits<boost::long_long_type>::min)()));
198       check_within_half(static_cast<T>((std::numeric_limits<boost::long_long_type>::min)()), j);
199       j = lltrunc(static_cast<T>((std::numeric_limits<boost::long_long_type>::max)()));
200       check_trunc_result(static_cast<T>((std::numeric_limits<boost::long_long_type>::max)()), T(j));
201       j = lltrunc(static_cast<T>((std::numeric_limits<boost::long_long_type>::min)()));
202       check_trunc_result(static_cast<T>((std::numeric_limits<boost::long_long_type>::min)()), T(j));
203    }
204 #endif
205 }
206
207 template <class T>
208 void test_round(T, const char* name )
209 {
210    BOOST_MATH_STD_USING
211 #ifdef BOOST_HAS_LONG_LONG
212    using boost::math::llround;  using boost::math::lltrunc;
213 #endif
214
215    std::cout << "Testing rounding with type " << name << std::endl;
216
217    for(int i = 0; i < 1000; ++i)
218    {
219       T arg = get_random<T>();
220       test_round_number<T>(arg);
221    }
222    //
223    // Finish off by testing the error handlers:
224    //
225    BOOST_MATH_CHECK_THROW(iround(static_cast<T>(1e20)), boost::math::rounding_error);
226    BOOST_MATH_CHECK_THROW(iround(static_cast<T>(-1e20)), boost::math::rounding_error);
227    BOOST_MATH_CHECK_THROW(lround(static_cast<T>(1e20)), boost::math::rounding_error);
228    BOOST_MATH_CHECK_THROW(lround(static_cast<T>(-1e20)), boost::math::rounding_error);
229 #ifdef BOOST_HAS_LONG_LONG
230    BOOST_MATH_CHECK_THROW(llround(static_cast<T>(1e20)), boost::math::rounding_error);
231    BOOST_MATH_CHECK_THROW(llround(static_cast<T>(-1e20)), boost::math::rounding_error);
232 #endif
233    if(std::numeric_limits<T>::has_infinity)
234    {
235       BOOST_MATH_CHECK_THROW(round(std::numeric_limits<T>::infinity()), boost::math::rounding_error);
236       BOOST_MATH_CHECK_THROW(iround(std::numeric_limits<T>::infinity()), boost::math::rounding_error);
237       BOOST_MATH_CHECK_THROW(iround(-std::numeric_limits<T>::infinity()), boost::math::rounding_error);
238       BOOST_MATH_CHECK_THROW(lround(std::numeric_limits<T>::infinity()), boost::math::rounding_error);
239       BOOST_MATH_CHECK_THROW(lround(-std::numeric_limits<T>::infinity()), boost::math::rounding_error);
240    #ifdef BOOST_HAS_LONG_LONG
241       BOOST_MATH_CHECK_THROW(llround(std::numeric_limits<T>::infinity()), boost::math::rounding_error);
242       BOOST_MATH_CHECK_THROW(llround(-std::numeric_limits<T>::infinity()), boost::math::rounding_error);
243    #endif
244    }
245    if(std::numeric_limits<T>::has_quiet_NaN)
246    {
247       BOOST_MATH_CHECK_THROW(round(std::numeric_limits<T>::quiet_NaN()), boost::math::rounding_error);
248       BOOST_MATH_CHECK_THROW(iround(std::numeric_limits<T>::quiet_NaN()), boost::math::rounding_error);
249       BOOST_MATH_CHECK_THROW(lround(std::numeric_limits<T>::quiet_NaN()), boost::math::rounding_error);
250    #ifdef BOOST_HAS_LONG_LONG
251       BOOST_MATH_CHECK_THROW(llround(std::numeric_limits<T>::quiet_NaN()), boost::math::rounding_error);
252    #endif
253    }
254    BOOST_MATH_CHECK_THROW(itrunc(static_cast<T>(1e20)), boost::math::rounding_error);
255    BOOST_MATH_CHECK_THROW(itrunc(static_cast<T>(-1e20)), boost::math::rounding_error);
256    BOOST_MATH_CHECK_THROW(ltrunc(static_cast<T>(1e20)), boost::math::rounding_error);
257    BOOST_MATH_CHECK_THROW(ltrunc(static_cast<T>(-1e20)), boost::math::rounding_error);
258 #ifdef BOOST_HAS_LONG_LONG
259    BOOST_MATH_CHECK_THROW(lltrunc(static_cast<T>(1e20)), boost::math::rounding_error);
260    BOOST_MATH_CHECK_THROW(lltrunc(static_cast<T>(-1e20)), boost::math::rounding_error);
261 #endif
262    if(std::numeric_limits<T>::has_infinity)
263    {
264       BOOST_MATH_CHECK_THROW(trunc(std::numeric_limits<T>::infinity()), boost::math::rounding_error);
265       BOOST_MATH_CHECK_THROW(itrunc(std::numeric_limits<T>::infinity()), boost::math::rounding_error);
266       BOOST_MATH_CHECK_THROW(itrunc(-std::numeric_limits<T>::infinity()), boost::math::rounding_error);
267       BOOST_MATH_CHECK_THROW(ltrunc(std::numeric_limits<T>::infinity()), boost::math::rounding_error);
268       BOOST_MATH_CHECK_THROW(ltrunc(-std::numeric_limits<T>::infinity()), boost::math::rounding_error);
269    #ifdef BOOST_HAS_LONG_LONG
270       BOOST_MATH_CHECK_THROW(lltrunc(std::numeric_limits<T>::infinity()), boost::math::rounding_error);
271       BOOST_MATH_CHECK_THROW(lltrunc(-std::numeric_limits<T>::infinity()), boost::math::rounding_error);
272    #endif
273    }
274    if(std::numeric_limits<T>::has_quiet_NaN)
275    {
276       BOOST_MATH_CHECK_THROW(trunc(std::numeric_limits<T>::quiet_NaN()), boost::math::rounding_error);
277       BOOST_MATH_CHECK_THROW(itrunc(std::numeric_limits<T>::quiet_NaN()), boost::math::rounding_error);
278       BOOST_MATH_CHECK_THROW(ltrunc(std::numeric_limits<T>::quiet_NaN()), boost::math::rounding_error);
279    #ifdef BOOST_HAS_LONG_LONG
280       BOOST_MATH_CHECK_THROW(lltrunc(std::numeric_limits<T>::quiet_NaN()), boost::math::rounding_error);
281    #endif
282    }
283    if(std::numeric_limits<T>::digits >= std::numeric_limits<int>::digits)
284    {
285       BOOST_MATH_CHECK_THROW(itrunc(static_cast<T>((std::numeric_limits<int>::max)()) + 1), boost::math::rounding_error);
286       BOOST_MATH_CHECK_THROW(itrunc(static_cast<T>((std::numeric_limits<int>::min)()) - 1), boost::math::rounding_error);
287    }
288    if(std::numeric_limits<T>::digits >= std::numeric_limits<long>::digits)
289    {
290       BOOST_MATH_CHECK_THROW(ltrunc(static_cast<T>((std::numeric_limits<long>::max)()) + 1), boost::math::rounding_error);
291       BOOST_MATH_CHECK_THROW(ltrunc(static_cast<T>((std::numeric_limits<long>::min)()) - 1), boost::math::rounding_error);
292    }
293 #ifndef BOOST_NO_LONG_LONG
294    if(std::numeric_limits<T>::digits >= std::numeric_limits<boost::long_long_type>::digits)
295    {
296       BOOST_MATH_CHECK_THROW(lltrunc(static_cast<T>((std::numeric_limits<boost::long_long_type>::max)()) + 1), boost::math::rounding_error);
297       BOOST_MATH_CHECK_THROW(lltrunc(static_cast<T>((std::numeric_limits<boost::long_long_type>::min)()) - 1), boost::math::rounding_error);
298    }
299 #endif
300    if(std::numeric_limits<T>::digits >= std::numeric_limits<int>::digits)
301    {
302       BOOST_MATH_CHECK_THROW(iround(static_cast<T>((std::numeric_limits<int>::max)()) + 1), boost::math::rounding_error);
303       BOOST_MATH_CHECK_THROW(iround(static_cast<T>((std::numeric_limits<int>::min)()) - 1), boost::math::rounding_error);
304    }
305    if(std::numeric_limits<T>::digits >= std::numeric_limits<long>::digits)
306    {
307       BOOST_MATH_CHECK_THROW(lround(static_cast<T>((std::numeric_limits<long>::max)()) + 1), boost::math::rounding_error);
308       BOOST_MATH_CHECK_THROW(lround(static_cast<T>((std::numeric_limits<long>::min)()) - 1), boost::math::rounding_error);
309    }
310 #ifndef BOOST_NO_LONG_LONG
311    if(std::numeric_limits<T>::digits >= std::numeric_limits<boost::long_long_type>::digits)
312    {
313       BOOST_MATH_CHECK_THROW(llround(static_cast<T>((std::numeric_limits<boost::long_long_type>::max)()) + 1), boost::math::rounding_error);
314       BOOST_MATH_CHECK_THROW(llround(static_cast<T>((std::numeric_limits<boost::long_long_type>::min)()) - 1), boost::math::rounding_error);
315    }
316 #endif
317    //
318    // try non-throwing error handlers:
319    //
320    boost::math::policies::policy<boost::math::policies::rounding_error<boost::math::policies::ignore_error> > pol;
321
322    if(std::numeric_limits<T>::digits >= std::numeric_limits<int>::digits)
323    {
324       BOOST_CHECK_EQUAL(iround((std::numeric_limits<int>::max)() + T(1.0), pol), (std::numeric_limits<int>::max)());
325       BOOST_CHECK_EQUAL(iround((std::numeric_limits<int>::min)() - T(1.0), pol), (std::numeric_limits<int>::min)());
326       BOOST_CHECK_EQUAL(itrunc((std::numeric_limits<int>::max)() + T(1.0), pol), (std::numeric_limits<int>::max)());
327       BOOST_CHECK_EQUAL(itrunc((std::numeric_limits<int>::min)() - T(1.0), pol), (std::numeric_limits<int>::min)());
328    }
329    if(std::numeric_limits<T>::digits >= std::numeric_limits<long>::digits)
330    {
331       BOOST_CHECK_EQUAL(lround((std::numeric_limits<long>::max)() + T(1.0), pol), (std::numeric_limits<long>::max)());
332       BOOST_CHECK_EQUAL(lround((std::numeric_limits<long>::min)() - T(1.0), pol), (std::numeric_limits<long>::min)());
333       BOOST_CHECK_EQUAL(ltrunc((std::numeric_limits<long>::max)() + T(1.0), pol), (std::numeric_limits<long>::max)());
334       BOOST_CHECK_EQUAL(ltrunc((std::numeric_limits<long>::min)() - T(1.0), pol), (std::numeric_limits<long>::min)());
335    }
336 #ifndef BOOST_NO_LONG_LONG
337    if(std::numeric_limits<T>::digits >= std::numeric_limits<long long>::digits)
338    {
339       BOOST_CHECK_EQUAL(llround((std::numeric_limits<long long>::max)() + T(1.0), pol), (std::numeric_limits<long long>::max)());
340       BOOST_CHECK_EQUAL(llround((std::numeric_limits<long long>::min)() - T(1.0), pol), (std::numeric_limits<long long>::min)());
341       BOOST_CHECK_EQUAL(lltrunc((std::numeric_limits<long long>::max)() + T(1.0), pol), (std::numeric_limits<long long>::max)());
342       BOOST_CHECK_EQUAL(lltrunc((std::numeric_limits<long long>::min)() - T(1.0), pol), (std::numeric_limits<long long>::min)());
343    }
344 #endif
345    // Again with bigger value:
346    T big = 1e20f;
347    BOOST_CHECK_EQUAL(iround(big, pol), (std::numeric_limits<int>::max)());
348    BOOST_CHECK_EQUAL(lround(big, pol), (std::numeric_limits<long>::max)());
349    BOOST_CHECK_EQUAL(iround(-big, pol), (std::numeric_limits<int>::min)());
350    BOOST_CHECK_EQUAL(lround(-big, pol), (std::numeric_limits<long>::min)());
351    BOOST_CHECK_EQUAL(itrunc(big, pol), (std::numeric_limits<int>::max)());
352    BOOST_CHECK_EQUAL(ltrunc(big, pol), (std::numeric_limits<long>::max)());
353    BOOST_CHECK_EQUAL(itrunc(-big, pol), (std::numeric_limits<int>::min)());
354    BOOST_CHECK_EQUAL(ltrunc(-big, pol), (std::numeric_limits<long>::min)());
355 #ifndef BOOST_NO_LONG_LONG
356    BOOST_CHECK_EQUAL(llround(big, pol), (std::numeric_limits<long long>::max)());
357    BOOST_CHECK_EQUAL(llround(-big, pol), (std::numeric_limits<long long>::min)());
358    BOOST_CHECK_EQUAL(lltrunc(big, pol), (std::numeric_limits<long long>::max)());
359    BOOST_CHECK_EQUAL(lltrunc(-big, pol), (std::numeric_limits<long long>::min)());
360 #endif
361
362    //
363    // Special cases that we know can go bad:
364    //
365    T half = 0.5f;
366    half = boost::math::float_prior(half);
367    test_round_number(half);
368    half = -0.5f;
369    half = boost::math::float_next(half);
370    test_round_number(half);
371
372    if(std::numeric_limits<T>::is_specialized)
373    {
374       //
375       // Odd and even integer values:
376       //
377       T val;
378       for(int i = 2; i < std::numeric_limits<T>::max_exponent; ++i)
379       {
380          val = ldexp(T(1), i);
381          test_round_number(val);
382          ++val;
383          test_round_number(val);
384          val = -val;
385          test_round_number(val);
386          ++val;
387          test_round_number(val);
388       }
389    }
390 }
391
392 BOOST_AUTO_TEST_CASE( test_main )
393 {
394    test_round(0.1F, "float");
395    test_round(0.1, "double");
396 #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
397    test_round(0.1L, "long double");
398    test_round(boost::math::concepts::real_concept(0.1), "real_concept");
399 #else
400    std::cout << "<note>The long double tests have been disabled on this platform "
401       "either because the long double overloads of the usual math functions are "
402       "not available at all, or because they are too inaccurate for these tests "
403       "to pass.</note>" << std::endl;
404 #endif
405
406    // test rounding of direct predecessor/successor of 0.5/-0.5 for float and double
407    test_round_number(-0.4999999701976776123046875f);
408    BOOST_CHECK_EQUAL(boost::math::round(-0.4999999701976776123046875f), 0.0f);
409
410    test_round_number(0.4999999701976776123046875f);
411    BOOST_CHECK_EQUAL(boost::math::round(0.4999999701976776123046875f), 0.0f);
412
413    BOOST_CHECK_EQUAL(boost::math::round(-0.499999999999999944488848768742172978818416595458984375), 0.0);
414    test_round_number(-0.499999999999999944488848768742172978818416595458984375);
415
416    BOOST_CHECK_EQUAL(boost::math::round(0.499999999999999944488848768742172978818416595458984375), 0.0);
417    test_round_number(0.499999999999999944488848768742172978818416595458984375);
418
419    // test rounding of integer numbers on the edge of the float/double mantissa width
420    BOOST_CHECK_EQUAL(boost::math::round(-16777215.0f), -16777215.0f);
421    test_round_number(-16777215.0f);
422
423    BOOST_CHECK_EQUAL(boost::math::round(-16777213.0f), -16777213.0f);
424    test_round_number(-16777213.0f);
425
426    BOOST_CHECK_EQUAL(boost::math::round(-8388611.0f), -8388611.0f);
427    test_round_number(-8388611.0f);
428
429    BOOST_CHECK_EQUAL(boost::math::round(-8388609.0f), -8388609.0f);
430    test_round_number(-8388609.0f);
431
432    BOOST_CHECK_EQUAL(boost::math::round(8388609.0f), 8388609.0f);
433    test_round_number(8388609.0f);
434
435    BOOST_CHECK_EQUAL(boost::math::round(8388611.0f), 8388611.0f);
436    test_round_number(8388611.0f);
437
438    BOOST_CHECK_EQUAL(boost::math::round(16777213.0f), 16777213.0f);
439    test_round_number(16777213.0f);
440
441    BOOST_CHECK_EQUAL(boost::math::round(16777215.0f), 16777215.0f);
442    test_round_number(16777215.0f);
443
444    BOOST_CHECK_EQUAL(boost::math::round(-9007199254740993.0), -9007199254740993.0);
445    test_round_number(-9007199254740993.0);
446
447    BOOST_CHECK_EQUAL(boost::math::round(-9007199254740991.0), -9007199254740991.0);
448    test_round_number(-9007199254740991.0);
449
450    BOOST_CHECK_EQUAL(boost::math::round(-4503599627370499.0), -4503599627370499.0);
451    test_round_number(-4503599627370499.0);
452
453    BOOST_CHECK_EQUAL(boost::math::round(-4503599627370497.0), -4503599627370497.0);
454    test_round_number(-4503599627370497.0);
455
456    BOOST_CHECK_EQUAL(boost::math::round(4503599627370497.0), 4503599627370497.0);
457    test_round_number(4503599627370497.0);
458
459    BOOST_CHECK_EQUAL(boost::math::round(4503599627370499.0), 4503599627370499.0);
460    test_round_number(4503599627370499.0);
461
462    BOOST_CHECK_EQUAL(boost::math::round(9007199254740991.0), 9007199254740991.0);
463    test_round_number(9007199254740991.0);
464
465    BOOST_CHECK_EQUAL(boost::math::round(9007199254740993.0), 9007199254740993.0);
466    test_round_number(9007199254740993.0);
467 }