Skip to content

Commit

Permalink
multiprecision: refactor addition with carry
Browse files Browse the repository at this point in the history
  • Loading branch information
ioxid committed Dec 20, 2024
1 parent 57aac7b commit 6368029
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ namespace nil::crypto3::multiprecision {
if constexpr (Bits1 % limb_bits != 0) {
// If we have set any bit above "Bits", then we have a carry.
carry = result.normalize();
BOOST_ASSERT(carry <= 1);
}

return carry;
Expand Down Expand Up @@ -286,6 +287,7 @@ namespace nil::crypto3::multiprecision {
if constexpr (Bits1 % limb_bits != 0) {
// If we have set any bit above "Bits", then we have a carry.
carry = result.normalize();
BOOST_ASSERT(carry <= 1);
}

return carry;
Expand Down Expand Up @@ -385,8 +387,9 @@ namespace nil::crypto3::multiprecision {
#endif

template<std::size_t Bits1, std::size_t Bits2>
[[nodiscard]] constexpr bool add_unsigned(big_uint<Bits1>& result, const big_uint<Bits2>& a,
const limb_type& b) noexcept {
[[nodiscard]] constexpr limb_type add_unsigned(big_uint<Bits1>& result,
const big_uint<Bits2>& a,
const limb_type& b) noexcept {
static_assert(Bits1 >= Bits2, "invalid argument size");

double_limb_type carry = b;
Expand Down Expand Up @@ -419,6 +422,8 @@ namespace nil::crypto3::multiprecision {
carry = result.normalize();
}

BOOST_ASSERT(carry <= max_limb_value);

return carry;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ namespace nil::crypto3::multiprecision {

static constexpr std::size_t static_limb_count =
(Bits / limb_bits) + (((Bits % limb_bits) != 0u) ? 1u : 0u);
static constexpr std::size_t upper_limb_bits =
(Bits % limb_bits) ? Bits % limb_bits : limb_bits;
static constexpr limb_type upper_limb_mask =
(Bits % limb_bits) ? (limb_type(1) << (Bits % limb_bits)) - 1 : (~limb_type(0u));

Expand All @@ -90,10 +92,15 @@ namespace nil::crypto3::multiprecision {
constexpr limb_pointer limbs() noexcept { return m_data.data(); }
constexpr const_limb_pointer limbs() const noexcept { return m_data.data(); }

constexpr bool normalize() noexcept {
bool result = limbs()[static_limb_count - 1] & ~upper_limb_mask;
limbs()[static_limb_count - 1] &= upper_limb_mask;
return result;
constexpr limb_type normalize() noexcept {
if constexpr (Bits % limb_bits != 0) {
limb_type result =
(limbs()[static_limb_count - 1] & ~upper_limb_mask) >> upper_limb_bits;
limbs()[static_limb_count - 1] &= upper_limb_mask;
return result;
} else {
return 0;
}
}

// Zeros out everything after limb[i]
Expand Down Expand Up @@ -544,6 +551,12 @@ namespace nil::crypto3::multiprecision {
return a;
}

template<std::size_t Bits2>
[[nodiscard]] friend constexpr bool add_assign_with_carry(
big_uint& a, const big_uint<Bits2>& b) noexcept {
return detail::add_unsigned(a, a, b);
}

template<typename T, std::enable_if_t<detail::is_integral_v<T>, int> = 0>
friend constexpr auto operator-(const big_uint& a, const T& b) {
detail::largest_big_uint_t<big_uint, T> result;
Expand Down Expand Up @@ -1310,9 +1323,9 @@ namespace nil::crypto3::multiprecision {
const big_uint<Bits2>& a,
const big_uint<Bits3>& b);
template<std::size_t Bits1, std::size_t Bits2>
friend constexpr bool detail::add_unsigned(big_uint<Bits1>& result,
const big_uint<Bits2>& a,
const limb_type& o) noexcept;
friend constexpr limb_type detail::add_unsigned(big_uint<Bits1>& result,
const big_uint<Bits2>& a,
const limb_type& o) noexcept;
template<detail::operation_mode Mode, std::size_t Bits1, std::size_t Bits2>
friend constexpr void detail::subtract_unsigned(big_uint<Bits1>& result,
const big_uint<Bits2>& a,
Expand All @@ -1331,14 +1344,6 @@ namespace nil::crypto3::multiprecision {
friend class detail::montgomery_modular_ops;
};

// Addition with carry

template<std::size_t Bits1, std::size_t Bits2>
[[nodiscard]] constexpr bool add_assign_with_carry(big_uint<Bits1>& a,
const big_uint<Bits2>& b) noexcept {
return detail::add_unsigned(a, a, b);
}

// For generic code

template<std::size_t Bits>
Expand Down

0 comments on commit 6368029

Please sign in to comment.