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