1 // Copyright John Maddock 2013.
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)
9 #define _SCL_SECURE_NO_WARNINGS
12 #include <boost/multiprecision/cpp_bin_float.hpp>
14 #include <boost/random/mersenne_twister.hpp>
15 #include <boost/random/uniform_int.hpp>
16 #include <boost/chrono.hpp>
18 #include <boost/array.hpp>
23 #pragma warning(disable : 4127)
26 template <class Clock>
29 typedef typename Clock::duration duration;
32 m_start = Clock::now();
36 return Clock::now() - m_start;
40 m_start = Clock::now();
44 typename Clock::time_point m_start;
47 void print_flags(std::ios_base::fmtflags f)
49 std::cout << "Formatting flags were: ";
50 if (f & std::ios_base::scientific)
51 std::cout << "scientific ";
52 if (f & std::ios_base::fixed)
53 std::cout << "fixed ";
54 if (f & std::ios_base::showpoint)
55 std::cout << "showpoint ";
56 if (f & std::ios_base::showpos)
57 std::cout << "showpos ";
58 std::cout << std::endl;
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}};
70 boost::array<boost::array<const char*, 13 * 9>, 40> string_data = {{
71 #include "libs/multiprecision/test/string_data.ipp"
74 double num = 123456789.0;
77 for (unsigned j = 0; j < 40; ++j)
80 for (unsigned prec = 1; prec < 14; ++prec)
82 for (unsigned i = 0; i < f.size(); ++i, ++col)
88 const char* expect = string_data[j][col];
89 if (ss.str() != expect)
91 std::cout << std::setprecision(20) << "Testing value " << val << std::endl;
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
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"}};
112 for (unsigned prec = 1; prec < 14; ++prec)
114 for (unsigned i = 0; i < f.size(); ++i, ++col)
116 std::stringstream ss;
120 const char* expect = zeros[col];
121 if (ss.str() != expect)
123 std::cout << std::setprecision(20) << "Testing value " << val << std::endl;
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
134 if (std::numeric_limits<mp_t>::has_infinity)
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");
140 BOOST_CHECK_EQUAL(val.str(), "-inf");
141 BOOST_CHECK_EQUAL(val.str(0, std::ios_base::showpos), "-inf");
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());
150 if (std::numeric_limits<mp_t>::has_quiet_NaN)
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));
158 // Min and max values:
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)());
171 typedef typename T::backend_type::exponent_type e_type;
172 static boost::random::mt19937 gen;
175 while (val != prev_val)
182 val = frexp(val, &e);
184 static boost::random::uniform_int_distribution<e_type> ui(0, std::numeric_limits<T>::max_exponent);
185 return ldexp(val, ui(gen));
189 void do_round_trip(const T& val, std::ios_base::fmtflags f)
191 std::stringstream ss;
192 #ifndef BOOST_NO_CXX11_NUMERIC_LIMITS
193 ss << std::setprecision(std::numeric_limits<T>::max_digits10);
195 ss << std::setprecision(std::numeric_limits<T>::digits10 + 3);
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);
206 void do_round_trip(const T& val)
208 do_round_trip(val, std::ios_base::fmtflags(0));
209 do_round_trip(val, std::ios_base::fmtflags(std::ios_base::scientific));
210 if ((fabs(val) > 1) && (fabs(val) < 1e100))
211 do_round_trip(val, std::ios_base::fmtflags(std::ios_base::fixed));
213 static int error_count = 0;
215 if (error_count != boost::detail::test_errors())
217 error_count = boost::detail::test_errors();
218 std::cout << "Errors occured while testing value....";
219 if (val.backend().sign())
221 std::cout << boost::multiprecision::cpp_int(val.backend().bits()) << "e" << val.backend().exponent() << std::endl;
226 void test_round_trip()
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;
233 stopwatch<boost::chrono::high_resolution_clock> w;
235 #ifndef CI_SUPPRESS_KNOWN_ISSUES
236 while (boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count() < 200)
238 while (boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count() < 50)
241 T val = generate_random<T>();
243 do_round_trip(T(-val));
244 do_round_trip(T(1 / val));
245 do_round_trip(T(-1 / val));
247 if (boost::detail::test_errors() > 200)
248 break; // escape if there are too many errors.
251 std::cout << "Execution time = " << boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count() << "s" << std::endl;
254 #if !defined(TEST1) && !defined(TEST2)
261 using namespace boost::multiprecision;
263 test<number<cpp_bin_float<113, digit_base_2> > >();
264 test_round_trip<number<cpp_bin_float<113, digit_base_2> > >();
267 test<number<cpp_bin_float<53, digit_base_2> > >();
268 test_round_trip<number<cpp_bin_float<53, digit_base_2> > >();
270 return boost::report_errors();