]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | { | |
70 | foo () : fvalue (3.1415927F), dvalue (3.1415926535897931) | |
71 | { | |
72 | } | |
73 | // Set both the values to -infinity : | |
74 | 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 : | |
81 | 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 : | |
88 | 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: | |
95 | 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 | ||
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 | ||
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 | ||
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 | */ |