]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/multiprecision/test/test_cpp_bin_float_io.cpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / libs / multiprecision / test / test_cpp_bin_float_io.cpp
CommitLineData
7c673cae
FG
1// Copyright John Maddock 2013.
2
3// Use, modification and distribution are subject to the
4// Boost Software License, Version 1.0.
5// (See accompanying file LICENSE_1_0.txt
6// or copy at http://www.boost.org/LICENSE_1_0.txt)
7
8#ifdef _MSC_VER
92f5a8d4 9#define _SCL_SECURE_NO_WARNINGS
7c673cae
FG
10#endif
11
12#include <boost/multiprecision/cpp_bin_float.hpp>
13
14#include <boost/random/mersenne_twister.hpp>
15#include <boost/random/uniform_int.hpp>
16#include <boost/chrono.hpp>
17#include "test.hpp"
18#include <boost/array.hpp>
19#include <iostream>
20#include <iomanip>
21
22#ifdef BOOST_MSVC
92f5a8d4 23#pragma warning(disable : 4127)
7c673cae
FG
24#endif
25
26template <class Clock>
27struct stopwatch
28{
29 typedef typename Clock::duration duration;
30 stopwatch()
31 {
32 m_start = Clock::now();
33 }
34 duration elapsed()
35 {
36 return Clock::now() - m_start;
37 }
38 void reset()
39 {
40 m_start = Clock::now();
41 }
42
92f5a8d4 43 private:
7c673cae
FG
44 typename Clock::time_point m_start;
45};
46
7c673cae
FG
47void print_flags(std::ios_base::fmtflags f)
48{
49 std::cout << "Formatting flags were: ";
92f5a8d4 50 if (f & std::ios_base::scientific)
7c673cae 51 std::cout << "scientific ";
92f5a8d4 52 if (f & std::ios_base::fixed)
7c673cae 53 std::cout << "fixed ";
92f5a8d4 54 if (f & std::ios_base::showpoint)
7c673cae 55 std::cout << "showpoint ";
92f5a8d4 56 if (f & std::ios_base::showpos)
7c673cae
FG
57 std::cout << "showpos ";
58 std::cout << std::endl;
59}
60
7c673cae
FG
61template <class T>
62void test()
63{
92f5a8d4
TL
64 typedef T mp_t;
65 boost::array<std::ios_base::fmtflags, 9> f =
66 {{std::ios_base::fmtflags(0), std::ios_base::showpoint, std::ios_base::showpos, std::ios_base::scientific, std::ios_base::scientific | std::ios_base::showpos,
67 std::ios_base::scientific | std::ios_base::showpoint, std::ios_base::fixed, std::ios_base::fixed | std::ios_base::showpoint,
68 std::ios_base::fixed | std::ios_base::showpos}};
7c673cae
FG
69
70 boost::array<boost::array<const char*, 13 * 9>, 40> string_data = {{
71#include "libs/multiprecision/test/string_data.ipp"
72 }};
73
92f5a8d4 74 double num = 123456789.0;
7c673cae 75 double denom = 1;
92f5a8d4
TL
76 double val = num;
77 for (unsigned j = 0; j < 40; ++j)
7c673cae
FG
78 {
79 unsigned col = 0;
92f5a8d4 80 for (unsigned prec = 1; prec < 14; ++prec)
7c673cae 81 {
92f5a8d4 82 for (unsigned i = 0; i < f.size(); ++i, ++col)
7c673cae
FG
83 {
84 std::stringstream ss;
85 ss.precision(prec);
86 ss.flags(f[i]);
87 ss << mp_t(val);
88 const char* expect = string_data[j][col];
92f5a8d4 89 if (ss.str() != expect)
7c673cae
FG
90 {
91 std::cout << std::setprecision(20) << "Testing value " << val << std::endl;
92 print_flags(f[i]);
93 std::cout << "Precision is: " << prec << std::endl;
94 std::cout << "Got: " << ss.str() << std::endl;
95 std::cout << "Expected: " << expect << std::endl;
96 ++boost::detail::test_errors();
97 mp_t(val).str(prec, f[i]); // for debugging
98 }
99 }
100 }
101 num = -num;
92f5a8d4 102 if (j & 1)
7c673cae
FG
103 denom *= 8;
104 val = num / denom;
105 }
106
92f5a8d4
TL
107 boost::array<const char*, 13 * 9> zeros =
108 {{"0", "0.", "+0", "0.0e+00", "+0.0e+00", "0.0e+00", "0.0", "0.0", "+0.0", "0", "0.0", "+0", "0.00e+00", "+0.00e+00", "0.00e+00", "0.00", "0.00", "+0.00", "0", "0.00", "+0", "0.000e+00", "+0.000e+00", "0.000e+00", "0.000", "0.000", "+0.000", "0", "0.000", "+0", "0.0000e+00", "+0.0000e+00", "0.0000e+00", "0.0000", "0.0000", "+0.0000", "0", "0.0000", "+0", "0.00000e+00", "+0.00000e+00", "0.00000e+00", "0.00000", "0.00000", "+0.00000", "0", "0.00000", "+0", "0.000000e+00", "+0.000000e+00", "0.000000e+00", "0.000000", "0.000000", "+0.000000", "0", "0.000000", "+0", "0.0000000e+00", "+0.0000000e+00", "0.0000000e+00", "0.0000000", "0.0000000", "+0.0000000", "0", "0.0000000", "+0", "0.00000000e+00", "+0.00000000e+00", "0.00000000e+00", "0.00000000", "0.00000000", "+0.00000000", "0", "0.00000000", "+0", "0.000000000e+00", "+0.000000000e+00", "0.000000000e+00", "0.000000000", "0.000000000", "+0.000000000", "0", "0.000000000", "+0", "0.0000000000e+00", "+0.0000000000e+00", "0.0000000000e+00", "0.0000000000", "0.0000000000", "+0.0000000000", "0", "0.0000000000", "+0", "0.00000000000e+00", "+0.00000000000e+00", "0.00000000000e+00", "0.00000000000", "0.00000000000", "+0.00000000000", "0", "0.00000000000", "+0", "0.000000000000e+00", "+0.000000000000e+00", "0.000000000000e+00", "0.000000000000", "0.000000000000", "+0.000000000000", "0", "0.000000000000", "+0", "0.0000000000000e+00", "+0.0000000000000e+00", "0.0000000000000e+00", "0.0000000000000", "0.0000000000000", "+0.0000000000000"}};
7c673cae
FG
109
110 unsigned col = 0;
92f5a8d4
TL
111 val = 0;
112 for (unsigned prec = 1; prec < 14; ++prec)
7c673cae 113 {
92f5a8d4 114 for (unsigned i = 0; i < f.size(); ++i, ++col)
7c673cae
FG
115 {
116 std::stringstream ss;
117 ss.precision(prec);
118 ss.flags(f[i]);
119 ss << mp_t(val);
120 const char* expect = zeros[col];
92f5a8d4 121 if (ss.str() != expect)
7c673cae
FG
122 {
123 std::cout << std::setprecision(20) << "Testing value " << val << std::endl;
124 print_flags(f[i]);
125 std::cout << "Precision is: " << prec << std::endl;
126 std::cout << "Got: " << ss.str() << std::endl;
127 std::cout << "Expected: " << expect << std::endl;
128 ++boost::detail::test_errors();
129 mp_t(val).str(prec, f[i]); // for debugging
130 }
131 }
132 }
133
92f5a8d4 134 if (std::numeric_limits<mp_t>::has_infinity)
7c673cae
FG
135 {
136 T val = std::numeric_limits<T>::infinity();
137 BOOST_CHECK_EQUAL(val.str(), "inf");
138 BOOST_CHECK_EQUAL(val.str(0, std::ios_base::showpos), "+inf");
139 val = -val;
140 BOOST_CHECK_EQUAL(val.str(), "-inf");
141 BOOST_CHECK_EQUAL(val.str(0, std::ios_base::showpos), "-inf");
142
143 val = static_cast<T>("inf");
144 BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
145 val = static_cast<T>("+inf");
146 BOOST_CHECK_EQUAL(val, std::numeric_limits<T>::infinity());
147 val = static_cast<T>("-inf");
148 BOOST_CHECK_EQUAL(val, -std::numeric_limits<T>::infinity());
149 }
92f5a8d4 150 if (std::numeric_limits<mp_t>::has_quiet_NaN)
7c673cae
FG
151 {
152 T val = std::numeric_limits<T>::quiet_NaN();
153 BOOST_CHECK_EQUAL(val.str(), "nan");
154 val = static_cast<T>("nan");
155 BOOST_CHECK((boost::math::isnan)(val));
156 }
157 //
158 // Min and max values:
159 //
160 T t((std::numeric_limits<T>::max)().str(std::numeric_limits<T>::max_digits10, std::ios_base::scientific));
161 BOOST_CHECK_EQUAL(t, (std::numeric_limits<T>::max)());
162 t = T((std::numeric_limits<T>::min)().str(std::numeric_limits<T>::max_digits10, std::ios_base::scientific));
163 BOOST_CHECK_EQUAL(t, (std::numeric_limits<T>::min)());
164 t = T((std::numeric_limits<T>::lowest)().str(std::numeric_limits<T>::max_digits10, std::ios_base::scientific));
165 BOOST_CHECK_EQUAL(t, (std::numeric_limits<T>::lowest)());
166}
167
168template <class T>
169T generate_random()
170{
171 typedef typename T::backend_type::exponent_type e_type;
92f5a8d4
TL
172 static boost::random::mt19937 gen;
173 T val = gen();
174 T prev_val = -1;
175 while (val != prev_val)
7c673cae
FG
176 {
177 val *= (gen.max)();
178 prev_val = val;
179 val += gen();
180 }
181 e_type e;
182 val = frexp(val, &e);
183
184 static boost::random::uniform_int_distribution<e_type> ui(0, std::numeric_limits<T>::max_exponent);
185 return ldexp(val, ui(gen));
186}
187
188template <class T>
189void do_round_trip(const T& val, std::ios_base::fmtflags f)
190{
191 std::stringstream ss;
192#ifndef BOOST_NO_CXX11_NUMERIC_LIMITS
193 ss << std::setprecision(std::numeric_limits<T>::max_digits10);
194#else
195 ss << std::setprecision(std::numeric_limits<T>::digits10 + 3);
196#endif
197 ss.flags(f);
198 ss << val;
199 T new_val = static_cast<T>(ss.str());
200 BOOST_CHECK_EQUAL(new_val, val);
201 new_val = static_cast<T>(val.str(0, f));
202 BOOST_CHECK_EQUAL(new_val, val);
203}
204
205template <class T>
206void do_round_trip(const T& val)
207{
208 do_round_trip(val, std::ios_base::fmtflags(0));
209 do_round_trip(val, std::ios_base::fmtflags(std::ios_base::scientific));
92f5a8d4 210 if ((fabs(val) > 1) && (fabs(val) < 1e100))
7c673cae
FG
211 do_round_trip(val, std::ios_base::fmtflags(std::ios_base::fixed));
212
213 static int error_count = 0;
214
92f5a8d4 215 if (error_count != boost::detail::test_errors())
7c673cae
FG
216 {
217 error_count = boost::detail::test_errors();
218 std::cout << "Errors occured while testing value....";
92f5a8d4 219 if (val.backend().sign())
7c673cae
FG
220 std::cout << "-";
221 std::cout << boost::multiprecision::cpp_int(val.backend().bits()) << "e" << val.backend().exponent() << std::endl;
222 }
223}
224
225template <class T>
226void test_round_trip()
227{
228 std::cout << "Testing type " << typeid(T).name() << std::endl;
229 std::cout << "digits = " << std::numeric_limits<T>::digits << std::endl;
230 std::cout << "digits10 = " << std::numeric_limits<T>::digits10 << std::endl;
231 std::cout << "max_digits10 = " << std::numeric_limits<T>::max_digits10 << std::endl;
232
233 stopwatch<boost::chrono::high_resolution_clock> w;
234
b32b8144 235#ifndef CI_SUPPRESS_KNOWN_ISSUES
92f5a8d4 236 while (boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count() < 200)
b32b8144 237#else
92f5a8d4 238 while (boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count() < 50)
b32b8144 239#endif
7c673cae
FG
240 {
241 T val = generate_random<T>();
242 do_round_trip(val);
243 do_round_trip(T(-val));
92f5a8d4
TL
244 do_round_trip(T(1 / val));
245 do_round_trip(T(-1 / val));
7c673cae 246
92f5a8d4
TL
247 if (boost::detail::test_errors() > 200)
248 break; // escape if there are too many errors.
7c673cae
FG
249 }
250
251 std::cout << "Execution time = " << boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count() << "s" << std::endl;
252}
253
254#if !defined(TEST1) && !defined(TEST2)
92f5a8d4
TL
255#define TEST1
256#define TEST2
7c673cae
FG
257#endif
258
259int main()
260{
261 using namespace boost::multiprecision;
262#ifdef TEST1
263 test<number<cpp_bin_float<113, digit_base_2> > >();
264 test_round_trip<number<cpp_bin_float<113, digit_base_2> > >();
265#endif
266#ifdef TEST2
267 test<number<cpp_bin_float<53, digit_base_2> > >();
268 test_round_trip<number<cpp_bin_float<53, digit_base_2> > >();
269#endif
270 return boost::report_errors();
271}