Server IP : 172.67.216.182 / Your IP : 162.158.108.157 Web Server : Apache System : Linux krdc-ubuntu-s-2vcpu-4gb-amd-blr1-01.localdomain 5.15.0-142-generic #152-Ubuntu SMP Mon May 19 10:54:31 UTC 2025 x86_64 User : www ( 1000) PHP Version : 7.4.33 Disable Function : passthru,exec,system,putenv,chroot,chgrp,chown,shell_exec,popen,proc_open,pcntl_exec,ini_alter,ini_restore,dl,openlog,syslog,readlink,symlink,popepassthru,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,imap_open,apache_setenv MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /www/server/mysql/src/boost/boost_1_59_0/boost/multiprecision/cpp_int/ |
Upload File : |
/////////////////////////////////////////////////////////////// // 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 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 <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; limb_type offset = static_cast<limb_type>(s / cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits); limb_type shift = static_cast<limb_type>(s % cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::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] >> (cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits - shift))) ++rs; // Most significant limb will overflow when shifted rs += offset; result.resize(rs, rs); bool truncated = result.size() != rs; typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::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(); if(shift) { // This code only works when shift is non-zero, otherwise we invoke undefined behaviour! if(!truncated) { if(rs > ors + offset) { pr[rs - 1 - i] = pr[ors - 1 - i] >> (cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::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] >> (cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::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] >> (cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::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; } else { for(; i < ors; ++i) pr[rs - 1 - i] = pr[ors - 1 - i]; for(; i < rs; ++i) pr[rs - 1 - i] = 0; } // // We may have shifted off the end and have leading zeros: // result.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_right_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; bool is_neg = result.sign(); if(is_neg) eval_increment(result); limb_type offset = static_cast<limb_type>(s / cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits); limb_type shift = static_cast<limb_type>(s % cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits); unsigned ors = result.size(); unsigned rs = ors; if(offset >= rs) { if(is_neg) result = signed_limb_type(-1); else result = limb_type(0); return; } rs -= offset; typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_pointer pr = result.limbs(); if((pr[ors - 1] >> shift) == 0) --rs; if(rs == 0) { if(is_neg) result = signed_limb_type(-1); else result = limb_type(0); return; } unsigned i = 0; if(shift) { // This code only works for non-zero shift, otherwise we invoke undefined behaviour! for(; i + offset + 1 < ors; ++i) { pr[i] = pr[i + offset] >> shift; pr[i] |= pr[i + offset + 1] << (cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits - shift); } pr[i] = pr[i + offset] >> shift; } else { for(; i < rs; ++i) pr[i] = pr[i + offset]; } result.resize(rs, rs); 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.limbs() >> s; } 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_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_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_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_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(); } } 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_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(); } }}} // namespaces #endif