$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r77212 - in sandbox/fixed_point: boost/fixed_point libs/fixed_point/example
From: vicente.botet_at_[hidden]
Date: 2012-03-04 07:33:56
Author: viboes
Date: 2012-03-04 07:33:55 EST (Sun, 04 Mar 2012)
New Revision: 77212
URL: http://svn.boost.org/trac/boost/changeset/77212
Log:
FixedPoint: Use integer max type to avoid overflows while rounding
Text files modified: 
   sandbox/fixed_point/boost/fixed_point/number.hpp       |    63 +++++++++++++++++++++++++++++---------- 
   sandbox/fixed_point/libs/fixed_point/example/ex_xx.cpp |    30 +++++++++++++++++++                     
   2 files changed, 77 insertions(+), 16 deletions(-)
Modified: sandbox/fixed_point/boost/fixed_point/number.hpp
==============================================================================
--- sandbox/fixed_point/boost/fixed_point/number.hpp	(original)
+++ sandbox/fixed_point/boost/fixed_point/number.hpp	2012-03-04 07:33:55 EST (Sun, 04 Mar 2012)
@@ -29,6 +29,7 @@
 #include <boost/integer/static_log2.hpp>
 #include <boost/ratio/detail/mpl/abs.hpp>
 #include <limits>
+#include <boost/integer_traits.hpp>
 
 #include <boost/config.hpp>
 //#include <boost/fixed_point/config.hpp>
@@ -75,6 +76,19 @@
       typename shift_impl<UT,Bits,P>::result_type shift(UT v) {
         return shift_impl<UT,Bits,P>::apply(v);
       }
+      template <bool IsSigned>
+      struct max_type;
+      template <>
+      struct max_type<true>
+      {
+        typedef boost::intmax_t type;
+      };
+      template <>
+      struct max_type<false>
+      {
+        typedef boost::uintmax_t type;
+      };
+
     }
 
     struct positive_overflow {};
@@ -90,9 +104,15 @@
         template <typename From, typename To>
         static typename To::underlying_type round(From const& rhs)
         {
-          BOOST_STATIC_CONSTEXPR typename To::underlying_type d = To::resolution_exp-From::resolution_exp;
-
-          return typename To::underlying_type(rhs.count()) >> d;
+          BOOST_STATIC_CONSTEXPR boost::uintmax_t d = To::resolution_exp-From::resolution_exp;
+          typedef typename detail::max_type<is_signed<typename To::underlying_type>::value>::type tmp_type;
+          BOOST_STATIC_ASSERT(d<(8*sizeof(tmp_type)));
+          //BOOST_MPL_ASSERT_MSG(d<(8*sizeof(tmp_type)), OVERFLOW, (mpl::int_<8*sizeof(tmp_type)>, mpl::int_<d>));
+
+          tmp_type res = tmp_type(rhs.count()) >> d;
+          BOOST_ASSERT(res<=To::max_index);
+          BOOST_ASSERT(res>=To::min_index);
+          return res;
         }
         template <typename To, typename From>
         static typename To::underlying_type round_divide(From const& lhs, From const& rhs)
@@ -116,11 +136,18 @@
         template <typename From, typename To>
         static typename To::underlying_type round(From const& rhs)
         {
-          BOOST_STATIC_CONSTEXPR typename To::underlying_type d = To::resolution_exp-From::resolution_exp;
+          BOOST_STATIC_CONSTEXPR boost::uintmax_t d = To::resolution_exp-From::resolution_exp;
+          typedef typename detail::max_type<is_signed<typename To::underlying_type>::value>::type tmp_type;
+          BOOST_STATIC_ASSERT(d<(8*sizeof(tmp_type)));
+
           typename To::underlying_type m(((rhs.count()>0)?rhs.count():-rhs.count()));
           typename To::underlying_type s(((rhs.count()>0)?+1:-1));
 
-          return s * (m >> d);
+          tmp_type res = s * (m >> d);
+          BOOST_ASSERT(res<=To::max_index);
+          BOOST_ASSERT(res>=To::min_index);
+          return res;
+          ;
         }
         template <typename To, typename From>
         static typename To::underlying_type round_divide(From const& lhs, From const& rhs)
@@ -135,11 +162,19 @@
         template <typename From, typename To>
         static typename To::underlying_type round(From const& rhs)
         {
-          BOOST_STATIC_CONSTEXPR typename To::underlying_type d = To::resolution_exp-From::resolution_exp;
-          typename To::underlying_type w = (1<<d)-1;
-          typename To::underlying_type i = rhs.count();
-
-          return (i+w) >> d;
+          BOOST_STATIC_CONSTEXPR boost::uintmax_t d = To::resolution_exp-From::resolution_exp;
+          typedef typename detail::max_type<is_signed<typename To::underlying_type>::value>::type tmp_type;
+          BOOST_STATIC_ASSERT(d<(8*sizeof(tmp_type)));
+
+          BOOST_STATIC_CONSTEXPR tmp_type w = (1<<d)-1;
+          tmp_type i = rhs.count();
+
+          BOOST_ASSERT(i<=(integer_traits<tmp_type>::const_max-w));
+
+          tmp_type res =  (i+w) >> d;
+          BOOST_ASSERT(res<=To::max_index);
+          BOOST_ASSERT(res>=To::min_index);
+          return res;
         }
         template <typename To, typename From>
         static typename To::underlying_type round_divide(From const& lhs, From const& rhs)
@@ -899,13 +934,10 @@
 
         BOOST_CONSTEXPR To operator()(const From& rhs) const
         {
-          std::cout << __FILE__ << "[" <<__LINE__<<"] "<< int(rhs.count()) <<std::endl;
           // Overflow
           underlying_type indx(((rhs.count()) >> (P2-P1)));
-          std::cout << __FILE__ << "[" <<__LINE__<<"] "<< int(indx) <<std::endl;
           if (rhs.count() > (typename From::underlying_type(To::max_index)<<(P2-P1)))
           {
-            std::cout << __FILE__ << "[" <<__LINE__<<"] "<< int(typename From::underlying_type(To::max_index)<<(P2-P1)) <<std::endl;
             return To(index(OP2::template on_positive_overflow<To,underlying_type>(indx)));
           }
           if (rhs.count() < (typename From::underlying_type(To::min_index)<<(P2-P1)))
@@ -1457,7 +1489,7 @@
         else
         {
           signed_number tmp=
-              divide<signed_number<Range, Resolution, RP, Overflow, Optimization>>(*this,
+              divide<signed_number<Range, Resolution, RP, Overflow, Optimization> >(*this,
               signed_number<-N+1, -N, Rounding, Overflow, Optimization>(index(1)));
           value_ = tmp.count();
         }
@@ -1747,7 +1779,7 @@
         else
         {
           unsigned_number tmp=
-              divide<unsigned_number<Range, Resolution, RP, Overflow, Optimization>>(*this,
+              divide<unsigned_number<Range, Resolution, RP, Overflow, Optimization> >(*this,
               unsigned_number<-N+1, -N, Rounding, Overflow, Optimization>(index(1)));
           value_ = tmp.count();
         }
@@ -2378,7 +2410,6 @@
     template <typename To, typename From>
     To number_cast(From const& f)
     {
-      //std::cout << __FILE__ << "[" <<__LINE__<<"] "<< f.count() <<std::endl;
       return fixed_point::detail::number_cast<From, To>()(f);
     }
   }
Modified: sandbox/fixed_point/libs/fixed_point/example/ex_xx.cpp
==============================================================================
--- sandbox/fixed_point/libs/fixed_point/example/ex_xx.cpp	(original)
+++ sandbox/fixed_point/libs/fixed_point/example/ex_xx.cpp	2012-03-04 07:33:55 EST (Sun, 04 Mar 2012)
@@ -60,18 +60,41 @@
     BOOST_TEST(n.count()==1);
   }
   {
+    unsigned_number<1,-32> n1((index(1)));
+    unsigned_number<64,31,round::negative> n2(n1);
+    std::cout << int(n2.count()) << std::endl;
+    BOOST_TEST(n2.count()==0);
+  }
+  {
+    std::cout << __FILE__ << "[" <<__LINE__<<"]"<<std::endl;
+    unsigned_number<8,0> n1((index(255)));
+    unsigned_number<8,0,round::negative> n2(n1);
+    BOOST_TEST(n2.count()==255);
+  }
+  {
+    std::cout << __FILE__ << "[" <<__LINE__<<"]"<<std::endl;
+    signed_number<9,-1> n1((index(-254)));
+    std::cout << __FILE__ << "[" <<__LINE__<<"]"<<std::endl;
+    signed_number<7,0,round::negative> n2(n1);
+    std::cout << __FILE__ << "[" <<__LINE__<<"]"<<std::endl;
+    BOOST_TEST(n2.count()==-127);
+  }
+  {
+    std::cout << __FILE__ << "[" <<__LINE__<<"]"<<std::endl;
     unsigned_number<2,-2> n1((index(1)));
     unsigned_number<2,-2,round::negative> n2(n1);
     BOOST_TEST(n1.count()==1);
     BOOST_TEST(n2.count()==1);
   }
   {
+    std::cout << __FILE__ << "[" <<__LINE__<<"]"<<std::endl;
     signed_number<2,-2> n1((index(1)));
     signed_number<2,-2,round::negative> n2(n1);
     BOOST_TEST(n1.count()==1);
     BOOST_TEST(n2.count()==1);
   }
   {
+    std::cout << __FILE__ << "[" <<__LINE__<<"]"<<std::endl;
     signed_number<2,-2> n1((index(1)));
     signed_number<2,-2,round::negative> n2;
     n2=n1;
@@ -170,6 +193,7 @@
     BOOST_TEST(n2.count()==1);
   }
   {
+    std::cout << __FILE__ << "[" <<__LINE__<<"]"<<std::endl;
     signed_number<2,-3> n1((index(-1)));
     signed_number<2,-2,round::negative> n2(n1);
     BOOST_TEST(n1.count()==-1);
@@ -177,14 +201,20 @@
     BOOST_TEST(n2.count()==-1);
   }
   {
+    std::cout << __FILE__ << "[" <<__LINE__<<"]"<<std::endl;
     signed_number<2,-3> n1((index(-1)));
+    std::cout << __FILE__ << "[" <<__LINE__<<"]"<<std::endl;
     signed_number<2,-2,round::positive> n2(n1);
+    std::cout << __FILE__ << "[" <<__LINE__<<"]"<<std::endl;
     std::cout << int(n2.count()) << std::endl;
     BOOST_TEST(n2.count()==0);
   }
   {
+    std::cout << __FILE__ << "[" <<__LINE__<<"]"<<std::endl;
     signed_number<2,-3> n1((index(-1)));
+    std::cout << __FILE__ << "[" <<__LINE__<<"]"<<std::endl;
     signed_number<2,-2,round::truncated> n2(n1);
+    std::cout << __FILE__ << "[" <<__LINE__<<"]"<<std::endl;
     std::cout << int(n2.count()) << std::endl;
     BOOST_TEST(n2.count()==0);
   }