mirror of
				https://github.com/saitohirga/WSJT-X.git
				synced 2025-11-03 21:40:52 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			569 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			569 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
[section:fp_facets Facets for Floating-Point Infinities and NaNs]
 | 
						|
 | 
						|
[import ../../example/nonfinite_facet_sstream.cpp]
 | 
						|
 | 
						|
[h4 Synopsis]
 | 
						|
 | 
						|
  namespace boost{ namespace math
 | 
						|
  {
 | 
						|
    // Values for flags.
 | 
						|
    const int legacy;
 | 
						|
    const int signed_zero;
 | 
						|
    const int trap_infinity;
 | 
						|
    const int trap_nan;
 | 
						|
 | 
						|
    template<
 | 
						|
        class CharType,
 | 
						|
        class OutputIterator = std::ostreambuf_iterator<CharType>
 | 
						|
    >
 | 
						|
    class nonfinite_num_put : public std::num_put<CharType, OutputIterator>
 | 
						|
    {
 | 
						|
    public:
 | 
						|
        explicit nonfinite_num_put(int flags = 0);
 | 
						|
    };
 | 
						|
 | 
						|
    template<
 | 
						|
        class CharType,
 | 
						|
        class InputIterator = std::istreambuf_iterator<CharType>
 | 
						|
    >
 | 
						|
    class nonfinite_num_get : public std::num_get<CharType, InputIterator>
 | 
						|
    {
 | 
						|
    public:
 | 
						|
        explicit nonfinite_num_get(int flags = 0);  // legacy, sign_zero ...
 | 
						|
    };
 | 
						|
  }} // namespace boost namespace math
 | 
						|
 | 
						|
To use these facets
 | 
						|
 | 
						|
  #include <boost\math\special_functions\nonfinite_num_facets.hpp>
 | 
						|
 | 
						|
 | 
						|
[section:facets_intro Introduction]
 | 
						|
 | 
						|
[h5 The Problem]
 | 
						|
 | 
						|
The C++98 standard does not specify how ['infinity] and ['NaN] are represented in text streams.
 | 
						|
As a result, different platforms use different string representations.
 | 
						|
This can cause undefined behavior when text files are moved between different platforms.
 | 
						|
Some platforms cannot even input parse their own output!
 | 
						|
So 'route-tripping' or loopback of output to input is not possible.
 | 
						|
For instance, the following test fails with MSVC:
 | 
						|
 | 
						|
  stringstream ss;
 | 
						|
  double inf = numeric_limits<double>::infinity();
 | 
						|
  double r;
 | 
						|
  ss << inf; // Write out.
 | 
						|
  ss >> r; // Read back in.
 | 
						|
 | 
						|
  cout << "infinity output was " << inf << endl; // 1.#INF
 | 
						|
  cout << "infinity input was " << r << endl; // 1
 | 
						|
 | 
						|
  assert(inf == y); // Fails!
 | 
						|
 | 
						|
[h5 The Solution]
 | 
						|
 | 
						|
The facets `nonfinite_num_put` and `nonfinite_num_get`
 | 
						|
format and parse all floating-point numbers,
 | 
						|
including `infinity` and `NaN`, in a consistent and portable manner.
 | 
						|
 | 
						|
The following test succeeds with MSVC.
 | 
						|
 | 
						|
[nonfinite_facets_sstream_1]
 | 
						|
 | 
						|
[tip To add two facets, `nonfinite_num_put` and `nonfinite_num_get`,
 | 
						|
you may have to add one at a time, using a temporary locale.
 | 
						|
 | 
						|
Or you can create a new locale in one step
 | 
						|
 | 
						|
`std::locale new_locale(std::locale(std::locale(std::locale(), new boost::math::nonfinite_num_put<char>), new boost::math::nonfinite_num_get<char>));`
 | 
						|
 | 
						|
and, for example, use it to imbue an input and output stringstream.
 | 
						|
]
 | 
						|
 | 
						|
[tip To just change an input or output stream, you can concisely write
 | 
						|
`cout.imbue (std::locale(std::locale(), new boost::math::nonfinite_num_put<char>));`
 | 
						|
or
 | 
						|
`cin.imbue (std::locale(std::locale(), new boost::math::nonfinite_num_get<char>));`
 | 
						|
]
 | 
						|
 | 
						|
[nonfinite_facets_sstream_2]
 | 
						|
 | 
						|
[h4 C++0X standard for output of infinity and NaN]
 | 
						|
 | 
						|
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf C++0X (final) draft standard]
 | 
						|
does not explicitly specify the representation (and input) of nonfinite values,
 | 
						|
leaving it implementation-defined.
 | 
						|
So without some specific action, input and output of nonfinite values is not portable.
 | 
						|
 | 
						|
[h4 C99 standard for output of infinity and NaN]
 | 
						|
 | 
						|
The [@http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf C99 standard]
 | 
						|
[*does] specify how infinity and NaN
 | 
						|
are formatted by printf and similar output functions,
 | 
						|
and parsed by scanf and similar input functions.
 | 
						|
 | 
						|
The following string representations are used:
 | 
						|
 | 
						|
[table C99 Representation of Infinity and NaN
 | 
						|
[[number] [string]]
 | 
						|
[[Positive infinity]["inf" or "infinity"]]
 | 
						|
[[Positive NaN]["nan" or "nan(...)"]]
 | 
						|
[[Negative infinity]["-inf" or "-infinity"]]
 | 
						|
[[Negative NaN]["-nan" or "-nan(...)"]]
 | 
						|
]
 | 
						|
 | 
						|
So following C99 provides a sensible 'standard' way
 | 
						|
of handling input and output of nonfinites in C++,
 | 
						|
and this implementation follows most of these formats.
 | 
						|
 | 
						|
[h5  Signaling NaNs]
 | 
						|
A particular type of NaN is the signaling NaN.
 | 
						|
The usual mechanism of signaling is by raising a floating-point exception.
 | 
						|
Signaling NaNs are defined by
 | 
						|
[@http://en.wikipedia.org/wiki/IEEE_floating-point_standard IEEE 754-2008].
 | 
						|
 | 
						|
Floating-point values with layout ['s]111 1111 1['a]xx xxxx xxxx xxxx xxxx xxxx
 | 
						|
where ['s] is the sign, ['x] is the payload, and bit ['a] determines the type of NaN.
 | 
						|
 | 
						|
If bit ['a] = 1, it is a quiet NaN.
 | 
						|
 | 
						|
If bit ['a] is zero and the payload ['x] is nonzero, then it is a signaling NaN.
 | 
						|
 | 
						|
Although there has been theoretical interest in the ability of a signaling NaN
 | 
						|
to raise an exception, for example to prevent use of an uninitialised variable,
 | 
						|
in practice there appears to be no useful application of signaling NaNs for
 | 
						|
most current processors.
 | 
						|
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf C++0X 18.3.2.2]
 | 
						|
still specifies a (implementation-defined) representation for signaling NaN,
 | 
						|
and `static constexpr bool has_signaling_NaN`
 | 
						|
a method of checking if a floating-point type has a representation for signaling NaN.
 | 
						|
 | 
						|
But in practice, most platforms treat signaling NaNs in the same as quiet NaNs.
 | 
						|
So, for example, they are represented by "nan" on output in
 | 
						|
[@http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf C99] format,
 | 
						|
and output as `1.#QNAN` by Microsoft compilers.
 | 
						|
 | 
						|
[note The C99 standard does not distinguish
 | 
						|
between the quiet NaN and signaling NaN values.
 | 
						|
A quiet NaN propagates through almost every arithmetic operation
 | 
						|
without raising a floating-point exception;
 | 
						|
a signaling NaN generally raises a floating-point exception
 | 
						|
when occurring as an arithmetic operand.
 | 
						|
 | 
						|
C99 specification does not define the behavior of signaling NaNs.
 | 
						|
NaNs created by IEC 60559 operations are always quiet.
 | 
						|
Therefore this implementation follows C99, and treats the signaling NaN bit
 | 
						|
as just a part of the NaN payload field.
 | 
						|
So this implementation does not distinguish between the two classes of NaN.]
 | 
						|
 | 
						|
[note An implementation may give zero and non-numeric values (such as infinities and NaNs)
 | 
						|
a sign or may leave them unsigned. Wherever such values are unsigned,
 | 
						|
any requirement in the C99 Standard to retrieve the sign shall produce an unspecified sign,
 | 
						|
and any requirement to set the sign shall be ignored.
 | 
						|
 | 
						|
This might apply to user-defined types, but in practice built-in floating-point
 | 
						|
types `float`, `double` and `long double` have well-behaved signs.]
 | 
						|
 | 
						|
The numbers can be of type `float`, `double` and `long double`.
 | 
						|
An optional + sign can be used with positive numbers (controlled by ios manipulator `showpos`).
 | 
						|
The function `printf` and similar C++ functions use standard formatting flags
 | 
						|
to put all lower or all upper case
 | 
						|
(controlled by `std::ios` manipulator `uppercase` and `lowercase`).
 | 
						|
 | 
						|
The function `scanf` and similar input functions are case-insensitive.
 | 
						|
 | 
						|
The dots in `nan(...)` stand for an arbitrary string.
 | 
						|
The meaning of that string is implementation dependent.
 | 
						|
It can be used to convey extra information about the NaN, from the 'payload'.
 | 
						|
A particular value of the payload might be used to indicate a ['missing value], for example.
 | 
						|
 | 
						|
This library uses the string representations specified by the C99 standard.
 | 
						|
 | 
						|
An example of an implementation that optionally includes the NaN payload information is at
 | 
						|
[@http://publib.boulder.ibm.com/infocenter/zos/v1r10/index.jsp?topic=/com.ibm.zos.r10.bpxbd00/fprints.htm AIX NaN fprintf].
 | 
						|
That implementation specifies for Binary Floating Point NANs:
 | 
						|
 | 
						|
* A NaN ordinal sequence is a left-parenthesis character '(',
 | 
						|
followed by a digit sequence representing
 | 
						|
an integer n, where 1 <= n <= INT_MAX-1,
 | 
						|
followed by a right-parenthesis character ')'.
 | 
						|
 | 
						|
* The integer value, n, is determined by the fraction bits of the NaN argument value as follows:
 | 
						|
 | 
						|
* For a signalling NaN value, NaN fraction bits are reversed (left to right)
 | 
						|
to produce bits (right to left) of an even integer value, 2*n.
 | 
						|
Then formatted output functions produce a (signalling) NaN ordinal sequence
 | 
						|
corresponding to the integer value n.
 | 
						|
 | 
						|
* For a quiet NaN value, NaN fraction bits are reversed (left to right)
 | 
						|
to produce bits (right to left) of an odd integer value, 2*n-1.
 | 
						|
Then formatted output functions produce a (quiet) NaN ordinal sequence
 | 
						|
corresponding to the integer value n.
 | 
						|
 | 
						|
[warning This implementation does not (yet) provide output of, or access to, the NaN payload.]
 | 
						|
 | 
						|
[endsect] [/section:intro Introduction]
 | 
						|
 | 
						|
[section:reference Reference]
 | 
						|
 | 
						|
[h5 The Facet `nonfinite_num_put`]
 | 
						|
 | 
						|
 template<
 | 
						|
   class CharType, class OutputIterator = std::ostreambuf_iterator<CharType>
 | 
						|
         >
 | 
						|
 class nonfinite_num_put;
 | 
						|
 | 
						|
The `class nonfinite_num_put<CharType, OutputIterator>`
 | 
						|
is derived from `std::num_put<CharType, OutputIterator>`.
 | 
						|
Thus it is a facet that formats numbers.
 | 
						|
The first template argument is the character type of the formatted strings,
 | 
						|
usually `char` or `wchar_t`.
 | 
						|
The second template argument is the type of iterator used to write the strings.
 | 
						|
It is required to be an output iterator.
 | 
						|
Usually the default `std::ostreambuf_iterator` is used.
 | 
						|
The public interface of the class consists of a single constructor only:
 | 
						|
 | 
						|
 nonfinite_num_put(int flags = 0);
 | 
						|
 | 
						|
The flags argument (effectively optional because a default of ` no_flags` is provided)
 | 
						|
is discussed below.
 | 
						|
The class template `nonfinite_num_put` is defined in the
 | 
						|
header `boost/math/nonfinite_num_facets.hpp`
 | 
						|
and lives in the namespace `boost::math`.
 | 
						|
 | 
						|
Unlike the C++ Standard facet `std::num_put`, the facet `nonfinite_num_put`
 | 
						|
formats `infinity` and `NaN` in a consistent and portable manner.
 | 
						|
It uses the following string representations:
 | 
						|
 | 
						|
[table
 | 
						|
[[Number][String]]
 | 
						|
[[Positive infinity][inf]]
 | 
						|
[[Positive NaN][nan]]
 | 
						|
[[Negative infinity][-inf]]
 | 
						|
[[Negative NaN][-nan]]
 | 
						|
]
 | 
						|
 | 
						|
The numbers can be of type `float`, `double` and `long double`.
 | 
						|
The strings can be in all lower case or all upper case.
 | 
						|
An optional + sign can be used with positive numbers.
 | 
						|
This can be controlled with the `uppercase`, `lowercase`, `showpos` and `noshowpos` manipulators.
 | 
						|
Formatting of integers, boolean values and finite floating-point numbers is simply delegated to the normal `std::num_put`.
 | 
						|
 | 
						|
 | 
						|
[h5 Facet `nonfinite_num_get`]
 | 
						|
 | 
						|
  template<class CharType, class InputIterator = std::istreambuf_iterator<CharType> > class nonfinite_num_get;
 | 
						|
 | 
						|
The class `nonfinite_num_get<CharType, InputIterator>` is derived from `std::num_get<CharType, IntputIterator>`.
 | 
						|
Thus it is a facet that parses strings that represent numbers.
 | 
						|
The first template argument is the character type of the strings,
 | 
						|
usually `char` or `wchar_t`.
 | 
						|
The second template argument is the type of iterator used to read the strings.
 | 
						|
It is required to be an input iterator. Usually the default is used.
 | 
						|
The public interface of the class consists of a single constructor only:
 | 
						|
 | 
						|
 nonfinite_num_get(int flags = 0);
 | 
						|
 | 
						|
The flags argument is discussed below.
 | 
						|
The `class template nonfinite_num_get`  is defined
 | 
						|
in the header `boost/math/nonfinite_num_facets.hpp`
 | 
						|
and lives in the `namespace boost::math`.
 | 
						|
 | 
						|
Unlike the facet `std::num_get`, the facet `nonfinite_num_get` parses strings
 | 
						|
that represent `infinity` and `NaN` in a consistent and portable manner.
 | 
						|
It recognizes precisely the string representations specified by the C99 standard:
 | 
						|
 | 
						|
[table
 | 
						|
[[Number][String]]
 | 
						|
[[Positive infinity][inf, infinity]]
 | 
						|
[[Positive NaN][nan, nan(...)]]
 | 
						|
[[Negative infinity][-inf, -infinity]]
 | 
						|
[[Negative NaN][-nan, -nan(...)]]
 | 
						|
]
 | 
						|
 | 
						|
The numbers can be of type `float`, `double` and `long double`.
 | 
						|
The facet is case-insensitive. An optional + sign can be used with positive numbers.
 | 
						|
The dots in nan(...) stand for an arbitrary string usually containing the ['NaN payload].
 | 
						|
Parsing of strings that represent integers, boolean values
 | 
						|
and finite floating-point numbers is delegated to `std::num_get`.
 | 
						|
 | 
						|
When the facet parses a string that represents `infinity` on a platform that lacks infinity,
 | 
						|
then the fail bit of the stream is set.
 | 
						|
 | 
						|
When the facet parses a string that represents `NaN` on a platform that lacks NaN,
 | 
						|
then the fail bit of the stream is set.
 | 
						|
 | 
						|
[h4 Flags]
 | 
						|
 | 
						|
The constructors for `nonfinite_num_put` and `nonfinite_num_get`
 | 
						|
take an optional bit flags argument.
 | 
						|
There are four different bit flags:
 | 
						|
 | 
						|
* legacy
 | 
						|
* signed_zero
 | 
						|
* trap_infinity
 | 
						|
* trap_nan
 | 
						|
 | 
						|
The flags can be combined with the OR `operator|`.
 | 
						|
 | 
						|
The flags are defined in the header `boost/math/nonfinite_num_facets.hpp`
 | 
						|
and live in the `namespace boost::math`.
 | 
						|
 | 
						|
[h5 legacy]
 | 
						|
 | 
						|
The legacy flag has no effect with the output facet `nonfinite_num_put`.
 | 
						|
 | 
						|
If the legacy flag is used with the `nonfinite_num_get` input facet,
 | 
						|
then the facet will recognize all the following string representations of `infinity` and `NaN`:
 | 
						|
 | 
						|
[table
 | 
						|
[[Number][String]]
 | 
						|
[[Positive infinity][inf, infinity, one#inf]]
 | 
						|
[[Positive NaN][nan, nan(...), nanq, nans, qnan, snan, one#ind, one#qnan, one#snan]]
 | 
						|
[[Negative infinity][-inf, -infinity, -one#inf]]
 | 
						|
[[Negative NaN][-nan, -nan(...), -nanq, -nans, -qnan, -snan, -one#ind, - one#qnan, -one#snan]]
 | 
						|
]
 | 
						|
 | 
						|
* The numbers can be of type `float`, `double` and `long double`.
 | 
						|
* The facet is case-insensitive.
 | 
						|
* An optional `+` sign can be used with the positive values.
 | 
						|
* The dots in `nan(...)` stand for an arbitrary string.
 | 
						|
* `one` stands for any string that `std::num_get` parses as the number `1`,
 | 
						|
typically "1.#INF", "1.QNAN" but also "000001.#INF"...
 | 
						|
 | 
						|
The list includes a number of non-standard string representations of infinity and NaN
 | 
						|
that are used by various existing implementations of the C++ standard library,
 | 
						|
and also string representations used by other programming languages.
 | 
						|
 | 
						|
[h5 signed_zero]
 | 
						|
 | 
						|
If the `signed_zero` flag is used with `nonfinite_num_put`,
 | 
						|
then the facet will always distinguish between positive and negative zero.
 | 
						|
It will format positive zero as "0" or "+0" and negative zero as "-0".
 | 
						|
The string representation of positive zero can be controlled
 | 
						|
with the `showpos` and `noshowpos` manipulators.
 | 
						|
 | 
						|
The `signed_zero flag` has no effect with the input facet `nonfinite_num_get`.
 | 
						|
The input facet `nonfinite_num_get` always parses "0" and "+0"
 | 
						|
as positive zero and "-0" as negative zero,
 | 
						|
as do most implementations of `std::num_get`.
 | 
						|
 | 
						|
[note If the `signed_zero` flag is not set (the default), then a negative zero value
 | 
						|
will be displayed on output in whatever way the platform normally handles it.
 | 
						|
For most platforms, this it will format positive zero as "0" or "+0" and negative zero as "-0".
 | 
						|
But setting the `signed_zero` flag may be more portable.]
 | 
						|
 | 
						|
[tip A negative zero value can be portably produced using the changesign function
 | 
						|
`(changesign)(static_cast<ValType>(0))` where `ValType` is `float`, `double` or `long double`,
 | 
						|
 or a User-Defined floating-point type (UDT) provided that this UDT has a sign
 | 
						|
and that the changesign function is implemented.]
 | 
						|
 | 
						|
[h5 trap_infinity]
 | 
						|
 | 
						|
If the `trap_infinity` flag is used with `nonfinite_num_put`,
 | 
						|
then the facet will throw an exception of type `std::ios_base::failure`
 | 
						|
when an attempt is made to format positive or negative infinity.
 | 
						|
If the facet is called from a stream insertion operator,
 | 
						|
then the stream will catch that exception and set either its `fail bit` or its `bad bit`.
 | 
						|
Which bit is set is platform dependent.
 | 
						|
 | 
						|
If the `trap_infinity` flag is used with `nonfinite_num_get`,
 | 
						|
then the facet will set the `fail bit` of the stream when an attempt is made
 | 
						|
to parse a string that represents positive or negative infinity.
 | 
						|
 | 
						|
 | 
						|
(See Design Rationale below for a discussion of this inconsistency.)
 | 
						|
 | 
						|
[h5 trap_nan]
 | 
						|
 | 
						|
Same as `trap_infinity`, but positive and negative NaN are trapped instead.
 | 
						|
 | 
						|
[endsect] [/section:reference Reference]
 | 
						|
 | 
						|
 | 
						|
[section:examples Examples]
 | 
						|
 | 
						|
[h5 Simple example with std::stringstreams]
 | 
						|
 | 
						|
[nonfinite_facets_sstream_1]
 | 
						|
[nonfinite_facets_sstream_2]
 | 
						|
 | 
						|
[h5 Use with lexical_cast]
 | 
						|
 | 
						|
[note From Boost 1.48, lexical_cast no longer uses stringstreams internally,
 | 
						|
and is now able to handle infinities and NaNs natively on most platforms.]
 | 
						|
 | 
						|
Without using a new locale that contains the nonfinite facets,
 | 
						|
previous versions of `lexical_cast` using stringstream were not portable
 | 
						|
(and often failed) if nonfinite values are found.
 | 
						|
 | 
						|
[nonfinite_facets_sstream_1]
 | 
						|
 | 
						|
Although other examples imbue individual streams with the new locale,
 | 
						|
for the streams constructed inside lexical_cast,
 | 
						|
it was necesary to assign to a global locale.
 | 
						|
 | 
						|
  locale::global(new_locale);
 | 
						|
 | 
						|
`lexical_cast` then works as expected, even with infinity and NaNs.
 | 
						|
 | 
						|
  double x = boost::lexical_cast<double>("inf");
 | 
						|
  assert(x == std::numeric:limits<double>::infinity());
 | 
						|
 | 
						|
  string s = boost::lexical_cast<string>(numeric_limits<double>::infinity());
 | 
						|
  assert(s == "inf");
 | 
						|
 | 
						|
[warning If you use stringstream inside your functions,
 | 
						|
you may still need to use a global locale to handle nonfinites correctly.
 | 
						|
Or you need to imbue your stringstream with suitable get and put facets.]
 | 
						|
 | 
						|
[warning You should be aware that the C++ specification does not explicitly require
 | 
						|
that input from decimal digits strings converts with rounding to the
 | 
						|
nearest representable floating-point binary value.
 | 
						|
(In contrast, decimal digits read by the compiler,
 | 
						|
for example by an assignment like `double d = 1.234567890123456789`,
 | 
						|
are guaranteed to assign the nearest representable value to double d).
 | 
						|
This implies that, no matter how many decimal digits you provide,
 | 
						|
there is a potential uncertainty of 1 least significant bit in the resulting binary value.]
 | 
						|
 | 
						|
See [@http://en.wikipedia.org/wiki/Floating_point#Representable_numbers.2C_conversion_and_rounding conversion and rounding]
 | 
						|
for more information on ['nearest representable] and ['rounding] and
 | 
						|
[@http://www.exploringbinary.com/ Exploring  Binary] for much detail on input and round-tripping difficulties.
 | 
						|
 | 
						|
Most iostream libraries do in fact achieve the desirable
 | 
						|
['nearest representable floating-point binary value] for all values of input.
 | 
						|
However one popular STL library does not quite achieve this for 64-bit doubles.  See
 | 
						|
[@http://connect.microsoft.com/VisualStudio/feedback/details/98770/decimal-digit-string-input-to-double-may-be-1-bit-wrong
 | 
						|
Decimal digit string input to double may be 1 bit wrong] for the bizarre full details.
 | 
						|
 | 
						|
If you are expecting to 'round-trip' `lexical_cast` or `serialization`,
 | 
						|
for example archiving and loading,
 | 
						|
and want to be [*absolutely certain that you will
 | 
						|
always get an exactly identical double value binary pattern],
 | 
						|
you should use the suggested 'workaround' below that is believed to work on all platforms.
 | 
						|
 | 
						|
You should output using all potentially significant decimal digits,
 | 
						|
by setting stream precision to `std::numeric_limits<double>::max_digits10`,
 | 
						|
(or for the appropriate floating-point type, if not double)
 | 
						|
and crucially, [*require `scientific` format], not `fixed` or automatic (default), for example:
 | 
						|
 | 
						|
  double output_value = any value;
 | 
						|
  std::stringstream s;
 | 
						|
  s << setprecison(std::numeric_limits<double>::max_digits10) << scientific << output_value;
 | 
						|
  s >> input_value;
 | 
						|
 | 
						|
 | 
						|
[h4 Use with serialization archives]
 | 
						|
 | 
						|
It is vital that the same locale is used
 | 
						|
when an archive is saved and when it is loaded.
 | 
						|
Otherwise, loading the archive may fail.
 | 
						|
By default, archives are saved and loaded with a classic C locale
 | 
						|
with a `boost::archive::codecvt_null` facet added.
 | 
						|
Normally you do not have to worry about that.
 | 
						|
 | 
						|
The constructors for the archive classes, as a side-effect,
 | 
						|
imbue the stream with such a locale.
 | 
						|
However, if you want to use the
 | 
						|
facets `nonfinite_num_put` and `nonfinite_num_get` with archives,
 | 
						|
then you have to manage the locale manually.
 | 
						|
That is done by calling the archive constructor with the flag
 | 
						|
`boost::archive::no_codecvt`, thereby ensuring that the archive constructor
 | 
						|
will [*not imbue the stream with a new locale].
 | 
						|
 | 
						|
The following code shows how to use `nonfinite_num_put` with a `text_oarchive`.
 | 
						|
 | 
						|
  locale default_locale(locale::classic(), new boost::archive::codecvt_null<char>);
 | 
						|
  locale my_locale(default_locale, new nonfinite_num_put<char>);
 | 
						|
 | 
						|
  ofstream ofs("test.txt");
 | 
						|
  ofs.imbue(my_locale);
 | 
						|
 | 
						|
  boost::archive::text_oarchive oa(ofs, no_codecvt);
 | 
						|
 | 
						|
  double x = numeric_limits<double>::infinity();
 | 
						|
  oa & x;
 | 
						|
 | 
						|
The same method works with `nonfinite_num_get` and `text_iarchive`.
 | 
						|
 | 
						|
If you use the `nonfinite_num_put` with `trap_infinity`
 | 
						|
and/or `trap_nan` flag with a serialization archive,
 | 
						|
then you must set the exception mask of the stream.
 | 
						|
Serialization archives do not check the stream state.
 | 
						|
 | 
						|
 | 
						|
[h5 Other examples]
 | 
						|
 | 
						|
[@../../example/nonfinite_facet_simple.cpp nonfinite_facet_simple.cpp]
 | 
						|
give some more simple demonstrations of the difference between using classic C locale
 | 
						|
and constructing a C99 infinty and NaN compliant locale for input and output.
 | 
						|
 | 
						|
See [@../../example/nonfinite_facet_sstream.cpp  nonfinite_facet_sstream.cpp]
 | 
						|
for this example of use with `std::stringstream`s.
 | 
						|
 | 
						|
For an example of how to enforce the MSVC 'legacy'
 | 
						|
"1.#INF"  and "1.#QNAN" representations of infinity and NaNs,
 | 
						|
for input and output,
 | 
						|
see [@../../example/nonfinite_legacy.cpp nonfinite_legacy.cpp].
 | 
						|
 | 
						|
Treatment of signaling NaN is demonstrated at
 | 
						|
[@../../example/nonfinite_signaling_NaN.cpp]
 | 
						|
 | 
						|
Example [@../../example/nonfinite_loopback_ok.cpp] shows loopback works OK.
 | 
						|
 | 
						|
Example [@../../example/nonfinite_num_facet.cpp] shows output and re-input
 | 
						|
of various finite and nonfinite values.
 | 
						|
 | 
						|
A simple example of trapping nonfinite output is at
 | 
						|
[@../../example/nonfinite_num_facet_trap.cpp nonfinite_num_facet_trap.cpp].
 | 
						|
 | 
						|
A very basic example of using Boost.Archive is at
 | 
						|
[@../../example/nonfinite_serialization_archives.cpp].
 | 
						|
 | 
						|
A full demonstration of serialization by Francois Mauger is at
 | 
						|
[@../../example/nonfinite_num_facet_serialization.cpp]
 | 
						|
 | 
						|
[endsect] [/section:examples Examples]
 | 
						|
 | 
						|
[section:portability Portability]
 | 
						|
 | 
						|
This library uses the floating-point number classification and sign-bit from Boost.Math library,
 | 
						|
and should work on all platforms where that library works.
 | 
						|
See the portability information for that library.
 | 
						|
 | 
						|
[endsect] [/section:portability Portability]
 | 
						|
 | 
						|
[section:rationale Design Rationale]
 | 
						|
 | 
						|
* The flags are implemented as a const data member of the facet.
 | 
						|
Facets are reference counted, and locales can share facets.
 | 
						|
Therefore changing the flags of a facet would have effects that are hard to predict.
 | 
						|
An alternative design would be to implement the flags
 | 
						|
using `std::ios_base::xalloc` and `std::ios_base::iword`.
 | 
						|
Then one could safely modify the flags, and one could define manipulators that do so.
 | 
						|
However, for that to work with dynamically linked libraries,
 | 
						|
a `.cpp` file would have to be added to the library.
 | 
						|
It was judged be more desirable to have a header-only library,
 | 
						|
than to have mutable flags and manipulators.
 | 
						|
 | 
						|
* The facet `nonfinite_num_put` throws an exception when
 | 
						|
the `trap_infinity` or `trap_nan` flag is set
 | 
						|
and an attempt is made to format infinity or NaN.
 | 
						|
It would be better if the facet set the `fail bit` of the stream.
 | 
						|
However, facets derived from `std::num_put` do not have access to the stream state.
 | 
						|
 | 
						|
[endsect] [/section:rationale Design Rationale]
 | 
						|
 | 
						|
[endsect] [/section:fp_facets Facets for Floating-Point Infinities and NaNs]
 | 
						|
 | 
						|
[/
 | 
						|
  Copyright Johan Rade and Paul A. Bristow 2011.
 | 
						|
  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).
 | 
						|
]
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 |