mirror of
				https://github.com/saitohirga/WSJT-X.git
				synced 2025-10-30 04:20:22 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			270 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			270 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /** 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|
 | |
| 
 | |
| */
 |