Changeset 73155


Ignore:
Timestamp:
Jul 16, 2011, 9:02:32 PM (6 years ago)
Author:
Antony Polukhin
Message:

Fixes #5689. Added code to work -NaN on any platform. Removed some warnings

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/boost/lexical_cast.hpp

    r73118 r73155  
    4141#include <boost/type_traits/is_signed.hpp>
    4242#include <boost/call_traits.hpp>
     43#include <boost/math/special_functions/sign.hpp>
     44#include <boost/math/special_functions/fpclassify.hpp>
    4345#include <boost/static_assert.hpp>
    4446#include <boost/detail/lcast_precision.hpp>
     
    768770
    769771                if( !has_minus ) value = std::numeric_limits<T>::quiet_NaN();
    770                 else value = -std::numeric_limits<T>::quiet_NaN();
     772                else value = (boost::math::changesign) (std::numeric_limits<T>::quiet_NaN());
    771773                return true;
    772774            } else
     
    785787            {
    786788                if( !has_minus ) value = std::numeric_limits<T>::infinity();
    787                 else value = -std::numeric_limits<T>::infinity();
     789                else value = (boost::math::changesign) (std::numeric_limits<T>::infinity());
    788790                return true;
    789791            }
     
    811813                               , '(', ')');
    812814        }
    813 
     815#ifndef BOOST_LCAST_NO_WCHAR_T
    814816        template <class T>
    815817        bool put_inf_nan(wchar_t* begin, wchar_t*& end, const T& value)
    816818        {
    817819            using namespace std;
    818             if (value != value)
    819             {
    820                 memcpy(begin,L"nan", sizeof(L"nan"));
    821                 end = begin + 3;
     820            if ( (boost::math::isnan)(value) )
     821            {
     822                if ( (boost::math::signbit)(value) )
     823                {
     824                    memcpy(begin,L"-nan", sizeof(L"-nan"));
     825                    end = begin + 4;
     826                } else
     827                {
     828                    memcpy(begin,L"nan", sizeof(L"nan"));
     829                    end = begin + 3;
     830                }
    822831                return true;
    823             } else if ( value > numeric_limits<T>::max() )
    824             {
    825                 memcpy(begin,L"inf", sizeof(L"inf"));
    826                 end = begin + 3;
     832            } else if ( (boost::math::isinf)(value) )
     833            {
     834                if ( (boost::math::signbit)(value) )
     835                {
     836                    memcpy(begin,L"-inf", sizeof(L"-inf"));
     837                    end = begin + 4;
     838                } else
     839                {
     840                    memcpy(begin,L"inf", sizeof(L"inf"));
     841                    end = begin + 3;
     842                }
    827843                return true;
    828             } else if ( value < -numeric_limits<T>::max() )
    829             {
    830                 memcpy(begin,L"-inf", sizeof(L"-inf"));
    831                 end = begin + 4;
    832                 return true;
    833844            }
    834845
    835846            return false;
    836847        }
    837 
     848#endif
    838849        template <class CharT, class T>
    839850        bool put_inf_nan(CharT* begin, CharT*& end, const T& value)
    840851        {
    841852            using namespace std;
    842             if (value != value)
    843             {
    844                 memcpy(begin,"nan", sizeof("nan"));
    845                 end = begin + 3;
     853            if ( (boost::math::isnan)(value) )
     854            {
     855                if ( (boost::math::signbit)(value) )
     856                {
     857                    memcpy(begin,"-nan", sizeof("-nan"));
     858                    end = begin + 4;
     859                } else
     860                {
     861                    memcpy(begin,"nan", sizeof("nan"));
     862                    end = begin + 3;
     863                }
    846864                return true;
    847             } else if ( value > numeric_limits<T>::max() )
    848             {
    849                 memcpy(begin,"inf", sizeof("inf"));
    850                 end = begin + 3;
    851                 return true;
    852             } else if ( value < -numeric_limits<T>::max() )
    853             {
    854                 memcpy(begin,"-inf", sizeof("-inf"));
    855                 end = begin + 4;
     865            } else if ( (boost::math::isinf)(value) )
     866            {
     867                if ( (boost::math::signbit)(value) )
     868                {
     869                    memcpy(begin,"-inf", sizeof("-inf"));
     870                    end = begin + 4;
     871                } else
     872                {
     873                    memcpy(begin,"inf", sizeof("inf"));
     874                    end = begin + 3;
     875                }
    856876                return true;
    857877            }
     
    10961116             */
    10971117            long double result = std::pow(10.0L, pow_of_10) * mantissa;
    1098             value = ( has_minus ? -1 * result : result);
    1099 
    1100             if ( value > (std::numeric_limits<T>::max)()        // is it +inf
    1101                     || value < -(std::numeric_limits<T>::max)() // is it -inf
    1102                     || value != value)                          // is it NaN
    1103                 return false;
     1118            value = static_cast<T>( has_minus ? -1 * result : result);
     1119
     1120            if ( (boost::math::isinf)(value) || (boost::math::isnan)(value) ) return false;
    11041121
    11051122            return true;
  • trunk/libs/conversion/test/lexical_cast_inf_nan_test.cpp

    r73118 r73155  
    1919#include <boost/lexical_cast.hpp>
    2020
    21 #include <boost/cstdint.hpp>
     21
     22#include <boost/math/special_functions/sign.hpp>
     23#include <boost/math/special_functions/fpclassify.hpp>
    2224#include <boost/test/unit_test.hpp>
    2325#include <boost/test/floating_point_comparison.hpp>
     
    3032
    3133template <class T>
     34bool is_pos_inf(T value)
     35{
     36    return (boost::math::isinf)(value) && !(boost::math::signbit)(value);
     37}
     38
     39template <class T>
     40bool is_neg_inf(T value)
     41{
     42    return (boost::math::isinf)(value) && (boost::math::signbit)(value);
     43}
     44
     45template <class T>
     46bool is_pos_nan(T value)
     47{
     48    return (boost::math::isnan)(value) && !(boost::math::signbit)(value);
     49}
     50
     51template <class T>
     52bool is_neg_nan(T value)
     53{
     54    return (boost::math::isnan)(value) && (boost::math::signbit)(value);
     55}
     56
     57template <class T>
    3258void test_inf_nan_templated()
    3359{
    3460    typedef T test_t;
    3561
    36     BOOST_CHECK(lexical_cast<test_t>("inf") > (std::numeric_limits<test_t >::max)() );
    37     BOOST_CHECK(lexical_cast<test_t>("INF") > (std::numeric_limits<test_t >::max)() );
     62    BOOST_CHECK( is_pos_inf( lexical_cast<test_t>("inf") ) );
     63    BOOST_CHECK( is_pos_inf( lexical_cast<test_t>("INF") ) );
    3864
    39     BOOST_CHECK(lexical_cast<test_t>("-inf") < -(std::numeric_limits<test_t >::max)() );
    40     BOOST_CHECK(lexical_cast<test_t>("-INF") < -(std::numeric_limits<test_t >::max)() );
     65    BOOST_CHECK( is_neg_inf( lexical_cast<test_t>("-inf") ) );
     66    BOOST_CHECK( is_neg_inf( lexical_cast<test_t>("-INF") ) );
    4167
    42     BOOST_CHECK(lexical_cast<test_t>("+inf") > (std::numeric_limits<test_t >::max)() );
    43     BOOST_CHECK(lexical_cast<test_t>("+INF") > (std::numeric_limits<test_t >::max)() );
     68    BOOST_CHECK( is_pos_inf( lexical_cast<test_t>("+inf") ) );
     69    BOOST_CHECK( is_pos_inf( lexical_cast<test_t>("+INF") ) );
    4470
    45     BOOST_CHECK(lexical_cast<test_t>("infinity") > (std::numeric_limits<test_t >::max)() );
    46     BOOST_CHECK(lexical_cast<test_t>("INFINITY") > (std::numeric_limits<test_t >::max)() );
     71    BOOST_CHECK( is_pos_inf( lexical_cast<test_t>("infinity") ) );
     72    BOOST_CHECK( is_pos_inf( lexical_cast<test_t>("INFINITY") ) );
    4773
    48     BOOST_CHECK(lexical_cast<test_t>("-infinity") < -(std::numeric_limits<test_t >::max)() );
    49     BOOST_CHECK(lexical_cast<test_t>("-INFINITY") < -(std::numeric_limits<test_t >::max)() );
     74    BOOST_CHECK( is_neg_inf( lexical_cast<test_t>("-infinity") ) );
     75    BOOST_CHECK( is_neg_inf( lexical_cast<test_t>("-INFINITY") ) );
    5076
    51     BOOST_CHECK(lexical_cast<test_t>("+infinity") > (std::numeric_limits<test_t >::max)() );
    52     BOOST_CHECK(lexical_cast<test_t>("+INFINITY") > (std::numeric_limits<test_t >::max)() );
     77    BOOST_CHECK( is_pos_inf( lexical_cast<test_t>("+infinity") ) );
     78    BOOST_CHECK( is_pos_inf( lexical_cast<test_t>("+INFINITY") ) );
    5379
    54     BOOST_CHECK( lexical_cast<test_t>("nan") != lexical_cast<test_t>("nan") );
    55     BOOST_CHECK( lexical_cast<test_t>("NAN") != lexical_cast<test_t>("NAN") );
     80    BOOST_CHECK( is_pos_nan( lexical_cast<test_t>("nan") ) );
     81    BOOST_CHECK( is_pos_nan( lexical_cast<test_t>("NAN") ) );
    5682
    57     BOOST_CHECK( lexical_cast<test_t>("-nan") != lexical_cast<test_t>("-nan") );
    58     BOOST_CHECK( lexical_cast<test_t>("-NAN") != lexical_cast<test_t>("-NAN") );
     83    BOOST_CHECK( is_neg_nan( lexical_cast<test_t>("-nan") ) );
     84    BOOST_CHECK( is_neg_nan( lexical_cast<test_t>("-NAN") ) );
    5985
    60     BOOST_CHECK( lexical_cast<test_t>("+nan") != lexical_cast<test_t>("+nan") );
    61     BOOST_CHECK( lexical_cast<test_t>("+NAN") != lexical_cast<test_t>("+NAN") );
     86    BOOST_CHECK( is_pos_nan( lexical_cast<test_t>("+nan") ) );
     87    BOOST_CHECK( is_pos_nan( lexical_cast<test_t>("+NAN") ) );
    6288
    63     BOOST_CHECK( lexical_cast<test_t>("nan()") != lexical_cast<test_t>("nan()") );
    64     BOOST_CHECK( lexical_cast<test_t>("NAN(some string)") != lexical_cast<test_t>("NAN(some string)") );
     89    BOOST_CHECK( is_pos_nan( lexical_cast<test_t>("nan()") ) );
     90    BOOST_CHECK( is_pos_nan( lexical_cast<test_t>("NAN(some string)") ) );
    6591    BOOST_CHECK_THROW( lexical_cast<test_t>("NAN(some string"), bad_lexical_cast );
    6692
    67     BOOST_CHECK(lexical_cast<std::string>( -std::numeric_limits<test_t >::infinity()) == "-inf" );
     93    BOOST_CHECK(lexical_cast<std::string>( (boost::math::changesign)(std::numeric_limits<test_t >::infinity()))
     94                == "-inf" );
    6895    BOOST_CHECK(lexical_cast<std::string>( std::numeric_limits<test_t >::infinity()) == "inf" );
    6996    BOOST_CHECK(lexical_cast<std::string>( std::numeric_limits<test_t >::quiet_NaN()) == "nan" );
     97    BOOST_CHECK(lexical_cast<std::string>(
     98                (boost::math::changesign)(std::numeric_limits<test_t >::quiet_NaN()))
     99                == "-nan" );
    70100
    71101#ifndef  BOOST_LCAST_NO_WCHAR_T
    72     BOOST_CHECK(lexical_cast<test_t>(L"inf") > (std::numeric_limits<test_t >::max)() );
    73     BOOST_CHECK(lexical_cast<test_t>(L"INF") > (std::numeric_limits<test_t >::max)() );
     102    BOOST_CHECK( is_pos_inf( lexical_cast<test_t>(L"inf") ) );
     103    BOOST_CHECK( is_pos_inf( lexical_cast<test_t>(L"INF") ) );
    74104
    75     BOOST_CHECK( lexical_cast<test_t>(L"nan") != lexical_cast<test_t>(L"nan") );
    76     BOOST_CHECK( lexical_cast<test_t>(L"NAN") != lexical_cast<test_t>(L"NAN") );
     105    BOOST_CHECK( is_neg_inf( lexical_cast<test_t>(L"-inf") ) );
     106    BOOST_CHECK( is_neg_inf( lexical_cast<test_t>(L"-INF") ) );
    77107
    78     BOOST_CHECK(lexical_cast<std::wstring>( -std::numeric_limits<test_t >::infinity()) == L"-inf" );
     108    BOOST_CHECK( is_pos_inf( lexical_cast<test_t>(L"+inf") ) );
     109    BOOST_CHECK( is_pos_inf( lexical_cast<test_t>(L"+INF") ) );
     110
     111    BOOST_CHECK( is_pos_inf( lexical_cast<test_t>(L"infinity") ) );
     112    BOOST_CHECK( is_pos_inf( lexical_cast<test_t>(L"INFINITY") ) );
     113
     114    BOOST_CHECK( is_neg_inf( lexical_cast<test_t>(L"-infinity") ) );
     115    BOOST_CHECK( is_neg_inf( lexical_cast<test_t>(L"-INFINITY") ) );
     116
     117    BOOST_CHECK( is_pos_inf( lexical_cast<test_t>(L"+infinity") ) );
     118    BOOST_CHECK( is_pos_inf( lexical_cast<test_t>(L"+INFINITY") ) );
     119
     120    BOOST_CHECK( is_pos_nan( lexical_cast<test_t>(L"nan") ) );
     121    BOOST_CHECK( is_pos_nan( lexical_cast<test_t>(L"NAN") ) );
     122
     123    BOOST_CHECK( is_neg_nan( lexical_cast<test_t>(L"-nan") ) );
     124    BOOST_CHECK( is_neg_nan( lexical_cast<test_t>(L"-NAN") ) );
     125
     126    BOOST_CHECK( is_pos_nan( lexical_cast<test_t>(L"+nan") ) );
     127    BOOST_CHECK( is_pos_nan( lexical_cast<test_t>(L"+NAN") ) );
     128
     129    BOOST_CHECK( is_pos_nan( lexical_cast<test_t>(L"nan()") ) );
     130    BOOST_CHECK( is_pos_nan( lexical_cast<test_t>(L"NAN(some string)") ) );
     131    BOOST_CHECK_THROW( lexical_cast<test_t>(L"NAN(some string"), bad_lexical_cast );
     132
     133    BOOST_CHECK(lexical_cast<std::wstring>( (boost::math::changesign)(std::numeric_limits<test_t >::infinity()))
     134                == L"-inf" );
    79135    BOOST_CHECK(lexical_cast<std::wstring>( std::numeric_limits<test_t >::infinity()) == L"inf" );
    80136    BOOST_CHECK(lexical_cast<std::wstring>( std::numeric_limits<test_t >::quiet_NaN()) == L"nan" );
    81 
     137    BOOST_CHECK(lexical_cast<std::wstring>(
     138                (boost::math::changesign)(std::numeric_limits<test_t >::quiet_NaN()))
     139                == L"-nan" );
    82140#endif
    83141}
Note: See TracChangeset for help on using the changeset viewer.