]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/multiprecision/example/numeric_limits_snips.cpp
import new upstream nautilus stable release 14.2.8
[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 // warning C4553: '==': result of expression not used; did you intend '='? is spurious.
270 }
271
272 {
273 //[denorm_min_1
274 std::cout.precision(std::numeric_limits<double>::max_digits10);
275 if (std::numeric_limits<double>::has_denorm == std::denorm_present)
276 {
277 double d = std::numeric_limits<double>::denorm_min();
278
279 std::cout << d << std::endl; // 4.9406564584124654e-324
280
281 int exponent;
282
283 double significand = frexp(d, &exponent);
284 std::cout << "exponent = " << std::hex << exponent << std::endl; // fffffbcf
285 std::cout << "significand = " << std::hex << significand << std::endl; // 0.50000000000000000
286 }
287 else
288 {
289 std::cout << "No denormalization. " << std::endl;
290 }
291 //] [denorm_min_1]
292 }
293
294 {
295 //[round_error_1
296 double round_err = std::numeric_limits<double>::epsilon() // 2.2204460492503131e-016
297 * std::numeric_limits<double>::round_error(); // 1/2
298 std::cout << round_err << std::endl; // 1.1102230246251565e-016
299 //] [/round_error_1]
300 }
301
302 {
303 typedef double T;
304 //[tolerance_1
305 /*`For example, if we want a tolerance that might suit about 9 arithmetical operations,
306 say sqrt(9) = 3, we could define:
307 */
308
309 T tolerance = 3 * std::numeric_limits<T>::epsilon();
310
311 /*`This is very widely used in Boost.Math testing
312 with Boost.Test's macro `BOOST_CHECK_CLOSE_FRACTION`
313 */
314
315 T expected = 1.0;
316 T calculated = 1.0 + std::numeric_limits<T>::epsilon();
317
318 BOOST_CHECK_CLOSE_FRACTION(expected, calculated, tolerance);
319
320 //] [/tolerance_1]
321 }
322
323 #if !(defined(CI_SUPPRESS_KNOWN_ISSUES) && defined(__GNUC__) && defined(_WIN32))
324 {
325 //[tolerance_2
326
327 using boost::multiprecision::number;
328 using boost::multiprecision::cpp_dec_float;
329 using boost::multiprecision::et_off;
330
331 typedef number<cpp_dec_float<50>, et_off > cpp_dec_float_50; // 50 decimal digits.
332 /*`[note that Boost.Test does not yet allow floating-point comparisons with expression templates on,
333 so the default expression template parameter has been replaced by `et_off`.]
334 */
335
336 cpp_dec_float_50 tolerance = 3 * std::numeric_limits<cpp_dec_float_50>::epsilon();
337 cpp_dec_float_50 expected = boost::math::constants::two_pi<cpp_dec_float_50>();
338 cpp_dec_float_50 calculated = 2 * boost::math::constants::pi<cpp_dec_float_50>();
339
340 BOOST_CHECK_CLOSE_FRACTION(expected, calculated, tolerance);
341
342 //] [/tolerance_2]
343 }
344
345 {
346 //[tolerance_3
347
348 using boost::multiprecision::cpp_bin_float_quad;
349
350 cpp_bin_float_quad tolerance = 3 * std::numeric_limits<cpp_bin_float_quad>::epsilon();
351 cpp_bin_float_quad expected = boost::math::constants::two_pi<cpp_bin_float_quad>();
352 cpp_bin_float_quad calculated = 2 * boost::math::constants::pi<cpp_bin_float_quad>();
353
354 BOOST_CHECK_CLOSE_FRACTION(expected, calculated, tolerance);
355
356 //] [/tolerance_3]
357 }
358
359 {
360 //[tolerance_4
361
362 using boost::multiprecision::cpp_bin_float_oct;
363
364 cpp_bin_float_oct tolerance = 3 * std::numeric_limits<cpp_bin_float_oct>::epsilon();
365 cpp_bin_float_oct expected = boost::math::constants::two_pi<cpp_bin_float_oct>();
366 cpp_bin_float_oct calculated = 2 * boost::math::constants::pi<cpp_bin_float_oct>();
367
368 BOOST_CHECK_CLOSE_FRACTION(expected, calculated, tolerance);
369
370 //] [/tolerance_4]
371 }
372
373 {
374 //[nan_1]
375
376 /*`NaN can be used with binary multiprecision types like `cpp_bin_float_quad`:
377 */
378 using boost::multiprecision::cpp_bin_float_quad;
379
380 if (std::numeric_limits<cpp_bin_float_quad>::has_quiet_NaN == true)
381 {
382 cpp_bin_float_quad tolerance = 3 * std::numeric_limits<cpp_bin_float_quad>::epsilon();
383
384 cpp_bin_float_quad NaN = std::numeric_limits<cpp_bin_float_quad>::quiet_NaN();
385 std::cout << "cpp_bin_float_quad NaN is " << NaN << std::endl; // cpp_bin_float_quad NaN is nan
386
387 cpp_bin_float_quad expected = NaN;
388 cpp_bin_float_quad calculated = 2 * NaN;
389 // Comparisons of NaN's always fail:
390 bool b = expected == calculated;
391 std::cout << b << std::endl;
392 BOOST_CHECK_NE(expected, expected);
393 BOOST_CHECK_NE(expected, calculated);
394 }
395 else
396 {
397 std::cout << "Type " << typeid(cpp_bin_float_quad).name() << " does not have NaNs!" << std::endl;
398 }
399
400 //] [/nan_1]
401 }
402
403 {
404 //[facet_1]
405
406 /*`
407 See [@boost:/libs/math/example/nonfinite_facet_sstream.cpp]
408 and we also need
409
410 #include <boost/math/special_functions/nonfinite_num_facets.hpp>
411
412 Then we can equally well use a multiprecision type cpp_bin_float_quad:
413
414 */
415 using boost::multiprecision::cpp_bin_float_quad;
416
417 typedef cpp_bin_float_quad T;
418
419 using boost::math::nonfinite_num_put;
420 using boost::math::nonfinite_num_get;
421 {
422 std::locale old_locale;
423 std::locale tmp_locale(old_locale, new nonfinite_num_put<char>);
424 std::locale new_locale(tmp_locale, new nonfinite_num_get<char>);
425 std::stringstream ss;
426 ss.imbue(new_locale);
427 T inf = std::numeric_limits<T>::infinity();
428 ss << inf; // Write out.
429 BOOST_ASSERT(ss.str() == "inf");
430 T r;
431 ss >> r; // Read back in.
432 BOOST_ASSERT(inf == r); // Confirms that the floating-point values really are identical.
433 std::cout << "infinity output was " << ss.str() << std::endl;
434 std::cout << "infinity input was " << r << std::endl;
435 }
436
437 /*`
438 ``
439 infinity output was inf
440 infinity input was inf
441 ``
442 Similarly we can do the same with NaN (except that we cannot use `assert` (because any comparisons with NaN always return false).
443 */
444 {
445 std::locale old_locale;
446 std::locale tmp_locale(old_locale, new nonfinite_num_put<char>);
447 std::locale new_locale(tmp_locale, new nonfinite_num_get<char>);
448 std::stringstream ss;
449 ss.imbue(new_locale);
450 T n;
451 T NaN = std::numeric_limits<T>::quiet_NaN();
452 ss << NaN; // Write out.
453 BOOST_ASSERT(ss.str() == "nan");
454 std::cout << "NaN output was " << ss.str() << std::endl;
455 ss >> n; // Read back in.
456 std::cout << "NaN input was " << n << std::endl;
457 }
458 /*`
459 ``
460 NaN output was nan
461 NaN input was nan
462 ``
463 */
464 //] [/facet_1]
465 }
466
467 #endif
468 #endif
469 } // BOOST_AUTO_TEST_CASE(test_numeric_limits_snips)
470