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