// 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 /*! \file \brief Basic tests of the nonfinite num facets. \detail 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) #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::spirit::detail::changesign; // Temporary spirit version. 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() { 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() { 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(); 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() { 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 = -std::numeric_limits::quiet_NaN(); ValType a3 = std::numeric_limits::signaling_NaN(); ValType a4 = -std::numeric_limits::signaling_NaN(); ss << a1 << ' ' << a2 << ' ' << a3 << ' ' << 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() { 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(); 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