• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1[section:fp_facets Facets for Floating-Point Infinities and NaNs]
2
3[import ../../example/nonfinite_facet_sstream.cpp]
4
5[h4 Synopsis]
6
7  namespace boost{ namespace math
8  {
9    // Values for flags.
10    const int legacy;
11    const int signed_zero;
12    const int trap_infinity;
13    const int trap_nan;
14
15    template<
16        class CharType,
17        class OutputIterator = std::ostreambuf_iterator<CharType>
18    >
19    class nonfinite_num_put : public std::num_put<CharType, OutputIterator>
20    {
21    public:
22        explicit nonfinite_num_put(int flags = 0);
23    };
24
25    template<
26        class CharType,
27        class InputIterator = std::istreambuf_iterator<CharType>
28    >
29    class nonfinite_num_get : public std::num_get<CharType, InputIterator>
30    {
31    public:
32        explicit nonfinite_num_get(int flags = 0);  // legacy, sign_zero ...
33    };
34  }} // namespace boost namespace math
35
36To use these facets
37
38  #include <boost\math\special_functions\nonfinite_num_facets.hpp>
39
40
41[section:facets_intro Introduction]
42
43[h5 The Problem]
44
45The C++98 standard does not specify how ['infinity] and ['NaN] are represented in text streams.
46As a result, different platforms use different string representations.
47This can cause undefined behavior when text files are moved between different platforms.
48Some platforms cannot even input parse their own output!
49So 'route-tripping' or loopback of output to input is not possible.
50For instance, the following test fails with MSVC:
51
52  stringstream ss;
53  double inf = numeric_limits<double>::infinity();
54  double r;
55  ss << inf; // Write out.
56  ss >> r; // Read back in.
57
58  cout << "infinity output was " << inf << endl; // 1.#INF
59  cout << "infinity input was " << r << endl; // 1
60
61  assert(inf == y); // Fails!
62
63[h5 The Solution]
64
65The facets `nonfinite_num_put` and `nonfinite_num_get`
66format and parse all floating-point numbers,
67including `infinity` and `NaN`, in a consistent and portable manner.
68
69The following test succeeds with MSVC.
70
71[nonfinite_facets_sstream_1]
72
73[tip To add two facets, `nonfinite_num_put` and `nonfinite_num_get`,
74you may have to add one at a time, using a temporary locale.
75
76Or you can create a new locale in one step
77
78`std::locale new_locale(std::locale(std::locale(std::locale(), new boost::math::nonfinite_num_put<char>), new boost::math::nonfinite_num_get<char>));`
79
80and, for example, use it to imbue an input and output stringstream.
81]
82
83[tip To just change an input or output stream, you can concisely write
84`cout.imbue (std::locale(std::locale(), new boost::math::nonfinite_num_put<char>));`
85or
86`cin.imbue (std::locale(std::locale(), new boost::math::nonfinite_num_get<char>));`
87]
88
89[nonfinite_facets_sstream_2]
90
91[h4 C++0X standard for output of infinity and NaN]
92
93[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf C++0X (final) draft standard]
94does not explicitly specify the representation (and input) of nonfinite values,
95leaving it implementation-defined.
96So without some specific action, input and output of nonfinite values is not portable.
97
98[h4 C99 standard for output of infinity and NaN]
99
100The [@http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf C99 standard]
101[*does] specify how infinity and NaN
102are formatted by printf and similar output functions,
103and parsed by scanf and similar input functions.
104
105The following string representations are used:
106
107[table C99 Representation of Infinity and NaN
108[[number] [string]]
109[[Positive infinity]["inf" or "infinity"]]
110[[Positive NaN]["nan" or "nan(...)"]]
111[[Negative infinity]["-inf" or "-infinity"]]
112[[Negative NaN]["-nan" or "-nan(...)"]]
113]
114
115So following C99 provides a sensible 'standard' way
116of handling input and output of nonfinites in C++,
117and this implementation follows most of these formats.
118
119[h5  Signaling NaNs]
120A particular type of NaN is the signaling NaN.
121The usual mechanism of signaling is by raising a floating-point exception.
122Signaling NaNs are defined by
123[@http://en.wikipedia.org/wiki/IEEE_floating-point_standard IEEE 754-2008].
124
125Floating-point values with layout ['s]111 1111 1['a]xx xxxx xxxx xxxx xxxx xxxx
126where ['s] is the sign, ['x] is the payload, and bit ['a] determines the type of NaN.
127
128If bit ['a] = 1, it is a quiet NaN.
129
130If bit ['a] is zero and the payload ['x] is nonzero, then it is a signaling NaN.
131
132Although there has been theoretical interest in the ability of a signaling NaN
133to raise an exception, for example to prevent use of an uninitialised variable,
134in practice there appears to be no useful application of signaling NaNs for
135most current processors.
136[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf C++0X 18.3.2.2]
137still specifies a (implementation-defined) representation for signaling NaN,
138and `static constexpr bool has_signaling_NaN`
139a method of checking if a floating-point type has a representation for signaling NaN.
140
141But in practice, most platforms treat signaling NaNs in the same as quiet NaNs.
142So, for example, they are represented by "nan" on output in
143[@http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf C99] format,
144and output as `1.#QNAN` by Microsoft compilers.
145
146[note The C99 standard does not distinguish
147between the quiet NaN and signaling NaN values.
148A quiet NaN propagates through almost every arithmetic operation
149without raising a floating-point exception;
150a signaling NaN generally raises a floating-point exception
151when occurring as an arithmetic operand.
152
153C99 specification does not define the behavior of signaling NaNs.
154NaNs created by IEC 60559 operations are always quiet.
155Therefore this implementation follows C99, and treats the signaling NaN bit
156as just a part of the NaN payload field.
157So this implementation does not distinguish between the two classes of NaN.]
158
159[note An implementation may give zero and non-numeric values (such as infinities and NaNs)
160a sign or may leave them unsigned. Wherever such values are unsigned,
161any requirement in the C99 Standard to retrieve the sign shall produce an unspecified sign,
162and any requirement to set the sign shall be ignored.
163
164This might apply to user-defined types, but in practice built-in floating-point
165types `float`, `double` and `long double` have well-behaved signs.]
166
167The numbers can be of type `float`, `double` and `long double`.
168An optional + sign can be used with positive numbers (controlled by ios manipulator `showpos`).
169The function `printf` and similar C++ functions use standard formatting flags
170to put all lower or all upper case
171(controlled by `std::ios` manipulator `uppercase` and `lowercase`).
172
173The function `scanf` and similar input functions are case-insensitive.
174
175The dots in `nan(...)` stand for an arbitrary string.
176The meaning of that string is implementation dependent.
177It can be used to convey extra information about the NaN, from the 'payload'.
178A particular value of the payload might be used to indicate a ['missing value], for example.
179
180This library uses the string representations specified by the C99 standard.
181
182An example of an implementation that optionally includes the NaN payload information is at
183[@http://publib.boulder.ibm.com/infocenter/zos/v1r10/index.jsp?topic=/com.ibm.zos.r10.bpxbd00/fprints.htm AIX NaN fprintf].
184That implementation specifies for Binary Floating Point NANs:
185
186* A NaN ordinal sequence is a left-parenthesis character '(',
187followed by a digit sequence representing
188an integer n, where 1 <= n <= INT_MAX-1,
189followed by a right-parenthesis character ')'.
190
191* The integer value, n, is determined by the fraction bits of the NaN argument value as follows:
192
193* For a signalling NaN value, NaN fraction bits are reversed (left to right)
194to produce bits (right to left) of an even integer value, 2*n.
195Then formatted output functions produce a (signalling) NaN ordinal sequence
196corresponding to the integer value n.
197
198* For a quiet NaN value, NaN fraction bits are reversed (left to right)
199to produce bits (right to left) of an odd integer value, 2*n-1.
200Then formatted output functions produce a (quiet) NaN ordinal sequence
201corresponding to the integer value n.
202
203[warning This implementation does not (yet) provide output of, or access to, the NaN payload.]
204
205[endsect] [/section:intro Introduction]
206
207[section:reference Reference]
208
209[h5 The Facet `nonfinite_num_put`]
210
211 template<
212   class CharType, class OutputIterator = std::ostreambuf_iterator<CharType>
213         >
214 class nonfinite_num_put;
215
216The `class nonfinite_num_put<CharType, OutputIterator>`
217is derived from `std::num_put<CharType, OutputIterator>`.
218Thus it is a facet that formats numbers.
219The first template argument is the character type of the formatted strings,
220usually `char` or `wchar_t`.
221The second template argument is the type of iterator used to write the strings.
222It is required to be an output iterator.
223Usually the default `std::ostreambuf_iterator` is used.
224The public interface of the class consists of a single constructor only:
225
226 nonfinite_num_put(int flags = 0);
227
228The flags argument (effectively optional because a default of ` no_flags` is provided)
229is discussed below.
230The class template `nonfinite_num_put` is defined in the
231header `boost/math/nonfinite_num_facets.hpp`
232and lives in the namespace `boost::math`.
233
234Unlike the C++ Standard facet `std::num_put`, the facet `nonfinite_num_put`
235formats `infinity` and `NaN` in a consistent and portable manner.
236It uses the following string representations:
237
238[table
239[[Number][String]]
240[[Positive infinity][inf]]
241[[Positive NaN][nan]]
242[[Negative infinity][-inf]]
243[[Negative NaN][-nan]]
244]
245
246The numbers can be of type `float`, `double` and `long double`.
247The strings can be in all lower case or all upper case.
248An optional + sign can be used with positive numbers.
249This can be controlled with the `uppercase`, `lowercase`, `showpos` and `noshowpos` manipulators.
250Formatting of integers, boolean values and finite floating-point numbers is simply delegated to the normal `std::num_put`.
251
252
253[h5 Facet `nonfinite_num_get`]
254
255  template<class CharType, class InputIterator = std::istreambuf_iterator<CharType> > class nonfinite_num_get;
256
257The class `nonfinite_num_get<CharType, InputIterator>` is derived from `std::num_get<CharType, IntputIterator>`.
258Thus it is a facet that parses strings that represent numbers.
259The first template argument is the character type of the strings,
260usually `char` or `wchar_t`.
261The second template argument is the type of iterator used to read the strings.
262It is required to be an input iterator. Usually the default is used.
263The public interface of the class consists of a single constructor only:
264
265 nonfinite_num_get(int flags = 0);
266
267The flags argument is discussed below.
268The `class template nonfinite_num_get`  is defined
269in the header `boost/math/nonfinite_num_facets.hpp`
270and lives in the `namespace boost::math`.
271
272Unlike the facet `std::num_get`, the facet `nonfinite_num_get` parses strings
273that represent `infinity` and `NaN` in a consistent and portable manner.
274It recognizes precisely the string representations specified by the C99 standard:
275
276[table
277[[Number][String]]
278[[Positive infinity][inf, infinity]]
279[[Positive NaN][nan, nan(...)]]
280[[Negative infinity][-inf, -infinity]]
281[[Negative NaN][-nan, -nan(...)]]
282]
283
284The numbers can be of type `float`, `double` and `long double`.
285The facet is case-insensitive. An optional + sign can be used with positive numbers.
286The dots in nan(...) stand for an arbitrary string usually containing the ['NaN payload].
287Parsing of strings that represent integers, boolean values
288and finite floating-point numbers is delegated to `std::num_get`.
289
290When the facet parses a string that represents `infinity` on a platform that lacks infinity,
291then the fail bit of the stream is set.
292
293When the facet parses a string that represents `NaN` on a platform that lacks NaN,
294then the fail bit of the stream is set.
295
296[h4 Flags]
297
298The constructors for `nonfinite_num_put` and `nonfinite_num_get`
299take an optional bit flags argument.
300There are four different bit flags:
301
302* legacy
303* signed_zero
304* trap_infinity
305* trap_nan
306
307The flags can be combined with the OR `operator|`.
308
309The flags are defined in the header `boost/math/nonfinite_num_facets.hpp`
310and live in the `namespace boost::math`.
311
312[h5 legacy]
313
314The legacy flag has no effect with the output facet `nonfinite_num_put`.
315
316If the legacy flag is used with the `nonfinite_num_get` input facet,
317then the facet will recognize all the following string representations of `infinity` and `NaN`:
318
319[table
320[[Number][String]]
321[[Positive infinity][inf, infinity, one#inf]]
322[[Positive NaN][nan, nan(...), nanq, nans, qnan, snan, one#ind, one#qnan, one#snan]]
323[[Negative infinity][-inf, -infinity, -one#inf]]
324[[Negative NaN][-nan, -nan(...), -nanq, -nans, -qnan, -snan, -one#ind, - one#qnan, -one#snan]]
325]
326
327* The numbers can be of type `float`, `double` and `long double`.
328* The facet is case-insensitive.
329* An optional `+` sign can be used with the positive values.
330* The dots in `nan(...)` stand for an arbitrary string.
331* `one` stands for any string that `std::num_get` parses as the number `1`,
332typically "1.#INF", "1.QNAN" but also "000001.#INF"...
333
334The list includes a number of non-standard string representations of infinity and NaN
335that are used by various existing implementations of the C++ standard library,
336and also string representations used by other programming languages.
337
338[h5 signed_zero]
339
340If the `signed_zero` flag is used with `nonfinite_num_put`,
341then the facet will always distinguish between positive and negative zero.
342It will format positive zero as "0" or "+0" and negative zero as "-0".
343The string representation of positive zero can be controlled
344with the `showpos` and `noshowpos` manipulators.
345
346The `signed_zero flag` has no effect with the input facet `nonfinite_num_get`.
347The input facet `nonfinite_num_get` always parses "0" and "+0"
348as positive zero and "-0" as negative zero,
349as do most implementations of `std::num_get`.
350
351[note If the `signed_zero` flag is not set (the default), then a negative zero value
352will be displayed on output in whatever way the platform normally handles it.
353For most platforms, this it will format positive zero as "0" or "+0" and negative zero as "-0".
354But setting the `signed_zero` flag may be more portable.]
355
356[tip A negative zero value can be portably produced using the changesign function
357`(changesign)(static_cast<ValType>(0))` where `ValType` is `float`, `double` or `long double`,
358 or a User-Defined floating-point type (UDT) provided that this UDT has a sign
359and that the changesign function is implemented.]
360
361[h5 trap_infinity]
362
363If the `trap_infinity` flag is used with `nonfinite_num_put`,
364then the facet will throw an exception of type `std::ios_base::failure`
365when an attempt is made to format positive or negative infinity.
366If the facet is called from a stream insertion operator,
367then the stream will catch that exception and set either its `fail bit` or its `bad bit`.
368Which bit is set is platform dependent.
369
370If the `trap_infinity` flag is used with `nonfinite_num_get`,
371then the facet will set the `fail bit` of the stream when an attempt is made
372to parse a string that represents positive or negative infinity.
373
374
375(See Design Rationale below for a discussion of this inconsistency.)
376
377[h5 trap_nan]
378
379Same as `trap_infinity`, but positive and negative NaN are trapped instead.
380
381[endsect] [/section:reference Reference]
382
383
384[section:examples Examples]
385
386[h5 Simple example with std::stringstreams]
387
388[nonfinite_facets_sstream_1]
389[nonfinite_facets_sstream_2]
390
391[h5 Use with lexical_cast]
392
393[note From Boost 1.48, lexical_cast no longer uses stringstreams internally,
394and is now able to handle infinities and NaNs natively on most platforms.]
395
396Without using a new locale that contains the nonfinite facets,
397previous versions of `lexical_cast` using stringstream were not portable
398(and often failed) if nonfinite values are found.
399
400[nonfinite_facets_sstream_1]
401
402Although other examples imbue individual streams with the new locale,
403for the streams constructed inside lexical_cast,
404it was necessary to assign to a global locale.
405
406  locale::global(new_locale);
407
408`lexical_cast` then works as expected, even with infinity and NaNs.
409
410  double x = boost::lexical_cast<double>("inf");
411  assert(x == std::numeric:limits<double>::infinity());
412
413  string s = boost::lexical_cast<string>(numeric_limits<double>::infinity());
414  assert(s == "inf");
415
416[warning If you use stringstream inside your functions,
417you may still need to use a global locale to handle nonfinites correctly.
418Or you need to imbue your stringstream with suitable get and put facets.]
419
420[warning You should be aware that the C++ specification does not explicitly require
421that input from decimal digits strings converts with rounding to the
422nearest representable floating-point binary value.
423(In contrast, decimal digits read by the compiler,
424for example by an assignment like `double d = 1.234567890123456789`,
425are guaranteed to assign the nearest representable value to double d).
426This implies that, no matter how many decimal digits you provide,
427there is a potential uncertainty of 1 least significant bit in the resulting binary value.]
428
429See [@http://en.wikipedia.org/wiki/Floating_point#Representable_numbers.2C_conversion_and_rounding conversion and rounding]
430for more information on ['nearest representable] and ['rounding] and
431[@http://www.exploringbinary.com/ Exploring  Binary] for much detail on input and round-tripping difficulties.
432
433Most iostream libraries do in fact achieve the desirable
434['nearest representable floating-point binary value] for all values of input.
435However one popular STL library does not quite achieve this for 64-bit doubles.  See
436[@http://connect.microsoft.com/VisualStudio/feedback/details/98770/decimal-digit-string-input-to-double-may-be-1-bit-wrong
437Decimal digit string input to double may be 1 bit wrong] for the bizarre full details.
438
439If you are expecting to 'round-trip' `lexical_cast` or `serialization`,
440for example archiving and loading,
441and want to be [*absolutely certain that you will
442always get an exactly identical double value binary pattern],
443you should use the suggested 'workaround' below that is believed to work on all platforms.
444
445You should output using all potentially significant decimal digits,
446by setting stream precision to `std::numeric_limits<double>::max_digits10`,
447(or for the appropriate floating-point type, if not double)
448and crucially, [*require `scientific` format], not `fixed` or automatic (default), for example:
449
450  double output_value = any value;
451  std::stringstream s;
452  s << setprecison(std::numeric_limits<double>::max_digits10) << scientific << output_value;
453  s >> input_value;
454
455
456[h4 Use with serialization archives]
457
458It is vital that the same locale is used
459when an archive is saved and when it is loaded.
460Otherwise, loading the archive may fail.
461By default, archives are saved and loaded with a classic C locale
462with a `boost::archive::codecvt_null` facet added.
463Normally you do not have to worry about that.
464
465The constructors for the archive classes, as a side-effect,
466imbue the stream with such a locale.
467However, if you want to use the
468facets `nonfinite_num_put` and `nonfinite_num_get` with archives,
469then you have to manage the locale manually.
470That is done by calling the archive constructor with the flag
471`boost::archive::no_codecvt`, thereby ensuring that the archive constructor
472will [*not imbue the stream with a new locale].
473
474The following code shows how to use `nonfinite_num_put` with a `text_oarchive`.
475
476  locale default_locale(locale::classic(), new boost::archive::codecvt_null<char>);
477  locale my_locale(default_locale, new nonfinite_num_put<char>);
478
479  ofstream ofs("test.txt");
480  ofs.imbue(my_locale);
481
482  boost::archive::text_oarchive oa(ofs, no_codecvt);
483
484  double x = numeric_limits<double>::infinity();
485  oa & x;
486
487The same method works with `nonfinite_num_get` and `text_iarchive`.
488
489If you use the `nonfinite_num_put` with `trap_infinity`
490and/or `trap_nan` flag with a serialization archive,
491then you must set the exception mask of the stream.
492Serialization archives do not check the stream state.
493
494
495[h5 Other examples]
496
497[@../../example/nonfinite_facet_simple.cpp nonfinite_facet_simple.cpp]
498give some more simple demonstrations of the difference between using classic C locale
499and constructing a C99 infinity and NaN compliant locale for input and output.
500
501See [@../../example/nonfinite_facet_sstream.cpp  nonfinite_facet_sstream.cpp]
502for this example of use with `std::stringstream`s.
503
504For an example of how to enforce the MSVC 'legacy'
505"1.#INF"  and "1.#QNAN" representations of infinity and NaNs,
506for input and output,
507see [@../../example/nonfinite_legacy.cpp nonfinite_legacy.cpp].
508
509Treatment of signaling NaN is demonstrated at
510[@../../example/nonfinite_signaling_NaN.cpp]
511
512Example [@../../example/nonfinite_loopback_ok.cpp] shows loopback works OK.
513
514Example [@../../example/nonfinite_num_facet.cpp] shows output and re-input
515of various finite and nonfinite values.
516
517A simple example of trapping nonfinite output is at
518[@../../example/nonfinite_num_facet_trap.cpp nonfinite_num_facet_trap.cpp].
519
520A very basic example of using Boost.Archive is at
521[@../../example/nonfinite_serialization_archives.cpp].
522
523A full demonstration of serialization by Francois Mauger is at
524[@../../example/nonfinite_num_facet_serialization.cpp]
525
526[endsect] [/section:examples Examples]
527
528[section:portability Portability]
529
530This library uses the floating-point number classification and sign-bit from Boost.Math library,
531and should work on all platforms where that library works.
532See the portability information for that library.
533
534[endsect] [/section:portability Portability]
535
536[section:rationale Design Rationale]
537
538* The flags are implemented as a const data member of the facet.
539Facets are reference counted, and locales can share facets.
540Therefore changing the flags of a facet would have effects that are hard to predict.
541An alternative design would be to implement the flags
542using `std::ios_base::xalloc` and `std::ios_base::iword`.
543Then one could safely modify the flags, and one could define manipulators that do so.
544However, for that to work with dynamically linked libraries,
545a `.cpp` file would have to be added to the library.
546It was judged be more desirable to have a header-only library,
547than to have mutable flags and manipulators.
548
549* The facet `nonfinite_num_put` throws an exception when
550the `trap_infinity` or `trap_nan` flag is set
551and an attempt is made to format infinity or NaN.
552It would be better if the facet set the `fail bit` of the stream.
553However, facets derived from `std::num_put` do not have access to the stream state.
554
555[endsect] [/section:rationale Design Rationale]
556
557[endsect] [/section:fp_facets Facets for Floating-Point Infinities and NaNs]
558
559[/
560  Copyright Johan Rade and Paul A. Bristow 2011.
561  Distributed under the Boost Software License, Version 1.0.
562  (See accompanying file LICENSE_1_0.txt or copy at
563  http://www.boost.org/LICENSE_1_0.txt).
564]
565
566
567
568
569