Imported Upstream version 1.72.0
[platform/upstream/boost.git] / 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