File indexing completed on 2025-01-18 09:42:13
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_MP_CPP_INT_BITWISE_HPP
0009 #define BOOST_MP_CPP_INT_BITWISE_HPP
0010
0011 #include <stdexcept>
0012 #include <type_traits>
0013 #include <boost/multiprecision/detail/endian.hpp>
0014 #include <boost/multiprecision/detail/no_exceptions_support.hpp>
0015 #include <boost/multiprecision/detail/assert.hpp>
0016
0017 #ifdef BOOST_MSVC
0018 #pragma warning(push)
0019 #pragma warning(disable : 4319)
0020 #endif
0021
0022
0023 namespace boost { namespace multiprecision { namespace backends {
0024
0025 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
0026 BOOST_MP_CXX14_CONSTEXPR void is_valid_bitwise_op(
0027 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
0028 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o, const std::integral_constant<int, checked>&)
0029 {
0030 if (result.sign() || o.sign())
0031 BOOST_MP_THROW_EXCEPTION(std::range_error("Bitwise operations on negative values results in undefined behavior."));
0032 }
0033
0034 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
0035 BOOST_MP_CXX14_CONSTEXPR void is_valid_bitwise_op(
0036 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&,
0037 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>&, const std::integral_constant<int, unchecked>&) {}
0038
0039 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_int_check_type Checked1, class Allocator1>
0040 BOOST_MP_CXX14_CONSTEXPR void is_valid_bitwise_op(
0041 const cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>& result, const std::integral_constant<int, checked>&)
0042 {
0043 if (result.sign())
0044 BOOST_MP_THROW_EXCEPTION(std::range_error("Bitwise operations on negative values results in undefined behavior."));
0045 }
0046
0047 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_int_check_type Checked1, class Allocator1>
0048 BOOST_MP_CXX14_CONSTEXPR void is_valid_bitwise_op(
0049 const cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1>&, const std::integral_constant<int, checked>&) {}
0050
0051 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
0052 BOOST_MP_CXX14_CONSTEXPR void is_valid_bitwise_op(
0053 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>&, const std::integral_constant<int, unchecked>&) {}
0054
0055 template <class CppInt1, class CppInt2, class Op>
0056 BOOST_MP_CXX14_CONSTEXPR void bitwise_op(
0057 CppInt1& result,
0058 const CppInt2& o,
0059 Op op, const std::integral_constant<bool, true>&) noexcept((is_non_throwing_cpp_int<CppInt1>::value))
0060 {
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074 is_valid_bitwise_op(result, o, typename CppInt1::checked_type());
0075
0076
0077
0078 std::size_t rs = result.size();
0079 std::size_t os = o.size();
0080 std::size_t m(0), x(0);
0081 minmax(rs, os, m, x);
0082 result.resize(x, x);
0083 typename CppInt1::limb_pointer pr = result.limbs();
0084 typename CppInt2::const_limb_pointer po = o.limbs();
0085 for (std::size_t i = rs; i < x; ++i)
0086 pr[i] = 0;
0087
0088 limb_type next_limb = 0;
0089
0090 if (!result.sign())
0091 {
0092 if (!o.sign())
0093 {
0094 for (std::size_t i = 0; i < os; ++i)
0095 pr[i] = op(pr[i], po[i]);
0096 for (std::size_t i = os; i < x; ++i)
0097 pr[i] = op(pr[i], limb_type(0));
0098 }
0099 else
0100 {
0101
0102 double_limb_type carry = 1;
0103 for (std::size_t i = 0; i < os; ++i)
0104 {
0105 carry += static_cast<double_limb_type>(~po[i]);
0106 pr[i] = op(pr[i], static_cast<limb_type>(carry));
0107 carry >>= CppInt1::limb_bits;
0108 }
0109 for (std::size_t i = os; i < x; ++i)
0110 {
0111 carry += static_cast<double_limb_type>(~limb_type(0));
0112 pr[i] = op(pr[i], static_cast<limb_type>(carry));
0113 carry >>= CppInt1::limb_bits;
0114 }
0115
0116 carry += static_cast<double_limb_type>(~limb_type(0));
0117 next_limb = op(limb_type(0), static_cast<limb_type>(carry));
0118 }
0119 }
0120 else
0121 {
0122 if (!o.sign())
0123 {
0124
0125 double_limb_type carry = 1;
0126 for (std::size_t i = 0; i < os; ++i)
0127 {
0128 carry += static_cast<double_limb_type>(~pr[i]);
0129 pr[i] = op(static_cast<limb_type>(carry), po[i]);
0130 carry >>= CppInt1::limb_bits;
0131 }
0132 for (std::size_t i = os; i < x; ++i)
0133 {
0134 carry += static_cast<double_limb_type>(~pr[i]);
0135 pr[i] = op(static_cast<limb_type>(carry), limb_type(0));
0136 carry >>= CppInt1::limb_bits;
0137 }
0138
0139 carry += static_cast<double_limb_type>(~limb_type(0));
0140 next_limb = op(static_cast<limb_type>(carry), limb_type(0));
0141 }
0142 else
0143 {
0144
0145 double_limb_type r_carry = 1;
0146 double_limb_type o_carry = 1;
0147 for (std::size_t i = 0; i < os; ++i)
0148 {
0149 r_carry += static_cast<double_limb_type>(~pr[i]);
0150 o_carry += static_cast<double_limb_type>(~po[i]);
0151 pr[i] = op(static_cast<limb_type>(r_carry), static_cast<limb_type>(o_carry));
0152 r_carry >>= CppInt1::limb_bits;
0153 o_carry >>= CppInt1::limb_bits;
0154 }
0155 for (std::size_t i = os; i < x; ++i)
0156 {
0157 r_carry += static_cast<double_limb_type>(~pr[i]);
0158 o_carry += static_cast<double_limb_type>(~limb_type(0));
0159 pr[i] = op(static_cast<limb_type>(r_carry), static_cast<limb_type>(o_carry));
0160 r_carry >>= CppInt1::limb_bits;
0161 o_carry >>= CppInt1::limb_bits;
0162 }
0163
0164 r_carry += static_cast<double_limb_type>(~limb_type(0));
0165 o_carry += static_cast<double_limb_type>(~limb_type(0));
0166 next_limb = op(static_cast<limb_type>(r_carry), static_cast<limb_type>(o_carry));
0167 }
0168 }
0169
0170
0171
0172 if (static_cast<signed_limb_type>(next_limb) < 0)
0173 {
0174 double_limb_type carry = 1;
0175 for (std::size_t i = 0; i < x; ++i)
0176 {
0177 carry += static_cast<double_limb_type>(~pr[i]);
0178 pr[i] = static_cast<limb_type>(carry);
0179 carry >>= CppInt1::limb_bits;
0180 }
0181 if (carry)
0182 {
0183 result.resize(x + 1, x);
0184 if (result.size() > x)
0185 result.limbs()[x] = static_cast<limb_type>(carry);
0186 }
0187 result.sign(true);
0188 }
0189 else
0190 result.sign(false);
0191
0192 result.normalize();
0193 }
0194
0195 template <class CppInt1, class CppInt2, class Op>
0196 BOOST_MP_CXX14_CONSTEXPR void bitwise_op(
0197 CppInt1& result,
0198 const CppInt2& o,
0199 Op op, const std::integral_constant<bool, false>&) noexcept((is_non_throwing_cpp_int<CppInt1>::value))
0200 {
0201
0202
0203
0204
0205
0206 std::size_t rs = result.size();
0207 std::size_t os = o.size();
0208 std::size_t m(0), x(0);
0209 minmax(rs, os, m, x);
0210 result.resize(x, x);
0211 typename CppInt1::limb_pointer pr = result.limbs();
0212 typename CppInt2::const_limb_pointer po = o.limbs();
0213 for (std::size_t i = rs; i < x; ++i)
0214 pr[i] = 0;
0215
0216 for (std::size_t i = 0; i < os; ++i)
0217 pr[i] = op(pr[i], po[i]);
0218 for (std::size_t i = os; i < x; ++i)
0219 pr[i] = op(pr[i], limb_type(0));
0220
0221 result.normalize();
0222 }
0223
0224 struct bit_and
0225 {
0226 BOOST_MP_CXX14_CONSTEXPR limb_type operator()(limb_type a, limb_type b) const noexcept { return a & b; }
0227 };
0228 struct bit_or
0229 {
0230 BOOST_MP_CXX14_CONSTEXPR limb_type operator()(limb_type a, limb_type b) const noexcept { return a | b; }
0231 };
0232 struct bit_xor
0233 {
0234 BOOST_MP_CXX14_CONSTEXPR limb_type operator()(limb_type a, limb_type b) const noexcept { return a ^ b; }
0235 };
0236
0237 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
0238 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!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
0239 eval_bitwise_and(
0240 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
0241 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
0242 {
0243 bitwise_op(result, o, bit_and(),
0244 std::integral_constant<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 > ());
0245 }
0246
0247 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
0248 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!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
0249 eval_bitwise_or(
0250 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
0251 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
0252 {
0253 bitwise_op(result, o, bit_or(),
0254 std::integral_constant<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 > ());
0255 }
0256
0257 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
0258 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!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
0259 eval_bitwise_xor(
0260 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
0261 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
0262 {
0263 bitwise_op(result, o, bit_xor(),
0264 std::integral_constant<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 > ());
0265 }
0266
0267
0268
0269 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_int_check_type Checked1, class Allocator1>
0270 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1> >::value>::type
0271 eval_bitwise_and(
0272 cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1>& result,
0273 limb_type l) noexcept
0274 {
0275 result.limbs()[0] &= l;
0276 result.resize(1, 1);
0277 }
0278
0279 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_int_check_type Checked1, class Allocator1>
0280 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1> >::value>::type
0281 eval_bitwise_or(
0282 cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1>& result,
0283 limb_type l) noexcept
0284 {
0285 result.limbs()[0] |= l;
0286 }
0287
0288 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_int_check_type Checked1, class Allocator1>
0289 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1> >::value>::type
0290 eval_bitwise_xor(
0291 cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1>& result,
0292 limb_type l) noexcept
0293 {
0294 result.limbs()[0] ^= l;
0295 }
0296
0297 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
0298 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<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
0299 eval_complement(
0300 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
0301 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
0302 {
0303 static_assert(((Checked1 != checked) || (Checked2 != checked)), "Attempt to take the complement of a signed type results in undefined behavior.");
0304
0305 result = o;
0306 eval_increment(result);
0307 result.negate();
0308 }
0309
0310 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
0311 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<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
0312 eval_complement(
0313 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
0314 const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
0315 {
0316 std::size_t os = o.size();
0317 result.resize(SIZE_MAX, os);
0318 for (std::size_t i = 0; i < os; ++i)
0319 result.limbs()[i] = ~o.limbs()[i];
0320 for (std::size_t i = os; i < result.size(); ++i)
0321 result.limbs()[i] = ~static_cast<limb_type>(0);
0322 result.normalize();
0323 }
0324
0325 template <class Int>
0326 inline void left_shift_byte(Int& result, double_limb_type s)
0327 {
0328 limb_type offset = static_cast<limb_type>(s / Int::limb_bits);
0329 limb_type shift = static_cast<limb_type>(s % Int::limb_bits);
0330 std::size_t ors = result.size();
0331 if ((ors == 1) && (!*result.limbs()))
0332 return;
0333 std::size_t rs = ors;
0334 if (shift && (result.limbs()[ors - 1] >> (Int::limb_bits - shift)))
0335 ++rs;
0336 rs += offset;
0337 result.resize(rs, rs);
0338 rs = result.size();
0339
0340 typename Int::limb_pointer pr = result.limbs();
0341
0342 if (rs != ors)
0343 pr[rs - 1] = 0u;
0344 std::size_t bytes = static_cast<std::size_t>(s / CHAR_BIT);
0345 std::size_t len = (std::min)(ors * sizeof(limb_type), rs * sizeof(limb_type) - bytes);
0346 if (bytes >= rs * sizeof(limb_type))
0347 result = static_cast<limb_type>(0u);
0348 else
0349 {
0350 unsigned char* pc = reinterpret_cast<unsigned char*>(pr);
0351 std::memmove(pc + bytes, pc, len);
0352 std::memset(pc, 0, bytes);
0353 }
0354 }
0355
0356 template <class Int>
0357 inline BOOST_MP_CXX14_CONSTEXPR void left_shift_limb(Int& result, double_limb_type s)
0358 {
0359 limb_type offset = static_cast<limb_type>(s / Int::limb_bits);
0360 limb_type shift = static_cast<limb_type>(s % Int::limb_bits);
0361
0362 std::size_t ors = result.size();
0363 if ((ors == 1) && (!*result.limbs()))
0364 return;
0365 std::size_t rs = ors;
0366 if (shift && (result.limbs()[ors - 1] >> (Int::limb_bits - shift)))
0367 ++rs;
0368 rs += offset;
0369 result.resize(rs, rs);
0370
0371 typename Int::limb_pointer pr = result.limbs();
0372
0373 if (offset > rs)
0374 {
0375
0376 result = static_cast<limb_type>(0);
0377 return;
0378 }
0379
0380 std::size_t i = rs - result.size();
0381 for (; i < ors; ++i)
0382 pr[rs - 1 - i] = pr[ors - 1 - i];
0383 #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
0384 if (BOOST_MP_IS_CONST_EVALUATED(s))
0385 {
0386 for (; i < rs; ++i)
0387 pr[rs - 1 - i] = 0;
0388 }
0389 else
0390 #endif
0391 {
0392 std::memset(pr, 0, (rs - i) * sizeof(*pr));
0393 }
0394 }
0395
0396 template <class Int>
0397 inline BOOST_MP_CXX14_CONSTEXPR void left_shift_generic(Int& result, double_limb_type s)
0398 {
0399 limb_type offset = static_cast<limb_type>(s / Int::limb_bits);
0400 limb_type shift = static_cast<limb_type>(s % Int::limb_bits);
0401
0402 std::size_t ors = result.size();
0403 if ((ors == 1) && (!*result.limbs()))
0404 return;
0405 std::size_t rs = ors;
0406 if (shift && (result.limbs()[ors - 1] >> (Int::limb_bits - shift)))
0407 ++rs;
0408 rs += offset;
0409 result.resize(rs, rs);
0410 bool truncated = result.size() != rs;
0411
0412 typename Int::limb_pointer pr = result.limbs();
0413
0414 if (offset > rs)
0415 {
0416
0417 result = static_cast<limb_type>(0);
0418 return;
0419 }
0420
0421 std::size_t i = rs - result.size();
0422
0423 BOOST_MP_ASSERT(shift);
0424 if (!truncated)
0425 {
0426 if (rs > ors + offset)
0427 {
0428 pr[rs - 1 - i] = pr[ors - 1 - i] >> (Int::limb_bits - shift);
0429 --rs;
0430 }
0431 else
0432 {
0433 pr[rs - 1 - i] = pr[ors - 1 - i] << shift;
0434 if (ors > 1)
0435 pr[rs - 1 - i] |= pr[ors - 2 - i] >> (Int::limb_bits - shift);
0436 ++i;
0437 }
0438 }
0439 for (; rs - i >= static_cast<std::size_t>(static_cast<std::size_t>(2u) + offset); ++i)
0440 {
0441 pr[rs - 1 - i] = pr[rs - 1 - i - offset] << shift;
0442 pr[rs - 1 - i] |= pr[rs - 2 - i - offset] >> (Int::limb_bits - shift);
0443 }
0444 if (rs - i >= static_cast<std::size_t>(static_cast<std::size_t>(1u) + offset))
0445 {
0446 pr[rs - 1 - i] = pr[rs - 1 - i - offset] << shift;
0447 ++i;
0448 }
0449 #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
0450 if (BOOST_MP_IS_CONST_EVALUATED(s))
0451 {
0452 for (; i < rs; ++i)
0453 pr[rs - 1 - i] = 0;
0454 }
0455 else
0456 #endif
0457 {
0458 std::memset(pr, 0, (rs - i) * sizeof(*pr));
0459 }
0460 }
0461
0462 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1>
0463 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value>::type
0464 eval_left_shift(
0465 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
0466 double_limb_type s) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
0467 {
0468 is_valid_bitwise_op(result, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
0469 if (!s)
0470 return;
0471
0472 #if BOOST_MP_ENDIAN_LITTLE_BYTE && defined(BOOST_MP_USE_LIMB_SHIFT)
0473 constexpr limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits - 1;
0474 constexpr limb_type byte_shift_mask = CHAR_BIT - 1;
0475
0476 if ((s & limb_shift_mask) == 0)
0477 {
0478 left_shift_limb(result, s);
0479 }
0480 #ifdef BOOST_MP_NO_CONSTEXPR_DETECTION
0481 else if ((s & byte_shift_mask) == 0)
0482 #else
0483 else if (((s & byte_shift_mask) == 0) && !BOOST_MP_IS_CONST_EVALUATED(s))
0484 #endif
0485 {
0486 left_shift_byte(result, s);
0487 }
0488 #elif BOOST_MP_ENDIAN_LITTLE_BYTE
0489 constexpr limb_type byte_shift_mask = CHAR_BIT - 1;
0490
0491 #ifdef BOOST_MP_NO_CONSTEXPR_DETECTION
0492 if ((s & byte_shift_mask) == 0)
0493 #else
0494 constexpr limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits - 1;
0495 if (BOOST_MP_IS_CONST_EVALUATED(s) && ((s & limb_shift_mask) == 0))
0496 left_shift_limb(result, s);
0497 else if (((s & byte_shift_mask) == 0) && !BOOST_MP_IS_CONST_EVALUATED(s))
0498 #endif
0499 {
0500 left_shift_byte(result, s);
0501 }
0502 #else
0503 constexpr limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::limb_bits - 1;
0504
0505 if ((s & limb_shift_mask) == 0)
0506 {
0507 left_shift_limb(result, s);
0508 }
0509 #endif
0510 else
0511 {
0512 left_shift_generic(result, s);
0513 }
0514
0515
0516
0517 result.normalize();
0518 }
0519
0520 template <class Int>
0521 inline void right_shift_byte(Int& result, double_limb_type s)
0522 {
0523 limb_type offset = static_cast<limb_type>(s / Int::limb_bits);
0524 BOOST_MP_ASSERT((s % CHAR_BIT) == 0);
0525 std::size_t ors = result.size();
0526 std::size_t rs = ors;
0527 if (offset >= rs)
0528 {
0529 result = limb_type(0);
0530 return;
0531 }
0532 rs -= offset;
0533 typename Int::limb_pointer pr = result.limbs();
0534 unsigned char* pc = reinterpret_cast<unsigned char*>(pr);
0535 limb_type shift = static_cast<limb_type>(s / CHAR_BIT);
0536 std::memmove(pc, pc + shift, ors * sizeof(pr[0]) - shift);
0537 shift = (sizeof(limb_type) - shift % sizeof(limb_type)) * CHAR_BIT;
0538 if (shift < Int::limb_bits)
0539 {
0540 pr[ors - offset - 1] &= (static_cast<limb_type>(1u) << shift) - 1;
0541 if (!pr[ors - offset - 1] && (rs > 1))
0542 --rs;
0543 }
0544 result.resize(rs, rs);
0545 }
0546
0547 template <class Int>
0548 inline BOOST_MP_CXX14_CONSTEXPR void right_shift_limb(Int& result, double_limb_type s)
0549 {
0550 limb_type offset = static_cast<limb_type>(s / Int::limb_bits);
0551 BOOST_MP_ASSERT((s % Int::limb_bits) == 0);
0552 std::size_t ors = result.size();
0553 std::size_t rs = ors;
0554 if (offset >= rs)
0555 {
0556 result = limb_type(0);
0557 return;
0558 }
0559 rs -= offset;
0560 typename Int::limb_pointer pr = result.limbs();
0561 std::size_t i = 0;
0562 for (; i < rs; ++i)
0563 pr[i] = pr[i + offset];
0564 result.resize(rs, rs);
0565 }
0566
0567 template <class Int>
0568 inline BOOST_MP_CXX14_CONSTEXPR void right_shift_generic(Int& result, double_limb_type s)
0569 {
0570 limb_type offset = static_cast<limb_type>(s / Int::limb_bits);
0571 limb_type shift = static_cast<limb_type>(s % Int::limb_bits);
0572 std::size_t ors = result.size();
0573 std::size_t rs = ors;
0574 if (offset >= rs)
0575 {
0576 result = limb_type(0);
0577 return;
0578 }
0579 rs -= offset;
0580 typename Int::limb_pointer pr = result.limbs();
0581 if ((pr[ors - 1] >> shift) == 0)
0582 {
0583 if (--rs == 0)
0584 {
0585 result = limb_type(0);
0586 return;
0587 }
0588 }
0589 std::size_t i = 0;
0590
0591
0592 BOOST_MP_ASSERT(shift);
0593 for (; i + offset + 1 < ors; ++i)
0594 {
0595 pr[i] = pr[i + offset] >> shift;
0596 pr[i] |= pr[i + offset + 1] << (Int::limb_bits - shift);
0597 }
0598 pr[i] = pr[i + offset] >> shift;
0599 result.resize(rs, rs);
0600 }
0601
0602 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_int_check_type Checked1, class Allocator1>
0603 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1> >::value>::type
0604 eval_right_shift(
0605 cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1>& result,
0606 double_limb_type s) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1> >::value))
0607 {
0608 is_valid_bitwise_op(result, typename cpp_int_backend<MinBits1, MaxBits1, unsigned_magnitude, Checked1, Allocator1>::checked_type());
0609 if (!s)
0610 return;
0611
0612 #if BOOST_MP_ENDIAN_LITTLE_BYTE && defined(BOOST_MP_USE_LIMB_SHIFT)
0613 constexpr limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::limb_bits - 1;
0614 constexpr limb_type byte_shift_mask = CHAR_BIT - 1;
0615
0616 if ((s & limb_shift_mask) == 0)
0617 right_shift_limb(result, s);
0618 #ifdef BOOST_MP_NO_CONSTEXPR_DETECTION
0619 else if ((s & byte_shift_mask) == 0)
0620 #else
0621 else if (((s & byte_shift_mask) == 0) && !BOOST_MP_IS_CONST_EVALUATED(s))
0622 #endif
0623 right_shift_byte(result, s);
0624 #elif BOOST_MP_ENDIAN_LITTLE_BYTE
0625 constexpr limb_type byte_shift_mask = CHAR_BIT - 1;
0626
0627 #ifdef BOOST_MP_NO_CONSTEXPR_DETECTION
0628 if ((s & byte_shift_mask) == 0)
0629 #else
0630 constexpr limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::limb_bits - 1;
0631 if (BOOST_MP_IS_CONST_EVALUATED(s) && ((s & limb_shift_mask) == 0))
0632 right_shift_limb(result, s);
0633 else if (((s & byte_shift_mask) == 0) && !BOOST_MP_IS_CONST_EVALUATED(s))
0634 #endif
0635 right_shift_byte(result, s);
0636 #else
0637 constexpr limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::limb_bits - 1;
0638
0639 if ((s & limb_shift_mask) == 0)
0640 right_shift_limb(result, s);
0641 #endif
0642 else
0643 right_shift_generic(result, s);
0644 }
0645 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_int_check_type Checked1, class Allocator1>
0646 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<!is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1> >::value>::type
0647 eval_right_shift(
0648 cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>& result,
0649 double_limb_type s) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1> >::value))
0650 {
0651 is_valid_bitwise_op(result, typename cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::checked_type());
0652 if (!s)
0653 return;
0654
0655 bool is_neg = result.sign();
0656 if (is_neg)
0657 eval_increment(result);
0658
0659 #if BOOST_MP_ENDIAN_LITTLE_BYTE && defined(BOOST_MP_USE_LIMB_SHIFT)
0660 constexpr limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::limb_bits - 1;
0661 constexpr limb_type byte_shift_mask = CHAR_BIT - 1;
0662
0663 if ((s & limb_shift_mask) == 0)
0664 right_shift_limb(result, s);
0665 #ifdef BOOST_MP_NO_CONSTEXPR_DETECTION
0666 else if ((s & byte_shift_mask) == 0)
0667 #else
0668 else if (((s & byte_shift_mask) == 0) && !BOOST_MP_IS_CONST_EVALUATED(s))
0669 #endif
0670 right_shift_byte(result, s);
0671 #elif BOOST_MP_ENDIAN_LITTLE_BYTE
0672 constexpr limb_type byte_shift_mask = CHAR_BIT - 1;
0673
0674 #ifdef BOOST_MP_NO_CONSTEXPR_DETECTION
0675 if ((s & byte_shift_mask) == 0)
0676 #else
0677 constexpr limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::limb_bits - 1;
0678 if (BOOST_MP_IS_CONST_EVALUATED(s) && ((s & limb_shift_mask) == 0))
0679 right_shift_limb(result, s);
0680 else if (((s & byte_shift_mask) == 0) && !BOOST_MP_IS_CONST_EVALUATED(s))
0681 #endif
0682 right_shift_byte(result, s);
0683 #else
0684 constexpr limb_type limb_shift_mask = cpp_int_backend<MinBits1, MaxBits1, signed_magnitude, Checked1, Allocator1>::limb_bits - 1;
0685
0686 if ((s & limb_shift_mask) == 0)
0687 right_shift_limb(result, s);
0688 #endif
0689 else
0690 right_shift_generic(result, s);
0691 if (is_neg)
0692 eval_decrement(result);
0693 }
0694
0695
0696
0697
0698 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class T>
0699 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value >::type
0700 eval_left_shift(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, T s) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
0701 {
0702 is_valid_bitwise_op(result, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
0703 *result.limbs() = detail::checked_left_shift(*result.limbs(), s, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
0704 result.normalize();
0705 }
0706
0707 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, class T>
0708 BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value >::type
0709 eval_right_shift(cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result, T s) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
0710 {
0711
0712 is_valid_bitwise_op(result, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
0713 *result.limbs() = (static_cast<unsigned>(s) >= sizeof(*result.limbs()) * CHAR_BIT) ? 0 : (result.sign() ? ((--*result.limbs()) >> s) + 1 : *result.limbs() >> s);
0714 if (result.sign() && (*result.limbs() == 0))
0715 result = static_cast<signed_limb_type>(-1);
0716 }
0717
0718 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
0719 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
0720 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
0721 eval_complement(
0722 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
0723 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
0724 {
0725 static_assert(((Checked1 != checked) || (Checked2 != checked)), "Attempt to take the complement of a signed type results in undefined behavior.");
0726
0727
0728
0729 if (o.sign())
0730 {
0731 *result.limbs() = *o.limbs() - 1;
0732 result.sign(false);
0733 }
0734 else
0735 {
0736 *result.limbs() = 1 + *o.limbs();
0737 result.sign(true);
0738 }
0739 result.normalize();
0740 }
0741
0742 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
0743 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
0744 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
0745 eval_complement(
0746 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
0747 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
0748 {
0749 *result.limbs() = ~*o.limbs();
0750 result.normalize();
0751 }
0752
0753 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
0754 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
0755 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
0756 eval_bitwise_and(
0757 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
0758 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
0759 {
0760 *result.limbs() &= *o.limbs();
0761 }
0762
0763 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
0764 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
0765 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
0766 eval_bitwise_and(
0767 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
0768 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
0769 {
0770 is_valid_bitwise_op(result, o, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
0771
0772 using default_ops::eval_bit_test;
0773 using default_ops::eval_increment;
0774
0775 if (result.sign() || o.sign())
0776 {
0777 constexpr std::size_t m = detail::static_unsigned_max<detail::static_unsigned_max<MinBits1, MinBits2>::value, detail::static_unsigned_max<MaxBits1, MaxBits2>::value>::value;
0778 cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t1(result);
0779 cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t2(o);
0780 eval_bitwise_and(t1, t2);
0781 bool s = eval_bit_test(t1, m + 1);
0782 if (s)
0783 {
0784 eval_complement(t1, t1);
0785 eval_increment(t1);
0786 }
0787 result = t1;
0788 result.sign(s);
0789 }
0790 else
0791 {
0792 *result.limbs() &= *o.limbs();
0793 }
0794 }
0795
0796 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
0797 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
0798 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
0799 eval_bitwise_or(
0800 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
0801 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
0802 {
0803 *result.limbs() |= *o.limbs();
0804 }
0805
0806 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
0807 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
0808 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
0809 eval_bitwise_or(
0810 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
0811 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
0812 {
0813 is_valid_bitwise_op(result, o, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
0814
0815 using default_ops::eval_bit_test;
0816 using default_ops::eval_increment;
0817
0818 if (result.sign() || o.sign())
0819 {
0820 constexpr std::size_t m = detail::static_unsigned_max<detail::static_unsigned_max<MinBits1, MinBits2>::value, detail::static_unsigned_max<MaxBits1, MaxBits2>::value>::value;
0821 cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t1(result);
0822 cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t2(o);
0823 eval_bitwise_or(t1, t2);
0824 bool s = eval_bit_test(t1, m + 1);
0825 if (s)
0826 {
0827 eval_complement(t1, t1);
0828 eval_increment(t1);
0829 }
0830 result = t1;
0831 result.sign(s);
0832 }
0833 else
0834 {
0835 *result.limbs() |= *o.limbs();
0836 result.normalize();
0837 }
0838 }
0839
0840 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
0841 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
0842 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
0843 eval_bitwise_xor(
0844 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
0845 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
0846 {
0847 *result.limbs() ^= *o.limbs();
0848 }
0849
0850 template <std::size_t MinBits1, std::size_t MaxBits1, cpp_integer_type SignType1, cpp_int_check_type Checked1, class Allocator1, std::size_t MinBits2, std::size_t MaxBits2, cpp_integer_type SignType2, cpp_int_check_type Checked2, class Allocator2>
0851 inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
0852 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
0853 eval_bitwise_xor(
0854 cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& result,
0855 const cpp_int_backend<MinBits2, MaxBits2, SignType2, Checked2, Allocator2>& o) noexcept((is_non_throwing_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value))
0856 {
0857 is_valid_bitwise_op(result, o, typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::checked_type());
0858
0859 using default_ops::eval_bit_test;
0860 using default_ops::eval_increment;
0861
0862 if (result.sign() || o.sign())
0863 {
0864 constexpr std::size_t m = detail::static_unsigned_max<detail::static_unsigned_max<MinBits1, MinBits2>::value, detail::static_unsigned_max<MaxBits1, MaxBits2>::value>::value;
0865 cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t1(result);
0866 cpp_int_backend<m + 1, m + 1, unsigned_magnitude, unchecked, void> t2(o);
0867 eval_bitwise_xor(t1, t2);
0868 bool s = eval_bit_test(t1, m + 1);
0869 if (s)
0870 {
0871 eval_complement(t1, t1);
0872 eval_increment(t1);
0873 }
0874 result = t1;
0875 result.sign(s);
0876 }
0877 else
0878 {
0879 *result.limbs() ^= *o.limbs();
0880 }
0881 }
0882
0883 }}}
0884
0885 #ifdef BOOST_MSVC
0886 #pragma warning(pop)
0887 #endif
0888
0889 #endif