$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
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();
 }