]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Distributed under the Boost Software License, Version 1.0. |
2 | // (See accompanying file LICENSE_1_0.txt | |
3 | // or copy at http://www.boost.org/LICENSE_1_0.txt) | |
4 | ||
5 | // Copyright (c) 2006 Johan Rade | |
6 | // Copyright (c) 2011 Paul A. Bristow | |
7 | ||
8 | /*! | |
9 | \file | |
10 | \brief Tests of nonfinite signaling NaN loopback. | |
11 | ||
12 | \detail nonfinite signaling NaN | |
13 | test outputs using nonfinite facets | |
14 | (output and input) and reads back in, and checks if loopback OK. | |
15 | ||
16 | Not expected to work on all platforms (if any). But shows that on MSVC, | |
17 | this legacy locale can ensure a consistent quiet NaN input from representations | |
18 | "1.#QNAN", "1.#SNAN" and "1.#IND" | |
19 | ||
20 | */ | |
21 | ||
22 | #ifdef _MSC_VER | |
23 | # pragma warning(disable : 4702) | |
24 | #endif | |
25 | ||
26 | #include <boost/math/special_functions/nonfinite_num_facets.hpp> | |
27 | using boost::math::nonfinite_num_get; | |
28 | using boost::math::nonfinite_num_put; | |
29 | ||
30 | #include <iostream> | |
31 | using std::cout; | |
32 | using std::endl; | |
33 | ||
34 | #include <locale> | |
35 | using std::locale; | |
36 | ||
37 | #include <string> | |
38 | using std::string; | |
39 | ||
40 | #include <sstream> | |
41 | using std::stringstream; | |
42 | using std::istringstream; | |
43 | ||
44 | #include <limits> | |
45 | using std::numeric_limits; | |
46 | ||
47 | int main() | |
48 | { | |
49 | if((std::numeric_limits<double>::has_infinity == false) || (std::numeric_limits<double>::infinity() == 0)) | |
50 | { | |
51 | std::cout << "Infinity not supported on this platform." << std::endl; | |
52 | return 0; | |
53 | } | |
54 | ||
55 | if((std::numeric_limits<double>::has_quiet_NaN == false) || (std::numeric_limits<double>::quiet_NaN() == 0)) | |
56 | { | |
57 | std::cout << "NaN not supported on this platform." << std::endl; | |
58 | return 0; | |
59 | } | |
60 | ||
61 | locale default_locale; // Current global locale. | |
62 | // Try to use the default locale first. | |
63 | // On MSVC this doesn't work. | |
64 | ||
65 | { // Try Quiet NaN | |
66 | stringstream ss; // Both input and output. | |
67 | ss.imbue(default_locale); // Redundant, of course. | |
68 | string infs; | |
69 | if(numeric_limits<double>::has_quiet_NaN) | |
70 | { // Make sure quiet NaN is specialised for type double. | |
71 | double qnan = numeric_limits<double>::quiet_NaN(); | |
72 | ss << qnan; // Output quiet_NaN. | |
73 | infs = ss.str(); // | |
74 | } | |
75 | else | |
76 | { // Need to provide a suitable string for quiet NaN. | |
77 | infs = "1.#QNAN"; | |
78 | ss << infs; | |
79 | } | |
80 | double r; | |
81 | ss >> r; // Read back in. | |
82 | ||
83 | cout << "quiet_NaN output was " << infs << endl; // "1.#QNAN" | |
84 | cout << "quiet_NaN input was " << r << endl; // "1" | |
85 | } | |
86 | ||
87 | #if (!defined __BORLANDC__ && !defined __CODEGEARC__) | |
88 | // These compilers trap when trying to create a signaling_NaN! | |
89 | { // Try Signaling NaN | |
90 | stringstream ss; // Both input and output. | |
91 | ss.imbue(default_locale); // Redundant, of course. | |
92 | string infs; | |
93 | if(numeric_limits<double>::has_signaling_NaN) | |
94 | { // Make sure signaling NaN is specialised for type double. | |
95 | double qnan = numeric_limits<double>::signaling_NaN(); | |
96 | ss << qnan; // Output signaling_NaN. | |
97 | infs = ss.str(); // | |
98 | } | |
99 | else | |
100 | { // Need to provide a suitable string for signaling NaN. | |
101 | infs = "1.#SNAN"; | |
102 | ss << infs; | |
103 | } | |
104 | double r; | |
105 | ss >> r; // Read back in. | |
106 | ||
107 | cout << "signaling_NaN output was " << infs << endl; // "1.#QNAN" (or "1.#SNAN"?) | |
108 | cout << "signaling_NaN input was " << r << endl; // "1" | |
109 | } | |
110 | #endif // Not Borland or CodeGear. | |
111 | ||
112 | // Create legacy_locale and store the nonfinite_num_get facet (with legacy flag) in it. | |
113 | locale legacy_locale(default_locale, new nonfinite_num_get<char>(boost::math::legacy)); | |
114 | // Note that the legacy flag has no effect on the nonfinite_num_put output facet. | |
115 | ||
116 | cout << "Use legacy locale." << endl; | |
117 | ||
118 | { // Try infinity. | |
119 | stringstream ss; // Both input and output. | |
120 | ss.imbue(legacy_locale); | |
121 | string infs; | |
122 | if(numeric_limits<double>::has_infinity) | |
123 | { // Make sure infinity is specialised for type double. | |
124 | double inf = numeric_limits<double>::infinity(); | |
125 | ss << inf; // Output infinity. | |
126 | infs = ss.str(); // | |
127 | } | |
128 | else | |
129 | { // Need to provide a suitable string for infinity. | |
130 | infs = "1.#INF"; | |
131 | ss << infs; | |
132 | } | |
133 | double r; | |
134 | ss >> r; // Read back in. | |
135 | ||
136 | cout << "infinity output was " << infs << endl; // "1.#INF" | |
137 | cout << "infinity input was " << r << endl; // "1.#INF" | |
138 | } | |
139 | ||
140 | { // Try input of "1.#SNAN". | |
141 | //double inf = numeric_limits<double>::signaling_NaN(); // Assigns "1.#QNAN" on MSVC. | |
142 | // So must use explicit string "1.#SNAN" instead. | |
143 | stringstream ss; // Both input and output. | |
144 | ss.imbue(legacy_locale); | |
145 | string s = "1.#SNAN"; | |
146 | ||
147 | ss << s; // Write out. | |
148 | double r; | |
149 | ||
150 | ss >> r; // Read back in. | |
151 | ||
152 | cout << "SNAN output was " << s << endl; // "1.#SNAN" | |
153 | cout << "SNAN input was " << r << endl; // "1.#QNAN" | |
154 | } | |
155 | ||
156 | { // Try input of "1.#IND" . | |
157 | stringstream ss; // Both input and output. | |
158 | ss.imbue(legacy_locale); | |
159 | string s = "1.#IND"; | |
160 | ss << s; // Write out. | |
161 | double r; | |
162 | ss >> r; // Read back in. | |
163 | ||
164 | cout << "IND output was " << s << endl; // "1.#IND" | |
165 | cout << "IND input was " << r << endl; // "1.#QNAN" | |
166 | } | |
167 | ||
168 | } // int main() | |
169 | ||
170 | /* | |
171 | ||
172 | Output: | |
173 | nonfinite_signaling_NaN.vcxproj -> J:\Cpp\fp_facet\fp_facet\Debug\nonfinite_signaling_NaN.exe | |
174 | ||
175 | quiet_NaN output was 1.#QNAN | |
176 | quiet_NaN input was 1 | |
177 | signaling_NaN output was 1.#QNAN | |
178 | signaling_NaN input was 1 | |
179 | Use legacy locale. | |
180 | infinity output was 1.#INF | |
181 | infinity input was 1.#INF | |
182 | SNAN output was 1.#SNAN | |
183 | SNAN input was 1.#QNAN | |
184 | IND output was 1.#IND | |
185 | IND input was 1.#QNAN | |
186 | ||
187 | ||
188 | */ | |
189 |