$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r81151 - in sandbox/big_number: boost/multiprecision boost/multiprecision/detail libs/multiprecision/test
From: john_at_[hidden]
Date: 2012-11-02 15:13:51
Author: johnmaddock
Date: 2012-11-02 15:13:50 EDT (Fri, 02 Nov 2012)
New Revision: 81151
URL: http://svn.boost.org/trac/boost/changeset/81151
Log:
Add non-member functions for mixed precision arithmetic + tests for same.
Fix a couple of bugs discovered along the way.
Added:
   sandbox/big_number/libs/multiprecision/test/test_mixed_cpp_int.cpp   (contents, props changed)
   sandbox/big_number/libs/multiprecision/test/test_mixed_float.cpp   (contents, props changed)
Text files modified: 
   sandbox/big_number/boost/multiprecision/cpp_dec_float.hpp      |     6 ++-                                     
   sandbox/big_number/boost/multiprecision/cpp_int.hpp            |     4 +-                                      
   sandbox/big_number/boost/multiprecision/detail/default_ops.hpp |    74 ++++++++++++++++++++++++++++++++++++--- 
   sandbox/big_number/libs/multiprecision/test/Jamfile.v2         |    11 +++++                                   
   4 files changed, 83 insertions(+), 12 deletions(-)
Modified: sandbox/big_number/boost/multiprecision/cpp_dec_float.hpp
==============================================================================
--- sandbox/big_number/boost/multiprecision/cpp_dec_float.hpp	(original)
+++ sandbox/big_number/boost/multiprecision/cpp_dec_float.hpp	2012-11-02 15:13:50 EDT (Fri, 02 Nov 2012)
@@ -376,8 +376,10 @@
       exp = f.exp;
       neg = f.neg;
       fpclass = static_cast<enum_fpclass_type>(static_cast<int>(f.fpclass));
-      std::copy(f.data.begin(), f.data.begin() + (std::min)(f.prec_elem, prec_elem), data.begin());
-      precision((std::min)(f.prec_elem, prec_elem));
+      unsigned elems = (std::min)(f.prec_elem, cpp_dec_float_elem_number);
+      std::copy(f.data.begin(), f.data.begin() + elems, data.begin());
+      std::fill(data.begin() + elems, data.end(), 0);
+      prec_elem = cpp_dec_float_elem_number;
       return *this;
    }
    cpp_dec_float& operator= (long long v) BOOST_NOEXCEPT
Modified: sandbox/big_number/boost/multiprecision/cpp_int.hpp
==============================================================================
--- sandbox/big_number/boost/multiprecision/cpp_int.hpp	(original)
+++ sandbox/big_number/boost/multiprecision/cpp_int.hpp	2012-11-02 15:13:50 EDT (Fri, 02 Nov 2012)
@@ -690,7 +690,7 @@
          BOOST_THROW_EXCEPTION(std::range_error("The argument to a cpp_int constructor exceeded the largest value it can represent."));
    }
    template <class T, int C>
-   void check_in_range(T val, const mpl::int_<C>&){}
+   void check_in_range(T, const mpl::int_<C>&){}
 
    template <class T>
    void check_in_range(T val)
@@ -817,7 +817,7 @@
          BOOST_THROW_EXCEPTION(std::range_error("The argument to an unsigned cpp_int constructor was negative."));
    }
    template <class T, int C, bool B>
-   BOOST_FORCEINLINE void check_in_range(T val, const mpl::int_<C>&, const mpl::bool_<B>&){}
+   BOOST_FORCEINLINE void check_in_range(T, const mpl::int_<C>&, const mpl::bool_<B>&){}
 
    template <class T>
    BOOST_FORCEINLINE void check_in_range(T val)
Modified: sandbox/big_number/boost/multiprecision/detail/default_ops.hpp
==============================================================================
--- sandbox/big_number/boost/multiprecision/detail/default_ops.hpp	(original)
+++ sandbox/big_number/boost/multiprecision/detail/default_ops.hpp	2012-11-02 15:13:50 EDT (Fri, 02 Nov 2012)
@@ -253,7 +253,7 @@
 inline void eval_add_default(T& t, const U& u, const V& v)
 {
    t = u;
-   eval_add(t, u);
+   eval_add(t, v);
 }
 template <class T, class U, class V>
 inline void eval_add(T& t, const U& u, const V& v)
@@ -358,7 +358,7 @@
 inline void eval_multiply_default(T& t, const U& u, const V& v)
 {
    t = u;
-   eval_multiply(t, u);
+   eval_multiply(t, v);
 }
 template <class T, class U, class V>
 inline void eval_multiply(T& t, const U& u, const V& v)
@@ -457,7 +457,7 @@
 inline void eval_divide_default(T& t, const U& u, const V& v)
 {
    t = u;
-   eval_divide(t, u);
+   eval_divide(t, v);
 }
 template <class T, class U, class V>
 inline void eval_divide(T& t, const U& u, const V& v)
@@ -515,7 +515,7 @@
 inline void eval_modulus_default(T& t, const U& u, const V& v)
 {
    t = u;
-   eval_modulus(t, u);
+   eval_modulus(t, v);
 }
 template <class T, class U, class V>
 inline void eval_modulus(T& t, const U& u, const V& v)
@@ -565,7 +565,7 @@
 inline void eval_bitwise_and_default(T& t, const U& u, const V& v)
 {
    t = u;
-   eval_bitwise_and(t, u);
+   eval_bitwise_and(t, v);
 }
 template <class T, class U, class V>
 inline void eval_bitwise_and(T& t, const U& u, const V& v)
@@ -615,7 +615,7 @@
 inline void eval_bitwise_or_default(T& t, const U& u, const V& v)
 {
    t = u;
-   eval_bitwise_or(t, u);
+   eval_bitwise_or(t, v);
 }
 template <class T, class U, class V>
 inline void eval_bitwise_or(T& t, const U& u, const V& v)
@@ -665,7 +665,7 @@
 inline void eval_bitwise_xor_default(T& t, const U& u, const V& v)
 {
    t = u;
-   eval_bitwise_xor(t, u);
+   eval_bitwise_xor(t, v);
 }
 template <class T, class U, class V>
 inline void eval_bitwise_xor(T& t, const U& u, const V& v)
@@ -1108,6 +1108,66 @@
 } // namespace math
 namespace multiprecision{
 
+template <class B1, class B2, class B3, expression_template_option ET1, expression_template_option ET2, expression_template_option ET3>
+inline number<B1, ET1>& add(number<B1, ET1>& result, const number<B2, ET2>& a, const number<B3, ET3>& b)
+{
+   BOOST_STATIC_ASSERT_MSG((is_convertible<B2, B1>::value), "No conversion to the target of a mixed precision addition exists");
+   BOOST_STATIC_ASSERT_MSG((is_convertible<B3, B1>::value), "No conversion to the target of a mixed precision addition exists");
+   using default_ops::eval_add;
+   eval_add(result.backend(), a.backend(), b.backend());
+   return result;
+}
+
+template <class B1, class B2, class B3, expression_template_option ET1, expression_template_option ET2, expression_template_option ET3>
+inline number<B1, ET1>& subtract(number<B1, ET1>& result, const number<B2, ET2>& a, const number<B3, ET3>& b)
+{
+   BOOST_STATIC_ASSERT_MSG((is_convertible<B2, B1>::value), "No conversion to the target of a mixed precision addition exists");
+   BOOST_STATIC_ASSERT_MSG((is_convertible<B3, B1>::value), "No conversion to the target of a mixed precision addition exists");
+   using default_ops::eval_subtract;
+   eval_subtract(result.backend(), a.backend(), b.backend());
+   return result;
+}
+
+template <class B1, class B2, class B3, expression_template_option ET1, expression_template_option ET2, expression_template_option ET3>
+inline number<B1, ET1>& multiply(number<B1, ET1>& result, const number<B2, ET2>& a, const number<B3, ET3>& b)
+{
+   BOOST_STATIC_ASSERT_MSG((is_convertible<B2, B1>::value), "No conversion to the target of a mixed precision addition exists");
+   BOOST_STATIC_ASSERT_MSG((is_convertible<B3, B1>::value), "No conversion to the target of a mixed precision addition exists");
+   using default_ops::eval_multiply;
+   eval_multiply(result.backend(), a.backend(), b.backend());
+   return result;
+}
+
+template <class B, expression_template_option ET, class I>
+inline typename enable_if_c<is_integral<I>::value, number<B, ET>&>::type 
+   add(number<B, ET>& result, const I& a, const I& b)
+{
+   using default_ops::eval_add;
+   typedef typename detail::canonical<I, B>::type canonical_type;
+   eval_add(result.backend(), static_cast<canonical_type>(a), static_cast<canonical_type>(b));
+   return result;
+}
+
+template <class B, expression_template_option ET, class I>
+inline typename enable_if_c<is_integral<I>::value, number<B, ET>&>::type 
+   subtract(number<B, ET>& result, const I& a, const I& b)
+{
+   using default_ops::eval_subtract;
+   typedef typename detail::canonical<I, B>::type canonical_type;
+   eval_subtract(result.backend(), static_cast<canonical_type>(a), static_cast<canonical_type>(b));
+   return result;
+}
+
+template <class B, expression_template_option ET, class I>
+inline typename enable_if_c<is_integral<I>::value, number<B, ET>&>::type 
+   multiply(number<B, ET>& result, const I& a, const I& b)
+{
+   using default_ops::eval_multiply;
+   typedef typename detail::canonical<I, B>::type canonical_type;
+   eval_multiply(result.backend(), static_cast<canonical_type>(a), static_cast<canonical_type>(b));
+   return result;
+}
+
 template <class tag, class A1, class A2, class A3, class A4, class Policy>
 inline typename detail::expression<tag, A1, A2, A3, A4>::result_type trunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
 {
Modified: sandbox/big_number/libs/multiprecision/test/Jamfile.v2
==============================================================================
--- sandbox/big_number/libs/multiprecision/test/Jamfile.v2	(original)
+++ sandbox/big_number/libs/multiprecision/test/Jamfile.v2	2012-11-02 15:13:50 EDT (Fri, 02 Nov 2012)
@@ -820,7 +820,16 @@
         : # requirements
          [ check-target-builds ../config//has_tommath : : <build>no ] ;
 run ../example/floating_point_examples.cpp : : : <toolset>gcc:<cxxflags>-std=c++0x ;
-run test_cpp_int_conv.cpp ;
+run test_cpp_int_conv.cpp;
+
+run test_mixed_cpp_int.cpp ;
+run test_mixed_float.cpp
+        : # command line
+        : # input files
+        : # requirements
+         [ check-target-builds ../config//has_gmp : <define>TEST_GMP <library>gmp : ]
+         [ check-target-builds ../config//has_mpfr : <define>TEST_MPFR <library>mpfr <library>gmp : ] ;
+
 
 compile include_test/mpfr_include_test.cpp
               : # requirements
Added: sandbox/big_number/libs/multiprecision/test/test_mixed_cpp_int.cpp
==============================================================================
--- (empty file)
+++ sandbox/big_number/libs/multiprecision/test/test_mixed_cpp_int.cpp	2012-11-02 15:13:50 EDT (Fri, 02 Nov 2012)
@@ -0,0 +1,85 @@
+///////////////////////////////////////////////////////////////
+//  Copyright 2012 John Maddock. Distributed under the Boost
+//  Software License, Version 1.0. (See accompanying file
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
+
+//
+// Compare arithmetic results using fixed_int to GMP results.
+//
+
+#ifdef _MSC_VER
+#  define _SCL_SECURE_NO_WARNINGS
+#endif
+
+#include <boost/multiprecision/cpp_int.hpp>
+#include "test.hpp"
+
+template <class Number, class BigNumber>
+void test()
+{
+   using namespace boost::multiprecision;
+   typedef Number test_type;
+
+   test_type h = (std::numeric_limits<test_type>::max)();
+   test_type l = (std::numeric_limits<test_type>::max)();
+   BigNumber r;
+
+   add(r, h, h);
+   BOOST_CHECK_EQUAL(r, cpp_int(h) + cpp_int(h));
+
+   multiply(r, h, h);
+   BOOST_CHECK_EQUAL(r, cpp_int(h) * cpp_int(h));
+
+   if(std::numeric_limits<test_type>::is_signed)
+   {
+      subtract(r, l, h);
+      BOOST_CHECK_EQUAL(r, cpp_int(l) - cpp_int(h));
+      subtract(r, h, l);
+      BOOST_CHECK_EQUAL(r, cpp_int(h) - cpp_int(l));
+      multiply(r, l, l);
+      BOOST_CHECK_EQUAL(r, cpp_int(l) * cpp_int(l));
+   }
+
+   //
+   // Try again with integer types as the source:
+   //
+   static const unsigned max_digits = std::numeric_limits<test_type>::is_signed ? std::numeric_limits<long long>::digits : std::numeric_limits<unsigned long long>::digits;
+   static const unsigned require_digits = std::numeric_limits<test_type>::digits <= 2 * max_digits ? std::numeric_limits<test_type>::digits / 2 : max_digits;
+   typedef typename boost::mpl::if_c<std::numeric_limits<test_type>::is_signed, typename boost::int_t<require_digits>::least, typename boost::uint_t<require_digits>::least>::type i_type;
+
+   i_type ih = (std::numeric_limits<i_type>::max)();
+   i_type il = (std::numeric_limits<i_type>::max)();
+
+   add(r, ih, ih);
+   BOOST_CHECK_EQUAL(r, cpp_int(ih) + cpp_int(ih));
+
+   multiply(r, ih, ih);
+   BOOST_CHECK_EQUAL(r, cpp_int(ih) * cpp_int(ih));
+
+   if(std::numeric_limits<test_type>::is_signed)
+   {
+      subtract(r, il, ih);
+      BOOST_CHECK_EQUAL(r, cpp_int(il) - cpp_int(ih));
+      subtract(r, ih, il);
+      BOOST_CHECK_EQUAL(r, cpp_int(ih) - cpp_int(il));
+      multiply(r, il, il);
+      BOOST_CHECK_EQUAL(r, cpp_int(il) * cpp_int(il));
+   }
+}
+
+int main()
+{
+   using namespace boost::multiprecision;
+
+   test<checked_int512_t, checked_int1024_t>();
+   test<checked_int256_t, checked_int512_t>();
+   test<number<cpp_int_backend<64, 64, signed_magnitude, checked, void>, et_off>, checked_int512_t>();
+
+   test<checked_uint512_t, checked_uint1024_t>();
+   test<checked_uint256_t, checked_uint512_t>();
+   test<number<cpp_int_backend<64, 64, unsigned_magnitude, checked, void>, et_off>, checked_uint512_t>();
+   return boost::report_errors();
+}
+
+
+
Added: sandbox/big_number/libs/multiprecision/test/test_mixed_float.cpp
==============================================================================
--- (empty file)
+++ sandbox/big_number/libs/multiprecision/test/test_mixed_float.cpp	2012-11-02 15:13:50 EDT (Fri, 02 Nov 2012)
@@ -0,0 +1,57 @@
+///////////////////////////////////////////////////////////////
+//  Copyright 2012 John Maddock. Distributed under the Boost
+//  Software License, Version 1.0. (See accompanying file
+//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
+
+//
+// Compare arithmetic results using fixed_int to GMP results.
+//
+
+#ifdef _MSC_VER
+#  define _SCL_SECURE_NO_WARNINGS
+#endif
+
+#ifdef TEST_GMP
+#include <boost/multiprecision/gmp.hpp>
+#endif
+#ifdef TEST_MPFR
+#include <boost/multiprecision/mpfr.hpp>
+#endif
+#include <boost/multiprecision/cpp_dec_float.hpp>
+#include "test.hpp"
+
+template <class Number, class BigNumber>
+void test()
+{
+   using namespace boost::multiprecision;
+   typedef Number test_type;
+
+   test_type a = 1;
+   a /= 3;
+   test_type b = -a;
+
+   BigNumber r;
+   BOOST_CHECK_EQUAL(add(r, a, a), BigNumber(a) + BigNumber(a));
+   BOOST_CHECK_EQUAL(subtract(r, a, b), BigNumber(a) - BigNumber(b));
+   BOOST_CHECK_EQUAL(subtract(r, b, a), BigNumber(b) - BigNumber(a));
+   BOOST_CHECK_EQUAL(multiply(r, a, a), BigNumber(a) * BigNumber(a));
+}
+
+int main()
+{
+   using namespace boost::multiprecision;
+
+   test<cpp_dec_float_50, cpp_dec_float_100>();
+
+#ifdef TEST_GMP
+   test<mpf_float_50, mpf_float_100>();
+#endif
+#ifdef TEST_MPFR
+   test<mpfr_float_50, mpfr_float_100>();
+#endif
+
+   return boost::report_errors();
+}
+
+
+