diff options
Diffstat (limited to 'src/boost/libs/math/example/nonfinite_facet_simple.cpp')
-rw-r--r-- | src/boost/libs/math/example/nonfinite_facet_simple.cpp | 269 |
1 files changed, 269 insertions, 0 deletions
diff --git a/src/boost/libs/math/example/nonfinite_facet_simple.cpp b/src/boost/libs/math/example/nonfinite_facet_simple.cpp new file mode 100644 index 00000000..3be01c2d --- /dev/null +++ b/src/boost/libs/math/example/nonfinite_facet_simple.cpp @@ -0,0 +1,269 @@ +/** 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| + +*/ |