]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/math/test/test_next_decimal.cpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / libs / math / test / test_next_decimal.cpp
CommitLineData
b32b8144
FG
1// (C) Copyright John Maddock 2008.
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#include <boost/math/tools/test.hpp>
10#define BOOST_TEST_MAIN
11#include <boost/test/unit_test.hpp>
92f5a8d4 12#include <boost/test/tools/floating_point_comparison.hpp>
b32b8144
FG
13#include <boost/math/special_functions/next.hpp>
14#include <boost/math/special_functions/ulp.hpp>
15#include <boost/multiprecision/cpp_dec_float.hpp>
16#include <boost/multiprecision/debug_adaptor.hpp>
17#include <iostream>
18#include <iomanip>
19
1e59de90 20#ifdef _MSC_VER
b32b8144
FG
21#pragma warning(disable:4127)
22#endif
23
24template <class T>
25bool is_normalized_value(const T& val)
26{
27 //
28 // Returns false if value has guard digits that are non-zero
29 //
1e59de90 30 std::intmax_t shift = std::numeric_limits<T>::digits - ilogb(val) - 1;
b32b8144
FG
31 T shifted = scalbn(val, shift);
32 return floor(shifted) == shifted;
33}
34
35template <class T>
36void test_value(const T& val, const char* name)
37{
38 using namespace boost::math;
39 T upper = tools::max_value<T>();
40 T lower = -upper;
41
42 std::cout << "Testing type " << name << " with initial value " << val << std::endl;
43
44 BOOST_CHECK_EQUAL(float_distance(float_next(val), val), -1);
45 BOOST_CHECK(float_next(val) > val);
46 BOOST_CHECK_EQUAL(float_distance(float_prior(val), val), 1);
47 BOOST_CHECK(float_prior(val) < val);
48 BOOST_CHECK_EQUAL(float_distance((boost::math::nextafter)(val, upper), val), -1);
49 BOOST_CHECK((boost::math::nextafter)(val, upper) > val);
50 BOOST_CHECK_EQUAL(float_distance((boost::math::nextafter)(val, lower), val), 1);
51 BOOST_CHECK((boost::math::nextafter)(val, lower) < val);
52 BOOST_CHECK_EQUAL(float_distance(float_next(float_next(val)), val), -2);
53 BOOST_CHECK_EQUAL(float_distance(float_prior(float_prior(val)), val), 2);
54 BOOST_CHECK_EQUAL(float_distance(float_prior(float_prior(val)), float_next(float_next(val))), 4);
55 BOOST_CHECK_EQUAL(float_distance(float_prior(float_next(val)), val), 0);
56 BOOST_CHECK_EQUAL(float_distance(float_next(float_prior(val)), val), 0);
57 if (is_normalized_value(val))
58 {
59 BOOST_CHECK_EQUAL(float_prior(float_next(val)), val);
60 BOOST_CHECK_EQUAL(float_next(float_prior(val)), val);
61 }
62 BOOST_CHECK_EQUAL(float_distance(float_advance(val, 4), val), -4);
63 BOOST_CHECK_EQUAL(float_distance(float_advance(val, -4), val), 4);
64 if(std::numeric_limits<T>::is_specialized && (std::numeric_limits<T>::has_denorm == std::denorm_present))
65 {
66 BOOST_CHECK_EQUAL(float_distance(float_advance(float_next(float_next(val)), 4), float_next(float_next(val))), -4);
67 BOOST_CHECK_EQUAL(float_distance(float_advance(float_next(float_next(val)), -4), float_next(float_next(val))), 4);
68 }
69 if (is_normalized_value(val))
70 {
71 if (val > 0)
72 {
73 T n = val + ulp(val);
74 T fn = float_next(val);
75 if (n > fn)
76 {
77 BOOST_CHECK_LE(ulp(val), boost::math::tools::min_value<T>());
78 }
79 else
80 {
81 BOOST_CHECK_EQUAL(fn, n);
82 }
83 }
84 else if (val == 0)
85 {
86 BOOST_CHECK_GE(boost::math::tools::min_value<T>(), ulp(val));
87 }
88 else
89 {
90 T n = val - ulp(val);
91 T fp = float_prior(val);
92 if (n < fp)
93 {
94 BOOST_CHECK_LE(ulp(val), boost::math::tools::min_value<T>());
95 }
96 else
97 {
98 BOOST_CHECK_EQUAL(fp, n);
99 }
100 }
101 }
102}
103
104template <class T>
105void test_values(const T& val, const char* name)
106{
1e59de90
TL
107 static const T a = T("1.3456724e22");
108 static const T b = T("1.3456724e-22");
b32b8144
FG
109 static const T z = 0;
110 static const T one = 1;
111 static const T radix = std::numeric_limits<T>::radix;
112
113 std::cout << "Testing type " << name << std::endl;
114
115 T den = (std::numeric_limits<T>::min)() / 4;
116 if(den != 0)
117 {
118 std::cout << "Denormals are active\n";
119 }
120 else
121 {
122 std::cout << "Denormals are flushed to zero.\n";
123 }
124
125 test_value(a, name);
126 test_value(T(-a), name);
127 test_value(b, name);
128 test_value(T(-b), name);
129 test_value(T(b / 3), name);
130 test_value(T(-b / 3), name);
131 test_value(boost::math::tools::epsilon<T>(), name);
132 test_value(T(-boost::math::tools::epsilon<T>()), name);
133 test_value(boost::math::tools::min_value<T>(), name);
134 test_value(T(-boost::math::tools::min_value<T>()), name);
135 if (std::numeric_limits<T>::is_specialized && (std::numeric_limits<T>::has_denorm == std::denorm_present) && ((std::numeric_limits<T>::min)() / 2 != 0))
136 {
137 test_value(z, name);
138 test_value(T(-z), name);
139 }
140 test_value(one, name);
141 test_value(T(-one), name);
142 test_value(radix, name);
143 test_value(T(-radix), name);
144
145 if(std::numeric_limits<T>::is_specialized && (std::numeric_limits<T>::has_denorm == std::denorm_present) && ((std::numeric_limits<T>::min)() / 2 != 0))
146 {
147 test_value(std::numeric_limits<T>::denorm_min(), name);
148 test_value(T(-std::numeric_limits<T>::denorm_min()), name);
149 test_value(T(2 * std::numeric_limits<T>::denorm_min()), name);
150 test_value(T(-2 * std::numeric_limits<T>::denorm_min()), name);
151 }
152
153 static const int primes[] = {
154 11, 13, 17, 19, 23, 29,
155 31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
156 73, 79, 83, 89, 97, 101, 103, 107, 109, 113,
157 127, 131, 137, 139, 149, 151, 157, 163, 167, 173,
158 179, 181, 191, 193, 197, 199, 211, 223, 227, 229,
159 233, 239, 241, 251, 257, 263, 269, 271, 277, 281,
160 283, 293, 307, 311, 313, 317, 331, 337, 347, 349,
161 353, 359, 367, 373, 379, 383, 389, 397, 401, 409,
162 419, 421, 431, 433, 439, 443, 449, 457, 461, 463,
163 };
164
165 for(unsigned i = 0; i < sizeof(primes)/sizeof(primes[0]); ++i)
166 {
167 T v1 = val;
168 T v2 = val;
169 for(int j = 0; j < primes[i]; ++j)
170 {
171 v1 = boost::math::float_next(v1);
172 v2 = boost::math::float_prior(v2);
173 }
174 BOOST_CHECK_EQUAL(boost::math::float_distance(v1, val), -primes[i]);
175 BOOST_CHECK_EQUAL(boost::math::float_distance(v2, val), primes[i]);
176 BOOST_CHECK_EQUAL(boost::math::float_advance(val, primes[i]), v1);
177 BOOST_CHECK_EQUAL(boost::math::float_advance(val, -primes[i]), v2);
178 }
179 if(std::numeric_limits<T>::is_specialized && (std::numeric_limits<T>::has_infinity))
180 {
181 BOOST_CHECK_EQUAL(boost::math::float_prior(std::numeric_limits<T>::infinity()), (std::numeric_limits<T>::max)());
182 BOOST_CHECK_EQUAL(boost::math::float_next(-std::numeric_limits<T>::infinity()), -(std::numeric_limits<T>::max)());
183 BOOST_MATH_CHECK_THROW(boost::math::float_prior(-std::numeric_limits<T>::infinity()), std::domain_error);
184 BOOST_MATH_CHECK_THROW(boost::math::float_next(std::numeric_limits<T>::infinity()), std::domain_error);
185 if(boost::math::policies:: BOOST_MATH_OVERFLOW_ERROR_POLICY == boost::math::policies::throw_on_error)
186 {
187 BOOST_MATH_CHECK_THROW(boost::math::float_prior(-(std::numeric_limits<T>::max)()), std::overflow_error);
188 BOOST_MATH_CHECK_THROW(boost::math::float_next((std::numeric_limits<T>::max)()), std::overflow_error);
189 }
190 else
191 {
192 BOOST_CHECK_EQUAL(boost::math::float_prior(-(std::numeric_limits<T>::max)()), -std::numeric_limits<T>::infinity());
193 BOOST_CHECK_EQUAL(boost::math::float_next((std::numeric_limits<T>::max)()), std::numeric_limits<T>::infinity());
194 }
195 }
196}
197
198BOOST_AUTO_TEST_CASE( test_main )
199{
200 // Very slow, but debuggable:
201 //test_values(boost::multiprecision::number<boost::multiprecision::debug_adaptor<boost::multiprecision::cpp_dec_float_50::backend_type> >(0), "cpp_dec_float_50");
202
f67539c2 203 // Faster, but no good for diagnosing the cause of any issues:
1e59de90 204 #ifndef BOOST_MATH_STANDALONE
b32b8144 205 test_values(boost::multiprecision::cpp_dec_float_50(0), "cpp_dec_float_50");
1e59de90 206 #endif
b32b8144
FG
207}
208
209