mirror of
				https://github.com/saitohirga/WSJT-X.git
				synced 2025-11-04 05:50:31 -05: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|
 | 
						|
 | 
						|
*/
 |