1 /** nonfinite_num_facet.cpp
2  *
3  * Copyright (c) 2011 Francois Mauger
4  * Copyright (c) 2011 Paul A. Bristow
5  *
6  * Distributed under the Boost Software License, Version 1.0.
7  * (See accompanying file LICENSE_1_0.txt
8  * or copy at http://www.boost.org/LICENSE_1_0.txt)
9  *
10  * This simple program illustrates how to use the
11  * `boost/math/nonfinite_num_facets.hpp' material from the original
12  * Floating Point  Utilities contribution by Johan Rade.
13  * Floating Point Utility library has been accepted into Boost,
14  * but the utilities have been/will be incorporated into Boost.Math library.
15  *
16 \file
17 
18 \brief A fairly simple example of using non_finite_num facet for
19 C99 standard output of infinity and NaN.
20 
21 \detail  This program illustrates how to use the
22  `boost/math/nonfinite_num_facets.hpp' material from the original
23   Floating Point  Utilities contribution by Johan Rade.
24   Floating Point Utility library has been accepted into Boost,
25   but the utilities have been/will be incorporated into Boost.Math library.
26 
27   Based on an example from Francois Mauger.
28 
29   Double and float variables are assigned ordinary finite values (pi),
30   and nonfinite like infinity and NaN.
31 
32   These values are then output and read back in, and then redisplayed.
33 
34 */
35 
36 #ifdef _MSC_VER
37 #   pragma warning(disable : 4127) // conditional expression is constant.
38 #endif
39 
40 #include <iostream>
41 #include <iomanip>
42 using std::cout;
43 using std::endl;
44 
45 #include <limits> // numeric_limits
46 using std::numeric_limits;
47 
48 #include <boost/cstdint.hpp>
49 
50 #include <boost/math/special_functions/nonfinite_num_facets.hpp>
51 
52 static const char sep = ','; // Separator of bracketed float and double values.
53 
54 // Use max_digits10 (or equivalent) to obtain
55 // all potentially significant decimal digits for the floating-point types.
56 
57 #ifdef BOOST_NO_CXX11_NUMERIC_LIMITS
58   std::streamsize  max_digits10_float = 2 + std::numeric_limits<float>::digits * 30103UL / 100000UL;
59   std::streamsize  max_digits10_double = 2 + std::numeric_limits<double>::digits * 30103UL / 100000UL;
60 #else
61   // Can use new C++0X max_digits10 (the maximum potentially significant digits).
62   std::streamsize  max_digits10_float = std::numeric_limits<float>::max_digits10;
63   std::streamsize  max_digits10_double = std::numeric_limits<double>::max_digits10;
64 #endif
65 
66 
67 /* A class with a float and a double */
68 struct foo
69 {
foofoo70   foo () : fvalue (3.1415927F), dvalue (3.1415926535897931)
71   {
72   }
73   // Set both the values to -infinity :
minus_infinityfoo74   void minus_infinity ()
75   {
76     fvalue = -std::numeric_limits<float>::infinity ();
77     dvalue = -std::numeric_limits<double>::infinity ();
78     return;
79   }
80   // Set the values to +infinity :
plus_infinityfoo81   void plus_infinity ()
82   {
83     fvalue = +std::numeric_limits<float>::infinity ();
84     dvalue = +std::numeric_limits<double>::infinity ();
85     return;
86   }
87   // Set the values to NaN :
nanfoo88   void nan ()
89   {
90     fvalue = +std::numeric_limits<float>::quiet_NaN ();
91     dvalue = +std::numeric_limits<double>::quiet_NaN ();
92     return;
93   }
94   // Print a foo:
printfoo95   void print (std::ostream & a_out, const std::string & a_title)
96   {
97     if (a_title.empty ()) a_out << "foo";
98     else a_out << a_title;
99     a_out << " : " << std::endl;
100     a_out << "|-- " << "fvalue = ";
101 
102     a_out.precision (max_digits10_float);
103     a_out << fvalue << std::endl;
104     a_out << "`-- " << "dvalue = ";
105     a_out.precision (max_digits10_double);
106     a_out << dvalue << std::endl;
107     return;
108   }
109 
110   // I/O operators for a foo structure of a float and a double :
111   friend std::ostream & operator<< (std::ostream & a_out, const foo & a_foo);
112   friend std::istream & operator>> (std::istream & a_in, foo & a_foo);
113 
114   // Attributes :
115   float  fvalue; // Single precision floating number.
116   double dvalue; // Double precision floating number.
117 };
118 
operator <<(std::ostream & a_out,const foo & a_foo)119 std::ostream & operator<< (std::ostream & a_out, const foo & a_foo)
120 { // Output bracketed FPs, for example "(3.1415927,3.1415926535897931)"
121   a_out.precision (max_digits10_float);
122   a_out << "(" << a_foo.fvalue << sep ;
123   a_out.precision (max_digits10_double);
124   a_out << a_foo.dvalue << ")";
125   return a_out;
126 }
127 
operator >>(std::istream & a_in,foo & a_foo)128 std::istream & operator>> (std::istream & a_in, foo & a_foo)
129 { // Input bracketed floating-point values into a foo structure,
130   // for example from "(3.1415927,3.1415926535897931)"
131   char c = 0;
132   a_in.get (c);
133   if (c != '(')
134   {
135     std::cerr << "ERROR: operator>> No ( " << std::endl;
136     a_in.setstate(std::ios::failbit);
137     return a_in;
138   }
139   float f;
140   a_in >> std::ws >> f;
141   if (! a_in)
142   {
143     return a_in;
144   }
145   a_in >> std::ws;
146   a_in.get (c);
147   if (c != sep)
148   {
149     std::cerr << "ERROR: operator>> c='" << c << "'" << std::endl;
150     std::cerr << "ERROR: operator>> No '" << sep << "'" << std::endl;
151     a_in.setstate(std::ios::failbit);
152     return a_in;
153   }
154   double d;
155   a_in >> std::ws >> d;
156   if (! a_in)
157   {
158     return a_in;
159   }
160   a_in >> std::ws;
161   a_in.get (c);
162   if (c != ')')
163   {
164     std::cerr << "ERROR: operator>> No ) " << std::endl;
165     a_in.setstate(std::ios::failbit);
166     return a_in;
167   }
168   a_foo.fvalue = f;
169   a_foo.dvalue = d;
170   return a_in;
171 } // std::istream & operator>> (std::istream & a_in, foo & a_foo)
172 
main()173 int main ()
174 {
175   std::cout << "nonfinite_num_facet simple example." << std::endl;
176 
177    if((std::numeric_limits<double>::has_infinity == false) || (std::numeric_limits<double>::infinity() == 0))
178   {
179     std::cout << "Infinity not supported on this platform." << std::endl;
180     return 0;
181   }
182 
183   if((std::numeric_limits<double>::has_quiet_NaN == false) || (std::numeric_limits<double>::quiet_NaN() == 0))
184   {
185     std::cout << "NaN not supported on this platform." << std::endl;
186     return 0;
187   }
188 
189 #ifdef BOOST_NO_CXX11_NUMERIC_LIMITS
190   cout << "BOOST_NO_CXX11_NUMERIC_LIMITS is defined, so no max_digits10 available either:"
191      "\n we'll have to calculate our own version." << endl;
192 #endif
193   std::cout << "std::numeric_limits<float>::max_digits10 is " << max_digits10_float << endl;
194   std::cout << "std::numeric_limits<double>::max_digits10 is " << max_digits10_double << endl;
195 
196    std::locale the_default_locale (std::locale::classic ());
197 
198   {
199     std::cout << "Write to a string buffer (using default locale) :" << std::endl;
200     foo f0; // pi
201     foo f1; f1.minus_infinity ();
202     foo f2; f2.plus_infinity ();
203     foo f3; f3.nan ();
204 
205     f0.print (std::cout, "f0"); // pi
206     f1.print (std::cout, "f1"); // +inf
207     f2.print (std::cout, "f2"); // -inf
208     f3.print (std::cout, "f3"); // NaN
209 
210     std::ostringstream oss;
211     std::locale C99_out_locale (the_default_locale, new boost::math::nonfinite_num_put<char>);
212     oss.imbue (C99_out_locale);
213     oss.precision (15);
214     oss << f0 << f1 << f2 << f3;
215     std::cout << "Output in C99 format is: \"" << oss.str () << "\"" << std::endl;
216     std::cout << "Output done." << std::endl;
217   }
218 
219   {
220     std::string the_string = "(3.1415927,3.1415926535897931)(-inf,-inf)(inf,inf)(nan,nan)"; // C99 format
221     // Must have correct separator!
222     std::cout << "Read C99 format from a string buffer containing \"" << the_string << "\""<< std::endl;
223 
224     std::locale C99_in_locale (the_default_locale, new boost::math::nonfinite_num_get<char>);
225     std::istringstream iss (the_string);
226     iss.imbue (C99_in_locale);
227 
228     foo f0, f1, f2, f3;
229     iss >> f0 >> f1 >> f2 >> f3;
230     if (! iss)
231     {
232        std::cerr << "Input Format error !" << std::endl;
233     }
234     else
235     {
236       std::cerr << "Input OK." << std::endl;
237       cout << "Display in default locale format " << endl;
238       f0.print (std::cout, "f0");
239       f1.print (std::cout, "f1");
240       f2.print (std::cout, "f2");
241       f3.print (std::cout, "f3");
242     }
243     std::cout << "Input done." << std::endl;
244   }
245 
246   std::cout << "End nonfinite_num_facet.cpp" << std::endl;
247   return 0;
248 } // int main()
249 
250  // end of test_nonfinite_num_facets.cpp
251 
252 /*
253 
254 Output:
255 
256 nonfinite_num_facet simple example.
257   std::numeric_limits<float>::max_digits10 is 8
258   std::numeric_limits<double>::max_digits10 is 17
259   Write to a string buffer (using default locale) :
260   f0 :
261   |-- fvalue = 3.1415927
262   `-- dvalue = 3.1415926535897931
263   f1 :
264   |-- fvalue = -1.#INF
265   `-- dvalue = -1.#INF
266   f2 :
267   |-- fvalue = 1.#INF
268   `-- dvalue = 1.#INF
269   f3 :
270   |-- fvalue = 1.#QNAN
271   `-- dvalue = 1.#QNAN
272   Output in C99 format is: "(3.1415927,3.1415926535897931)(-inf,-inf)(inf,inf)(nan,nan)"
273   Output done.
274   Read C99 format from a string buffer containing "(3.1415927,3.1415926535897931)(-inf,-inf)(inf,inf)(nan,nan)"
275   Display in default locale format
276   f0 :
277   |-- fvalue = 3.1415927
278   `-- dvalue = 3.1415926535897931
279   f1 :
280   |-- fvalue = -1.#INF
281   `-- dvalue = -1.#INF
282   f2 :
283   |-- fvalue = 1.#INF
284   `-- dvalue = 1.#INF
285   f3 :
286   |-- fvalue = 1.#QNAN
287   `-- dvalue = 1.#QNAN
288   Input done.
289   End nonfinite_num_facet.cpp
290 
291 */
292