1 2 // Copyright 2011 Paul A. Bristow 3 4 // Distributed under the Boost Software License, Version 1.0. 5 // (See accompanying file LICENSE_1_0.txt 6 // or copy at http://www.boost.org/LICENSE_1_0.txt) 7 8 // test_nonfinite_trap.cpp 9 10 #ifdef _MSC_VER 11 # pragma warning(disable : 4127) // Expression is constant. 12 #endif 13 14 #define BOOST_TEST_MAIN 15 16 #include <boost/test/unit_test.hpp> 17 #include <libs/math/test/almost_equal.ipp> // Similar to BOOST_CLOSE_FRACTION. 18 #include <libs/math/test/s_.ipp> // To create test strings like std::basic_string<CharType> s = S_("0 -0"); 19 #include <boost/math/special_functions/nonfinite_num_facets.hpp> 20 21 #include <locale> 22 #include <sstream> 23 #include <iomanip> 24 25 namespace { 26 27 // Using an anonymous namespace resolves ambiguities on platforms 28 // with fpclassify etc functions at global scope. 29 30 using namespace boost::math; 31 using boost::math::signbit; 32 using boost::math::changesign; 33 using (boost::math::isnan)(; 34 35 //------------------------------------------------------------------------------ 36 // Test nonfinite_num_put and nonfinite_num_get facets by checking 37 // loopback (output and re-input) of a few values, 38 // but using all the built-in char and floating-point types. 39 // Only the default output is used but various ostream options are tested separately below. 40 // Finite, infinite and NaN values (positive and negative) are used for the test. 41 42 void trap_test_finite(); 43 void trap_test_inf(); 44 void trap_test_nan(); 45 46 BOOST_AUTO_TEST_CASE(trap_test) 47 { 48 trap_test_finite(); 49 trap_test_inf(); 50 trap_test_nan(); 51 } 52 53 //------------------------------------------------------------------------------ 54 55 template<class CharType, class ValType> void trap_test_finite_impl(); 56 57 void trap_test_finite() 58 { // Test finite using all the built-in char and floating-point types. 59 trap_test_finite_impl<char, float>(); 60 trap_test_finite_impl<char, double>(); 61 trap_test_finite_impl<char, long double>(); 62 trap_test_finite_impl<wchar_t, float>(); 63 trap_test_finite_impl<wchar_t, double>(); 64 trap_test_finite_impl<wchar_t, long double>(); 65 } 66 67 template<class CharType, class ValType> void trap_test_finite_impl() 68 { 69 std::locale old_locale; 70 std::locale tmp_locale(old_locale, 71 new nonfinite_num_put<CharType>(trap_infinity | trap_nan)); 72 std::locale new_locale(tmp_locale, 73 new nonfinite_num_get<CharType>(trap_infinity | trap_nan)); 74 75 std::basic_stringstream<CharType> ss; 76 ss.imbue(new_locale); 77 78 ValType a1 = (ValType)1.2; 79 ValType a2 = (ValType)-3.5; 80 ValType a3 = (std::numeric_limits<ValType>::max)(); 81 ValType a4 = -(std::numeric_limits<ValType>::max)(); 82 ss << a1 << ' ' << a2 << ' ' << a3 << ' ' << a4; // 1.2, -3.5, max, -max 83 84 ValType b1, b2, b3, b4; 85 ss >> b1 >> b2 >> b3 >> b4; 86 87 BOOST_CHECK(almost_equal(b1, a1)); 88 BOOST_CHECK(almost_equal(b2, a2)); 89 BOOST_CHECK(almost_equal(b3, a3)); 90 BOOST_CHECK(almost_equal(b4, a4)); 91 BOOST_CHECK(b3 != std::numeric_limits<ValType>::infinity()); 92 BOOST_CHECK(b4 != -std::numeric_limits<ValType>::infinity()); 93 BOOST_CHECK(ss.rdstate() == std::ios_base::eofbit); 94 95 ss.clear(); 96 ss.str(S_("")); 97 98 ss << "++5"; 99 ValType b5; 100 ss >> b5; 101 BOOST_CHECK(ss.rdstate() == std::ios_base::failbit); 102 } 103 104 //------------------------------------------------------------------------------ 105 106 template<class CharType, class ValType> void trap_test_inf_impl(); 107 template<class CharType, class ValType> void trap_test_put_inf_impl(); 108 template<class CharType, class ValType> void trap_test_get_inf_impl(); 109 110 void trap_test_inf() 111 { // Test infinity using all the built-in char and floating-point types. 112 trap_test_inf_impl<char, float>(); 113 trap_test_inf_impl<char, double>(); 114 trap_test_inf_impl<char, long double>(); 115 trap_test_inf_impl<wchar_t, float>(); 116 trap_test_inf_impl<wchar_t, double>(); 117 trap_test_inf_impl<wchar_t, long double>(); 118 } 119 120 template<class CharType, class ValType> void trap_test_inf_impl() 121 { 122 trap_test_put_inf_impl<CharType, ValType>(); 123 trap_test_get_inf_impl<CharType, ValType>(); 124 } 125 126 template<class CharType, class ValType> void trap_test_put_inf_impl() 127 { 128 std::locale old_locale; 129 std::locale new_locale(old_locale, 130 new nonfinite_num_put<CharType>(trap_infinity)); 131 132 std::basic_stringstream<CharType> ss; 133 ss.imbue(new_locale); 134 135 ValType a1 = std::numeric_limits<ValType>::infinity(); 136 ss << a1; 137 BOOST_CHECK(ss.rdstate() == std::ios_base::failbit 138 || ss.rdstate() == std::ios_base::badbit); 139 ss.clear(); 140 141 ValType a2 = -std::numeric_limits<ValType>::infinity(); 142 ss << a2; 143 BOOST_CHECK(ss.rdstate() == std::ios_base::failbit 144 || ss.rdstate() == std::ios_base::badbit); 145 } 146 147 template<class CharType, class ValType> void trap_test_get_inf_impl() 148 { 149 std::locale old_locale; 150 std::locale tmp_locale(old_locale, new nonfinite_num_put<CharType>); 151 std::locale new_locale(tmp_locale, 152 new nonfinite_num_get<CharType>(trap_infinity)); 153 154 std::basic_stringstream<CharType> ss; 155 ss.imbue(new_locale); 156 157 ValType a1 = std::numeric_limits<ValType>::infinity(); 158 ss << a1; 159 ValType b1; 160 ss >> b1; 161 BOOST_CHECK(ss.rdstate() == std::ios_base::failbit); 162 163 ss.clear(); 164 ss.str(S_("")); 165 166 ValType a2 = -std::numeric_limits<ValType>::infinity(); 167 ss << a2; 168 ValType b2; 169 ss >> b2; 170 BOOST_CHECK(ss.rdstate() == std::ios_base::failbit); 171 } 172 173 //------------------------------------------------------------------------------ 174 175 template<class CharType, class ValType> void trap_test_nan_impl(); 176 template<class CharType, class ValType> void trap_test_put_nan_impl(); 177 template<class CharType, class ValType> void trap_test_get_nan_impl(); 178 179 void trap_test_nan() 180 { // Test NaN using all the built-in char and floating-point types. 181 trap_test_nan_impl<char, float>(); 182 trap_test_nan_impl<char, double>(); 183 trap_test_nan_impl<char, long double>(); 184 trap_test_nan_impl<wchar_t, float>(); 185 trap_test_nan_impl<wchar_t, double>(); 186 trap_test_nan_impl<wchar_t, long double>(); 187 } 188 189 template<class CharType, class ValType> void trap_test_nan_impl() 190 { 191 trap_test_put_nan_impl<CharType, ValType>(); 192 trap_test_get_nan_impl<CharType, ValType>(); 193 } 194 195 template<class CharType, class ValType> void trap_test_put_nan_impl() 196 { 197 std::locale old_locale; 198 std::locale new_locale(old_locale, 199 new nonfinite_num_put<CharType>(trap_nan)); 200 201 std::basic_stringstream<CharType> ss; 202 ss.imbue(new_locale); 203 204 ValType a1 = std::numeric_limits<ValType>::quiet_NaN(); 205 ss << a1; 206 BOOST_CHECK(ss.rdstate() == std::ios_base::failbit 207 || ss.rdstate() == std::ios_base::badbit); 208 ss.clear(); 209 210 ValType a2 = std::numeric_limits<ValType>::signaling_NaN(); 211 ss << a2; 212 BOOST_CHECK(ss.rdstate() == std::ios_base::failbit 213 || ss.rdstate() == std::ios_base::badbit); 214 } 215 216 template<class CharType, class ValType> void trap_test_get_nan_impl() 217 { 218 std::locale old_locale; 219 std::locale tmp_locale(old_locale, new nonfinite_num_put<CharType>); 220 std::locale new_locale(tmp_locale, 221 new nonfinite_num_get<CharType>(trap_nan)); 222 223 std::basic_stringstream<CharType> ss; 224 ss.imbue(new_locale); 225 226 ValType a1 = std::numeric_limits<ValType>::quiet_NaN(); 227 ss << a1; 228 ValType b1; 229 ss >> b1; 230 BOOST_CHECK(ss.rdstate() == std::ios_base::failbit); 231 232 ss.clear(); 233 ss.str(S_("")); 234 235 ValType a2 = std::numeric_limits<ValType>::signaling_NaN(); 236 ss << a2; 237 ValType b2; 238 ss >> b2; 239 BOOST_CHECK(ss.rdstate() == std::ios_base::failbit); 240 } 241 242 //------------------------------------------------------------------------------ 243 244 // Test a selection of stream output options comparing result with expected string. 245 // Only uses CharType = char and ValType = double. 246 // Other types have already been tested above. 247 248 #define CHECKOUT(manips, expected)\ 249 {\ 250 std::locale old_locale;\ 251 std::locale tmp_locale(old_locale, new nonfinite_num_put<char>(0)); /* default flags. */\ 252 std::locale new_locale(tmp_locale, new nonfinite_num_get<char>);\ 253 std::ostringstream ss;\ 254 ss.imbue(new_locale);\ 255 ss << manips;\ 256 std::basic_string<char> s = S_(expected);\ 257 BOOST_CHECK_EQUAL(ss.str(), s);\ 258 }\ 259 260 BOOST_AUTO_TEST_CASE(check_trap_nan) 261 { // Check that with trap_nan set, it really does throw exception. 262 std::locale old_locale; 263 std::locale tmp_locale(old_locale, new nonfinite_num_put<char>(trap_nan)); 264 std::locale new_locale(tmp_locale, new nonfinite_num_get<char>); 265 std::ostringstream os; 266 os.imbue(new_locale); 267 os.exceptions(std::ios_base::badbit | std::ios_base::failbit); // Enable throwing exceptions. 268 double nan = std::numeric_limits<double>::quiet_NaN(); 269 BOOST_MATH_CHECK_THROW((os << nan), std::runtime_error); 270 // warning : in "check_trap_nan": exception std::runtime_error is expected 271 } // BOOST_AUTO_TEST_CASE(check_trap_nan) 272 273 BOOST_AUTO_TEST_CASE(check_trap_inf) 274 { // Check that with trap_nan set, it really does throw exception. 275 std::locale old_locale; 276 std::locale tmp_locale(old_locale, new nonfinite_num_put<char>(trap_infinity)); 277 std::locale new_locale(tmp_locale, new nonfinite_num_get<char>); 278 std::ostringstream os; 279 os.imbue(new_locale); 280 os.exceptions(std::ios_base::badbit | std::ios_base::failbit); // Enable throwing exceptions. 281 double inf = std::numeric_limits<double>::infinity(); 282 BOOST_MATH_CHECK_THROW((os << inf), std::runtime_error); 283 // warning : in "check_trap_inf": exception std::runtime_error is expected. 284 285 } // BOOST_AUTO_TEST_CASE(check_trap_nan_inf) 286 287 BOOST_AUTO_TEST_CASE(output_tests) 288 { 289 // Positive zero. 290 CHECKOUT(0, "0"); // integer zero. 291 CHECKOUT(0., "0"); // double zero. 292 293 double nan = std::numeric_limits<double>::quiet_NaN(); 294 double inf = std::numeric_limits<double>::infinity(); 295 296 CHECKOUT(inf, "inf"); // infinity. 297 CHECKOUT(-inf, "-inf"); // infinity. 298 CHECKOUT(std::showpos << inf, "+inf"); // infinity. 299 300 CHECKOUT(std::setw(6) << std::showpos << inf, " +inf"); // infinity. 301 CHECKOUT(std::right << std::setw(6) << std::showpos << inf, " +inf"); // infinity. 302 CHECKOUT(std::left << std::setw(6) << std::showpos << inf, "+inf "); // infinity. 303 CHECKOUT(std::left << std::setw(6) << std::setprecision(6) << inf, "inf "); // infinity. 304 CHECKOUT(std::left << std::setw(6) << std::setfill('*') << std::setprecision(6) << inf, "inf***"); // infinity. 305 CHECKOUT(std::right << std::setw(6) << std::setfill('*') << std::setprecision(6) << inf, "***inf"); // infinity. 306 CHECKOUT(std::internal<< std::setw(6) << std::showpos << inf, "+ inf"); // infinity. 307 CHECKOUT(std::internal<< std::setw(6) << std::setfill('*') << std::showpos << inf, "+**inf"); // infinity. 308 CHECKOUT(std::internal<< std::setw(6) << std::setfill('*') << std::showpos << -inf, "-**inf"); // infinity. 309 310 CHECKOUT(nan, "nan"); // nan 311 CHECKOUT(std::setw(1) << nan, "nan"); // nan, even if width was too small. 312 CHECKOUT(std::setprecision(10) << nan, "nan"); // setprecision has no effect. 313 } // BOOST_AUTO_TEST_CASE(output_tests) 314 315 } // anonymous namespace 316 317 /* 318 319 Output: 320 321 test_nonfinite_io.cpp 322 test_nonfinite_io.vcxproj -> J:\Cpp\MathToolkit\test\Math_test\Debug\test_nonfinite_io.exe 323 Running 4 test cases... 324 Platform: Win32 325 Compiler: Microsoft Visual C++ version 10.0 326 STL : Dinkumware standard library version 520 327 Boost : 1.49.0 328 Entering test suite "Master Test Suite" 329 Entering test case "trap_test" 330 Leaving test case "trap_test"; testing time: 7ms 331 Entering test case "check_trap_nan" 332 Leaving test case "check_trap_nan" 333 Entering test case "check_trap_inf" 334 Leaving test case "check_trap_inf"; testing time: 1ms 335 Entering test case "output_tests" 336 Leaving test case "output_tests"; testing time: 3ms 337 Leaving test suite "Master Test Suite" 338 339 *** No errors detected 340 341 */ 342 343