]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/multiprecision/example/numeric_limits_snips.cpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / libs / multiprecision / example / numeric_limits_snips.cpp
1 // Copyright Paul A. Bristow 2013
2 // Copyright John Maddock 2013
3 // Copyright Christopher Kormanyos
4
5 // Use, modification and distribution are subject to the
6 // Boost Software License, Version 1.0.
7 // (See accompanying file LICENSE_1_0.txt
8 // or copy at http://www.boost.org/LICENSE_1_0.txt)
9
10 // Examples of numeric_limits usage as snippets for multiprecision documentation.
11
12 // Includes text as Quickbook comments.
13
14 #include <iostream>
15 #include <iomanip>
16 #include <string>
17 #include <sstream>
18 #include <limits> // numeric_limits
19 #include <iomanip>
20 #include <locale>
21 #include <boost/assert.hpp>
22
23 #include <boost/math/constants/constants.hpp>
24 #include <boost/math/special_functions/nonfinite_num_facets.hpp>
25
26 #include <boost/math/special_functions/factorials.hpp>
27 #include <boost/math/special_functions/next.hpp>
28 #include <boost/math/tools/precision.hpp>
29 #include <boost/multiprecision/cpp_dec_float.hpp> // is decimal.
30 #include <boost/multiprecision/cpp_bin_float.hpp> // is binary.
31
32 #define BOOST_TEST_MAIN
33 #include <boost/test/unit_test.hpp> // Boost.Test
34 #include <boost/test/floating_point_comparison.hpp>
35
36 static long double const log10Two = 0.30102999566398119521373889472449L; // log10(2.)
37
38 template <typename T>
39 int max_digits10()
40 {
41 int significand_digits = std::numeric_limits<T>::digits;
42 // BOOST_CONSTEXPR_OR_CONST int significand_digits = std::numeric_limits<T>::digits;
43 return static_cast<int>(ceil(1 + significand_digits * log10Two));
44 } // template <typename T> int max_digits10()
45
46 // Used to test max_digits10<>() function below.
47 //#define BOOST_NO_CXX11_NUMERIC_LIMITS
48
49 BOOST_AUTO_TEST_CASE(test_numeric_limits_snips)
50 {
51 #if !(defined(CI_SUPPRESS_KNOWN_ISSUES) && defined(BOOST_MSVC) && (BOOST_MSVC == 1600))
52 try
53 {
54
55 // Example of portable way to get `std::numeric_limits<T>::max_digits10`.
56 //[max_digits10_1
57
58 /*`For example, to be portable (including obselete platforms) for type `T` where `T` may be:
59 `float`, `double`, `long double`, `128-bit quad type`, `cpp_bin_float_50` ...
60 */
61
62 typedef float T;
63
64 #if defined BOOST_NO_CXX11_NUMERIC_LIMITS
65 // No max_digits10 implemented.
66 std::cout.precision(max_digits10<T>());
67 #else
68 #if(_MSC_VER <= 1600)
69 // Wrong value for std::numeric_limits<float>::max_digits10.
70 std::cout.precision(max_digits10<T>());
71 #else // Use the C++11 max_digits10.
72 std::cout.precision(std::numeric_limits<T>::max_digits10);
73 #endif
74 #endif
75
76 std::cout << "std::cout.precision(max_digits10) = " << std::cout.precision() << std::endl; // 9
77
78 double x = 1.2345678901234567889;
79
80 std::cout << "x = " << x << std::endl; //
81
82 /*`which should output:
83
84 std::cout.precision(max_digits10) = 9
85 x = 1.23456789
86 */
87
88 //] [/max_digits10_1]
89
90 {
91 //[max_digits10_2
92
93 double write = 2./3; // Any arbitrary value that cannot be represented exactly.
94 double read = 0;
95 std::stringstream s;
96 s.precision(std::numeric_limits<double>::digits10); // or `float64_t` for 64-bit IEE754 double.
97 s << write;
98 s >> read;
99 if(read != write)
100 {
101 std::cout << std::setprecision(std::numeric_limits<double>::digits10)
102 << read << " != " << write << std::endl;
103 }
104
105 //] [/max_digits10_2]
106 // 0.666666666666667 != 0.666666666666667
107 }
108
109 {
110 //[max_digits10_3
111
112 double pi = boost::math::double_constants::pi;
113 std::cout.precision(std::numeric_limits<double>::max_digits10);
114 std::cout << pi << std::endl; // 3.1415926535897931
115
116 //] [/max_digits10_3]
117 }
118 {
119 //[max_digits10_4
120 /*`and similarly for a much higher precision type:
121 */
122
123 using namespace boost::multiprecision;
124
125 typedef number<cpp_dec_float<50> > cpp_dec_float_50; // 50 decimal digits.
126
127 using boost::multiprecision::cpp_dec_float_50;
128
129 cpp_dec_float_50 pi = boost::math::constants::pi<cpp_dec_float_50>();
130 std::cout.precision(std::numeric_limits<cpp_dec_float_50>::max_digits10);
131 std::cout << pi << std::endl;
132 // 3.141592653589793238462643383279502884197169399375105820974944592307816406
133 //] [/max_digits10_4]
134 }
135
136 {
137 //[max_digits10_5
138
139 for (int i = 2; i < 15; i++)
140 {
141 std::cout << std::setw(std::numeric_limits<int>::max_digits10)
142 << boost::math::factorial<double>(i) << std::endl;
143 }
144
145 //] [/max_digits10_5]
146 }
147
148 }
149 catch(std::exception ex)
150 {
151 std::cout << "Caught Exception " << ex.what() << std::endl;
152 }
153
154 {
155 //[max_digits10_6
156
157 typedef double T;
158
159 bool denorm = std::numeric_limits<T>::denorm_min() < std::numeric_limits<T>::min();
160 BOOST_ASSERT(denorm);
161
162 //] [/max_digits10_6]
163 }
164
165 {
166 unsigned char c = 255;
167 std::cout << "char c = " << (int)c << std::endl;
168 }
169
170 {
171 //[digits10_1
172 std::cout
173 << std::setw(std::numeric_limits<short>::digits10 +1 +1) // digits10+1, and +1 for sign.
174 << std::showpos << (std::numeric_limits<short>::max)() // +32767
175 << std::endl
176 << std::setw(std::numeric_limits<short>::digits10 +1 +1)
177 << (std::numeric_limits<short>::min)() << std::endl; // -32767
178 //] [/digits10_1]
179 }
180
181 {
182 //[digits10_2
183 std::cout
184 << std::setw(std::numeric_limits<unsigned short>::digits10 +1 +1) // digits10+1, and +1 for sign.
185 << std::showpos << (std::numeric_limits<unsigned short>::max)() // 65535
186 << std::endl
187 << std::setw(std::numeric_limits<unsigned short>::digits10 +1 +1) // digits10+1, and +1 for sign.
188 << (std::numeric_limits<unsigned short>::min)() << std::endl; // 0
189 //] [/digits10_2]
190 }
191
192 std::cout <<std::noshowpos << std::endl;
193
194 {
195 //[digits10_3
196 std::cout.precision(std::numeric_limits<double>::max_digits10);
197 double d = 1e15;
198 double dp1 = d+1;
199 std::cout << d << "\n" << dp1 << std::endl;
200 // 1000000000000000
201 // 1000000000000001
202 std::cout << dp1 - d << std::endl; // 1
203 //] [/digits10_3]
204 }
205
206 {
207 //[digits10_4
208 std::cout.precision(std::numeric_limits<double>::max_digits10);
209 double d = 1e16;
210 double dp1 = d+1;
211 std::cout << d << "\n" << dp1 << std::endl;
212 // 10000000000000000
213 // 10000000000000000
214 std::cout << dp1 - d << std::endl; // 0 !!!
215 //] [/digits10_4]
216 }
217
218 {
219 //[epsilon_1
220 std::cout.precision(std::numeric_limits<double>::max_digits10);
221 double d = 1.;
222 double eps = std::numeric_limits<double>::epsilon();
223 double dpeps = d+eps;
224 std::cout << std::showpoint // Ensure all trailing zeros are shown.
225 << d << "\n" // 1.0000000000000000
226 << dpeps << std::endl; // 2.2204460492503131e-016
227 std::cout << dpeps - d // 1.0000000000000002
228 << std::endl;
229 //] [epsilon_1]
230 }
231
232 {
233 //[epsilon_2
234 double one = 1.;
235 double nad = boost::math::float_next(one);
236 std::cout << nad << "\n" // 1.0000000000000002
237 << nad - one // 2.2204460492503131e-016
238 << std::endl;
239 //] [epsilon_2]
240 }
241 {
242 //[epsilon_3
243 std::cout.precision(std::numeric_limits<double>::max_digits10);
244 double d = 1.;
245 double eps = std::numeric_limits<double>::epsilon();
246 double dpeps = d + eps/2;
247
248 std::cout << std::showpoint // Ensure all trailing zeros are shown.
249 << dpeps << "\n" // 1.0000000000000000
250 << eps/2 << std::endl; // 1.1102230246251565e-016
251 std::cout << dpeps - d // 0.00000000000000000
252 << std::endl;
253 //] [epsilon_3]
254 }
255
256 {
257 typedef double RealType;
258 //[epsilon_4
259 /*`A tolerance might be defined using this version of epsilon thus:
260 */
261 RealType tolerance = boost::math::tools::epsilon<RealType>() * 2;
262 //] [epsilon_4]
263 }
264
265 {
266 //[digits10_5
267 -(std::numeric_limits<double>::max)() == std::numeric_limits<double>::lowest();
268 //] [/digits10_5]
269 }
270
271 {
272 //[denorm_min_1
273 std::cout.precision(std::numeric_limits<double>::max_digits10);
274 if (std::numeric_limits<double>::has_denorm == std::denorm_present)
275 {
276 double d = std::numeric_limits<double>::denorm_min();
277
278 std::cout << d << std::endl; // 4.9406564584124654e-324
279
280 int exponent;
281
282 double significand = frexp(d, &exponent);
283 std::cout << "exponent = " << std::hex << exponent << std::endl; // fffffbcf
284 std::cout << "significand = " << std::hex << significand << std::endl; // 0.50000000000000000
285 }
286 else
287 {
288 std::cout << "No denormalization. " << std::endl;
289 }
290 //] [denorm_min_1]
291 }
292
293 {
294 //[round_error_1
295 double round_err = std::numeric_limits<double>::epsilon() // 2.2204460492503131e-016
296 * std::numeric_limits<double>::round_error(); // 1/2
297 std::cout << round_err << std::endl; // 1.1102230246251565e-016
298 //] [/round_error_1]
299 }
300
301 {
302 typedef double T;
303 //[tolerance_1
304 /*`For example, if we want a tolerance that might suit about 9 arithmetical operations,
305 say sqrt(9) = 3, we could define:
306 */
307
308 T tolerance = 3 * std::numeric_limits<T>::epsilon();
309
310 /*`This is very widely used in Boost.Math testing
311 with Boost.Test's macro `BOOST_CHECK_CLOSE_FRACTION`
312 */
313
314 T expected = 1.0;
315 T calculated = 1.0 + std::numeric_limits<T>::epsilon();
316
317 BOOST_CHECK_CLOSE_FRACTION(expected, calculated, tolerance);
318
319 //] [/tolerance_1]
320 }
321
322 #if !(defined(CI_SUPPRESS_KNOWN_ISSUES) && defined(__GNUC__) && defined(_WIN32))
323 {
324 //[tolerance_2
325
326 using boost::multiprecision::number;
327 using boost::multiprecision::cpp_dec_float;
328 using boost::multiprecision::et_off;
329
330 typedef number<cpp_dec_float<50>, et_off > cpp_dec_float_50; // 50 decimal digits.
331 /*`[note that Boost.Test does not yet allow floating-point comparisons with expression templates on,
332 so the default expression template parameter has been replaced by `et_off`.]
333 */
334
335 cpp_dec_float_50 tolerance = 3 * std::numeric_limits<cpp_dec_float_50>::epsilon();
336 cpp_dec_float_50 expected = boost::math::constants::two_pi<cpp_dec_float_50>();
337 cpp_dec_float_50 calculated = 2 * boost::math::constants::pi<cpp_dec_float_50>();
338
339 BOOST_CHECK_CLOSE_FRACTION(expected, calculated, tolerance);
340
341 //] [/tolerance_2]
342 }
343
344 {
345 //[tolerance_3
346
347 using boost::multiprecision::cpp_bin_float_quad;
348
349 cpp_bin_float_quad tolerance = 3 * std::numeric_limits<cpp_bin_float_quad>::epsilon();
350 cpp_bin_float_quad expected = boost::math::constants::two_pi<cpp_bin_float_quad>();
351 cpp_bin_float_quad calculated = 2 * boost::math::constants::pi<cpp_bin_float_quad>();
352
353 BOOST_CHECK_CLOSE_FRACTION(expected, calculated, tolerance);
354
355 //] [/tolerance_3]
356 }
357
358 {
359 //[nan_1]
360
361 /*`NaN can be used with binary multiprecision types like `cpp_bin_float_quad`:
362 */
363 using boost::multiprecision::cpp_bin_float_quad;
364
365 if (std::numeric_limits<cpp_bin_float_quad>::has_quiet_NaN == true)
366 {
367 cpp_bin_float_quad tolerance = 3 * std::numeric_limits<cpp_bin_float_quad>::epsilon();
368
369 cpp_bin_float_quad NaN = std::numeric_limits<cpp_bin_float_quad>::quiet_NaN();
370 std::cout << "cpp_bin_float_quad NaN is " << NaN << std::endl; // cpp_bin_float_quad NaN is nan
371
372 cpp_bin_float_quad expected = NaN;
373 cpp_bin_float_quad calculated = 2 * NaN;
374 // Comparisons of NaN's always fail:
375 bool b = expected == calculated;
376 std::cout << b << std::endl;
377 BOOST_CHECK_NE(expected, expected);
378 BOOST_CHECK_NE(expected, calculated);
379 }
380 else
381 {
382 std::cout << "Type " << typeid(cpp_bin_float_quad).name() << " does not have NaNs!" << std::endl;
383 }
384
385 //] [/nan_1]
386 }
387
388 {
389 //[facet_1]
390
391 /*`
392 See [@boost:/libs/math/example/nonfinite_facet_sstream.cpp]
393 and we also need
394
395 #include <boost/math/special_functions/nonfinite_num_facets.hpp>
396
397 Then we can equally well use a multiprecision type cpp_bin_float_quad:
398
399 */
400 using boost::multiprecision::cpp_bin_float_quad;
401
402 typedef cpp_bin_float_quad T;
403
404 using boost::math::nonfinite_num_put;
405 using boost::math::nonfinite_num_get;
406 {
407 std::locale old_locale;
408 std::locale tmp_locale(old_locale, new nonfinite_num_put<char>);
409 std::locale new_locale(tmp_locale, new nonfinite_num_get<char>);
410 std::stringstream ss;
411 ss.imbue(new_locale);
412 T inf = std::numeric_limits<T>::infinity();
413 ss << inf; // Write out.
414 assert(ss.str() == "inf");
415 T r;
416 ss >> r; // Read back in.
417 assert(inf == r); // Confirms that the floating-point values really are identical.
418 std::cout << "infinity output was " << ss.str() << std::endl;
419 std::cout << "infinity input was " << r << std::endl;
420 }
421
422 /*`
423 infinity output was inf
424 infinity input was inf
425
426 Similarly we can do the same with NaN (except that we cannot use `assert`)
427 */
428 {
429 std::locale old_locale;
430 std::locale tmp_locale(old_locale, new nonfinite_num_put<char>);
431 std::locale new_locale(tmp_locale, new nonfinite_num_get<char>);
432 std::stringstream ss;
433 ss.imbue(new_locale);
434 T n;
435 T NaN = std::numeric_limits<T>::quiet_NaN();
436 ss << NaN; // Write out.
437 assert(ss.str() == "nan");
438 std::cout << "NaN output was " << ss.str() << std::endl;
439 ss >> n; // Read back in.
440 std::cout << "NaN input was " << n << std::endl;
441 }
442 /*`
443 NaN output was nan
444 NaN input was nan
445
446 */
447 //] [/facet_1]
448 }
449
450 #endif
451 #endif
452 } // BOOST_AUTO_TEST_CASE(test_numeric_limits_snips)
453