// Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) // Copyright (c) 2006 Johan Rade // Copyright (c) 2011 Paul A. Bristow comments // Copyright (c) 2011 John Maddock /*! \file \brief Basic tests of the nonfinite num facets. \detail If has_infinity and has_nan, then basic_test outputs using nonfinite_num_put facet and reads back in using nonfinite_num_ facet, and checks loopback OK. Also checks that output of infinity, -infinity and NaN are as expected, using C99 specification "nan -nan nan -nan" and "inf -inf". Also includes a few combinations of display manipulators (left, right, internal, showpos) and checks that can input C99 infinity and NaN too. */ #ifdef _MSC_VER # pragma warning(disable : 4702) // Unreachable code. #endif #include #include #include #define BOOST_TEST_MAIN #include #include "almost_equal.ipp" #include "s_.ipp" #include namespace { // The anonymous namespace resolves ambiguities on // platforms with fpclassify etc functions at global scope. using namespace boost::math; using boost::math::signbit; using boost::math::changesign; using boost::math::isnan; //------------------------------------------------------------------------------ void basic_test_finite(); void basic_test_inf(); void basic_test_nan(); void basic_test_format(); BOOST_AUTO_TEST_CASE(basic_test) { basic_test_finite(); basic_test_inf(); basic_test_nan(); basic_test_format(); } //------------------------------------------------------------------------------ template void basic_test_finite_impl(); void basic_test_finite() { basic_test_finite_impl(); basic_test_finite_impl(); basic_test_finite_impl(); basic_test_finite_impl(); basic_test_finite_impl(); basic_test_finite_impl(); } template void basic_test_finite_impl() { if((std::numeric_limits::has_infinity == 0) || (std::numeric_limits::infinity() == 0)) return; std::locale old_locale; std::locale tmp_locale(old_locale, new nonfinite_num_put); std::locale new_locale(tmp_locale, new nonfinite_num_get); std::basic_stringstream ss; ss.imbue(new_locale); ValType a1 = (ValType)1.2; ValType a2 = (ValType)-3.5; ValType a3 = (std::numeric_limits::max)(); ValType a4 = -(std::numeric_limits::max)(); ss << a1 << ' ' << a2 << ' ' << a3 << ' ' << a4; ValType b1, b2, b3, b4; ss >> b1 >> b2 >> b3 >> b4; BOOST_CHECK(almost_equal(b1, a1)); BOOST_CHECK(almost_equal(b2, a2)); BOOST_CHECK(almost_equal(b3, a3)); BOOST_CHECK(almost_equal(b4, a4)); BOOST_CHECK(b3 != std::numeric_limits::infinity()); BOOST_CHECK(b4 != -std::numeric_limits::infinity()); BOOST_CHECK(ss.rdstate() == std::ios_base::eofbit); ss.clear(); ss.str(S_("")); ss << "++5"; ValType b5; ss >> b5; BOOST_CHECK(ss.rdstate() == std::ios_base::failbit); } //------------------------------------------------------------------------------ template void basic_test_inf_impl(); void basic_test_inf() { basic_test_inf_impl(); basic_test_inf_impl(); basic_test_inf_impl(); basic_test_inf_impl(); basic_test_inf_impl(); basic_test_inf_impl(); } template void basic_test_inf_impl() { if((std::numeric_limits::has_infinity == 0) || (std::numeric_limits::infinity() == 0)) return; std::locale old_locale; std::locale tmp_locale(old_locale, new nonfinite_num_put); std::locale new_locale(tmp_locale, new nonfinite_num_get); std::basic_stringstream ss; ss.imbue(new_locale); ValType a1 = std::numeric_limits::infinity(); ValType a2 = -std::numeric_limits::infinity(); BOOST_CHECK((boost::math::isinf)(a1)); BOOST_CHECK((boost::math::isinf)(a2)); ss << a1 << ' ' << a2; std::basic_string s = S_("inf -inf"); BOOST_CHECK(ss.str() == s); ss << " infinity"; // Alternative C99 representation of infinity. ValType b1, b2, b3; ss >> b1; ss >> b2; ss >> b3; BOOST_CHECK(b1 == a1); BOOST_CHECK(b2 == a2); BOOST_CHECK(b3 == std::numeric_limits::infinity()); BOOST_CHECK(ss.rdstate() == std::ios_base::eofbit); } //------------------------------------------------------------------------------ template void basic_test_nan_impl(); void basic_test_nan() { basic_test_nan_impl(); basic_test_nan_impl(); basic_test_nan_impl(); basic_test_nan_impl(); basic_test_nan_impl(); basic_test_nan_impl(); } template void basic_test_nan_impl() { if((std::numeric_limits::has_quiet_NaN == 0) || (std::numeric_limits::quiet_NaN() == 0)) return; std::locale old_locale; std::locale tmp_locale(old_locale, new nonfinite_num_put); std::locale new_locale(tmp_locale, new nonfinite_num_get); std::basic_stringstream ss; ss.imbue(new_locale); ValType a1 = std::numeric_limits::quiet_NaN(); ValType a2 = (boost::math::changesign)(std::numeric_limits::quiet_NaN()); ValType a3 = std::numeric_limits::signaling_NaN(); ValType a4 = (boost::math::changesign)(std::numeric_limits::signaling_NaN()); ss << a1 << ' ' << a2 << ' ' << a3 << ' ' << a4; BOOST_CHECK((boost::math::isnan)(a1) && (boost::math::isnan)(a2) && (boost::math::isnan)(a3) && (boost::math::isnan)(a4)); std::basic_string s = S_("nan -nan nan -nan"); BOOST_CHECK(ss.str() == s); // Alternative C99 representation of NaN. ss << " nan(foo)"; ValType b1, b2, b3, b4, b5; ss >> b1 >> b2 >> b3 >> b4 >> b5; BOOST_CHECK((isnan)(b1)); BOOST_CHECK((isnan)(b2)); BOOST_CHECK((isnan)(b3)); BOOST_CHECK((isnan)(b4)); BOOST_CHECK((isnan)(b5)); BOOST_CHECK(!(signbit)(b1)); BOOST_CHECK((signbit)(b2)); BOOST_CHECK(!(signbit)(b3)); BOOST_CHECK((signbit)(b4)); BOOST_CHECK(!(signbit)(b5)); BOOST_CHECK(ss.rdstate() == std::ios_base::eofbit); } //------------------------------------------------------------------------------ template void basic_test_format_impl(); void basic_test_format() { basic_test_format_impl(); basic_test_format_impl(); basic_test_format_impl(); basic_test_format_impl(); basic_test_format_impl(); basic_test_format_impl(); } template void basic_test_format_impl() { if((std::numeric_limits::has_infinity == 0) || (std::numeric_limits::infinity() == 0)) return; std::locale old_locale; std::locale tmp_locale(old_locale, new nonfinite_num_put); std::locale new_locale(tmp_locale, new nonfinite_num_get); std::basic_stringstream ss; ss.imbue(new_locale); ValType a = std::numeric_limits::infinity(); BOOST_CHECK((boost::math::isinf)(a)); ss << std::setw(6) << a; // Expect right justified in field of six, so 3 leading spaces. ss << '|'; ss << std::setw(2) << a; // Too narrow for "inf", but should still be "inf". ss << '|'; ss << std::left << std::setw(5) << a; // 5 - 3 leaves two trailing spaces. ss << '|'; ss << std::showpos << std::internal << std::setw(7) << a; // 3 internal spaces between + and "inf". ss << '|'; ss << std::uppercase << std::right << std::setw(6) << a; // still showpos, so "space, space, +INF". std::basic_string s = S_(" inf|inf|inf |+ inf| +INF"); BOOST_CHECK(ss.str() == s); } //------------------------------------------------------------------------------ } // anonymous namespace