diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index b4728f3..99aeb24 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -40,6 +40,8 @@ #include #include #include +#include +#include #include #include #include @@ -767,7 +769,7 @@ namespace boost } if( !has_minus ) value = std::numeric_limits::quiet_NaN(); - else value = -std::numeric_limits::quiet_NaN(); + else value = (boost::math::changesign) (std::numeric_limits::quiet_NaN()); return true; } else if (( /* 'INF' or 'inf' */ @@ -784,7 +786,7 @@ namespace boost ) { if( !has_minus ) value = std::numeric_limits::infinity(); - else value = -std::numeric_limits::infinity(); + else value = (boost::math::changesign) (std::numeric_limits::infinity()); return true; } @@ -810,49 +812,67 @@ namespace boost , "INFINITY", "infinity" , '(', ')'); } - +#ifndef BOOST_LCAST_NO_WCHAR_T template bool put_inf_nan(wchar_t* begin, wchar_t*& end, const T& value) { using namespace std; - if (value != value) + if ( (boost::math::isnan)(value) ) { - memcpy(begin,L"nan", sizeof(L"nan")); - end = begin + 3; + if ( (boost::math::signbit)(value) ) + { + memcpy(begin,L"-nan", sizeof(L"-nan")); + end = begin + 4; + } else + { + memcpy(begin,L"nan", sizeof(L"nan")); + end = begin + 3; + } return true; - } else if ( value > numeric_limits::max() ) + } else if ( (boost::math::isinf)(value) ) { - memcpy(begin,L"inf", sizeof(L"inf")); - end = begin + 3; - return true; - } else if ( value < -numeric_limits::max() ) - { - memcpy(begin,L"-inf", sizeof(L"-inf")); - end = begin + 4; + if ( (boost::math::signbit)(value) ) + { + memcpy(begin,L"-inf", sizeof(L"-inf")); + end = begin + 4; + } else + { + memcpy(begin,L"inf", sizeof(L"inf")); + end = begin + 3; + } return true; } return false; } - +#endif template bool put_inf_nan(CharT* begin, CharT*& end, const T& value) { using namespace std; - if (value != value) + if ( (boost::math::isnan)(value) ) { - memcpy(begin,"nan", sizeof("nan")); - end = begin + 3; + if ( (boost::math::signbit)(value) ) + { + memcpy(begin,"-nan", sizeof("-nan")); + end = begin + 4; + } else + { + memcpy(begin,"nan", sizeof("nan")); + end = begin + 3; + } return true; - } else if ( value > numeric_limits::max() ) + } else if ( (boost::math::isinf)(value) ) { - memcpy(begin,"inf", sizeof("inf")); - end = begin + 3; - return true; - } else if ( value < -numeric_limits::max() ) - { - memcpy(begin,"-inf", sizeof("-inf")); - end = begin + 4; + if ( (boost::math::signbit)(value) ) + { + memcpy(begin,"-inf", sizeof("-inf")); + end = begin + 4; + } else + { + memcpy(begin,"inf", sizeof("inf")); + end = begin + 3; + } return true; } @@ -1095,12 +1115,9 @@ namespace boost * with long doubles (and with doubles if sizeof(double)==sizeof(long double)). */ long double result = std::pow(10.0L, pow_of_10) * mantissa; - value = ( has_minus ? -1 * result : result); + value = static_cast( has_minus ? -1 * result : result); - if ( value > (std::numeric_limits::max)() // is it +inf - || value < -(std::numeric_limits::max)() // is it -inf - || value != value) // is it NaN - return false; + if ( (boost::math::isinf)(value) || (boost::math::isnan)(value) ) return false; return true; } diff --git a/test/lexical_cast_inf_nan_test.cpp b/test/lexical_cast_inf_nan_test.cpp index 64a4957..ee50dee 100755 --- a/test/lexical_cast_inf_nan_test.cpp +++ b/test/lexical_cast_inf_nan_test.cpp @@ -18,7 +18,9 @@ #include -#include + +#include +#include #include #include @@ -28,57 +30,113 @@ using namespace boost; +template +bool is_pos_inf(T value) +{ + return (boost::math::isinf)(value) && !(boost::math::signbit)(value); +} + +template +bool is_neg_inf(T value) +{ + return (boost::math::isinf)(value) && (boost::math::signbit)(value); +} + +template +bool is_pos_nan(T value) +{ + return (boost::math::isnan)(value) && !(boost::math::signbit)(value); +} + +template +bool is_neg_nan(T value) +{ + return (boost::math::isnan)(value) && (boost::math::signbit)(value); +} + template void test_inf_nan_templated() { typedef T test_t; - BOOST_CHECK(lexical_cast("inf") > (std::numeric_limits::max)() ); - BOOST_CHECK(lexical_cast("INF") > (std::numeric_limits::max)() ); + BOOST_CHECK( is_pos_inf( lexical_cast("inf") ) ); + BOOST_CHECK( is_pos_inf( lexical_cast("INF") ) ); - BOOST_CHECK(lexical_cast("-inf") < -(std::numeric_limits::max)() ); - BOOST_CHECK(lexical_cast("-INF") < -(std::numeric_limits::max)() ); + BOOST_CHECK( is_neg_inf( lexical_cast("-inf") ) ); + BOOST_CHECK( is_neg_inf( lexical_cast("-INF") ) ); - BOOST_CHECK(lexical_cast("+inf") > (std::numeric_limits::max)() ); - BOOST_CHECK(lexical_cast("+INF") > (std::numeric_limits::max)() ); + BOOST_CHECK( is_pos_inf( lexical_cast("+inf") ) ); + BOOST_CHECK( is_pos_inf( lexical_cast("+INF") ) ); - BOOST_CHECK(lexical_cast("infinity") > (std::numeric_limits::max)() ); - BOOST_CHECK(lexical_cast("INFINITY") > (std::numeric_limits::max)() ); + BOOST_CHECK( is_pos_inf( lexical_cast("infinity") ) ); + BOOST_CHECK( is_pos_inf( lexical_cast("INFINITY") ) ); - BOOST_CHECK(lexical_cast("-infinity") < -(std::numeric_limits::max)() ); - BOOST_CHECK(lexical_cast("-INFINITY") < -(std::numeric_limits::max)() ); + BOOST_CHECK( is_neg_inf( lexical_cast("-infinity") ) ); + BOOST_CHECK( is_neg_inf( lexical_cast("-INFINITY") ) ); - BOOST_CHECK(lexical_cast("+infinity") > (std::numeric_limits::max)() ); - BOOST_CHECK(lexical_cast("+INFINITY") > (std::numeric_limits::max)() ); + BOOST_CHECK( is_pos_inf( lexical_cast("+infinity") ) ); + BOOST_CHECK( is_pos_inf( lexical_cast("+INFINITY") ) ); - BOOST_CHECK( lexical_cast("nan") != lexical_cast("nan") ); - BOOST_CHECK( lexical_cast("NAN") != lexical_cast("NAN") ); + BOOST_CHECK( is_pos_nan( lexical_cast("nan") ) ); + BOOST_CHECK( is_pos_nan( lexical_cast("NAN") ) ); - BOOST_CHECK( lexical_cast("-nan") != lexical_cast("-nan") ); - BOOST_CHECK( lexical_cast("-NAN") != lexical_cast("-NAN") ); + BOOST_CHECK( is_neg_nan( lexical_cast("-nan") ) ); + BOOST_CHECK( is_neg_nan( lexical_cast("-NAN") ) ); - BOOST_CHECK( lexical_cast("+nan") != lexical_cast("+nan") ); - BOOST_CHECK( lexical_cast("+NAN") != lexical_cast("+NAN") ); + BOOST_CHECK( is_pos_nan( lexical_cast("+nan") ) ); + BOOST_CHECK( is_pos_nan( lexical_cast("+NAN") ) ); - BOOST_CHECK( lexical_cast("nan()") != lexical_cast("nan()") ); - BOOST_CHECK( lexical_cast("NAN(some string)") != lexical_cast("NAN(some string)") ); + BOOST_CHECK( is_pos_nan( lexical_cast("nan()") ) ); + BOOST_CHECK( is_pos_nan( lexical_cast("NAN(some string)") ) ); BOOST_CHECK_THROW( lexical_cast("NAN(some string"), bad_lexical_cast ); - BOOST_CHECK(lexical_cast( -std::numeric_limits::infinity()) == "-inf" ); + BOOST_CHECK(lexical_cast( (boost::math::changesign)(std::numeric_limits::infinity())) + == "-inf" ); BOOST_CHECK(lexical_cast( std::numeric_limits::infinity()) == "inf" ); BOOST_CHECK(lexical_cast( std::numeric_limits::quiet_NaN()) == "nan" ); + BOOST_CHECK(lexical_cast( + (boost::math::changesign)(std::numeric_limits::quiet_NaN())) + == "-nan" ); #ifndef BOOST_LCAST_NO_WCHAR_T - BOOST_CHECK(lexical_cast(L"inf") > (std::numeric_limits::max)() ); - BOOST_CHECK(lexical_cast(L"INF") > (std::numeric_limits::max)() ); + BOOST_CHECK( is_pos_inf( lexical_cast(L"inf") ) ); + BOOST_CHECK( is_pos_inf( lexical_cast(L"INF") ) ); - BOOST_CHECK( lexical_cast(L"nan") != lexical_cast(L"nan") ); - BOOST_CHECK( lexical_cast(L"NAN") != lexical_cast(L"NAN") ); + BOOST_CHECK( is_neg_inf( lexical_cast(L"-inf") ) ); + BOOST_CHECK( is_neg_inf( lexical_cast(L"-INF") ) ); - BOOST_CHECK(lexical_cast( -std::numeric_limits::infinity()) == L"-inf" ); + BOOST_CHECK( is_pos_inf( lexical_cast(L"+inf") ) ); + BOOST_CHECK( is_pos_inf( lexical_cast(L"+INF") ) ); + + BOOST_CHECK( is_pos_inf( lexical_cast(L"infinity") ) ); + BOOST_CHECK( is_pos_inf( lexical_cast(L"INFINITY") ) ); + + BOOST_CHECK( is_neg_inf( lexical_cast(L"-infinity") ) ); + BOOST_CHECK( is_neg_inf( lexical_cast(L"-INFINITY") ) ); + + BOOST_CHECK( is_pos_inf( lexical_cast(L"+infinity") ) ); + BOOST_CHECK( is_pos_inf( lexical_cast(L"+INFINITY") ) ); + + BOOST_CHECK( is_pos_nan( lexical_cast(L"nan") ) ); + BOOST_CHECK( is_pos_nan( lexical_cast(L"NAN") ) ); + + BOOST_CHECK( is_neg_nan( lexical_cast(L"-nan") ) ); + BOOST_CHECK( is_neg_nan( lexical_cast(L"-NAN") ) ); + + BOOST_CHECK( is_pos_nan( lexical_cast(L"+nan") ) ); + BOOST_CHECK( is_pos_nan( lexical_cast(L"+NAN") ) ); + + BOOST_CHECK( is_pos_nan( lexical_cast(L"nan()") ) ); + BOOST_CHECK( is_pos_nan( lexical_cast(L"NAN(some string)") ) ); + BOOST_CHECK_THROW( lexical_cast(L"NAN(some string"), bad_lexical_cast ); + + BOOST_CHECK(lexical_cast( (boost::math::changesign)(std::numeric_limits::infinity())) + == L"-inf" ); BOOST_CHECK(lexical_cast( std::numeric_limits::infinity()) == L"inf" ); BOOST_CHECK(lexical_cast( std::numeric_limits::quiet_NaN()) == L"nan" ); - + BOOST_CHECK(lexical_cast( + (boost::math::changesign)(std::numeric_limits::quiet_NaN())) + == L"-nan" ); #endif }