123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269 |
- /** nonfinite_num_facet.cpp
- *
- * Copyright (c) 2011 Paul A. Bristow
- *
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE_1_0.txt
- * or copy at http://www.boost.org/LICENSE_1_0.txt)
- *
- * This very simple program illustrates how to use the
- * `boost/math/nonfinite_num_facets.hpp' to obtain C99
- * representation of infinity and NaN.
- * (from the original
- * Floating Point Utilities contribution by Johan Rade.
- * Floating Point Utility library has been accepted into Boost,
- * but the utilities are incorporated into Boost.Math library.
- *
- \file
- \brief A very simple example of using non_finite_num facet for
- C99 standard output of infinity and NaN.
- \detail Provided infinity and nan are supported,
- this example shows how to create a C99 non-finite locale,
- and imbue input and output streams with the non_finite_num put and get facets.
- This allow output and input of infinity and NaN in a Standard portable way,
- This permits 'loop-back' of output back into input (and portably across different system too).
- This is particularly useful when used with Boost.Serialization so that non-finite NaNs and infinity
- values in text and xml archives can be handled correctly and portably.
- */
- #ifdef _MSC_VER
- # pragma warning (disable : 4127) // conditional expression is constant.
- #endif
- #include <iostream>
- using std::cout;
- using std::endl;
- using std::cerr;
- #include <iomanip>
- using std::setw;
- using std::left;
- using std::right;
- using std::internal;
- #include <string>
- using std::string;
- #include <sstream>
- using std::istringstream;
- #include <limits>
- using std::numeric_limits;
- #include <locale>
- using std::locale;
- #include <boost/math/special_functions/nonfinite_num_facets.hpp>
- // from Johan Rade Floating Point Utilities.
- int main ()
- {
- std::cout << "Nonfinite_num_facet very simple example." << std::endl;
- if((std::numeric_limits<double>::has_infinity == 0) || (std::numeric_limits<double>::infinity() == 0))
- {
- std::cout << "Infinity not supported on this platform." << std::endl;
- return 0;
- }
- if((std::numeric_limits<double>::has_quiet_NaN == 0) || (std::numeric_limits<double>::quiet_NaN() == 0))
- {
- std::cout << "NaN not supported on this platform." << std::endl;
- return 0;
- }
- std::locale default_locale (std::locale::classic ()); // Note the currrent (default C) locale.
- // Create plus and minus infinity.
- double plus_infinity = +std::numeric_limits<double>::infinity();
- double minus_infinity = -std::numeric_limits<double>::infinity();
- // and create a NaN (NotANumber)
- double NaN = +std::numeric_limits<double>::quiet_NaN ();
- double negated_NaN = (boost::math::changesign)(std::numeric_limits<double>::quiet_NaN ());
- // Output the nonfinite values using the current (default C) locale.
- // The default representations differ from system to system,
- // for example, using Microsoft compilers, 1.#INF, -1.#INF, and 1.#QNAN,
- // Linux "inf", "-inf", "nan"
- cout << "Using C locale" << endl;
- cout << "+std::numeric_limits<double>::infinity() = " << plus_infinity << endl;
- cout << "-std::numeric_limits<double>::infinity() = " << minus_infinity << endl;
- cout << "+std::numeric_limits<double>::quiet_NaN () = " << NaN << endl;
- // Display negated NaN.
- cout << "negated NaN " << negated_NaN << endl; // "-1.IND" or "-nan".
-
- // Create a new output locale, and add the nonfinite_num_put facet
- std::locale C99_out_locale (default_locale, new boost::math::nonfinite_num_put<char>);
- // and imbue the cout stream with the new locale.
- cout.imbue (C99_out_locale);
- // Or for the same effect more concisely:
- cout.imbue (locale(locale(), new boost::math::nonfinite_num_put<char>));
- // Output using the new locale:
- cout << "Using C99_out_locale " << endl;
- cout << "+std::numeric_limits<double>::infinity() = " << plus_infinity << endl;
- cout << "-std::numeric_limits<double>::infinity() = " << minus_infinity << endl;
- cout << "+std::numeric_limits<double>::quiet_NaN () = " << NaN << endl;
- // Expect "inf", "-inf", "nan".
- // Display negated NaN.
- cout << "negated NaN " << negated_NaN << endl; // Expect "-nan".
- // Create a string with the expected C99 representation of plus infinity.
- std::string inf = "inf";
- { // Try to read an infinity value using the default C locale.
- // Create an input stream which will provide "inf"
- std::istringstream iss (inf);
- // Create a double ready to take the input,
- double infinity;
- // and read "inf" from the stringstream:
- iss >> infinity;
- // This will not work on all platforms! (Intel-Linux-13.0.1 fails EXIT STATUS: 139)
- if (! iss)
- { // Reading infinity went wrong!
- std::cerr << "C locale input format error!" << std::endl;
- }
- } // Using default C locale.
- { // Now retry using C99 facets.
- // Create a new input locale and add the nonfinite_num_get facet.
- std::locale C99_in_locale (default_locale, new boost::math::nonfinite_num_get<char>);
- // Create an input stream which will provide "inf".
- std::istringstream iss (inf);
- // Imbue the stream with the C99 input locale.
- iss.imbue (C99_in_locale);
- // Create a double ready to take the input,
- double infinity;
- // and read from the stringstream:
- iss >> infinity;
- if (! iss)
- { // Reading infinity went wrong!
- std::cout << "C99 input format error!" << std::endl;
- }
- // Expect to get an infinity, which will display still using the C99 locale as "inf"
- cout << "infinity in C99 representation is " << infinity << endl;
- // To check, we can switch back to the default C locale.
- cout.imbue (default_locale);
- cout << "infinity in default C representation is " << infinity << endl;
- } // using C99 locale.
- {
- // A 'loop-back example, output to a stringstream, and reading it back in.
- // Create C99 input and output locales.
- std::locale C99_out_locale (default_locale, new boost::math::nonfinite_num_put<char>);
- std::locale C99_in_locale (default_locale, new boost::math::nonfinite_num_get<char>);
- std::ostringstream oss;
- oss.imbue(C99_out_locale);
- oss << plus_infinity;
- std::istringstream iss(oss.str()); // So stream contains "inf".
- iss.imbue (C99_in_locale);
- std::string s;
- iss >> s;
- cout.imbue(C99_out_locale);
- if (oss.str() != s)
- {
- cout << plus_infinity << " != " << s << " loopback failed!" << endl;
- }
- else
- {
- cout << plus_infinity << " == " << s << " as expected." << endl;
- }
- }
- // Example varying the width and position of the nonfinite representations.
- // With the nonfinite_num_put and _get facets, the width of the output is constant.
- #ifdef BOOST_NO_CXX11_NUMERIC_LIMITS
- cout << "BOOST_NO_CXX11_NUMERIC_LIMITS is defined, so no max_digits10 available." << endl;
- std::streamsize max_digits10 = 2 + std::numeric_limits<double>::digits * 30103UL / 100000UL;
- #else
- // Can use new C++0X max_digits10 (the maximum potentially significant digits).
- std::streamsize max_digits10 = std::numeric_limits<double>::max_digits10;
- #endif
- cout << "std::numeric_limits<double>::max_digits10 is " << max_digits10 << endl;
- cout.precision(max_digits10);
- double pi = 3.141592653589793238462643383279502884197169399375105820974944;
- // Expect 17 (probably) decimal digits (regardless of locale).
- // cout has the default locale.
- cout << "pi = " << pi << endl; // pi = 3.1415926535897931
- cout.imbue (C99_out_locale); // Use cout with the C99 locale
- // (expect the same output for a double).
- cout << "pi = " << pi << endl; // pi = 3.1415926535897931
- cout << "infinity in C99 representation is " << plus_infinity << endl;
- //int width = 2; // Check effect if width too small is OK.
- // (There was a disturbed layout on older MSVC?).
- int width = 20;
- // Similarly if we can switch back to the default C locale.
- cout.imbue (default_locale);
- cout << "infinity in default C representation is " << plus_infinity << endl;
- cout << "infinity in default C representation (setw(" << width << ") is |" << setw(width) << plus_infinity <<'|' << endl;
- cout << "infinity in default C representation (setw(" << width << ") is |" << left << setw(width) << plus_infinity <<'|' << endl;
- cout << "infinity in default C representation (setw(" << width << ") is |" << internal << setw(width) << plus_infinity <<'|' << endl;
- cout.imbue (C99_out_locale);
- cout << "infinity in C99 representation (setw(" << width << ") is |" << right << setw(width) << plus_infinity <<'|'<< endl;
- cout << "infinity in C99 representation (setw(" << width << ") is |" << left << setw(width) << plus_infinity <<'|'<< endl;
- cout << "infinity in C99 representation (setw(" << width << ") is |" << internal << setw(width) << plus_infinity <<'|'<< endl;
- return 0;
- } // int main()
- // end of test_nonfinite_num_facets.cpp
- /*
- Output:
- simple_nonfinite_facet.vcxproj -> J:\Cpp\MathToolkit\test\Math_test\Release\nonfinite_facet_simple.exe
- Nonfinite_num_facet very simple example.
- Using C locale
- +std::numeric_limits<double>::infinity() = 1.#INF
- -std::numeric_limits<double>::infinity() = -1.#INF
- +std::numeric_limits<double>::quiet_NaN () = 1.#QNAN
- Using C99_out_locale
- +std::numeric_limits<double>::infinity() = inf
- -std::numeric_limits<double>::infinity() = -inf
- +std::numeric_limits<double>::quiet_NaN () = nan
- infinity in C99 representation is inf
- infinity in default C representation is 1.#INF
- 3
- 3
- inf == inf as expected.
- std::numeric_limits<double>::max_digits10 is 17
- pi = 3.1415926535897931
- C locale input format error!
- pi = 3.1415926535897931
- infinity in C99 representation is inf
- infinity in default C representation is 1.#INF
- infinity in default C representation (setw(20) is 1.#INF|
- infinity in default C representation (setw(20) is 1.#INF |
- infinity in default C representation (setw(20) is 1.#INF|
- infinity in C99 representation (setw(20) is inf|
- infinity in C99 representation (setw(20) is inf |
- infinity in C99 representation (setw(20) is inf|
- */
|