657 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			657 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
|   | /////////////////////////////////////////////////////////////// | ||
|  | //  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_ | ||
|  | // | ||
|  | // Comparison operators for cpp_int_backend: | ||
|  | // | ||
|  | #ifndef BOOST_MP_CPP_INT_MISC_HPP | ||
|  | #define BOOST_MP_CPP_INT_MISC_HPP | ||
|  | 
 | ||
|  | #include <boost/multiprecision/detail/bitscan.hpp> // lsb etc | ||
|  | #include <boost/integer/common_factor_rt.hpp> // gcd/lcm | ||
|  | #include <boost/functional/hash_fwd.hpp> | ||
|  | 
 | ||
|  | #ifdef BOOST_MSVC | ||
|  | #pragma warning(push) | ||
|  | #pragma warning(disable:4702) | ||
|  | #pragma warning(disable:4127) // conditional expression is constant | ||
|  | #pragma warning(disable:4146) // unary minus operator applied to unsigned type, result still unsigned | ||
|  | #endif | ||
|  | 
 | ||
|  | 
 | ||
|  | namespace boost{ namespace multiprecision{ namespace backends{ | ||
|  | 
 | ||
|  | template <class R, class CppInt> | ||
|  | void check_in_range(const CppInt& val, const mpl::int_<checked>&) | ||
|  | { | ||
|  |    typedef typename boost::multiprecision::detail::canonical<R, CppInt>::type cast_type; | ||
|  |    if(val.sign()) | ||
|  |    { | ||
|  |       if(val.compare(static_cast<cast_type>((std::numeric_limits<R>::min)())) < 0) | ||
|  |          BOOST_THROW_EXCEPTION(std::overflow_error("Could not convert to the target type - -value is out of range.")); | ||
|  |    } | ||
|  |    else | ||
|  |    { | ||
|  |       if(val.compare(static_cast<cast_type>((std::numeric_limits<R>::max)())) > 0) | ||
|  |          BOOST_THROW_EXCEPTION(std::overflow_error("Could not convert to the target type - -value is out of range.")); | ||
|  |    } | ||
|  | } | ||
|  | template <class R, class CppInt> | ||
|  | inline void check_in_range(const CppInt& /*val*/, const mpl::int_<unchecked>&) BOOST_NOEXCEPT {} | ||
|  | 
 | ||
|  | inline void check_is_negative(const mpl::true_&) BOOST_NOEXCEPT {} | ||
|  | inline void check_is_negative(const mpl::false_&) | ||
|  | { | ||
|  |    BOOST_THROW_EXCEPTION(std::range_error("Attempt to assign a negative value to an unsigned type.")); | ||
|  | } | ||
|  | 
 | ||
|  | template <class Integer> | ||
|  | inline Integer negate_integer(Integer i, const mpl::true_&) BOOST_NOEXCEPT | ||
|  | { | ||
|  |    return -i; | ||
|  | } | ||
|  | template <class Integer> | ||
|  | inline Integer negate_integer(Integer i, const mpl::false_&) BOOST_NOEXCEPT | ||
|  | { | ||
|  |    return ~(i-1); | ||
|  | } | ||
|  | 
 | ||
|  | template <class R, unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | ||
|  | inline typename enable_if_c<is_integral<R>::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, void>::type | ||
|  |    eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& backend) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | ||
|  | { | ||
|  |    typedef mpl::int_<Checked1> checked_type; | ||
|  |    check_in_range<R>(backend, checked_type()); | ||
|  | 
 | ||
|  |    *result = static_cast<R>(backend.limbs()[0]); | ||
|  |    unsigned shift = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits; | ||
|  |    for(unsigned i = 1; (i < backend.size()) && (shift < static_cast<unsigned>(std::numeric_limits<R>::digits)); ++i) | ||
|  |    { | ||
|  |       *result += static_cast<R>(backend.limbs()[i]) << shift; | ||
|  |       shift += cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits; | ||
|  |    } | ||
|  |    if(backend.sign()) | ||
|  |    { | ||
|  |       check_is_negative(boost::is_signed<R>()); | ||
|  |       *result = negate_integer(*result, boost::is_signed<R>()); | ||
|  |    } | ||
|  | } | ||
|  | 
 | ||
|  | template <class R, unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | ||
|  | inline typename enable_if_c<is_floating_point<R>::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, void>::type | ||
|  |    eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& backend) BOOST_MP_NOEXCEPT_IF(is_arithmetic<R>::value) | ||
|  | { | ||
|  |    typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::const_limb_pointer p = backend.limbs(); | ||
|  |    unsigned shift = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits; | ||
|  |    *result = static_cast<R>(*p); | ||
|  |    for(unsigned i = 1; i < backend.size(); ++i) | ||
|  |    { | ||
|  |       *result += static_cast<R>(std::ldexp(static_cast<long double>(p[i]), shift)); | ||
|  |       shift += cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits; | ||
|  |    } | ||
|  |    if(backend.sign()) | ||
|  |       *result = -*result; | ||
|  | } | ||
|  | 
 | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | ||
|  | BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, bool>::type | ||
|  |    eval_is_zero(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val) BOOST_NOEXCEPT | ||
|  | { | ||
|  |    return (val.size() == 1) && (val.limbs()[0] == 0); | ||
|  | } | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | ||
|  | BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, int>::type | ||
|  |    eval_get_sign(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val) BOOST_NOEXCEPT | ||
|  | { | ||
|  |    return eval_is_zero(val) ? 0 : val.sign() ? -1 : 1; | ||
|  | } | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | ||
|  | BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type | ||
|  |    eval_abs(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | ||
|  | { | ||
|  |    result = val; | ||
|  |    result.sign(false); | ||
|  | } | ||
|  | 
 | ||
|  | // | ||
|  | // Get the location of the least-significant-bit: | ||
|  | // | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | ||
|  | inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::type | ||
|  |    eval_lsb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a) | ||
|  | { | ||
|  |    using default_ops::eval_get_sign; | ||
|  |    if(eval_get_sign(a) == 0) | ||
|  |    { | ||
|  |       BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand.")); | ||
|  |    } | ||
|  |    if(a.sign()) | ||
|  |    { | ||
|  |       BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined.")); | ||
|  |    } | ||
|  | 
 | ||
|  |    // | ||
|  |    // Find the index of the least significant limb that is non-zero: | ||
|  |    // | ||
|  |    unsigned index = 0; | ||
|  |    while(!a.limbs()[index] && (index < a.size())) | ||
|  |       ++index; | ||
|  |    // | ||
|  |    // Find the index of the least significant bit within that limb: | ||
|  |    // | ||
|  |    unsigned result = boost::multiprecision::detail::find_lsb(a.limbs()[index]); | ||
|  | 
 | ||
|  |    return result + index * cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits; | ||
|  | } | ||
|  | 
 | ||
|  | // | ||
|  | // Get the location of the most-significant-bit: | ||
|  | // | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | ||
|  | inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::type | ||
|  | eval_msb_imp(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a) | ||
|  | { | ||
|  |    // | ||
|  |    // Find the index of the most significant bit that is non-zero: | ||
|  |    // | ||
|  |    return (a.size() - 1) * cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits + boost::multiprecision::detail::find_msb(a.limbs()[a.size() - 1]); | ||
|  | } | ||
|  | 
 | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | ||
|  | inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::type | ||
|  |    eval_msb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a) | ||
|  | { | ||
|  |    using default_ops::eval_get_sign; | ||
|  |    if(eval_get_sign(a) == 0) | ||
|  |    { | ||
|  |       BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand.")); | ||
|  |    } | ||
|  |    if(a.sign()) | ||
|  |    { | ||
|  |       BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined.")); | ||
|  |    } | ||
|  |    return eval_msb_imp(a); | ||
|  | } | ||
|  | 
 | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | ||
|  | inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, bool>::type | ||
|  |    eval_bit_test(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val, unsigned index) BOOST_NOEXCEPT | ||
|  | { | ||
|  |    unsigned offset = index / cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits; | ||
|  |    unsigned shift = index % cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits; | ||
|  |    limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u); | ||
|  |    if(offset >= val.size()) | ||
|  |       return false; | ||
|  |    return val.limbs()[offset] & mask ? true : false; | ||
|  | } | ||
|  | 
 | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | ||
|  | inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type | ||
|  |    eval_bit_set(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val, unsigned index) | ||
|  | { | ||
|  |    unsigned offset = index / cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits; | ||
|  |    unsigned shift = index % cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits; | ||
|  |    limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u); | ||
|  |    if(offset >= val.size()) | ||
|  |    { | ||
|  |       unsigned os = val.size(); | ||
|  |       val.resize(offset + 1, offset + 1); | ||
|  |       if(offset >= val.size()) | ||
|  |          return;  // fixed precision overflow | ||
|  |       for(unsigned i = os; i <= offset; ++i) | ||
|  |          val.limbs()[i] = 0; | ||
|  |    } | ||
|  |    val.limbs()[offset] |= mask; | ||
|  | } | ||
|  | 
 | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | ||
|  | inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type | ||
|  |    eval_bit_unset(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val, unsigned index) BOOST_NOEXCEPT | ||
|  | { | ||
|  |    unsigned offset = index / cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits; | ||
|  |    unsigned shift = index % cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits; | ||
|  |    limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u); | ||
|  |    if(offset >= val.size()) | ||
|  |       return; | ||
|  |    val.limbs()[offset] &= ~mask; | ||
|  |    val.normalize(); | ||
|  | } | ||
|  | 
 | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | ||
|  | inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type | ||
|  |    eval_bit_flip(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val, unsigned index) | ||
|  | { | ||
|  |    unsigned offset = index / cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits; | ||
|  |    unsigned shift = index % cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits; | ||
|  |    limb_type mask = shift ? limb_type(1u) << shift : limb_type(1u); | ||
|  |    if(offset >= val.size()) | ||
|  |    { | ||
|  |       unsigned os = val.size(); | ||
|  |       val.resize(offset + 1, offset + 1); | ||
|  |       if(offset >= val.size()) | ||
|  |          return;  // fixed precision overflow | ||
|  |       for(unsigned i = os; i <= offset; ++i) | ||
|  |          val.limbs()[i] = 0; | ||
|  |    } | ||
|  |    val.limbs()[offset] ^= mask; | ||
|  |    val.normalize(); | ||
|  | } | ||
|  | 
 | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | ||
|  | inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type | ||
|  |    eval_qr( | ||
|  |       const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& x, | ||
|  |       const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& y, | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& q, | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& r) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | ||
|  | { | ||
|  |    divide_unsigned_helper(&q, x, y, r); | ||
|  |    q.sign(x.sign() != y.sign()); | ||
|  |    r.sign(x.sign()); | ||
|  | } | ||
|  | 
 | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | ||
|  | inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type | ||
|  |    eval_qr( | ||
|  |       const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& x, | ||
|  |       limb_type y, | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& q, | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& r) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | ||
|  | { | ||
|  |    divide_unsigned_helper(&q, x, y, r); | ||
|  |    q.sign(x.sign()); | ||
|  |    r.sign(x.sign()); | ||
|  | } | ||
|  | 
 | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class U> | ||
|  | inline typename enable_if_c<is_integral<U>::value>::type eval_qr( | ||
|  |       const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& x, | ||
|  |       U y, | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& q, | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& r) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | ||
|  | { | ||
|  |    using default_ops::eval_qr; | ||
|  |    cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> t; | ||
|  |    t = y; | ||
|  |    eval_qr(x, t, q, r); | ||
|  | } | ||
|  | 
 | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Integer> | ||
|  | inline typename enable_if_c<is_unsigned<Integer>::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, Integer>::type | ||
|  |    eval_integer_modulus(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& x, Integer val) | ||
|  | { | ||
|  |    if((sizeof(Integer) <= sizeof(limb_type)) || (val <= (std::numeric_limits<limb_type>::max)())) | ||
|  |    { | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> d; | ||
|  |       divide_unsigned_helper(static_cast<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>*>(0), x, static_cast<limb_type>(val), d); | ||
|  |       return d.limbs()[0]; | ||
|  |    } | ||
|  |    else | ||
|  |    { | ||
|  |       return default_ops::eval_integer_modulus(x, val); | ||
|  |    } | ||
|  | } | ||
|  | 
 | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Integer> | ||
|  | BOOST_MP_FORCEINLINE typename enable_if_c<is_signed<Integer>::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, Integer>::type | ||
|  |    eval_integer_modulus(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& x, Integer val) | ||
|  | { | ||
|  |    return eval_integer_modulus(x, boost::multiprecision::detail::unsigned_abs(val)); | ||
|  | } | ||
|  | 
 | ||
|  | inline limb_type integer_gcd_reduce(limb_type u, limb_type v) | ||
|  | { | ||
|  |    do | ||
|  |    { | ||
|  |       if(u > v) | ||
|  |          std::swap(u, v); | ||
|  |       if(u == v) | ||
|  |          break; | ||
|  |       v -= u; | ||
|  |       v >>= boost::multiprecision::detail::find_lsb(v); | ||
|  |    } while(true); | ||
|  |    return u; | ||
|  | } | ||
|  | 
 | ||
|  | inline double_limb_type integer_gcd_reduce(double_limb_type u, double_limb_type v) | ||
|  | { | ||
|  |    do | ||
|  |    { | ||
|  |       if(u > v) | ||
|  |          std::swap(u, v); | ||
|  |       if(u == v) | ||
|  |          break; | ||
|  |       if(v <= ~static_cast<limb_type>(0)) | ||
|  |       { | ||
|  |          u = integer_gcd_reduce(static_cast<limb_type>(v), static_cast<limb_type>(u)); | ||
|  |          break; | ||
|  |       } | ||
|  |       v -= u; | ||
|  | #ifdef __MSVC_RUNTIME_CHECKS | ||
|  |       while((v & 1u) == 0) | ||
|  | #else | ||
|  |       while((static_cast<unsigned>(v) & 1u) == 0) | ||
|  | #endif | ||
|  |          v >>= 1; | ||
|  |    } while(true); | ||
|  |    return u; | ||
|  | } | ||
|  | 
 | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | ||
|  | inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type | ||
|  |    eval_gcd( | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,  | ||
|  |       const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,  | ||
|  |       limb_type v) | ||
|  | { | ||
|  |    using default_ops::eval_lsb; | ||
|  |    using default_ops::eval_is_zero; | ||
|  |    using default_ops::eval_get_sign; | ||
|  | 
 | ||
|  |    int shift; | ||
|  | 
 | ||
|  |    cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> u(a); | ||
|  | 
 | ||
|  |    int s = eval_get_sign(u); | ||
|  | 
 | ||
|  |    /* GCD(0,x) := x */ | ||
|  |    if(s < 0) | ||
|  |    { | ||
|  |       u.negate(); | ||
|  |    } | ||
|  |    else if(s == 0) | ||
|  |    { | ||
|  |       result = v; | ||
|  |       return; | ||
|  |    } | ||
|  |    if(v == 0) | ||
|  |    { | ||
|  |       result = u; | ||
|  |       return; | ||
|  |    } | ||
|  | 
 | ||
|  |    /* Let shift := lg K, where K is the greatest power of 2 | ||
|  |    dividing both u and v. */ | ||
|  | 
 | ||
|  |    unsigned us = eval_lsb(u); | ||
|  |    unsigned vs = boost::multiprecision::detail::find_lsb(v); | ||
|  |    shift = (std::min)(us, vs); | ||
|  |    eval_right_shift(u, us); | ||
|  |    if(vs) | ||
|  |       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.size() <= 2) | ||
|  |       { | ||
|  |          if(u.size() == 1) | ||
|  |             v = integer_gcd_reduce(*u.limbs(), v); | ||
|  |          else | ||
|  |          { | ||
|  |             double_limb_type i; | ||
|  |             i = u.limbs()[0] | (static_cast<double_limb_type>(u.limbs()[1]) << sizeof(limb_type) * CHAR_BIT); | ||
|  |             v = static_cast<limb_type>(integer_gcd_reduce(i, static_cast<double_limb_type>(v))); | ||
|  |          } | ||
|  |          break; | ||
|  |       } | ||
|  |       eval_subtract(u, v); | ||
|  |       us = eval_lsb(u); | ||
|  |       eval_right_shift(u, us); | ||
|  |    }  | ||
|  |    while(true); | ||
|  | 
 | ||
|  |    result = v; | ||
|  |    eval_left_shift(result, shift); | ||
|  | } | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Integer> | ||
|  | inline typename enable_if_c<is_unsigned<Integer>::value && (sizeof(Integer) <= sizeof(limb_type)) && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type | ||
|  |    eval_gcd( | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,  | ||
|  |       const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,  | ||
|  |       const Integer& v) | ||
|  | { | ||
|  |    eval_gcd(result, a, static_cast<limb_type>(v)); | ||
|  | } | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class Integer> | ||
|  | inline typename enable_if_c<is_signed<Integer>::value && (sizeof(Integer) <= sizeof(limb_type)) && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type | ||
|  |    eval_gcd( | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,  | ||
|  |       const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,  | ||
|  |       const Integer& v) | ||
|  | { | ||
|  |    eval_gcd(result, a, static_cast<limb_type>(v < 0 ? -v : v)); | ||
|  | } | ||
|  | 
 | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | ||
|  | inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type | ||
|  |    eval_gcd( | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,  | ||
|  |       const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a,  | ||
|  |       const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& b) | ||
|  | { | ||
|  |    using default_ops::eval_lsb; | ||
|  |    using default_ops::eval_is_zero; | ||
|  |    using default_ops::eval_get_sign; | ||
|  | 
 | ||
|  |    if(a.size() == 1) | ||
|  |    { | ||
|  |       eval_gcd(result, b, *a.limbs()); | ||
|  |       return; | ||
|  |    } | ||
|  |    if(b.size() == 1) | ||
|  |    { | ||
|  |       eval_gcd(result, a, *b.limbs()); | ||
|  |       return; | ||
|  |    } | ||
|  | 
 | ||
|  |    int shift; | ||
|  | 
 | ||
|  |    cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> u(a), v(b); | ||
|  | 
 | ||
|  |    int s = eval_get_sign(u); | ||
|  | 
 | ||
|  |    /* GCD(0,x) := x */ | ||
|  |    if(s < 0) | ||
|  |    { | ||
|  |       u.negate(); | ||
|  |    } | ||
|  |    else if(s == 0) | ||
|  |    { | ||
|  |       result = v; | ||
|  |       return; | ||
|  |    } | ||
|  |    s = eval_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 = eval_lsb(u); | ||
|  |    unsigned vs = eval_lsb(v); | ||
|  |    shift = (std::min)(us, vs); | ||
|  |    eval_right_shift(u, us); | ||
|  |    eval_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. */ | ||
|  |       s = u.compare(v); | ||
|  |       if(s > 0) | ||
|  |          u.swap(v); | ||
|  |       if(s == 0) | ||
|  |          break; | ||
|  |       if(v.size() <= 2) | ||
|  |       { | ||
|  |          if(v.size() == 1) | ||
|  |             u = integer_gcd_reduce(*v.limbs(), *u.limbs()); | ||
|  |          else | ||
|  |          { | ||
|  |             double_limb_type i, j; | ||
|  |             i = v.limbs()[0] | (static_cast<double_limb_type>(v.limbs()[1]) << sizeof(limb_type) * CHAR_BIT); | ||
|  |             j = (u.size() == 1) ? *u.limbs() : u.limbs()[0] | (static_cast<double_limb_type>(u.limbs()[1]) << sizeof(limb_type) * CHAR_BIT); | ||
|  |             u = integer_gcd_reduce(i, j); | ||
|  |          } | ||
|  |          break; | ||
|  |       } | ||
|  |       eval_subtract(v, u); | ||
|  |       vs = eval_lsb(v); | ||
|  |       eval_right_shift(v, vs); | ||
|  |    }  | ||
|  |    while(true); | ||
|  | 
 | ||
|  |    result = u; | ||
|  |    eval_left_shift(result, shift); | ||
|  | } | ||
|  | // | ||
|  | // Now again for trivial backends: | ||
|  | // | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | ||
|  | BOOST_MP_FORCEINLINE typename enable_if_c<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type | ||
|  |    eval_gcd(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& b) BOOST_NOEXCEPT | ||
|  | { | ||
|  |    *result.limbs() = boost::integer::gcd(*a.limbs(), *b.limbs()); | ||
|  | } | ||
|  | // This one is only enabled for unchecked cpp_int's, for checked int's we need the checking in the default version: | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | ||
|  | BOOST_MP_FORCEINLINE typename enable_if_c<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && (Checked1 == unchecked)>::type | ||
|  |    eval_lcm(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& b) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | ||
|  | { | ||
|  |    *result.limbs() = boost::integer::lcm(*a.limbs(), *b.limbs()); | ||
|  |    result.normalize(); // result may overflow the specified number of bits | ||
|  | } | ||
|  | 
 | ||
|  | inline void conversion_overflow(const mpl::int_<checked>&) | ||
|  | { | ||
|  |    BOOST_THROW_EXCEPTION(std::overflow_error("Overflow in conversion to narrower type")); | ||
|  | } | ||
|  | inline void conversion_overflow(const mpl::int_<unchecked>&){} | ||
|  | 
 | ||
|  | template <class R, unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | ||
|  | inline typename enable_if_c< | ||
|  |             is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value | ||
|  |             && is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value | ||
|  |             && boost::is_convertible<typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type, R>::value | ||
|  |          >::type | ||
|  |    eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val) | ||
|  | { | ||
|  |    typedef typename common_type<R, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type>::type common_type; | ||
|  |    if(std::numeric_limits<R>::is_specialized && (static_cast<common_type>(*val.limbs()) > static_cast<common_type>((std::numeric_limits<R>::max)()))) | ||
|  |    { | ||
|  |       if(val.isneg()) | ||
|  |       { | ||
|  |          if(static_cast<common_type>(*val.limbs()) > -static_cast<common_type>((std::numeric_limits<R>::min)())) | ||
|  |             conversion_overflow(typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type()); | ||
|  |          *result = (std::numeric_limits<R>::min)(); | ||
|  |       } | ||
|  |       else | ||
|  |       { | ||
|  |          conversion_overflow(typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type()); | ||
|  |          *result = (std::numeric_limits<R>::max)(); | ||
|  |       } | ||
|  |    } | ||
|  |    else | ||
|  |    { | ||
|  |       *result = static_cast<R>(*val.limbs()); | ||
|  |       if(val.isneg()) | ||
|  |       { | ||
|  |          check_is_negative(mpl::bool_<is_signed_number<R>::value || (number_category<R>::value == number_kind_floating_point)>()); | ||
|  |          *result = negate_integer(*result, mpl::bool_<is_signed_number<R>::value || (number_category<R>::value == number_kind_floating_point)>()); | ||
|  |       } | ||
|  |    } | ||
|  | } | ||
|  | 
 | ||
|  | template <class R, unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | ||
|  | inline typename enable_if_c< | ||
|  |             is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value | ||
|  |             && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value | ||
|  |             && boost::is_convertible<typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type, R>::value | ||
|  |          >::type | ||
|  |    eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val) | ||
|  | { | ||
|  |    typedef typename common_type<R, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type>::type common_type; | ||
|  |    if(std::numeric_limits<R>::is_specialized && (static_cast<common_type>(*val.limbs()) > static_cast<common_type>((std::numeric_limits<R>::max)()))) | ||
|  |    { | ||
|  |       conversion_overflow(typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type()); | ||
|  |       *result = (std::numeric_limits<R>::max)(); | ||
|  |    } | ||
|  |    else | ||
|  |       *result = static_cast<R>(*val.limbs()); | ||
|  | } | ||
|  | 
 | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | ||
|  | inline typename enable_if_c<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::type | ||
|  |    eval_lsb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a) | ||
|  | { | ||
|  |    using default_ops::eval_get_sign; | ||
|  |    if(eval_get_sign(a) == 0) | ||
|  |    { | ||
|  |       BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand.")); | ||
|  |    } | ||
|  |    if(a.sign()) | ||
|  |    { | ||
|  |       BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined.")); | ||
|  |    } | ||
|  |    // | ||
|  |    // Find the index of the least significant bit within that limb: | ||
|  |    // | ||
|  |    return boost::multiprecision::detail::find_lsb(*a.limbs()); | ||
|  | } | ||
|  | 
 | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | ||
|  | inline typename enable_if_c<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::type | ||
|  | eval_msb_imp(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a) | ||
|  | { | ||
|  |    // | ||
|  |    // Find the index of the least significant bit within that limb: | ||
|  |    // | ||
|  |    return boost::multiprecision::detail::find_msb(*a.limbs()); | ||
|  | } | ||
|  | 
 | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | ||
|  | inline typename enable_if_c<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value, unsigned>::type | ||
|  |    eval_msb(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& a) | ||
|  | { | ||
|  |    using default_ops::eval_get_sign; | ||
|  |    if(eval_get_sign(a) == 0) | ||
|  |    { | ||
|  |       BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand.")); | ||
|  |    } | ||
|  |    if(a.sign()) | ||
|  |    { | ||
|  |       BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined.")); | ||
|  |    } | ||
|  |    return eval_msb_imp(a); | ||
|  | } | ||
|  | 
 | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | ||
|  | inline std::size_t hash_value(const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val) BOOST_NOEXCEPT | ||
|  | { | ||
|  |    std::size_t result = 0; | ||
|  |    for(unsigned i = 0; i < val.size(); ++i) | ||
|  |    { | ||
|  |       boost::hash_combine(result, val.limbs()[i]); | ||
|  |    } | ||
|  |    boost::hash_combine(result, val.sign()); | ||
|  |    return result; | ||
|  | } | ||
|  | 
 | ||
|  | #ifdef BOOST_MSVC | ||
|  | #pragma warning(pop) | ||
|  | #endif | ||
|  | 
 | ||
|  | }}} // namespaces | ||
|  | 
 | ||
|  | #endif |