843 lines
		
	
	
		
			39 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			843 lines
		
	
	
		
			39 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_BIT_HPP | ||
|  | #define BOOST_MP_CPP_INT_BIT_HPP | ||
|  | 
 | ||
|  | #ifdef _MSC_VER | ||
|  | #pragma warning(push) | ||
|  | #pragma warning(disable:4319) | ||
|  | #endif | ||
|  | 
 | ||
|  | namespace boost{ namespace multiprecision{ namespace backends{ | ||
|  | 
 | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2> | ||
|  | void is_valid_bitwise_op( | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, | ||
|  |       const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o, const mpl::int_<checked>&) | ||
|  | { | ||
|  |    if(result.sign() || o.sign()) | ||
|  |       BOOST_THROW_EXCEPTION(std::range_error("Bitwise operations on negative values results in undefined behavior.")); | ||
|  | } | ||
|  | 
 | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2> | ||
|  | void is_valid_bitwise_op( | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&, | ||
|  |       const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& , const mpl::int_<unchecked>&){} | ||
|  | 
 | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_int_check_type Checked1, class Allocator1> | ||
|  | void is_valid_bitwise_op( | ||
|  |       const cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>& result, const mpl::int_<checked>&) | ||
|  | { | ||
|  |    if(result.sign()) | ||
|  |       BOOST_THROW_EXCEPTION(std::range_error("Bitwise operations on negative values results in undefined behavior.")); | ||
|  | } | ||
|  | 
 | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_int_check_type Checked1, class Allocator1> | ||
|  | void is_valid_bitwise_op( | ||
|  |    const cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1>&, const mpl::int_<checked>&){} | ||
|  | 
 | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | ||
|  | void is_valid_bitwise_op( | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&, const mpl::int_<unchecked>&){} | ||
|  | 
 | ||
|  | template <class CppInt1, class CppInt2, class Op> | ||
|  | void bitwise_op( | ||
|  |    CppInt1& result, | ||
|  |    const CppInt2& o, | ||
|  |    Op op, const mpl::true_&) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<CppInt1>::value)) | ||
|  | { | ||
|  |    // | ||
|  |    // There are 4 cases: | ||
|  |    // * Both positive. | ||
|  |    // * result negative, o positive. | ||
|  |    // * o negative, result positive. | ||
|  |    // * Both negative. | ||
|  |    // | ||
|  |    // When one arg is negative we convert to 2's complement form "on the fly", | ||
|  |    // and then convert back to signed-magnitude form at the end. | ||
|  |    // | ||
|  |    // Note however, that if the type is checked, then bitwise ops on negative values | ||
|  |    // are not permitted and an exception will result. | ||
|  |    // | ||
|  |    is_valid_bitwise_op(result, o, typename CppInt1::checked_type()); | ||
|  |    // | ||
|  |    // First figure out how big the result needs to be and set up some data: | ||
|  |    // | ||
|  |    unsigned rs = result.size(); | ||
|  |    unsigned os = o.size(); | ||
|  |    unsigned m, x; | ||
|  |    minmax(rs, os, m, x); | ||
|  |    result.resize(x, x); | ||
|  |    typename CppInt1::limb_pointer pr = result.limbs(); | ||
|  |    typename CppInt2::const_limb_pointer po = o.limbs(); | ||
|  |    for(unsigned i = rs; i < x; ++i) | ||
|  |       pr[i] = 0; | ||
|  | 
 | ||
|  |    limb_type next_limb = 0; | ||
|  | 
 | ||
|  |    if(!result.sign()) | ||
|  |    { | ||
|  |       if(!o.sign()) | ||
|  |       { | ||
|  |          for(unsigned i = 0; i < os; ++i) | ||
|  |             pr[i] = op(pr[i], po[i]); | ||
|  |          for(unsigned i = os; i < x; ++i) | ||
|  |             pr[i] = op(pr[i], limb_type(0)); | ||
|  |       } | ||
|  |       else | ||
|  |       { | ||
|  |          // "o" is negative: | ||
|  |          double_limb_type carry = 1; | ||
|  |          for(unsigned i = 0; i < os; ++i) | ||
|  |          { | ||
|  |             carry += static_cast<double_limb_type>(~po[i]); | ||
|  |             pr[i] = op(pr[i], static_cast<limb_type>(carry)); | ||
|  |             carry >>= CppInt1::limb_bits; | ||
|  |          } | ||
|  |          for(unsigned i = os; i < x; ++i) | ||
|  |          { | ||
|  |             carry += static_cast<double_limb_type>(~limb_type(0)); | ||
|  |             pr[i] = op(pr[i], static_cast<limb_type>(carry)); | ||
|  |             carry >>= CppInt1::limb_bits; | ||
|  |          } | ||
|  |          // Set the overflow into the "extra" limb: | ||
|  |          carry += static_cast<double_limb_type>(~limb_type(0)); | ||
|  |          next_limb = op(limb_type(0), static_cast<limb_type>(carry)); | ||
|  |       } | ||
|  |    } | ||
|  |    else | ||
|  |    { | ||
|  |       if(!o.sign()) | ||
|  |       { | ||
|  |          // "result" is negative: | ||
|  |          double_limb_type carry = 1; | ||
|  |          for(unsigned i = 0; i < os; ++i) | ||
|  |          { | ||
|  |             carry += static_cast<double_limb_type>(~pr[i]); | ||
|  |             pr[i] = op(static_cast<limb_type>(carry), po[i]); | ||
|  |             carry >>= CppInt1::limb_bits; | ||
|  |          } | ||
|  |          for(unsigned i = os; i < x; ++i) | ||
|  |          { | ||
|  |             carry += static_cast<double_limb_type>(~pr[i]); | ||
|  |             pr[i] = op(static_cast<limb_type>(carry), limb_type(0)); | ||
|  |             carry >>= CppInt1::limb_bits; | ||
|  |          } | ||
|  |          // Set the overflow into the "extra" limb: | ||
|  |          carry += static_cast<double_limb_type>(~limb_type(0)); | ||
|  |          next_limb = op(static_cast<limb_type>(carry), limb_type(0)); | ||
|  |       } | ||
|  |       else | ||
|  |       { | ||
|  |          // both are negative: | ||
|  |          double_limb_type r_carry = 1; | ||
|  |          double_limb_type o_carry = 1; | ||
|  |          for(unsigned i = 0; i < os; ++i) | ||
|  |          { | ||
|  |             r_carry += static_cast<double_limb_type>(~pr[i]); | ||
|  |             o_carry += static_cast<double_limb_type>(~po[i]); | ||
|  |             pr[i] = op(static_cast<limb_type>(r_carry), static_cast<limb_type>(o_carry)); | ||
|  |             r_carry >>= CppInt1::limb_bits; | ||
|  |             o_carry >>= CppInt1::limb_bits; | ||
|  |          } | ||
|  |          for(unsigned i = os; i < x; ++i) | ||
|  |          { | ||
|  |             r_carry += static_cast<double_limb_type>(~pr[i]); | ||
|  |             o_carry += static_cast<double_limb_type>(~limb_type(0)); | ||
|  |             pr[i] = op(static_cast<limb_type>(r_carry), static_cast<limb_type>(o_carry)); | ||
|  |             r_carry >>= CppInt1::limb_bits; | ||
|  |             o_carry >>= CppInt1::limb_bits; | ||
|  |          } | ||
|  |          // Set the overflow into the "extra" limb: | ||
|  |          r_carry += static_cast<double_limb_type>(~limb_type(0)); | ||
|  |          o_carry += static_cast<double_limb_type>(~limb_type(0)); | ||
|  |          next_limb = op(static_cast<limb_type>(r_carry), static_cast<limb_type>(o_carry)); | ||
|  |       } | ||
|  |    } | ||
|  |    // | ||
|  |    // See if the result is negative or not: | ||
|  |    // | ||
|  |    if(static_cast<signed_limb_type>(next_limb) < 0) | ||
|  |    { | ||
|  |       double_limb_type carry = 1; | ||
|  |       for(unsigned i = 0; i < x; ++i) | ||
|  |       { | ||
|  |          carry += static_cast<double_limb_type>(~pr[i]); | ||
|  |          pr[i] = static_cast<limb_type>(carry); | ||
|  |          carry >>= CppInt1::limb_bits; | ||
|  |       } | ||
|  |       if(carry) | ||
|  |       { | ||
|  |          result.resize(x + 1, x); | ||
|  |          if(result.size() > x) | ||
|  |             result.limbs()[x] = static_cast<limb_type>(carry); | ||
|  |       } | ||
|  |       result.sign(true); | ||
|  |    } | ||
|  |    else | ||
|  |       result.sign(false); | ||
|  | 
 | ||
|  |    result.normalize(); | ||
|  | } | ||
|  | 
 | ||
|  | template <class CppInt1, class CppInt2, class Op> | ||
|  | void bitwise_op( | ||
|  |    CppInt1& result, | ||
|  |    const CppInt2& o, | ||
|  |    Op op, const mpl::false_&) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<CppInt1>::value)) | ||
|  | { | ||
|  |    // | ||
|  |    // Both arguments are unsigned types, very simple case handled as a special case. | ||
|  |    // | ||
|  |    // First figure out how big the result needs to be and set up some data: | ||
|  |    // | ||
|  |    unsigned rs = result.size(); | ||
|  |    unsigned os = o.size(); | ||
|  |    unsigned m, x; | ||
|  |    minmax(rs, os, m, x); | ||
|  |    result.resize(x, x); | ||
|  |    typename CppInt1::limb_pointer pr = result.limbs(); | ||
|  |    typename CppInt2::const_limb_pointer po = o.limbs(); | ||
|  |    for(unsigned i = rs; i < x; ++i) | ||
|  |       pr[i] = 0; | ||
|  | 
 | ||
|  |    for(unsigned i = 0; i < os; ++i) | ||
|  |       pr[i] = op(pr[i], po[i]); | ||
|  |    for(unsigned i = os; i < x; ++i) | ||
|  |       pr[i] = op(pr[i], limb_type(0)); | ||
|  | 
 | ||
|  |    result.normalize(); | ||
|  | } | ||
|  | 
 | ||
|  | struct bit_and{ limb_type operator()(limb_type a, limb_type b)const BOOST_NOEXCEPT { return a & b; } }; | ||
|  | struct bit_or { limb_type operator()(limb_type a, limb_type b)const BOOST_NOEXCEPT { return a | b; } }; | ||
|  | struct bit_xor{ limb_type operator()(limb_type a, limb_type b)const BOOST_NOEXCEPT { return a ^ b; } }; | ||
|  | 
 | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2> | ||
|  | BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value >::type | ||
|  |    eval_bitwise_and( | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, | ||
|  |       const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | ||
|  | { | ||
|  |    bitwise_op(result, o, bit_and(),  | ||
|  |       mpl::bool_<std::numeric_limits<number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> > >::is_signed || std::numeric_limits<number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> > >::is_signed>()); | ||
|  | } | ||
|  | 
 | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2> | ||
|  | BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value >::type | ||
|  |    eval_bitwise_or( | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, | ||
|  |       const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | ||
|  | { | ||
|  |    bitwise_op(result, o, bit_or(), | ||
|  |       mpl::bool_<std::numeric_limits<number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> > >::is_signed || std::numeric_limits<number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> > >::is_signed>()); | ||
|  | } | ||
|  | 
 | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2> | ||
|  | BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value >::type | ||
|  |    eval_bitwise_xor( | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, | ||
|  |       const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | ||
|  | { | ||
|  |    bitwise_op(result, o, bit_xor(), | ||
|  |       mpl::bool_<std::numeric_limits<number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> > >::is_signed || std::numeric_limits<number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> > >::is_signed>()); | ||
|  | } | ||
|  | // | ||
|  | // Again for operands which are single limbs: | ||
|  | // | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_int_check_type Checked1, class Allocator1> | ||
|  | BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1> >::value>::type | ||
|  |    eval_bitwise_and( | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1>& result, | ||
|  |       limb_type l) BOOST_NOEXCEPT | ||
|  | { | ||
|  |    result.limbs()[0] &= l; | ||
|  |    result.resize(1, 1); | ||
|  | } | ||
|  | 
 | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_int_check_type Checked1, class Allocator1> | ||
|  | BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1> >::value>::type | ||
|  |    eval_bitwise_or( | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1>& result, | ||
|  |       limb_type l) BOOST_NOEXCEPT | ||
|  | { | ||
|  |    result.limbs()[0] |= l; | ||
|  | } | ||
|  | 
 | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_int_check_type Checked1, class Allocator1> | ||
|  | BOOST_MP_FORCEINLINE typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1> >::value>::type | ||
|  |    eval_bitwise_xor( | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1>& result, | ||
|  |       limb_type l) BOOST_NOEXCEPT | ||
|  | { | ||
|  |    result.limbs()[0] ^= l; | ||
|  | } | ||
|  | 
 | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2> | ||
|  | BOOST_MP_FORCEINLINE typename enable_if_c<is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value >::type | ||
|  |    eval_complement( | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, | ||
|  |       const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | ||
|  | { | ||
|  |    BOOST_STATIC_ASSERT_MSG(((Checked1 != checked) || (Checked2 != checked)), "Attempt to take the complement of a signed type results in undefined behavior."); | ||
|  |    // Increment and negate: | ||
|  |    result = o; | ||
|  |    eval_increment(result); | ||
|  |    result.negate(); | ||
|  | } | ||
|  | 
 | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1> | ||
|  | BOOST_MP_FORCEINLINE typename enable_if_c<is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value && !is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value >::type | ||
|  |    eval_complement( | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, | ||
|  |       const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | ||
|  | { | ||
|  |    unsigned os = o.size(); | ||
|  |    result.resize(UINT_MAX, os); | ||
|  |    for(unsigned i = 0; i < os; ++i) | ||
|  |       result.limbs()[i] = ~o.limbs()[i]; | ||
|  |    for(unsigned i = os; i < result.size(); ++i) | ||
|  |       result.limbs()[i] = ~static_cast<limb_type>(0); | ||
|  |    result.normalize(); | ||
|  | } | ||
|  | 
 | ||
|  | template <class Int> | ||
|  | inline void left_shift_byte(Int& result, double_limb_type s) | ||
|  | { | ||
|  |    limb_type offset = static_cast<limb_type>(s / Int::limb_bits); | ||
|  |    limb_type shift = static_cast<limb_type>(s % Int::limb_bits); | ||
|  |    unsigned ors = result.size(); | ||
|  |    if((ors == 1) && (!*result.limbs())) | ||
|  |       return; // shifting zero yields zero. | ||
|  |    unsigned rs = ors; | ||
|  |    if(shift && (result.limbs()[ors - 1] >> (Int::limb_bits - shift))) | ||
|  |       ++rs; // Most significant limb will overflow when shifted | ||
|  |    rs += offset; | ||
|  |    result.resize(rs, rs); | ||
|  |    rs = result.size(); | ||
|  | 
 | ||
|  |    typename Int::limb_pointer pr = result.limbs(); | ||
|  | 
 | ||
|  |    if(rs != ors) | ||
|  |       pr[rs - 1] = 0u; | ||
|  |    std::size_t bytes = static_cast<std::size_t>(s / CHAR_BIT); | ||
|  |    std::size_t len = std::min(ors * sizeof(limb_type), rs * sizeof(limb_type) - bytes); | ||
|  |    if(bytes >= rs * sizeof(limb_type)) | ||
|  |       result = static_cast<limb_type>(0u); | ||
|  |    else | ||
|  |    { | ||
|  |       unsigned char* pc = reinterpret_cast<unsigned char*>(pr); | ||
|  |       std::memmove(pc + bytes, pc, len); | ||
|  |       std::memset(pc, 0, bytes); | ||
|  |    } | ||
|  | } | ||
|  | 
 | ||
|  | template <class Int> | ||
|  | inline void left_shift_limb(Int& result, double_limb_type s) | ||
|  | { | ||
|  |    limb_type offset = static_cast<limb_type>(s / Int::limb_bits); | ||
|  |    limb_type shift = static_cast<limb_type>(s % Int::limb_bits); | ||
|  | 
 | ||
|  |    unsigned ors = result.size(); | ||
|  |    if((ors == 1) && (!*result.limbs())) | ||
|  |       return; // shifting zero yields zero. | ||
|  |    unsigned rs = ors; | ||
|  |    if(shift && (result.limbs()[ors - 1] >> (Int::limb_bits - shift))) | ||
|  |       ++rs; // Most significant limb will overflow when shifted | ||
|  |    rs += offset; | ||
|  |    result.resize(rs, rs); | ||
|  | 
 | ||
|  |    typename Int::limb_pointer pr = result.limbs(); | ||
|  | 
 | ||
|  |    if(offset > rs) | ||
|  |    { | ||
|  |       // The result is shifted past the end of the result: | ||
|  |       result = static_cast<limb_type>(0); | ||
|  |       return; | ||
|  |    } | ||
|  | 
 | ||
|  |    unsigned i = rs - result.size(); | ||
|  |    for(; i < ors; ++i) | ||
|  |       pr[rs - 1 - i] = pr[ors - 1 - i]; | ||
|  |    for(; i < rs; ++i) | ||
|  |       pr[rs - 1 - i] = 0; | ||
|  | } | ||
|  | 
 | ||
|  | template <class Int> | ||
|  | inline void left_shift_generic(Int& result, double_limb_type s) | ||
|  | { | ||
|  |    limb_type offset = static_cast<limb_type>(s / Int::limb_bits); | ||
|  |    limb_type shift = static_cast<limb_type>(s % Int::limb_bits); | ||
|  | 
 | ||
|  |    unsigned ors = result.size(); | ||
|  |    if((ors == 1) && (!*result.limbs())) | ||
|  |       return; // shifting zero yields zero. | ||
|  |    unsigned rs = ors; | ||
|  |    if(shift && (result.limbs()[ors - 1] >> (Int::limb_bits - shift))) | ||
|  |       ++rs; // Most significant limb will overflow when shifted | ||
|  |    rs += offset; | ||
|  |    result.resize(rs, rs); | ||
|  |    bool truncated = result.size() != rs; | ||
|  | 
 | ||
|  |    typename Int::limb_pointer pr = result.limbs(); | ||
|  | 
 | ||
|  |    if(offset > rs) | ||
|  |    { | ||
|  |       // The result is shifted past the end of the result: | ||
|  |       result = static_cast<limb_type>(0); | ||
|  |       return; | ||
|  |    } | ||
|  | 
 | ||
|  |    unsigned i = rs - result.size(); | ||
|  |    // This code only works when shift is non-zero, otherwise we invoke undefined behaviour! | ||
|  |    BOOST_ASSERT(shift); | ||
|  |    if(!truncated) | ||
|  |    { | ||
|  |       if(rs > ors + offset) | ||
|  |       { | ||
|  |          pr[rs - 1 - i] = pr[ors - 1 - i] >> (Int::limb_bits - shift); | ||
|  |          --rs; | ||
|  |       } | ||
|  |       else | ||
|  |       { | ||
|  |          pr[rs - 1 - i] = pr[ors - 1 - i] << shift; | ||
|  |          if(ors > 1) | ||
|  |             pr[rs - 1 - i] |= pr[ors - 2 - i] >> (Int::limb_bits - shift); | ||
|  |          ++i; | ||
|  |       } | ||
|  |    } | ||
|  |    for(; ors > 1 + i; ++i) | ||
|  |    { | ||
|  |       pr[rs - 1 - i] = pr[ors - 1 - i] << shift; | ||
|  |       pr[rs - 1 - i] |= pr[ors - 2 - i] >> (Int::limb_bits - shift); | ||
|  |    } | ||
|  |    if(ors >= 1 + i) | ||
|  |    { | ||
|  |       pr[rs - 1 - i] = pr[ors - 1 - i] << shift; | ||
|  |       ++i; | ||
|  |    } | ||
|  |    for(; i < rs; ++i) | ||
|  |       pr[rs - 1 - i] = 0; | ||
|  | } | ||
|  | 
 | ||
|  | 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_left_shift( | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, | ||
|  |       double_limb_type s) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | ||
|  | { | ||
|  |    is_valid_bitwise_op(result, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type()); | ||
|  |    if(!s) | ||
|  |       return; | ||
|  | 
 | ||
|  | #if defined(BOOST_LITTLE_ENDIAN) && defined(BOOST_MP_USE_LIMB_SHIFT) | ||
|  |    static const limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits - 1; | ||
|  |    static const limb_type byte_shift_mask = CHAR_BIT - 1; | ||
|  |    if((s & limb_shift_mask) == 0) | ||
|  |    { | ||
|  |       left_shift_limb(result, s); | ||
|  |    } | ||
|  |    else if((s & byte_shift_mask) == 0) | ||
|  |    { | ||
|  |       left_shift_byte(result, s); | ||
|  |    } | ||
|  | #elif defined(BOOST_LITTLE_ENDIAN) | ||
|  |    static const limb_type byte_shift_mask = CHAR_BIT - 1; | ||
|  |    if((s & byte_shift_mask) == 0) | ||
|  |    { | ||
|  |       left_shift_byte(result, s); | ||
|  |    } | ||
|  | #else | ||
|  |    static const limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits - 1; | ||
|  |    if((s & limb_shift_mask) == 0) | ||
|  |    { | ||
|  |       left_shift_limb(result, s); | ||
|  |    } | ||
|  | #endif | ||
|  |    else | ||
|  |    { | ||
|  |       left_shift_generic(result, s); | ||
|  |    } | ||
|  |    // | ||
|  |    // We may have shifted off the end and have leading zeros: | ||
|  |    // | ||
|  |    result.normalize(); | ||
|  | } | ||
|  | 
 | ||
|  | template <class Int> | ||
|  | inline void right_shift_byte(Int& result, double_limb_type s) | ||
|  | { | ||
|  |    limb_type offset = static_cast<limb_type>(s / Int::limb_bits); | ||
|  |    limb_type shift; | ||
|  |    BOOST_ASSERT((s % CHAR_BIT) == 0); | ||
|  |    unsigned ors = result.size(); | ||
|  |    unsigned rs = ors; | ||
|  |    if(offset >= rs) | ||
|  |    { | ||
|  |       result = limb_type(0); | ||
|  |       return; | ||
|  |    } | ||
|  |    rs -= offset; | ||
|  |    typename Int::limb_pointer pr = result.limbs(); | ||
|  |    unsigned char* pc = reinterpret_cast<unsigned char*>(pr); | ||
|  |    shift = static_cast<limb_type>(s / CHAR_BIT); | ||
|  |    std::memmove(pc, pc + shift, ors * sizeof(pr[0]) - shift); | ||
|  |    shift = (sizeof(limb_type) - shift % sizeof(limb_type)) * CHAR_BIT; | ||
|  |    if(shift < Int::limb_bits) | ||
|  |    { | ||
|  |       pr[ors - offset - 1] &= (static_cast<limb_type>(1u) << shift) - 1; | ||
|  |       if(!pr[ors - offset - 1] && (rs > 1)) | ||
|  |          --rs; | ||
|  |    } | ||
|  |    result.resize(rs, rs); | ||
|  | } | ||
|  | 
 | ||
|  | template <class Int> | ||
|  | inline void right_shift_limb(Int& result, double_limb_type s) | ||
|  | { | ||
|  |    limb_type offset = static_cast<limb_type>(s / Int::limb_bits); | ||
|  |    BOOST_ASSERT((s % Int::limb_bits) == 0); | ||
|  |    unsigned ors = result.size(); | ||
|  |    unsigned rs = ors; | ||
|  |    if(offset >= rs) | ||
|  |    { | ||
|  |       result = limb_type(0); | ||
|  |       return; | ||
|  |    } | ||
|  |    rs -= offset; | ||
|  |    typename Int::limb_pointer pr = result.limbs(); | ||
|  |    unsigned i = 0; | ||
|  |    for(; i < rs; ++i) | ||
|  |       pr[i] = pr[i + offset]; | ||
|  |    result.resize(rs, rs); | ||
|  | } | ||
|  | 
 | ||
|  | template <class Int> | ||
|  | inline void right_shift_generic(Int& result, double_limb_type s) | ||
|  | { | ||
|  |    limb_type offset = static_cast<limb_type>(s / Int::limb_bits); | ||
|  |    limb_type shift = static_cast<limb_type>(s % Int::limb_bits); | ||
|  |    unsigned ors = result.size(); | ||
|  |    unsigned rs = ors; | ||
|  |    if(offset >= rs) | ||
|  |    { | ||
|  |       result = limb_type(0); | ||
|  |       return; | ||
|  |    } | ||
|  |    rs -= offset; | ||
|  |    typename Int::limb_pointer pr = result.limbs(); | ||
|  |    if((pr[ors - 1] >> shift) == 0) | ||
|  |    { | ||
|  |       if(--rs == 0) | ||
|  |       { | ||
|  |          result = limb_type(0); | ||
|  |          return; | ||
|  |       } | ||
|  |    } | ||
|  |    unsigned i = 0; | ||
|  | 
 | ||
|  |    // This code only works for non-zero shift, otherwise we invoke undefined behaviour! | ||
|  |    BOOST_ASSERT(shift); | ||
|  |    for(; i + offset + 1 < ors; ++i) | ||
|  |    { | ||
|  |       pr[i] = pr[i + offset] >> shift; | ||
|  |       pr[i] |= pr[i + offset + 1] << (Int::limb_bits - shift); | ||
|  |    } | ||
|  |    pr[i] = pr[i + offset] >> shift; | ||
|  |    result.resize(rs, rs); | ||
|  | } | ||
|  | 
 | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_int_check_type Checked1, class Allocator1> | ||
|  | inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1> >::value>::type | ||
|  |    eval_right_shift( | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1>& result, | ||
|  |       double_limb_type s) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1> >::value)) | ||
|  | { | ||
|  |    is_valid_bitwise_op(result, typename cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1>::checked_type()); | ||
|  |    if(!s) | ||
|  |       return; | ||
|  | 
 | ||
|  | #if defined(BOOST_LITTLE_ENDIAN) && defined(BOOST_MP_USE_LIMB_SHIFT) | ||
|  |    static const limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::limb_bits - 1; | ||
|  |    static const limb_type byte_shift_mask = CHAR_BIT - 1; | ||
|  |    if((s & limb_shift_mask) == 0) | ||
|  |       right_shift_limb(result, s); | ||
|  |    else if((s & byte_shift_mask) == 0) | ||
|  |       right_shift_byte(result, s); | ||
|  | #elif defined(BOOST_LITTLE_ENDIAN) | ||
|  |    static const limb_type byte_shift_mask = CHAR_BIT - 1; | ||
|  |    if((s & byte_shift_mask) == 0) | ||
|  |       right_shift_byte(result, s); | ||
|  | #else | ||
|  |    static const limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::limb_bits - 1; | ||
|  |    if((s & limb_shift_mask) == 0) | ||
|  |       right_shift_limb(result, s); | ||
|  | #endif | ||
|  |    else | ||
|  |       right_shift_generic(result, s); | ||
|  | } | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_int_check_type Checked1, class Allocator1> | ||
|  | inline typename enable_if_c<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1> >::value>::type | ||
|  |    eval_right_shift( | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>& result, | ||
|  |       double_limb_type s) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1> >::value)) | ||
|  | { | ||
|  |    is_valid_bitwise_op(result, typename cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::checked_type()); | ||
|  |    if(!s) | ||
|  |       return; | ||
|  | 
 | ||
|  |    bool is_neg = result.sign(); | ||
|  |    if(is_neg) | ||
|  |       eval_increment(result); | ||
|  | 
 | ||
|  | #if defined(BOOST_LITTLE_ENDIAN) && defined(BOOST_MP_USE_LIMB_SHIFT) | ||
|  |    static const limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::limb_bits - 1; | ||
|  |    static const limb_type byte_shift_mask = CHAR_BIT - 1; | ||
|  |    if((s & limb_shift_mask) == 0) | ||
|  |       right_shift_limb(result, s); | ||
|  |    else if((s & byte_shift_mask) == 0) | ||
|  |       right_shift_byte(result, s); | ||
|  | #elif defined(BOOST_LITTLE_ENDIAN) | ||
|  |    static const limb_type byte_shift_mask = CHAR_BIT - 1; | ||
|  |    if((s & byte_shift_mask) == 0) | ||
|  |       right_shift_byte(result, s); | ||
|  | #else | ||
|  |    static const limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::limb_bits - 1; | ||
|  |    if((s & limb_shift_mask) == 0) | ||
|  |       right_shift_limb(result, s); | ||
|  | #endif | ||
|  |    else | ||
|  |       right_shift_generic(result, s); | ||
|  |    if(is_neg) | ||
|  |       eval_decrement(result); | ||
|  | } | ||
|  | 
 | ||
|  | // | ||
|  | // Over again for trivial cpp_int's: | ||
|  | // | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class T> | ||
|  | BOOST_MP_FORCEINLINE typename enable_if<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> > >::type | ||
|  |    eval_left_shift(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, T s) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | ||
|  | { | ||
|  |    is_valid_bitwise_op(result, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type()); | ||
|  |    *result.limbs() = detail::checked_left_shift(*result.limbs(), s, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type()); | ||
|  |    result.normalize(); | ||
|  | } | ||
|  | 
 | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class T> | ||
|  | BOOST_MP_FORCEINLINE typename enable_if<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> > >::type | ||
|  |    eval_right_shift(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, T s) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | ||
|  | { | ||
|  |    // Nothing to check here... just make sure we don't invoke undefined behavior: | ||
|  |    is_valid_bitwise_op(result, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type()); | ||
|  |    *result.limbs() = (static_cast<unsigned>(s) >= sizeof(*result.limbs()) * CHAR_BIT) ? 0 : (result.sign() ? ((--*result.limbs()) >> s) + 1 : *result.limbs() >> s); | ||
|  |    if(result.sign() && (*result.limbs() == 0)) | ||
|  |       result = static_cast<signed_limb_type>(-1); | ||
|  | } | ||
|  | 
 | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2> | ||
|  | inline typename enable_if_c< | ||
|  |          is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value | ||
|  |          && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value | ||
|  |          && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value) | ||
|  |          >::type | ||
|  |    eval_complement( | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, | ||
|  |       const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | ||
|  | { | ||
|  |    BOOST_STATIC_ASSERT_MSG(((Checked1 != checked) || (Checked2 != checked)), "Attempt to take the complement of a signed type results in undefined behavior."); | ||
|  |    // | ||
|  |    // If we're not checked then emulate 2's complement behavior: | ||
|  |    // | ||
|  |    if(o.sign()) | ||
|  |    { | ||
|  |       *result.limbs() = *o.limbs() - 1; | ||
|  |       result.sign(false); | ||
|  |    } | ||
|  |    else | ||
|  |    { | ||
|  |       *result.limbs() = 1 + *o.limbs(); | ||
|  |       result.sign(true); | ||
|  |    } | ||
|  |    result.normalize(); | ||
|  | } | ||
|  | 
 | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2> | ||
|  | inline typename enable_if_c< | ||
|  |          is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value | ||
|  |          && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value | ||
|  |          && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value | ||
|  |          && is_unsigned_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value | ||
|  |          >::type | ||
|  |    eval_complement( | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, | ||
|  |       const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | ||
|  | { | ||
|  |    *result.limbs() = ~*o.limbs(); | ||
|  |    result.normalize(); | ||
|  | } | ||
|  | 
 | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2> | ||
|  | inline typename enable_if_c< | ||
|  |          is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value | ||
|  |          && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value | ||
|  |          && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value | ||
|  |          && is_unsigned_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value | ||
|  |          >::type | ||
|  |    eval_bitwise_and( | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, | ||
|  |       const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | ||
|  | { | ||
|  |    *result.limbs() &= *o.limbs(); | ||
|  | } | ||
|  | 
 | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2> | ||
|  | inline typename enable_if_c< | ||
|  |          is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value | ||
|  |          && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value | ||
|  |          && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value) | ||
|  |          >::type | ||
|  |    eval_bitwise_and( | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, | ||
|  |       const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | ||
|  | { | ||
|  |    is_valid_bitwise_op(result, o, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type()); | ||
|  | 
 | ||
|  |    using default_ops::eval_bit_test; | ||
|  |    using default_ops::eval_increment; | ||
|  | 
 | ||
|  |    if(result.sign() || o.sign()) | ||
|  |    { | ||
|  |       static const unsigned m = static_unsigned_max<static_unsigned_max<MinBits1, MinBits2>::value, static_unsigned_max<MaxBits1, MaxBits2>::value>::value; | ||
|  |       cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t1(result); | ||
|  |       cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t2(o); | ||
|  |       eval_bitwise_and(t1, t2); | ||
|  |       bool s = eval_bit_test(t1, m + 1); | ||
|  |       if(s) | ||
|  |       { | ||
|  |          eval_complement(t1, t1); | ||
|  |          eval_increment(t1); | ||
|  |       } | ||
|  |       result = t1; | ||
|  |       result.sign(s); | ||
|  |    } | ||
|  |    else | ||
|  |    { | ||
|  |       *result.limbs() &= *o.limbs(); | ||
|  |    } | ||
|  | } | ||
|  | 
 | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2> | ||
|  | inline typename enable_if_c< | ||
|  |          is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value | ||
|  |          && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value | ||
|  |          && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value | ||
|  |          && is_unsigned_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value | ||
|  |          >::type | ||
|  |    eval_bitwise_or( | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, | ||
|  |       const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | ||
|  | { | ||
|  |    *result.limbs() |= *o.limbs(); | ||
|  | } | ||
|  | 
 | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2> | ||
|  | inline typename enable_if_c< | ||
|  |          is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value | ||
|  |          && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value | ||
|  |          && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value) | ||
|  |          >::type | ||
|  |    eval_bitwise_or( | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, | ||
|  |       const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | ||
|  | { | ||
|  |    is_valid_bitwise_op(result, o, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type()); | ||
|  | 
 | ||
|  |    using default_ops::eval_bit_test; | ||
|  |    using default_ops::eval_increment; | ||
|  | 
 | ||
|  |    if(result.sign() || o.sign()) | ||
|  |    { | ||
|  |       static const unsigned m = static_unsigned_max<static_unsigned_max<MinBits1, MinBits2>::value, static_unsigned_max<MaxBits1, MaxBits2>::value>::value; | ||
|  |       cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t1(result); | ||
|  |       cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t2(o); | ||
|  |       eval_bitwise_or(t1, t2); | ||
|  |       bool s = eval_bit_test(t1, m + 1); | ||
|  |       if(s) | ||
|  |       { | ||
|  |          eval_complement(t1, t1); | ||
|  |          eval_increment(t1); | ||
|  |       } | ||
|  |       result = t1; | ||
|  |       result.sign(s); | ||
|  |    } | ||
|  |    else | ||
|  |    { | ||
|  |       *result.limbs() |= *o.limbs(); | ||
|  |       result.normalize(); | ||
|  |    } | ||
|  | } | ||
|  | 
 | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2> | ||
|  | inline typename enable_if_c< | ||
|  |          is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value | ||
|  |          && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value | ||
|  |          && is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value | ||
|  |          && is_unsigned_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value | ||
|  |          >::type | ||
|  |    eval_bitwise_xor( | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, | ||
|  |       const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | ||
|  | { | ||
|  |    *result.limbs() ^= *o.limbs(); | ||
|  | } | ||
|  | 
 | ||
|  | template <unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, unsigned MinBits2, unsigned MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2> | ||
|  | inline typename enable_if_c< | ||
|  |          is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value | ||
|  |          && is_trivial_cpp_int<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value | ||
|  |          && (is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value || is_signed_number<cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2> >::value) | ||
|  |          >::type | ||
|  |    eval_bitwise_xor( | ||
|  |       cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, | ||
|  |       const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) BOOST_MP_NOEXCEPT_IF((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value)) | ||
|  | { | ||
|  |    is_valid_bitwise_op(result, o, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type()); | ||
|  | 
 | ||
|  |    using default_ops::eval_bit_test; | ||
|  |    using default_ops::eval_increment; | ||
|  | 
 | ||
|  |    if(result.sign() || o.sign()) | ||
|  |    { | ||
|  |       static const unsigned m = static_unsigned_max<static_unsigned_max<MinBits1, MinBits2>::value, static_unsigned_max<MaxBits1, MaxBits2>::value>::value; | ||
|  |       cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t1(result); | ||
|  |       cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t2(o); | ||
|  |       eval_bitwise_xor(t1, t2); | ||
|  |       bool s = eval_bit_test(t1, m + 1); | ||
|  |       if(s) | ||
|  |       { | ||
|  |          eval_complement(t1, t1); | ||
|  |          eval_increment(t1); | ||
|  |       } | ||
|  |       result = t1; | ||
|  |       result.sign(s); | ||
|  |    } | ||
|  |    else | ||
|  |    { | ||
|  |       *result.limbs() ^= *o.limbs(); | ||
|  |    } | ||
|  | } | ||
|  | 
 | ||
|  | }}} // namespaces | ||
|  | 
 | ||
|  | #ifdef _MSC_VER | ||
|  | #pragma warning(pop) | ||
|  | #endif | ||
|  | 
 | ||
|  | #endif |