| 54 | |
| 55 | template <class CppInt1, class CppInt2, class Op> |
| 56 | BOOST_MP_CXX14_CONSTEXPR void bitwise_op( |
| 57 | CppInt1& result, |
| 58 | const CppInt2& o, |
| 59 | Op op, const std::integral_constant<bool, true>&) noexcept((is_non_throwing_cpp_int<CppInt1>::value)) |
| 60 | { |
| 61 | // |
| 62 | // There are 4 cases: |
| 63 | // * Both positive. |
| 64 | // * result negative, o positive. |
| 65 | // * o negative, result positive. |
| 66 | // * Both negative. |
| 67 | // |
| 68 | // When one arg is negative we convert to 2's complement form "on the fly", |
| 69 | // and then convert back to signed-magnitude form at the end. |
| 70 | // |
| 71 | // Note however, that if the type is checked, then bitwise ops on negative values |
| 72 | // are not permitted and an exception will result. |
| 73 | // |
| 74 | is_valid_bitwise_op(result, o, typename CppInt1::checked_type()); |
| 75 | // |
| 76 | // First figure out how big the result needs to be and set up some data: |
| 77 | // |
| 78 | std::size_t rs = result.size(); |
| 79 | std::size_t os = o.size(); |
| 80 | std::size_t m(0), x(0); |
| 81 | minmax(rs, os, m, x); |
| 82 | result.resize(x, x); |
| 83 | typename CppInt1::limb_pointer pr = result.limbs(); |
| 84 | typename CppInt2::const_limb_pointer po = o.limbs(); |
| 85 | for (std::size_t i = rs; i < x; ++i) |
| 86 | pr[i] = 0; |
| 87 | |
| 88 | limb_type next_limb = 0; |
| 89 | |
| 90 | if (!result.sign()) |
| 91 | { |
| 92 | if (!o.sign()) |
| 93 | { |
| 94 | for (std::size_t i = 0; i < os; ++i) |
| 95 | pr[i] = op(pr[i], po[i]); |
| 96 | for (std::size_t i = os; i < x; ++i) |
| 97 | pr[i] = op(pr[i], limb_type(0)); |
| 98 | } |
| 99 | else |
| 100 | { |
| 101 | // "o" is negative: |
| 102 | double_limb_type carry = 1; |
| 103 | for (std::size_t i = 0; i < os; ++i) |
| 104 | { |
| 105 | carry += static_cast<double_limb_type>(~po[i]); |
| 106 | pr[i] = op(pr[i], static_cast<limb_type>(carry)); |
| 107 | carry >>= CppInt1::limb_bits; |
| 108 | } |
| 109 | for (std::size_t i = os; i < x; ++i) |
| 110 | { |
| 111 | carry += static_cast<double_limb_type>(~limb_type(0)); |
| 112 | pr[i] = op(pr[i], static_cast<limb_type>(carry)); |
| 113 | carry >>= CppInt1::limb_bits; |
no test coverage detected