nonfinite_facet_simple.cpp 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. /** nonfinite_num_facet.cpp
  2. *
  3. * Copyright (c) 2011 Paul A. Bristow
  4. *
  5. * Distributed under the Boost Software License, Version 1.0.
  6. * (See accompanying file LICENSE_1_0.txt
  7. * or copy at http://www.boost.org/LICENSE_1_0.txt)
  8. *
  9. * This very simple program illustrates how to use the
  10. * `boost/math/nonfinite_num_facets.hpp' to obtain C99
  11. * representation of infinity and NaN.
  12. * (from the original
  13. * Floating Point Utilities contribution by Johan Rade.
  14. * Floating Point Utility library has been accepted into Boost,
  15. * but the utilities are incorporated into Boost.Math library.
  16. *
  17. \file
  18. \brief A very simple example of using non_finite_num facet for
  19. C99 standard output of infinity and NaN.
  20. \detail Provided infinity and nan are supported,
  21. this example shows how to create a C99 non-finite locale,
  22. and imbue input and output streams with the non_finite_num put and get facets.
  23. This allow output and input of infinity and NaN in a Standard portable way,
  24. This permits 'loop-back' of output back into input (and portably across different system too).
  25. This is particularly useful when used with Boost.Serialization so that non-finite NaNs and infinity
  26. values in text and xml archives can be handled correctly and portably.
  27. */
  28. #ifdef _MSC_VER
  29. # pragma warning (disable : 4127) // conditional expression is constant.
  30. #endif
  31. #include <iostream>
  32. using std::cout;
  33. using std::endl;
  34. using std::cerr;
  35. #include <iomanip>
  36. using std::setw;
  37. using std::left;
  38. using std::right;
  39. using std::internal;
  40. #include <string>
  41. using std::string;
  42. #include <sstream>
  43. using std::istringstream;
  44. #include <limits>
  45. using std::numeric_limits;
  46. #include <locale>
  47. using std::locale;
  48. #include <boost/math/special_functions/nonfinite_num_facets.hpp>
  49. // from Johan Rade Floating Point Utilities.
  50. int main ()
  51. {
  52. std::cout << "Nonfinite_num_facet very simple example." << std::endl;
  53. if((std::numeric_limits<double>::has_infinity == 0) || (std::numeric_limits<double>::infinity() == 0))
  54. {
  55. std::cout << "Infinity not supported on this platform." << std::endl;
  56. return 0;
  57. }
  58. if((std::numeric_limits<double>::has_quiet_NaN == 0) || (std::numeric_limits<double>::quiet_NaN() == 0))
  59. {
  60. std::cout << "NaN not supported on this platform." << std::endl;
  61. return 0;
  62. }
  63. std::locale default_locale (std::locale::classic ()); // Note the currrent (default C) locale.
  64. // Create plus and minus infinity.
  65. double plus_infinity = +std::numeric_limits<double>::infinity();
  66. double minus_infinity = -std::numeric_limits<double>::infinity();
  67. // and create a NaN (NotANumber)
  68. double NaN = +std::numeric_limits<double>::quiet_NaN ();
  69. double negated_NaN = (boost::math::changesign)(std::numeric_limits<double>::quiet_NaN ());
  70. // Output the nonfinite values using the current (default C) locale.
  71. // The default representations differ from system to system,
  72. // for example, using Microsoft compilers, 1.#INF, -1.#INF, and 1.#QNAN,
  73. // Linux "inf", "-inf", "nan"
  74. cout << "Using C locale" << endl;
  75. cout << "+std::numeric_limits<double>::infinity() = " << plus_infinity << endl;
  76. cout << "-std::numeric_limits<double>::infinity() = " << minus_infinity << endl;
  77. cout << "+std::numeric_limits<double>::quiet_NaN () = " << NaN << endl;
  78. // Display negated NaN.
  79. cout << "negated NaN " << negated_NaN << endl; // "-1.IND" or "-nan".
  80. // Create a new output locale, and add the nonfinite_num_put facet
  81. std::locale C99_out_locale (default_locale, new boost::math::nonfinite_num_put<char>);
  82. // and imbue the cout stream with the new locale.
  83. cout.imbue (C99_out_locale);
  84. // Or for the same effect more concisely:
  85. cout.imbue (locale(locale(), new boost::math::nonfinite_num_put<char>));
  86. // Output using the new locale:
  87. cout << "Using C99_out_locale " << endl;
  88. cout << "+std::numeric_limits<double>::infinity() = " << plus_infinity << endl;
  89. cout << "-std::numeric_limits<double>::infinity() = " << minus_infinity << endl;
  90. cout << "+std::numeric_limits<double>::quiet_NaN () = " << NaN << endl;
  91. // Expect "inf", "-inf", "nan".
  92. // Display negated NaN.
  93. cout << "negated NaN " << negated_NaN << endl; // Expect "-nan".
  94. // Create a string with the expected C99 representation of plus infinity.
  95. std::string inf = "inf";
  96. { // Try to read an infinity value using the default C locale.
  97. // Create an input stream which will provide "inf"
  98. std::istringstream iss (inf);
  99. // Create a double ready to take the input,
  100. double infinity;
  101. // and read "inf" from the stringstream:
  102. iss >> infinity;
  103. // This will not work on all platforms! (Intel-Linux-13.0.1 fails EXIT STATUS: 139)
  104. if (! iss)
  105. { // Reading infinity went wrong!
  106. std::cerr << "C locale input format error!" << std::endl;
  107. }
  108. } // Using default C locale.
  109. { // Now retry using C99 facets.
  110. // Create a new input locale and add the nonfinite_num_get facet.
  111. std::locale C99_in_locale (default_locale, new boost::math::nonfinite_num_get<char>);
  112. // Create an input stream which will provide "inf".
  113. std::istringstream iss (inf);
  114. // Imbue the stream with the C99 input locale.
  115. iss.imbue (C99_in_locale);
  116. // Create a double ready to take the input,
  117. double infinity;
  118. // and read from the stringstream:
  119. iss >> infinity;
  120. if (! iss)
  121. { // Reading infinity went wrong!
  122. std::cout << "C99 input format error!" << std::endl;
  123. }
  124. // Expect to get an infinity, which will display still using the C99 locale as "inf"
  125. cout << "infinity in C99 representation is " << infinity << endl;
  126. // To check, we can switch back to the default C locale.
  127. cout.imbue (default_locale);
  128. cout << "infinity in default C representation is " << infinity << endl;
  129. } // using C99 locale.
  130. {
  131. // A 'loop-back example, output to a stringstream, and reading it back in.
  132. // Create C99 input and output locales.
  133. std::locale C99_out_locale (default_locale, new boost::math::nonfinite_num_put<char>);
  134. std::locale C99_in_locale (default_locale, new boost::math::nonfinite_num_get<char>);
  135. std::ostringstream oss;
  136. oss.imbue(C99_out_locale);
  137. oss << plus_infinity;
  138. std::istringstream iss(oss.str()); // So stream contains "inf".
  139. iss.imbue (C99_in_locale);
  140. std::string s;
  141. iss >> s;
  142. cout.imbue(C99_out_locale);
  143. if (oss.str() != s)
  144. {
  145. cout << plus_infinity << " != " << s << " loopback failed!" << endl;
  146. }
  147. else
  148. {
  149. cout << plus_infinity << " == " << s << " as expected." << endl;
  150. }
  151. }
  152. // Example varying the width and position of the nonfinite representations.
  153. // With the nonfinite_num_put and _get facets, the width of the output is constant.
  154. #ifdef BOOST_NO_CXX11_NUMERIC_LIMITS
  155. cout << "BOOST_NO_CXX11_NUMERIC_LIMITS is defined, so no max_digits10 available." << endl;
  156. std::streamsize max_digits10 = 2 + std::numeric_limits<double>::digits * 30103UL / 100000UL;
  157. #else
  158. // Can use new C++0X max_digits10 (the maximum potentially significant digits).
  159. std::streamsize max_digits10 = std::numeric_limits<double>::max_digits10;
  160. #endif
  161. cout << "std::numeric_limits<double>::max_digits10 is " << max_digits10 << endl;
  162. cout.precision(max_digits10);
  163. double pi = 3.141592653589793238462643383279502884197169399375105820974944;
  164. // Expect 17 (probably) decimal digits (regardless of locale).
  165. // cout has the default locale.
  166. cout << "pi = " << pi << endl; // pi = 3.1415926535897931
  167. cout.imbue (C99_out_locale); // Use cout with the C99 locale
  168. // (expect the same output for a double).
  169. cout << "pi = " << pi << endl; // pi = 3.1415926535897931
  170. cout << "infinity in C99 representation is " << plus_infinity << endl;
  171. //int width = 2; // Check effect if width too small is OK.
  172. // (There was a disturbed layout on older MSVC?).
  173. int width = 20;
  174. // Similarly if we can switch back to the default C locale.
  175. cout.imbue (default_locale);
  176. cout << "infinity in default C representation is " << plus_infinity << endl;
  177. cout << "infinity in default C representation (setw(" << width << ") is |" << setw(width) << plus_infinity <<'|' << endl;
  178. cout << "infinity in default C representation (setw(" << width << ") is |" << left << setw(width) << plus_infinity <<'|' << endl;
  179. cout << "infinity in default C representation (setw(" << width << ") is |" << internal << setw(width) << plus_infinity <<'|' << endl;
  180. cout.imbue (C99_out_locale);
  181. cout << "infinity in C99 representation (setw(" << width << ") is |" << right << setw(width) << plus_infinity <<'|'<< endl;
  182. cout << "infinity in C99 representation (setw(" << width << ") is |" << left << setw(width) << plus_infinity <<'|'<< endl;
  183. cout << "infinity in C99 representation (setw(" << width << ") is |" << internal << setw(width) << plus_infinity <<'|'<< endl;
  184. return 0;
  185. } // int main()
  186. // end of test_nonfinite_num_facets.cpp
  187. /*
  188. Output:
  189. simple_nonfinite_facet.vcxproj -> J:\Cpp\MathToolkit\test\Math_test\Release\nonfinite_facet_simple.exe
  190. Nonfinite_num_facet very simple example.
  191. Using C locale
  192. +std::numeric_limits<double>::infinity() = 1.#INF
  193. -std::numeric_limits<double>::infinity() = -1.#INF
  194. +std::numeric_limits<double>::quiet_NaN () = 1.#QNAN
  195. Using C99_out_locale
  196. +std::numeric_limits<double>::infinity() = inf
  197. -std::numeric_limits<double>::infinity() = -inf
  198. +std::numeric_limits<double>::quiet_NaN () = nan
  199. infinity in C99 representation is inf
  200. infinity in default C representation is 1.#INF
  201. 3
  202. 3
  203. inf == inf as expected.
  204. std::numeric_limits<double>::max_digits10 is 17
  205. pi = 3.1415926535897931
  206. C locale input format error!
  207. pi = 3.1415926535897931
  208. infinity in C99 representation is inf
  209. infinity in default C representation is 1.#INF
  210. infinity in default C representation (setw(20) is 1.#INF|
  211. infinity in default C representation (setw(20) is 1.#INF |
  212. infinity in default C representation (setw(20) is 1.#INF|
  213. infinity in C99 representation (setw(20) is inf|
  214. infinity in C99 representation (setw(20) is inf |
  215. infinity in C99 representation (setw(20) is inf|
  216. */