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()47int 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