Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r76706 - in sandbox/big_number: boost/multiprecision boost/multiprecision/detail boost/multiprecision/detail/functions libs/multiprecision/performance libs/multiprecision/test
From: john_at_[hidden]
Date: 2012-01-26 05:11:14


Author: johnmaddock
Date: 2012-01-26 05:11:10 EST (Thu, 26 Jan 2012)
New Revision: 76706
URL: http://svn.boost.org/trac/boost/changeset/76706

Log:
Fix bug in fixed_int::convert_to with negative numbers.
Fix bug in fixed_int shift operator when shifting by 0.
Add preliminary gcd/lcm support for integer types.
Add static asserts to floating-point only functions.
Text files modified:
   sandbox/big_number/boost/multiprecision/detail/default_ops.hpp | 91 ++++++++++++++++++++++++
   sandbox/big_number/boost/multiprecision/detail/functions/pow.hpp | 8 ++
   sandbox/big_number/boost/multiprecision/detail/functions/trig.hpp | 8 ++
   sandbox/big_number/boost/multiprecision/fixed_int.hpp | 146 +++++++++++++++++++++++++++++++++++++++
   sandbox/big_number/boost/multiprecision/gmp.hpp | 25 ++++++
   sandbox/big_number/boost/multiprecision/tommath.hpp | 8 ++
   sandbox/big_number/libs/multiprecision/performance/performance_test.cpp | 15 +++
   sandbox/big_number/libs/multiprecision/test/test_arithmetic.cpp | 22 ++++++
   sandbox/big_number/libs/multiprecision/test/test_fixed_int.cpp | 3
   9 files changed, 324 insertions(+), 2 deletions(-)

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-01-26 05:11:10 EST (Thu, 26 Jan 2012)
@@ -405,6 +405,7 @@
 template <class T>
 void eval_fabs(T& result, const T& arg)
 {
+ BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_floating_point, "The fabs function is only valid for floating point types.");
    typedef typename T::signed_types type_list;
    typedef typename mpl::front<type_list>::type front;
    result = arg;
@@ -415,12 +416,14 @@
 template <class Backend>
 inline int eval_fpclassify(const Backend& arg)
 {
+ BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_floating_point, "The fpclassify function is only valid for floating point types.");
    return is_zero(arg) ? FP_ZERO : FP_NORMAL;
 }
 
 template <class T>
 inline void eval_fmod(T& result, const T& a, const T& b)
 {
+ BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_floating_point, "The fmod function is only valid for floating point types.");
    if((&result == &a) || (&result == &b))
    {
       T temp;
@@ -440,6 +443,7 @@
 template <class T>
 inline void eval_trunc(T& result, const T& a)
 {
+ BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_floating_point, "The trunc function is only valid for floating point types.");
    int c = eval_fpclassify(a);
    if(c == FP_NAN || c == FP_INFINITE)
    {
@@ -455,6 +459,7 @@
 template <class T>
 inline void eval_round(T& result, const T& a)
 {
+ BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_floating_point, "The round function is only valid for floating point types.");
    typedef typename boost::multiprecision::detail::canonical<float, T>::type fp_type;
    int c = eval_fpclassify(a);
    if(c == FP_NAN || c == FP_INFINITE)
@@ -474,6 +479,33 @@
    }
 }
 
+template <class T, class Arithmetic>
+inline typename enable_if<is_integral<Arithmetic> >::type eval_gcd(T& result, const T& a, const Arithmetic& b)
+{
+ typedef typename boost::multiprecision::detail::canonical<Arithmetic, T>::type si_type;
+ T t;
+ t = static_cast<si_type>(b);
+ eval_gcd(result, a, t);
+}
+template <class T, class Arithmetic>
+inline typename enable_if<is_integral<Arithmetic> >::type eval_gcd(T& result, const Arithmetic& a, const T& b)
+{
+ eval_gcd(result, b, a);
+}
+template <class T, class Arithmetic>
+inline typename enable_if<is_integral<Arithmetic> >::type eval_lcm(T& result, const T& a, const Arithmetic& b)
+{
+ typedef typename boost::multiprecision::detail::canonical<Arithmetic, T>::type si_type;
+ T t;
+ t = static_cast<si_type>(b);
+ eval_lcm(result, a, t);
+}
+template <class T, class Arithmetic>
+inline typename enable_if<is_integral<Arithmetic> >::type eval_lcm(T& result, const Arithmetic& a, const T& b)
+{
+ eval_lcm(result, b, a);
+}
+
 //
 // These have to implemented by the backend, declared here so that our macro generated code compiles OK.
 //
@@ -831,6 +863,12 @@
       using default_ops:: BOOST_JOIN(eval_,func);\
       BOOST_JOIN(eval_,func)(result, arg, a);\
    }\
+ template <class Arithmetic> \
+ void operator()(Backend& result, const Arithmetic& arg, const Backend& a)const\
+ {\
+ using default_ops:: BOOST_JOIN(eval_,func);\
+ BOOST_JOIN(eval_,func)(result, arg, a);\
+ }\
 };\
 \
 }\
@@ -960,6 +998,52 @@
       a\
     );\
 }\
+template <class Backend, class Arithmetic> \
+typename enable_if<\
+ is_arithmetic<Arithmetic>,\
+ detail::mp_exp<\
+ detail::function\
+ , detail::BOOST_JOIN(func, _funct)<Backend> \
+ , Arithmetic \
+ , mp_number<Backend>\
+ > \
+>::type \
+func(const Arithmetic& arg, const mp_number<Backend>& a)\
+{\
+ return detail::mp_exp<\
+ detail::function\
+ , detail::BOOST_JOIN(func, _funct)<Backend> \
+ , Arithmetic \
+ , mp_number<Backend>\
+ >(\
+ detail::BOOST_JOIN(func, _funct)<Backend>() \
+ , arg,\
+ a\
+ );\
+}\
+template <class tag, class A1, class A2, class A3, class Arithmetic> \
+typename enable_if<\
+ is_arithmetic<Arithmetic>,\
+ detail::mp_exp<\
+ detail::function\
+ , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::mp_exp<tag, A1, A2, A3> >::type> \
+ , Arithmetic \
+ , detail::mp_exp<tag, A1, A2, A3>\
+ > \
+>::type \
+func(const Arithmetic& arg, const detail::mp_exp<tag, A1, A2, A3>& a)\
+{\
+ return detail::mp_exp<\
+ detail::function\
+ , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::mp_exp<tag, A1, A2, A3> >::type> \
+ , Arithmetic \
+ , detail::mp_exp<tag, A1, A2, A3>\
+ >(\
+ detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::mp_exp<tag, A1, A2, A3> >::type>() \
+ , arg,\
+ a\
+ );\
+}\
 
 
 #define HETERO_BINARY_OP_FUNCTOR(func, Arg2)\
@@ -1042,6 +1126,13 @@
 BINARY_OP_FUNCTOR(fmod)
 BINARY_OP_FUNCTOR(atan2)
 
+//
+// Integer functions:
+//
+BINARY_OP_FUNCTOR(gcd)
+BINARY_OP_FUNCTOR(lcm)
+
+
 #undef BINARY_OP_FUNCTOR
 #undef UNARY_OP_FUNCTOR
 

Modified: sandbox/big_number/boost/multiprecision/detail/functions/pow.hpp
==============================================================================
--- sandbox/big_number/boost/multiprecision/detail/functions/pow.hpp (original)
+++ sandbox/big_number/boost/multiprecision/detail/functions/pow.hpp 2012-01-26 05:11:10 EST (Thu, 26 Jan 2012)
@@ -86,6 +86,7 @@
 template<typename T, typename U>
 inline void eval_pow(T& result, const T& t, const U& p)
 {
+ BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_floating_point, "The pow function is only valid for floating point types.");
    typedef typename is_integral<U>::type tag_type;
    detail::pow_imp(result, t, p, tag_type());
 }
@@ -184,6 +185,7 @@
 template <class T>
 void eval_exp(T& result, const T& x)
 {
+ BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_floating_point, "The ldexp function is only valid for floating point types.");
    if(&x == &result)
    {
       T temp;
@@ -323,6 +325,7 @@
 template <class T>
 void eval_log(T& result, const T& arg)
 {
+ BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_floating_point, "The log function is only valid for floating point types.");
    //
    // We use a variation of http://dlmf.nist.gov/4.45#i
    // using frexp to reduce the argument to x * 2^n,
@@ -410,6 +413,7 @@
 template <class T>
 void eval_log10(T& result, const T& arg)
 {
+ BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_floating_point, "The fabs function is only valid for floating point types.");
    eval_log(result, arg);
    divide(result, get_constant_log10<T>());
 }
@@ -417,6 +421,7 @@
 template<typename T>
 inline void eval_pow(T& result, const T& x, const T& a)
 {
+ BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_floating_point, "The pow function is only valid for floating point types.");
    typedef typename boost::multiprecision::detail::canonical<int, T>::type si_type;
    typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
    typedef typename T::exponent_type exp_type;
@@ -636,18 +641,21 @@
 template <class T>
 inline void eval_sinh(T& result, const T& x)
 {
+ BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_floating_point, "The sinh function is only valid for floating point types.");
    detail::sinhcosh(x, &result, static_cast<T*>(0));
 }
 
 template <class T>
 inline void eval_cosh(T& result, const T& x)
 {
+ BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_floating_point, "The cosh function is only valid for floating point types.");
    detail::sinhcosh(x, static_cast<T*>(0), &result);
 }
 
 template <class T>
 inline void eval_tanh(T& result, const T& x)
 {
+ BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_floating_point, "The tanh function is only valid for floating point types.");
   T c;
   detail::sinhcosh(x, &result, &c);
   divide(result, c);

Modified: sandbox/big_number/boost/multiprecision/detail/functions/trig.hpp
==============================================================================
--- sandbox/big_number/boost/multiprecision/detail/functions/trig.hpp (original)
+++ sandbox/big_number/boost/multiprecision/detail/functions/trig.hpp 2012-01-26 05:11:10 EST (Thu, 26 Jan 2012)
@@ -68,6 +68,7 @@
 template <class T>
 void eval_sin(T& result, const T& x)
 {
+ BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_floating_point, "The sin function is only valid for floating point types.");
    if(&result == &x)
    {
       T temp;
@@ -213,6 +214,7 @@
 template <class T>
 void eval_cos(T& result, const T& x)
 {
+ BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_floating_point, "The cos function is only valid for floating point types.");
    if(&result == &x)
    {
       T temp;
@@ -355,6 +357,7 @@
 template <class T>
 void eval_tan(T& result, const T& x)
 {
+ BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_floating_point, "The tan function is only valid for floating point types.");
    T t;
    eval_sin(result, x);
    eval_cos(t, x);
@@ -426,6 +429,7 @@
 template <class T>
 void eval_asin(T& result, const T& x)
 {
+ BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_floating_point, "The asin function is only valid for floating point types.");
    typedef typename boost::multiprecision::detail::canonical<boost::int32_t, T>::type si_type;
    typedef typename boost::multiprecision::detail::canonical<boost::uint32_t, T>::type ui_type;
    typedef typename T::exponent_type exp_type;
@@ -535,6 +539,7 @@
 template <class T>
 inline void eval_acos(T& result, const T& x)
 {
+ BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_floating_point, "The acos function is only valid for floating point types.");
    typedef typename boost::multiprecision::detail::canonical<boost::uint32_t, T>::type ui_type;
 
    switch(eval_fpclassify(x))
@@ -576,6 +581,7 @@
 template <class T>
 void eval_atan(T& result, const T& x)
 {
+ BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_floating_point, "The atan function is only valid for floating point types.");
    typedef typename boost::multiprecision::detail::canonical<boost::int32_t, T>::type si_type;
    typedef typename boost::multiprecision::detail::canonical<boost::uint32_t, T>::type ui_type;
    typedef typename T::exponent_type exp_type;
@@ -666,6 +672,7 @@
 template <class T>
 void eval_atan2(T& result, const T& y, const T& x)
 {
+ BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_floating_point, "The atan2 function is only valid for floating point types.");
    if(&result == &y)
    {
       T temp(y);
@@ -763,6 +770,7 @@
 template <class T, class Arithmetic>
 typename disable_if<is_same<T, Arithmetic> >::type eval_atan2(T& result, const T& a, const Arithmetic& b)
 {
+ BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_floating_point, "The atan2 function is only valid for floating point types.");
    T x;
    x = static_cast<typename boost::multiprecision::detail::canonical<Arithmetic, T>::type>(b);
    eval_atan2(result, a, x);

Modified: sandbox/big_number/boost/multiprecision/fixed_int.hpp
==============================================================================
--- sandbox/big_number/boost/multiprecision/fixed_int.hpp (original)
+++ sandbox/big_number/boost/multiprecision/fixed_int.hpp 2012-01-26 05:11:10 EST (Thu, 26 Jan 2012)
@@ -1254,6 +1254,8 @@
 template <unsigned Bits, bool Signed>
 inline void left_shift(fixed_int<Bits, Signed>& result, double_limb_type s)
 {
+ if(!s)
+ return;
    if(s >= Bits)
    {
       result = static_cast<limb_type>(0);
@@ -1287,6 +1289,8 @@
 template <unsigned Bits, bool Signed>
 inline void right_shift(fixed_int<Bits, Signed>& result, double_limb_type s)
 {
+ if(!s)
+ return;
    limb_type fill = (Signed && (result.data()[0] & fixed_int<Bits, Signed>::sign_bit_mask)) ? fixed_int<Bits, Signed>::max_limb_value : 0u;
    if(s >= Bits)
    {
@@ -1327,7 +1331,22 @@
 }
 
 template <class R, unsigned Bits, bool Signed>
-inline typename enable_if<is_integral<R>, void>::type convert_to(R* result, const fixed_int<Bits, Signed>& backend)
+inline typename enable_if<is_integral<R>, void>::type convert_to(R* result, const fixed_int<Bits, Signed>& backend, const mpl::true_&)
+{
+ if(backend.data()[0] & fixed_int<Bits, Signed>::sign_bit_mask)
+ {
+ fixed_int<Bits, Signed> t(backend);
+ t.negate();
+ convert_to(result, t, mpl::false_());
+ *result = -*result;
+ return;
+ }
+ else
+ convert_to(result, backend, mpl::false_());
+}
+
+template <class R, unsigned Bits, bool Signed>
+inline typename enable_if<is_integral<R>, void>::type convert_to(R* result, const fixed_int<Bits, Signed>& backend, const mpl::false_&)
 {
    unsigned shift = (fixed_int<Bits, Signed>::limb_count - 1) * fixed_int<Bits, Signed>::limb_bits;
    *result = 0;
@@ -1339,8 +1358,23 @@
 }
 
 template <class R, unsigned Bits, bool Signed>
+inline typename enable_if<is_integral<R>, void>::type convert_to(R* result, const fixed_int<Bits, Signed>& backend)
+{
+ typedef mpl::bool_<Signed && std::numeric_limits<R>::is_signed> tag_type;
+ convert_to(result, backend, tag_type());
+}
+
+template <class R, unsigned Bits, bool Signed>
 inline typename enable_if<is_floating_point<R>, void>::type convert_to(R* result, const fixed_int<Bits, Signed>& backend)
 {
+ if(Signed && (backend.data()[0] & fixed_int<Bits, Signed>::sign_bit_mask))
+ {
+ fixed_int<Bits, Signed> t(backend);
+ t.negate();
+ convert_to(result, t);
+ *result = -*result;
+ return;
+ }
    unsigned shift = (fixed_int<Bits, Signed>::limb_count - 1) * fixed_int<Bits, Signed>::limb_bits;
    *result = 0;
    for(unsigned i = 0; i < fixed_int<Bits, Signed>::limb_count; ++i)
@@ -1371,6 +1405,116 @@
    return is_zero(val) ? 0 : val.data()[0] & fixed_int<Bits, true>::sign_bit_mask ? -1 : 1;
 }
 
+namespace detail{
+//
+// Get the location of the least-significant-bit:
+//
+template <unsigned Bits, bool Signed>
+inline unsigned get_lsb(const fixed_int<Bits, Signed>& a)
+{
+ BOOST_ASSERT(get_sign(a) != 0);
+
+ unsigned result = 0;
+ //
+ // Find the index of the least significant limb that is non-zero:
+ //
+ int index = fixed_int<Bits, Signed>::limb_count - 1;
+ while(!a.data()[index] && index)
+ --index;
+ //
+ // Find the index of the least significant bit within that limb:
+ //
+ limb_type l = a.data()[index];
+ while(!(l & 1u))
+ {
+ l >>= 1;
+ ++result;
+ }
+
+ return result + (fixed_int<Bits, Signed>::limb_count - 1 - index) * fixed_int<Bits, Signed>::limb_bits;
+}
+
+}
+
+template <unsigned Bits, bool Signed>
+inline void eval_gcd(fixed_int<Bits, Signed>& result, const fixed_int<Bits, Signed>& a, const fixed_int<Bits, Signed>& b)
+{
+ int shift;
+
+ fixed_int<Bits, Signed> u(a), v(b);
+
+ int s = get_sign(u);
+
+ /* GCD(0,x) := x */
+ if(s < 0)
+ {
+ u.negate();
+ }
+ else if(s == 0)
+ {
+ result = v;
+ return;
+ }
+ s = get_sign(v);
+ if(s < 0)
+ {
+ v.negate();
+ }
+ else if(s == 0)
+ {
+ result = u;
+ return;
+ }
+
+ /* Let shift := lg K, where K is the greatest power of 2
+ dividing both u and v. */
+
+ unsigned us = detail::get_lsb(u);
+ unsigned vs = detail::get_lsb(v);
+ shift = (std::min)(us, vs);
+ right_shift(u, us);
+ right_shift(v, vs);
+
+ do
+ {
+ /* Now u and v are both odd, so diff(u, v) is even.
+ Let u = min(u, v), v = diff(u, v)/2. */
+ if(u.compare(v) > 0)
+ u.swap(v);
+ subtract(v, u);
+ // Termination condition tries not to do a full compare if possible:
+ if(!v.data()[fixed_int<Bits, Signed>::limb_count - 1] && is_zero(v))
+ break;
+ vs = detail::get_lsb(v);
+ right_shift(v, vs);
+ BOOST_ASSERT((v.data()[fixed_int<Bits, Signed>::limb_count - 1] & 1));
+ BOOST_ASSERT((u.data()[fixed_int<Bits, Signed>::limb_count - 1] & 1));
+ }
+ while(true);
+
+ result = u;
+ left_shift(result, shift);
+}
+
+template <unsigned Bits, bool Signed>
+inline void eval_lcm(fixed_int<Bits, Signed>& result, const fixed_int<Bits, Signed>& a, const fixed_int<Bits, Signed>& b)
+{
+ fixed_int<Bits, Signed> t;
+ eval_gcd(t, a, b);
+
+ if(is_zero(t))
+ {
+ result = 0;
+ }
+ else
+ {
+ divide(result, a, t);
+ multiply(result, b);
+ }
+ if(get_sign(result) < 0)
+ result.negate();
+}
+
 template <unsigned Bits, bool Signed>
 struct number_category<fixed_int<Bits, Signed> > : public mpl::int_<number_kind_integer>{};
 

Modified: sandbox/big_number/boost/multiprecision/gmp.hpp
==============================================================================
--- sandbox/big_number/boost/multiprecision/gmp.hpp (original)
+++ sandbox/big_number/boost/multiprecision/gmp.hpp 2012-01-26 05:11:10 EST (Thu, 26 Jan 2012)
@@ -1392,6 +1392,31 @@
    mpz_abs(result.data(), val.data());
 }
 
+inline void eval_gcd(gmp_int& result, const gmp_int& a, const gmp_int& b)
+{
+ mpz_gcd(result.data(), a.data(), b.data());
+}
+inline void eval_lcm(gmp_int& result, const gmp_int& a, const gmp_int& b)
+{
+ mpz_lcm(result.data(), a.data(), b.data());
+}
+inline void eval_gcd(gmp_int& result, const gmp_int& a, const unsigned long b)
+{
+ mpz_gcd_ui(result.data(), a.data(), b);
+}
+inline void eval_lcm(gmp_int& result, const gmp_int& a, const unsigned long b)
+{
+ mpz_lcm_ui(result.data(), a.data(), b);
+}
+inline void eval_gcd(gmp_int& result, const gmp_int& a, const long b)
+{
+ mpz_gcd_ui(result.data(), a.data(), std::abs(b));
+}
+inline void eval_lcm(gmp_int& result, const gmp_int& a, const long b)
+{
+ mpz_lcm_ui(result.data(), a.data(), std::abs(b));
+}
+
 struct gmp_rational;
 void add(gmp_rational& t, const gmp_rational& o);
 

Modified: sandbox/big_number/boost/multiprecision/tommath.hpp
==============================================================================
--- sandbox/big_number/boost/multiprecision/tommath.hpp (original)
+++ sandbox/big_number/boost/multiprecision/tommath.hpp 2012-01-26 05:11:10 EST (Thu, 26 Jan 2012)
@@ -432,6 +432,14 @@
 {
    detail::check_tommath_result(mp_abs(const_cast< ::mp_int*>(&val.data()), &result.data()));
 }
+inline void eval_gcd(tommath_int& result, const tommath_int& a, const tommath_int& b)
+{
+ detail::check_tommath_result(mp_gcd(const_cast< ::mp_int*>(&a.data()), const_cast< ::mp_int*>(&b.data()), const_cast< ::mp_int*>(&result.data())));
+}
+inline void eval_lcm(tommath_int& result, const tommath_int& a, const tommath_int& b)
+{
+ detail::check_tommath_result(mp_lcm(const_cast< ::mp_int*>(&a.data()), const_cast< ::mp_int*>(&b.data()), const_cast< ::mp_int*>(&result.data())));
+}
 
 
 template<>

Modified: sandbox/big_number/libs/multiprecision/performance/performance_test.cpp
==============================================================================
--- sandbox/big_number/libs/multiprecision/performance/performance_test.cpp (original)
+++ sandbox/big_number/libs/multiprecision/performance/performance_test.cpp 2012-01-26 05:11:10 EST (Thu, 26 Jan 2012)
@@ -15,6 +15,7 @@
    && !defined(TEST_FIXED_INT)
 # define TEST_MPF
 # define TEST_MPZ
+# define TEST_MPQ
 # define TEST_MPFR
 # define TEST_CPP_FLOAT
 # define TEST_MPQ
@@ -299,6 +300,16 @@
       }
       return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
    }
+ double test_gcd()
+ {
+ stopwatch<boost::chrono::high_resolution_clock> w;
+ for(unsigned i = 0; i < 1000; ++i)
+ {
+ for(unsigned i = 0; i < b.size(); ++i)
+ a[i] = gcd(b[i], c[i]);
+ }
+ return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
+ }
 private:
    T generate_random()
    {
@@ -445,6 +456,7 @@
    report_result(cat, type, "|(int)", precision, t.test_or_int());
    report_result(cat, type, "&(int)", precision, t.test_and_int());
    report_result(cat, type, "^(int)", precision, t.test_xor_int());
+ report_result(cat, type, "gcd", precision, t.test_gcd());
 }
 template <class Number, int N, class U>
 void test_int_ops(tester<Number, N>& t, const char* type, unsigned precision, const U&)
@@ -564,7 +576,8 @@
    test<boost::multiprecision::mpz_int>("gmp_int", 256);
    test<boost::multiprecision::mpz_int>("gmp_int", 512);
    test<boost::multiprecision::mpz_int>("gmp_int", 1024);
-
+#endif
+#ifdef TEST_MPQ
    test<boost::multiprecision::mpq_rational>("mpq_rational", 64);
    test<boost::multiprecision::mpq_rational>("mpq_rational", 128);
    test<boost::multiprecision::mpq_rational>("mpq_rational", 256);

Modified: sandbox/big_number/libs/multiprecision/test/test_arithmetic.cpp
==============================================================================
--- sandbox/big_number/libs/multiprecision/test/test_arithmetic.cpp (original)
+++ sandbox/big_number/libs/multiprecision/test/test_arithmetic.cpp 2012-01-26 05:11:10 EST (Thu, 26 Jan 2012)
@@ -9,6 +9,7 @@
 
 #include <boost/detail/lightweight_test.hpp>
 #include <boost/math/special_functions/pow.hpp>
+#include <boost/math/common_factor_rt.hpp>
 
 #if !defined(TEST_MPF_50) && !defined(TEST_MPF) && !defined(TEST_BACKEND) && !defined(TEST_MPZ) && \
    !defined(TEST_CPP_FLOAT) && !defined(TEST_MPFR) && !defined(TEST_MPFR_50) && !defined(TEST_MPQ) \
@@ -345,6 +346,14 @@
    //
    // Non-member functions:
    //
+ a = 400;
+ b = 45;
+ BOOST_TEST(gcd(a, b) == boost::math::gcd(400, 45));
+ BOOST_TEST(lcm(a, b) == boost::math::lcm(400, 45));
+ BOOST_TEST(gcd(a, 45) == boost::math::gcd(400, 45));
+ BOOST_TEST(lcm(a, 45) == boost::math::lcm(400, 45));
+ BOOST_TEST(gcd(400, b) == boost::math::gcd(400, 45));
+ BOOST_TEST(lcm(400, b) == boost::math::lcm(400, 45));
    if(std::numeric_limits<Real>::is_signed)
    {
       a = -20;
@@ -355,6 +364,15 @@
       BOOST_TEST(abs(a) == 20);
       BOOST_TEST(abs(-a) == 20);
       BOOST_TEST(abs(+a) == 20);
+
+ a = -400;
+ b = 45;
+ BOOST_TEST(gcd(a, b) == boost::math::gcd(-400, 45));
+ BOOST_TEST(lcm(a, b) == boost::math::lcm(-400, 45));
+ BOOST_TEST(gcd(a, 45) == boost::math::gcd(-400, 45));
+ BOOST_TEST(lcm(a, 45) == boost::math::lcm(-400, 45));
+ BOOST_TEST(gcd(-400, b) == boost::math::gcd(-400, 45));
+ BOOST_TEST(lcm(-400, b) == boost::math::lcm(-400, 45));
    }
 }
 
@@ -458,6 +476,10 @@
    BOOST_TEST(n2 == Real(n2));
    BOOST_TEST(n3 == Real(n3));
    BOOST_TEST(n4 == Real(n4));
+ BOOST_TEST(Real(n1).template convert_to<Num>() == n1);
+ BOOST_TEST(Real(n2).template convert_to<Num>() == n2);
+ BOOST_TEST(Real(n3).template convert_to<Num>() == n3);
+ BOOST_TEST(Real(n4).template convert_to<Num>() == n4);
 #if defined(TEST_MPFR) || defined(TEST_MPFR_50)
    Num tol = 10 * std::numeric_limits<Num>::epsilon();
 #else

Modified: sandbox/big_number/libs/multiprecision/test/test_fixed_int.cpp
==============================================================================
--- sandbox/big_number/libs/multiprecision/test/test_fixed_int.cpp (original)
+++ sandbox/big_number/libs/multiprecision/test/test_fixed_int.cpp 2012-01-26 05:11:10 EST (Thu, 26 Jan 2012)
@@ -119,6 +119,8 @@
       BOOST_CHECK_EQUAL(mpz_int(si|a).str(), packed_type(si|a1).str());
       BOOST_CHECK_EQUAL(mpz_int(si&a).str(), packed_type(si&a1).str());
       BOOST_CHECK_EQUAL(mpz_int(si^a).str(), packed_type(si^a1).str());
+ BOOST_CHECK_EQUAL(mpz_int(gcd(a, b)).str(), packed_type(gcd(a1, b1)).str());
+ BOOST_CHECK_EQUAL(mpz_int(lcm(c, d)).str(), packed_type(lcm(c1, d1)).str());
 
       if(last_error_count != boost::detail::test_errors())
       {
@@ -135,6 +137,7 @@
          std::cout << "d1 = " << d1 << std::endl;
          std::cout << "a + b = " << a+b << std::endl;
          std::cout << "a1 + b1 = " << a1+b1 << std::endl;
+ std::cout << std::dec;
          std::cout << "a - b = " << a-b << std::endl;
          std::cout << "a1 - b1 = " << a1-b1 << std::endl;
          std::cout << "-a + b = " << mpz_int(-a)+b << std::endl;


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