Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r71353 - in trunk: boost/spirit/home/karma/numeric/detail boost/spirit/home/support libs/spirit/test/karma
From: hartmut.kaiser_at_[hidden]
Date: 2011-04-17 11:46:29


Author: hkaiser
Date: 2011-04-17 11:46:28 EDT (Sun, 17 Apr 2011)
New Revision: 71353
URL: http://svn.boost.org/trac/boost/changeset/71353

Log:
Spirit: fixing another problem with adapted ADTs related to numerics
Text files modified:
   trunk/boost/spirit/home/karma/numeric/detail/numeric_utils.hpp | 87 ++++++++++++++++++++++++++++++++++++++++
   trunk/boost/spirit/home/karma/numeric/detail/real_utils.hpp | 50 +---------------------
   trunk/boost/spirit/home/support/adapt_adt_attributes.hpp | 21 +++++++++
   trunk/boost/spirit/home/support/numeric_traits.hpp | 6 ++
   trunk/libs/spirit/test/karma/regression_numerics_adapt_adt.cpp | 39 +++++++++++++++++
   5 files changed, 157 insertions(+), 46 deletions(-)

Modified: trunk/boost/spirit/home/karma/numeric/detail/numeric_utils.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/numeric/detail/numeric_utils.hpp (original)
+++ trunk/boost/spirit/home/karma/numeric/detail/numeric_utils.hpp 2011-04-17 11:46:28 EDT (Sun, 17 Apr 2011)
@@ -236,6 +236,93 @@
     }
 
     ///////////////////////////////////////////////////////////////////////
+ template <typename T, typename Enable/* = void*/>
+ struct is_nan
+ {
+ static bool call(T n)
+ {
+ // NaN numbers are not equal to anything
+ return (n != n) ? true : false;
+ }
+ };
+
+ template <>
+ struct is_nan<float>
+ {
+ static bool call(float n)
+ {
+ return (math::fpclassify)(n) == FP_NAN;
+ }
+ };
+
+ template <>
+ struct is_nan<double>
+ {
+ static bool call(double n)
+ {
+ return (math::fpclassify)(n) == FP_NAN;
+ }
+ };
+
+ template <>
+ struct is_nan<long double>
+ {
+ static bool call(long double n)
+ {
+ return (math::fpclassify)(n) == FP_NAN;
+ }
+ };
+
+ template <typename T>
+ inline bool test_nan(T n)
+ {
+ return is_nan<T>::call(n);
+ }
+
+ ///////////////////////////////////////////////////////////////////////
+ template <typename T, typename Enable/* = void*/>
+ struct is_infinite
+ {
+ static bool call(T n)
+ {
+ return (n == std::numeric_limits<T>::infinity()) ? true : false;
+ }
+ };
+
+ template <>
+ struct is_infinite<float>
+ {
+ static bool call(float n)
+ {
+ return (math::fpclassify)(n) == FP_INFINITE;
+ }
+ };
+
+ template <>
+ struct is_infinite<double>
+ {
+ static bool call(double n)
+ {
+ return (math::fpclassify)(n) == FP_INFINITE;
+ }
+ };
+
+ template <>
+ struct is_infinite<long double>
+ {
+ static bool call(long double n)
+ {
+ return (math::fpclassify)(n) == FP_INFINITE;
+ }
+ };
+
+ template <typename T>
+ inline bool test_infinite(T n)
+ {
+ return is_infinite<T>::call(n);
+ }
+
+ ///////////////////////////////////////////////////////////////////////
     struct cast_to_long
     {
         static long call(float n, mpl::false_)

Modified: trunk/boost/spirit/home/karma/numeric/detail/real_utils.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/numeric/detail/real_utils.hpp (original)
+++ trunk/boost/spirit/home/karma/numeric/detail/real_utils.hpp 2011-04-17 11:46:28 EDT (Sun, 17 Apr 2011)
@@ -41,63 +41,21 @@
       , typename Tag = unused_type>
     struct real_inserter
     {
- template <typename OutputIterator>
- static bool
- call (OutputIterator& sink, float n, Policies const& p = Policies())
- {
- int fpclass = (math::fpclassify)(n);
- if ((int)FP_NAN == fpclass) {
- return Policies::template nan<CharEncoding, Tag>(
- sink, n, p.force_sign(n));
- }
- else if ((int)FP_INFINITE == fpclass) {
- return Policies::template inf<CharEncoding, Tag>(
- sink, n, p.force_sign(n));
- }
- return p.template call<real_inserter>(sink, n, p);
- }
-
- template <typename OutputIterator>
- static bool
- call (OutputIterator& sink, double n, Policies const& p = Policies())
- {
- int fpclass = (math::fpclassify)(n);
- if ((int)FP_NAN == fpclass) {
- return Policies::template nan<CharEncoding, Tag>(
- sink, n, p.force_sign(n));
- }
- else if ((int)FP_INFINITE == fpclass) {
- return Policies::template inf<CharEncoding, Tag>(
- sink, n, p.force_sign(n));
- }
- return p.template call<real_inserter>(sink, n, p);
- }
-
- template <typename OutputIterator>
+ template <typename OutputIterator, typename U>
         static bool
- call (OutputIterator& sink, long double n, Policies const& p = Policies())
+ call (OutputIterator& sink, U n, Policies const& p = Policies())
         {
- int fpclass = (math::fpclassify)(n);
- if ((int)FP_NAN == fpclass) {
+ if (traits::test_nan(n)) {
                 return Policies::template nan<CharEncoding, Tag>(
                     sink, n, p.force_sign(n));
             }
- else if ((int)FP_INFINITE == fpclass) {
+ else if (traits::test_infinite(n)) {
                 return Policies::template inf<CharEncoding, Tag>(
                     sink, n, p.force_sign(n));
             }
             return p.template call<real_inserter>(sink, n, p);
         }
 
- template <typename OutputIterator, typename U>
- static bool
- call (OutputIterator& sink, U n, Policies const& p = Policies())
- {
- // we have no means of testing whether the number is normalized if
- // the type is not float, double or long double
- return p.template call<real_inserter>(sink, T(n), p);
- }
-
 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
 # pragma warning(push)
 # pragma warning(disable: 4100) // 'p': unreferenced formal parameter

Modified: trunk/boost/spirit/home/support/adapt_adt_attributes.hpp
==============================================================================
--- trunk/boost/spirit/home/support/adapt_adt_attributes.hpp (original)
+++ trunk/boost/spirit/home/support/adapt_adt_attributes.hpp 2011-04-17 11:46:28 EDT (Sun, 17 Apr 2011)
@@ -251,6 +251,7 @@
         }
     };
 
+ ///////////////////////////////////////////////////////////////////////////
     // customization point specializations for numeric generators
     template <typename T, int N, bool Const>
     struct absolute_value<fusion::extension::adt_attribute_proxy<T, N, Const> >
@@ -285,6 +286,26 @@
             return test_zero(val.get());
         }
     };
+
+ template <typename T, int N, bool Const>
+ struct is_nan<fusion::extension::adt_attribute_proxy<T, N, Const> >
+ {
+ static bool
+ call(fusion::extension::adt_attribute_proxy<T, N, Const> const& val)
+ {
+ return test_nan(val.get());
+ }
+ };
+
+ template <typename T, int N, bool Const>
+ struct is_infinite<fusion::extension::adt_attribute_proxy<T, N, Const> >
+ {
+ static bool
+ call(fusion::extension::adt_attribute_proxy<T, N, Const> const& val)
+ {
+ return test_infinite(val.get());
+ }
+ };
 }}}
 
 #endif

Modified: trunk/boost/spirit/home/support/numeric_traits.hpp
==============================================================================
--- trunk/boost/spirit/home/support/numeric_traits.hpp (original)
+++ trunk/boost/spirit/home/support/numeric_traits.hpp 2011-04-17 11:46:28 EDT (Sun, 17 Apr 2011)
@@ -107,6 +107,12 @@
 
     template <typename T, typename Enable = void>
     struct pow10_helper;
+
+ template <typename T, typename Enable = void>
+ struct is_nan;
+
+ template <typename T, typename Enable = void>
+ struct is_infinite;
 }}}
 
 #endif

Modified: trunk/libs/spirit/test/karma/regression_numerics_adapt_adt.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/regression_numerics_adapt_adt.cpp (original)
+++ trunk/libs/spirit/test/karma/regression_numerics_adapt_adt.cpp 2011-04-17 11:46:28 EDT (Sun, 17 Apr 2011)
@@ -68,6 +68,26 @@
 );
 
 ///////////////////////////////////////////////////////////////////////////////
+class data3
+{
+private:
+ double data_;
+
+public:
+ data3(double data = 0.0)
+ : data_(data)
+ {}
+
+ double data() const { return data_;}
+ void set_data(double data) { data_ = data;}
+};
+
+BOOST_FUSION_ADAPT_ADT(
+ data3,
+ (double, double, obj.data(), obj.set_data(val))
+);
+
+///////////////////////////////////////////////////////////////////////////////
 int main ()
 {
     using spirit_test::test;
@@ -89,5 +109,24 @@
         BOOST_TEST(test("data: test\n", "data: " << string << "\n", d));
     }
 
+ {
+ using boost::spirit::karma::double_;
+
+ BOOST_TEST(test("x=0.0\n", "x=" << double_ << "\n", data3(0)));
+ BOOST_TEST(test("x=1.1\n", "x=" << double_ << "\n", data3(1.1)));
+ BOOST_TEST(test("x=1.0e10\n", "x=" << double_ << "\n", data3(1e10)));
+
+ BOOST_TEST(test("x=inf\n", "x=" << double_ << "\n",
+ data3(std::numeric_limits<double>::infinity())));
+ if (std::numeric_limits<double>::has_quiet_NaN) {
+ BOOST_TEST(test("x=nan\n", "x=" << double_ << "\n",
+ data3(std::numeric_limits<double>::quiet_NaN())));
+ }
+ if (std::numeric_limits<double>::has_signaling_NaN) {
+ BOOST_TEST(test("x=nan\n", "x=" << double_ << "\n",
+ data3(std::numeric_limits<double>::signaling_NaN())));
+ }
+ }
+
     return boost::report_errors();
 }


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