• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
main()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 
190