Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r73155 - in trunk: boost libs/conversion/test
From: antoshkka_at_[hidden]
Date: 2011-07-16 17:02:33


Author: apolukhin
Date: 2011-07-16 17:02:32 EDT (Sat, 16 Jul 2011)
New Revision: 73155
URL: http://svn.boost.org/trac/boost/changeset/73155

Log:
Fixes #5689. Added code to work -NaN on any platform. Removed some warnings
Text files modified:
   trunk/boost/lexical_cast.hpp | 79 ++++++++++++++++----------
   trunk/libs/conversion/test/lexical_cast_inf_nan_test.cpp | 114 ++++++++++++++++++++++++++++++---------
   2 files changed, 134 insertions(+), 59 deletions(-)

Modified: trunk/boost/lexical_cast.hpp
==============================================================================
--- trunk/boost/lexical_cast.hpp (original)
+++ trunk/boost/lexical_cast.hpp 2011-07-16 17:02:32 EDT (Sat, 16 Jul 2011)
@@ -40,6 +40,8 @@
 #include <boost/type_traits/make_unsigned.hpp>
 #include <boost/type_traits/is_signed.hpp>
 #include <boost/call_traits.hpp>
+#include <boost/math/special_functions/sign.hpp>
+#include <boost/math/special_functions/fpclassify.hpp>
 #include <boost/static_assert.hpp>
 #include <boost/detail/lcast_precision.hpp>
 #include <boost/detail/workaround.hpp>
@@ -767,7 +769,7 @@
                 }
 
                 if( !has_minus ) value = std::numeric_limits<T>::quiet_NaN();
- else value = -std::numeric_limits<T>::quiet_NaN();
+ else value = (boost::math::changesign) (std::numeric_limits<T>::quiet_NaN());
                 return true;
             } else
             if (( /* 'INF' or 'inf' */
@@ -784,7 +786,7 @@
              )
             {
                 if( !has_minus ) value = std::numeric_limits<T>::infinity();
- else value = -std::numeric_limits<T>::infinity();
+ else value = (boost::math::changesign) (std::numeric_limits<T>::infinity());
                 return true;
             }
 
@@ -810,49 +812,67 @@
                                , "INFINITY", "infinity"
                                , '(', ')');
         }
-
+#ifndef BOOST_LCAST_NO_WCHAR_T
         template <class T>
         bool put_inf_nan(wchar_t* begin, wchar_t*& end, const T& value)
         {
             using namespace std;
- if (value != value)
- {
- memcpy(begin,L"nan", sizeof(L"nan"));
- end = begin + 3;
- return true;
- } else if ( value > numeric_limits<T>::max() )
+ if ( (boost::math::isnan)(value) )
             {
- memcpy(begin,L"inf", sizeof(L"inf"));
- 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<T>::max() )
+ } else if ( (boost::math::isinf)(value) )
             {
- 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 <class CharT, class T>
         bool put_inf_nan(CharT* begin, CharT*& end, const T& value)
         {
             using namespace std;
- if (value != value)
- {
- memcpy(begin,"nan", sizeof("nan"));
- end = begin + 3;
- return true;
- } else if ( value > numeric_limits<T>::max() )
+ if ( (boost::math::isnan)(value) )
             {
- memcpy(begin,"inf", sizeof("inf"));
- 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<T>::max() )
+ } else if ( (boost::math::isinf)(value) )
             {
- 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 @@
              * 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<T>( has_minus ? -1 * result : result);
 
- if ( value > (std::numeric_limits<T>::max)() // is it +inf
- || value < -(std::numeric_limits<T>::max)() // is it -inf
- || value != value) // is it NaN
- return false;
+ if ( (boost::math::isinf)(value) || (boost::math::isnan)(value) ) return false;
 
             return true;
         }

Modified: trunk/libs/conversion/test/lexical_cast_inf_nan_test.cpp
==============================================================================
--- trunk/libs/conversion/test/lexical_cast_inf_nan_test.cpp (original)
+++ trunk/libs/conversion/test/lexical_cast_inf_nan_test.cpp 2011-07-16 17:02:32 EDT (Sat, 16 Jul 2011)
@@ -18,7 +18,9 @@
 
 #include <boost/lexical_cast.hpp>
 
-#include <boost/cstdint.hpp>
+
+#include <boost/math/special_functions/sign.hpp>
+#include <boost/math/special_functions/fpclassify.hpp>
 #include <boost/test/unit_test.hpp>
 #include <boost/test/floating_point_comparison.hpp>
 
@@ -29,56 +31,112 @@
 using namespace boost;
 
 template <class T>
+bool is_pos_inf(T value)
+{
+ return (boost::math::isinf)(value) && !(boost::math::signbit)(value);
+}
+
+template <class T>
+bool is_neg_inf(T value)
+{
+ return (boost::math::isinf)(value) && (boost::math::signbit)(value);
+}
+
+template <class T>
+bool is_pos_nan(T value)
+{
+ return (boost::math::isnan)(value) && !(boost::math::signbit)(value);
+}
+
+template <class T>
+bool is_neg_nan(T value)
+{
+ return (boost::math::isnan)(value) && (boost::math::signbit)(value);
+}
+
+template <class T>
 void test_inf_nan_templated()
 {
     typedef T test_t;
 
- BOOST_CHECK(lexical_cast<test_t>("inf") > (std::numeric_limits<test_t >::max)() );
- BOOST_CHECK(lexical_cast<test_t>("INF") > (std::numeric_limits<test_t >::max)() );
+ BOOST_CHECK( is_pos_inf( lexical_cast<test_t>("inf") ) );
+ BOOST_CHECK( is_pos_inf( lexical_cast<test_t>("INF") ) );
 
- BOOST_CHECK(lexical_cast<test_t>("-inf") < -(std::numeric_limits<test_t >::max)() );
- BOOST_CHECK(lexical_cast<test_t>("-INF") < -(std::numeric_limits<test_t >::max)() );
+ BOOST_CHECK( is_neg_inf( lexical_cast<test_t>("-inf") ) );
+ BOOST_CHECK( is_neg_inf( lexical_cast<test_t>("-INF") ) );
 
- BOOST_CHECK(lexical_cast<test_t>("+inf") > (std::numeric_limits<test_t >::max)() );
- BOOST_CHECK(lexical_cast<test_t>("+INF") > (std::numeric_limits<test_t >::max)() );
+ BOOST_CHECK( is_pos_inf( lexical_cast<test_t>("+inf") ) );
+ BOOST_CHECK( is_pos_inf( lexical_cast<test_t>("+INF") ) );
 
- BOOST_CHECK(lexical_cast<test_t>("infinity") > (std::numeric_limits<test_t >::max)() );
- BOOST_CHECK(lexical_cast<test_t>("INFINITY") > (std::numeric_limits<test_t >::max)() );
+ BOOST_CHECK( is_pos_inf( lexical_cast<test_t>("infinity") ) );
+ BOOST_CHECK( is_pos_inf( lexical_cast<test_t>("INFINITY") ) );
 
- BOOST_CHECK(lexical_cast<test_t>("-infinity") < -(std::numeric_limits<test_t >::max)() );
- BOOST_CHECK(lexical_cast<test_t>("-INFINITY") < -(std::numeric_limits<test_t >::max)() );
+ BOOST_CHECK( is_neg_inf( lexical_cast<test_t>("-infinity") ) );
+ BOOST_CHECK( is_neg_inf( lexical_cast<test_t>("-INFINITY") ) );
 
- BOOST_CHECK(lexical_cast<test_t>("+infinity") > (std::numeric_limits<test_t >::max)() );
- BOOST_CHECK(lexical_cast<test_t>("+INFINITY") > (std::numeric_limits<test_t >::max)() );
+ BOOST_CHECK( is_pos_inf( lexical_cast<test_t>("+infinity") ) );
+ BOOST_CHECK( is_pos_inf( lexical_cast<test_t>("+INFINITY") ) );
 
- BOOST_CHECK( lexical_cast<test_t>("nan") != lexical_cast<test_t>("nan") );
- BOOST_CHECK( lexical_cast<test_t>("NAN") != lexical_cast<test_t>("NAN") );
+ BOOST_CHECK( is_pos_nan( lexical_cast<test_t>("nan") ) );
+ BOOST_CHECK( is_pos_nan( lexical_cast<test_t>("NAN") ) );
 
- BOOST_CHECK( lexical_cast<test_t>("-nan") != lexical_cast<test_t>("-nan") );
- BOOST_CHECK( lexical_cast<test_t>("-NAN") != lexical_cast<test_t>("-NAN") );
+ BOOST_CHECK( is_neg_nan( lexical_cast<test_t>("-nan") ) );
+ BOOST_CHECK( is_neg_nan( lexical_cast<test_t>("-NAN") ) );
 
- BOOST_CHECK( lexical_cast<test_t>("+nan") != lexical_cast<test_t>("+nan") );
- BOOST_CHECK( lexical_cast<test_t>("+NAN") != lexical_cast<test_t>("+NAN") );
+ BOOST_CHECK( is_pos_nan( lexical_cast<test_t>("+nan") ) );
+ BOOST_CHECK( is_pos_nan( lexical_cast<test_t>("+NAN") ) );
 
- BOOST_CHECK( lexical_cast<test_t>("nan()") != lexical_cast<test_t>("nan()") );
- BOOST_CHECK( lexical_cast<test_t>("NAN(some string)") != lexical_cast<test_t>("NAN(some string)") );
+ BOOST_CHECK( is_pos_nan( lexical_cast<test_t>("nan()") ) );
+ BOOST_CHECK( is_pos_nan( lexical_cast<test_t>("NAN(some string)") ) );
     BOOST_CHECK_THROW( lexical_cast<test_t>("NAN(some string"), bad_lexical_cast );
 
- BOOST_CHECK(lexical_cast<std::string>( -std::numeric_limits<test_t >::infinity()) == "-inf" );
+ BOOST_CHECK(lexical_cast<std::string>( (boost::math::changesign)(std::numeric_limits<test_t >::infinity()))
+ == "-inf" );
     BOOST_CHECK(lexical_cast<std::string>( std::numeric_limits<test_t >::infinity()) == "inf" );
     BOOST_CHECK(lexical_cast<std::string>( std::numeric_limits<test_t >::quiet_NaN()) == "nan" );
+ BOOST_CHECK(lexical_cast<std::string>(
+ (boost::math::changesign)(std::numeric_limits<test_t >::quiet_NaN()))
+ == "-nan" );
 
 #ifndef BOOST_LCAST_NO_WCHAR_T
- BOOST_CHECK(lexical_cast<test_t>(L"inf") > (std::numeric_limits<test_t >::max)() );
- BOOST_CHECK(lexical_cast<test_t>(L"INF") > (std::numeric_limits<test_t >::max)() );
+ BOOST_CHECK( is_pos_inf( lexical_cast<test_t>(L"inf") ) );
+ BOOST_CHECK( is_pos_inf( lexical_cast<test_t>(L"INF") ) );
+
+ BOOST_CHECK( is_neg_inf( lexical_cast<test_t>(L"-inf") ) );
+ BOOST_CHECK( is_neg_inf( lexical_cast<test_t>(L"-INF") ) );
+
+ BOOST_CHECK( is_pos_inf( lexical_cast<test_t>(L"+inf") ) );
+ BOOST_CHECK( is_pos_inf( lexical_cast<test_t>(L"+INF") ) );
+
+ BOOST_CHECK( is_pos_inf( lexical_cast<test_t>(L"infinity") ) );
+ BOOST_CHECK( is_pos_inf( lexical_cast<test_t>(L"INFINITY") ) );
 
- BOOST_CHECK( lexical_cast<test_t>(L"nan") != lexical_cast<test_t>(L"nan") );
- BOOST_CHECK( lexical_cast<test_t>(L"NAN") != lexical_cast<test_t>(L"NAN") );
+ BOOST_CHECK( is_neg_inf( lexical_cast<test_t>(L"-infinity") ) );
+ BOOST_CHECK( is_neg_inf( lexical_cast<test_t>(L"-INFINITY") ) );
 
- BOOST_CHECK(lexical_cast<std::wstring>( -std::numeric_limits<test_t >::infinity()) == L"-inf" );
+ BOOST_CHECK( is_pos_inf( lexical_cast<test_t>(L"+infinity") ) );
+ BOOST_CHECK( is_pos_inf( lexical_cast<test_t>(L"+INFINITY") ) );
+
+ BOOST_CHECK( is_pos_nan( lexical_cast<test_t>(L"nan") ) );
+ BOOST_CHECK( is_pos_nan( lexical_cast<test_t>(L"NAN") ) );
+
+ BOOST_CHECK( is_neg_nan( lexical_cast<test_t>(L"-nan") ) );
+ BOOST_CHECK( is_neg_nan( lexical_cast<test_t>(L"-NAN") ) );
+
+ BOOST_CHECK( is_pos_nan( lexical_cast<test_t>(L"+nan") ) );
+ BOOST_CHECK( is_pos_nan( lexical_cast<test_t>(L"+NAN") ) );
+
+ BOOST_CHECK( is_pos_nan( lexical_cast<test_t>(L"nan()") ) );
+ BOOST_CHECK( is_pos_nan( lexical_cast<test_t>(L"NAN(some string)") ) );
+ BOOST_CHECK_THROW( lexical_cast<test_t>(L"NAN(some string"), bad_lexical_cast );
+
+ BOOST_CHECK(lexical_cast<std::wstring>( (boost::math::changesign)(std::numeric_limits<test_t >::infinity()))
+ == L"-inf" );
     BOOST_CHECK(lexical_cast<std::wstring>( std::numeric_limits<test_t >::infinity()) == L"inf" );
     BOOST_CHECK(lexical_cast<std::wstring>( std::numeric_limits<test_t >::quiet_NaN()) == L"nan" );
-
+ BOOST_CHECK(lexical_cast<std::wstring>(
+ (boost::math::changesign)(std::numeric_limits<test_t >::quiet_NaN()))
+ == L"-nan" );
 #endif
 }
 


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk