• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** nonfinite_num_facet_serialization.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 sample program by Francois Mauger illustrates how to use the
11  * `boost/math/nonfinite_num_facets.hpp'  material  from the  original
12  * Floating Point  Utilities contribution by  Johan Rade.  Here  it is
13  * shown  how  non  finite  floating  number  can  be  serialized  and
14  * deserialized from  I/O streams and/or Boost  text/XML archives.  It
15  * produces two archives stored in `test.txt' and `test.xml' files.
16  *
17  * Tested with Boost 1.44, gcc 4.4.1, Linux/i686 (32bits).
18  * Tested with Boost.1.46.1  MSVC 10.0 32 bit.
19  */
20 
21 #ifdef _MSC_VER
22 #   pragma warning(push)
23 //#   pragma warning(disable : 4100) // unreferenced formal parameter.
24 #endif
25 
26 #include <iostream>
27 #include <sstream>
28 #include <fstream>
29 #include <limits>
30 
31 #include <boost/cstdint.hpp>
32 #include <boost/serialization/nvp.hpp>
33 #include <boost/archive/text_oarchive.hpp>
34 #include <boost/archive/text_iarchive.hpp>
35 #include <boost/archive/xml_oarchive.hpp>
36 #include <boost/archive/xml_iarchive.hpp>
37 #include <boost/archive/codecvt_null.hpp>
38 
39 // from the Floating Point Utilities :
40 #include <boost/math/special_functions/nonfinite_num_facets.hpp>
41 
42 static const char sep = ','; // Separator of bracketed float and double values.
43 
44 // Use max_digits10 (or equivalent) to obtain
45 // all potentially significant decimal digits for the floating-point types.
46 
47 #ifdef BOOST_NO_CXX11_NUMERIC_LIMITS
48   std::streamsize  max_digits10_float = 2 + std::numeric_limits<float>::digits * 30103UL / 100000UL;
49   std::streamsize  max_digits10_double = 2 + std::numeric_limits<double>::digits * 30103UL / 100000UL;
50 #else
51   // Can use new C++0X max_digits10 (the maximum potentially significant digits).
52   std::streamsize  max_digits10_float = std::numeric_limits<float>::max_digits10;
53   std::streamsize  max_digits10_double = std::numeric_limits<double>::max_digits10;
54 #endif
55 
56 
57 /* A class with a float and a double */
58 struct foo
59 {
foofoo60   foo () : fvalue (3.1415927F), dvalue (3.1415926535897931)
61   { // Construct using 32 and 64-bit max_digits10 decimal digits value of pi.
62   }
63   // Set the values at -infinity :
minus_infinityfoo64   void minus_infinity ()
65   {
66     fvalue = -std::numeric_limits<float>::infinity ();
67     dvalue = -std::numeric_limits<double>::infinity ();
68     return;
69   }
70   // Set the values at +infinity :
plus_infinityfoo71   void plus_infinity ()
72   {
73     fvalue = +std::numeric_limits<float>::infinity ();
74     dvalue = +std::numeric_limits<double>::infinity ();
75     return;
76   }
77   // Set the values at NaN :
nanfoo78   void nan ()
79   {
80     fvalue = +std::numeric_limits<float>::quiet_NaN ();
81     dvalue = +std::numeric_limits<double>::quiet_NaN ();
82     return;
83   }
84   // Print :
printfoo85   void print (std::ostream & a_out, const std::string & a_title)
86   {
87     if (a_title.empty ()) a_out << "foo";
88     else a_out << a_title;
89     a_out << " : " << std::endl;
90     a_out << "|-- " << "fvalue = ";
91     a_out.precision (7);
92     a_out << fvalue << std::endl;
93     a_out << "`-- " << "dvalue = ";
94     a_out.precision (15);
95     a_out << dvalue << std::endl;
96     return;
97   }
98 
99   // I/O operators :
100   friend std::ostream & operator<< (std::ostream & a_out, const foo & a_foo);
101   friend std::istream & operator>> (std::istream & a_in, foo & a_foo);
102 
103   // Boost serialization :
104   template <class Archive>
serializefoo105   void serialize (Archive & ar, int /*version*/)
106   {
107     ar & BOOST_SERIALIZATION_NVP (fvalue);
108     ar & BOOST_SERIALIZATION_NVP (dvalue);
109     return;
110   }
111 
112   // Attributes :
113   float  fvalue; // Single precision floating-point number.
114   double dvalue; // Double precision floating-point number.
115 };
116 
operator <<(std::ostream & a_out,const foo & a_foo)117 std::ostream & operator<< (std::ostream & a_out, const foo & a_foo)
118 { // Output bracketed FPs, for example "(3.1415927,3.1415926535897931)"
119   a_out.precision (max_digits10_float);
120   a_out << "(" << a_foo.fvalue << sep ;
121   a_out.precision (max_digits10_double);
122   a_out << a_foo.dvalue << ")";
123   return a_out;
124 }
125 
operator >>(std::istream & a_in,foo & a_foo)126 std::istream & operator>> (std::istream & a_in, foo & a_foo)
127 { // Input bracketed floating-point values into a foo structure,
128   // for example from "(3.1415927,3.1415926535897931)"
129   char c = 0;
130   a_in.get (c);
131   if (c != '(')
132   {
133     std::cerr << "ERROR: operator>> No ( " << std::endl;
134     a_in.setstate(std::ios::failbit);
135     return a_in;
136   }
137   float f;
138   a_in >> std::ws >> f;
139   if (! a_in)
140   {
141     return a_in;
142   }
143   a_in >> std::ws;
144   a_in.get (c);
145   if (c != sep)
146   {
147     std::cerr << "ERROR: operator>> c='" << c << "'" << std::endl;
148     std::cerr << "ERROR: operator>> No '" << sep << "'" << std::endl;
149     a_in.setstate(std::ios::failbit);
150     return a_in;
151   }
152   double d;
153   a_in >> std::ws >> d;
154   if (! a_in)
155   {
156     return a_in;
157   }
158   a_in >> std::ws;
159   a_in.get (c);
160   if (c != ')')
161   {
162     std::cerr << "ERROR: operator>> No ) " << std::endl;
163     a_in.setstate(std::ios::failbit);
164     return a_in;
165   }
166   a_foo.fvalue = f;
167   a_foo.dvalue = d;
168   return a_in;
169 }
170 
main(void)171 int main (void)
172 {
173   std::clog << std::endl
174       << "Nonfinite_serialization.cpp' example program." << std::endl;
175 
176 #ifdef BOOST_NO_CXX11_NUMERIC_LIMITS
177   std::cout << "BOOST_NO_CXX11_NUMERIC_LIMITS is defined, so no max_digits10 available either,"
178      "using our own version instead." << std::endl;
179 #endif
180   std::cout << "std::numeric_limits<float>::max_digits10 is " << max_digits10_float << std::endl;
181   std::cout << "std::numeric_limits<double>::max_digits10 is " << max_digits10_double << std::endl;
182 
183   std::locale the_default_locale (std::locale::classic (),
184           new boost::archive::codecvt_null<char>);
185 
186   // Demonstrate use of nonfinite facets with stringstreams.
187   {
188     std::clog << "Construct some foo structures with a finite and nonfinites." << std::endl;
189     foo f0;
190     foo f1; f1.minus_infinity ();
191     foo f2; f2.plus_infinity ();
192     foo f3; f3.nan ();
193     // Display them.
194     f0.print (std::clog, "f0");
195     f1.print (std::clog, "f1");
196     f2.print (std::clog, "f2");
197     f3.print (std::clog, "f3");
198     std::clog << " Write to a string buffer." << std::endl;
199 
200     std::ostringstream oss;
201     std::locale the_out_locale (the_default_locale, new boost::math::nonfinite_num_put<char>);
202     oss.imbue (the_out_locale);
203     oss.precision (max_digits10_double);
204     oss << f0 << f1 << f2 << f3;
205     std::clog << "Output is: `" << oss.str () << "'" << std::endl;
206     std::clog << "Done output to ostringstream." << std::endl;
207   }
208 
209   {
210     std::clog << "Read foo structures from a string buffer." << std::endl;
211 
212     std::string the_string = "(3.1415927,3.1415926535897931)(-inf,-inf)(inf,inf)(nan,nan)";
213     std::clog << "Input is: `" << the_string << "'" << std::endl;
214 
215     std::locale the_in_locale (the_default_locale, new boost::math::nonfinite_num_get<char>);
216     std::istringstream iss (the_string);
217     iss.imbue (the_in_locale);
218 
219     foo f0, f1, f2, f3;
220     iss >> f0 >> f1 >> f2 >> f3;
221     if (! iss)
222     {
223       std::cerr << "Format error !" << std::endl;
224     }
225     else
226     {
227       std::cerr << "Read OK." << std::endl;
228       f0.print (std::clog, "f0");
229       f1.print (std::clog, "f1");
230       f2.print (std::clog, "f2");
231       f3.print (std::clog, "f3");
232     }
233     std::clog << "Done input from istringstream." << std::endl;
234   }
235 
236   {  // Demonstrate use of nonfinite facets for Serialization with Boost text archives.
237     std::clog << "Serialize (using Boost text archive)." << std::endl;
238     // Construct some foo structures with a finite and nonfinites.
239     foo f0;
240     foo f1; f1.minus_infinity ();
241     foo f2; f2.plus_infinity ();
242     foo f3; f3.nan ();
243     // Display them.
244     f0.print (std::clog, "f0");
245     f1.print (std::clog, "f1");
246     f2.print (std::clog, "f2");
247     f3.print (std::clog, "f3");
248 
249     std::locale the_out_locale (the_default_locale, new boost::math::nonfinite_num_put<char>);
250     // Use a temporary folder .temps (which contains "boost-no-inspect" so that it will not be inspected, and made 'hidden' too).
251     std::ofstream fout ("./.temps/nonfinite_archive_test.txt");
252     fout.imbue (the_out_locale);
253     boost::archive::text_oarchive toar (fout, boost::archive::no_codecvt);
254     // Write to archive.
255     toar & f0;
256     toar & f1;
257     toar & f2;
258     toar & f3;
259     std::clog << "Done." << std::endl;
260   }
261 
262   {
263     std::clog << "Deserialize (Boost text archive)..." << std::endl;
264     std::locale the_in_locale (the_default_locale, new boost::math::nonfinite_num_get<char>);
265      // Use a temporary folder .temps (which contains "boost-no-inspect" so that it will not be inspected, and made 'hidden' too).
266     std::ifstream fin ("./.temps/nonfinite_archive_test.txt");
267     fin.imbue (the_in_locale);
268     boost::archive::text_iarchive tiar (fin, boost::archive::no_codecvt);
269     foo f0, f1, f2, f3;
270     // Read from archive.
271     tiar & f0;
272     tiar & f1;
273     tiar & f2;
274     tiar & f3;
275     // Display foos.
276     f0.print (std::clog, "f0");
277     f1.print (std::clog, "f1");
278     f2.print (std::clog, "f2");
279     f3.print (std::clog, "f3");
280 
281     std::clog << "Done." << std::endl;
282   }
283 
284   {   // Demonstrate use of nonfinite facets for Serialization with Boost XML Archive.
285     std::clog << "Serialize (Boost XML archive)..." << std::endl;
286     // Construct some foo structures with a finite and nonfinites.
287     foo f0;
288     foo f1; f1.minus_infinity ();
289     foo f2; f2.plus_infinity ();
290     foo f3; f3.nan ();
291      // Display foos.
292     f0.print (std::clog, "f0");
293     f1.print (std::clog, "f1");
294     f2.print (std::clog, "f2");
295     f3.print (std::clog, "f3");
296 
297     std::locale the_out_locale (the_default_locale, new boost::math::nonfinite_num_put<char>);
298       // Use a temporary folder /.temps (which contains "boost-no-inspect" so that it will not be inspected, and made 'hidden' too).
299     std::ofstream fout ("./.temps/nonfinite_XML_archive_test.txt");
300     fout.imbue (the_out_locale);
301     boost::archive::xml_oarchive xoar (fout, boost::archive::no_codecvt);
302 
303     xoar & BOOST_SERIALIZATION_NVP (f0);
304     xoar & BOOST_SERIALIZATION_NVP (f1);
305     xoar & BOOST_SERIALIZATION_NVP (f2);
306     xoar & BOOST_SERIALIZATION_NVP (f3);
307     std::clog << "Done." << std::endl;
308   }
309 
310   {
311     std::clog << "Deserialize (Boost XML archive)..." << std::endl;
312     std::locale the_in_locale (the_default_locale, new boost::math::nonfinite_num_get<char>);
313     // Use a temporary folder /.temps (which contains "boost-no-inspect" so that it will not be inspected, and made 'hidden' too).
314     std::ifstream fin ("./.temps/nonfinite_XML_archive_test.txt");  // Previously written above.
315     fin.imbue (the_in_locale);
316     boost::archive::xml_iarchive xiar (fin, boost::archive::no_codecvt);
317     foo f0, f1, f2, f3;
318 
319     xiar & BOOST_SERIALIZATION_NVP (f0);
320     xiar & BOOST_SERIALIZATION_NVP (f1);
321     xiar & BOOST_SERIALIZATION_NVP (f2);
322     xiar & BOOST_SERIALIZATION_NVP (f3);
323 
324     f0.print (std::clog, "f0");
325     f1.print (std::clog, "f1");
326     f2.print (std::clog, "f2");
327     f3.print (std::clog, "f3");
328 
329     std::clog << "Done." << std::endl;
330   }
331 
332   std::clog << "End nonfinite_serialization.cpp' example program." << std::endl;
333   return 0;
334 }
335 
336 /*
337 
338 Output:
339 
340   Nonfinite_serialization.cpp' example program.
341   std::numeric_limits<float>::max_digits10 is 8
342   std::numeric_limits<double>::max_digits10 is 17
343   Construct some foo structures with a finite and nonfinites.
344   f0 :
345   |-- fvalue = 3.141593
346   `-- dvalue = 3.14159265358979
347   f1 :
348   |-- fvalue = -1.#INF
349   `-- dvalue = -1.#INF
350   f2 :
351   |-- fvalue = 1.#INF
352   `-- dvalue = 1.#INF
353   f3 :
354   |-- fvalue = 1.#QNAN
355   `-- dvalue = 1.#QNAN
356    Write to a string buffer.
357   Output is: `(3.1415927,3.1415926535897931)(-inf,-inf)(inf,inf)(nan,nan)'
358   Done output to ostringstream.
359   Read foo structures from a string buffer.
360   Input is: `(3.1415927,3.1415926535897931)(-inf,-inf)(inf,inf)(nan,nan)'
361   Read OK.
362   f0 :
363   |-- fvalue = 3.141593
364   `-- dvalue = 3.14159265358979
365   f1 :
366   |-- fvalue = -1.#INF
367   `-- dvalue = -1.#INF
368   f2 :
369   |-- fvalue = 1.#INF
370   `-- dvalue = 1.#INF
371   f3 :
372   |-- fvalue = 1.#QNAN
373   `-- dvalue = 1.#QNAN
374   Done input from istringstream.
375   Serialize (using Boost text archive).
376   f0 :
377   |-- fvalue = 3.141593
378   `-- dvalue = 3.14159265358979
379   f1 :
380   |-- fvalue = -1.#INF
381   `-- dvalue = -1.#INF
382   f2 :
383   |-- fvalue = 1.#INF
384   `-- dvalue = 1.#INF
385   f3 :
386   |-- fvalue = 1.#QNAN
387   `-- dvalue = 1.#QNAN
388   Done.
389   Deserialize (Boost text archive)...
390   f0 :
391   |-- fvalue = 3.141593
392   `-- dvalue = 3.14159265358979
393   f1 :
394   |-- fvalue = -1.#INF
395   `-- dvalue = -1.#INF
396   f2 :
397   |-- fvalue = 1.#INF
398   `-- dvalue = 1.#INF
399   f3 :
400   |-- fvalue = 1.#QNAN
401   `-- dvalue = 1.#QNAN
402   Done.
403   Serialize (Boost XML archive)...
404   f0 :
405   |-- fvalue = 3.141593
406   `-- dvalue = 3.14159265358979
407   f1 :
408   |-- fvalue = -1.#INF
409   `-- dvalue = -1.#INF
410   f2 :
411   |-- fvalue = 1.#INF
412   `-- dvalue = 1.#INF
413   f3 :
414   |-- fvalue = 1.#QNAN
415   `-- dvalue = 1.#QNAN
416   Done.
417   Deserialize (Boost XML archive)...
418   f0 :
419   |-- fvalue = 3.141593
420   `-- dvalue = 3.14159265358979
421   f1 :
422   |-- fvalue = -1.#INF
423   `-- dvalue = -1.#INF
424   f2 :
425   |-- fvalue = 1.#INF
426   `-- dvalue = 1.#INF
427   f3 :
428   |-- fvalue = 1.#QNAN
429   `-- dvalue = 1.#QNAN
430   Done.
431   End nonfinite_serialization.cpp' example program.
432 
433   */
434