Skip to content

Commit

Permalink
Multiprecision refactoring: refactor modular
Browse files Browse the repository at this point in the history
  • Loading branch information
ioxid committed Oct 24, 2024
1 parent 3b819db commit 30fc662
Show file tree
Hide file tree
Showing 29 changed files with 2,175 additions and 1,909 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@
// #include <boost/multiprecision/detail/constexpr.hpp>
#include <type_traits>

#include "nil/crypto3/multiprecision/big_integer/basic_ops/add_unsigned.hpp"
#include "nil/crypto3/multiprecision/big_integer/big_integer_impl.hpp"
#include "nil/crypto3/multiprecision/big_integer/detail/config.hpp"
#include "nil/crypto3/multiprecision/big_integer/ops/add_unsigned.hpp"
#include "nil/crypto3/multiprecision/big_integer/storage.hpp"

namespace nil::crypto3::multiprecision {
namespace nil::crypto3::multiprecision::detail {

template<unsigned Bits>
inline constexpr void add_unsigned(big_integer<Bits>& result, const big_integer<Bits>& a,
Expand Down Expand Up @@ -91,84 +91,80 @@ namespace nil::crypto3::multiprecision {
// above:
//
template<unsigned Bits>
NIL_CO3_MP_FORCEINLINE constexpr void eval_add(big_integer<Bits>& result,
const big_integer<Bits>& o) noexcept {
eval_add(result, result, o);
NIL_CO3_MP_FORCEINLINE constexpr void add(big_integer<Bits>& result, const big_integer<Bits>& a,
const big_integer<Bits>& b) noexcept {
add_unsigned(result, a, b);
}
template<unsigned Bits>
inline constexpr void eval_add(big_integer<Bits>& result, const big_integer<Bits>& a,
const big_integer<Bits>& b) noexcept {
add_unsigned(result, a, b);
NIL_CO3_MP_FORCEINLINE constexpr void add(big_integer<Bits>& result,
const big_integer<Bits>& o) noexcept {
add(result, result, o);
}

template<unsigned Bits>
NIL_CO3_MP_FORCEINLINE constexpr void eval_add(big_integer<Bits>& result,
const limb_type& o) noexcept {
NIL_CO3_MP_FORCEINLINE constexpr void add(big_integer<Bits>& result,
const limb_type& o) noexcept {
add_unsigned(result, result, o);
}
template<unsigned Bits>
NIL_CO3_MP_FORCEINLINE constexpr void eval_add(big_integer<Bits>& result,
const big_integer<Bits>& a,
const limb_type& o) noexcept {
NIL_CO3_MP_FORCEINLINE constexpr void add(big_integer<Bits>& result, const big_integer<Bits>& a,
const limb_type& o) noexcept {
add_unsigned(result, a, o);
}
template<unsigned Bits>
NIL_CO3_MP_FORCEINLINE constexpr void eval_subtract(big_integer<Bits>& result,
const limb_type& o) noexcept {
NIL_CO3_MP_FORCEINLINE constexpr void subtract(big_integer<Bits>& result,
const limb_type& o) noexcept {
subtract_unsigned(result, result, o);
}
template<unsigned Bits>
NIL_CO3_MP_FORCEINLINE constexpr void eval_subtract(big_integer<Bits>& result,
const big_integer<Bits>& a,
const limb_type& o) noexcept {
NIL_CO3_MP_FORCEINLINE constexpr void subtract(big_integer<Bits>& result,
const big_integer<Bits>& a,
const limb_type& o) noexcept {
subtract_unsigned(result, a, o);
}

template<unsigned Bits>
NIL_CO3_MP_FORCEINLINE constexpr void eval_increment(big_integer<Bits>& result) noexcept {
NIL_CO3_MP_FORCEINLINE constexpr void increment(big_integer<Bits>& result) noexcept {
if ((result.limbs()[0] < big_integer<Bits>::max_limb_value)) {
++result.limbs()[0];
} else {
eval_add(result, (limb_type)1);
add(result, static_cast<limb_type>(1u));
}
}

template<unsigned Bits>
NIL_CO3_MP_FORCEINLINE constexpr void eval_decrement(big_integer<Bits>& result) noexcept {
constexpr const limb_type one = 1;

NIL_CO3_MP_FORCEINLINE constexpr void decrement(big_integer<Bits>& result) noexcept {
if (result.limbs()[0]) {
--result.limbs()[0];
} else {
eval_subtract(result, one);
subtract(result, static_cast<limb_type>(1u));
}
}

template<unsigned Bits>
NIL_CO3_MP_FORCEINLINE constexpr void eval_subtract(big_integer<Bits>& result,
const big_integer<Bits>& o) noexcept {
eval_subtract(result, result, o);
NIL_CO3_MP_FORCEINLINE constexpr void subtract(big_integer<Bits>& result,
const big_integer<Bits>& a,
const big_integer<Bits>& b) noexcept {
subtract_unsigned(result, a, b);
}

template<unsigned Bits>
NIL_CO3_MP_FORCEINLINE constexpr void eval_subtract(big_integer<Bits>& result,
const big_integer<Bits>& a,
const big_integer<Bits>& b) noexcept {
subtract_unsigned(result, a, b);
NIL_CO3_MP_FORCEINLINE constexpr void subtract(big_integer<Bits>& result,
const big_integer<Bits>& o) noexcept {
subtract(result, result, o);
}

template<unsigned Bits1, unsigned Bits2>
NIL_CO3_MP_FORCEINLINE constexpr typename std::enable_if<(Bits1 >= Bits2)>::type eval_subtract(
NIL_CO3_MP_FORCEINLINE constexpr typename std::enable_if<(Bits1 >= Bits2)>::type subtract(
big_integer<Bits1>& result, const big_integer<Bits2>& o) noexcept {
big_integer<Bits1> o_larger = o;
eval_subtract(result, result, o_larger);
subtract(result, result, o_larger);
}

template<unsigned Bits1, unsigned Bits2>
NIL_CO3_MP_FORCEINLINE constexpr typename std::enable_if<(Bits1 >= Bits2)>::type eval_subtract(
NIL_CO3_MP_FORCEINLINE constexpr typename std::enable_if<(Bits1 >= Bits2)>::type subtract(
big_integer<Bits1>& result, const big_integer<Bits1>& a,
const big_integer<Bits2>& b) noexcept {
big_integer<Bits1> b_larger = b;
subtract_unsigned(result, a, b_larger);
}
} // namespace nil::crypto3::multiprecision
} // namespace nil::crypto3::multiprecision::detail
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
#include "nil/crypto3/multiprecision/big_integer/big_integer_impl.hpp"
#include "nil/crypto3/multiprecision/big_integer/storage.hpp"

namespace nil::crypto3::multiprecision {
namespace nil::crypto3::multiprecision::detail {
template<unsigned Bits>
inline constexpr void add_unsigned_constexpr(big_integer<Bits>& result,
const big_integer<Bits>& a,
Expand Down Expand Up @@ -288,4 +288,4 @@ namespace nil::crypto3::multiprecision {
}

#endif
} // namespace nil::crypto3::multiprecision
} // namespace nil::crypto3::multiprecision::detail
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,7 @@
#include "nil/crypto3/multiprecision/big_integer/detail/config.hpp"
#include "nil/crypto3/multiprecision/big_integer/storage.hpp"

#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4319)
#endif

namespace nil::crypto3::multiprecision {
namespace nil::crypto3::multiprecision::detail {
template<unsigned Bits, class Op>
constexpr void bitwise_op(big_integer<Bits>& result, const big_integer<Bits>& o,
Op op) noexcept {
Expand Down Expand Up @@ -49,47 +44,47 @@ namespace nil::crypto3::multiprecision {
}

template<unsigned Bits>
NIL_CO3_MP_FORCEINLINE constexpr void eval_bitwise_and(big_integer<Bits>& result,
const big_integer<Bits>& o) noexcept {
NIL_CO3_MP_FORCEINLINE constexpr void bitwise_and(big_integer<Bits>& result,
const big_integer<Bits>& o) noexcept {
bitwise_op(result, o, std::bit_and());
}

template<unsigned Bits>
NIL_CO3_MP_FORCEINLINE constexpr void eval_bitwise_or(big_integer<Bits>& result,
const big_integer<Bits>& o) noexcept {
NIL_CO3_MP_FORCEINLINE constexpr void bitwise_or(big_integer<Bits>& result,
const big_integer<Bits>& o) noexcept {
bitwise_op(result, o, std::bit_or());
}

template<unsigned Bits>
NIL_CO3_MP_FORCEINLINE constexpr void eval_bitwise_xor(big_integer<Bits>& result,
const big_integer<Bits>& o) noexcept {
NIL_CO3_MP_FORCEINLINE constexpr void bitwise_xor(big_integer<Bits>& result,
const big_integer<Bits>& o) noexcept {
bitwise_op(result, o, std::bit_xor());
}
//
// Again for operands which are single limbs:
//
template<unsigned Bits>
NIL_CO3_MP_FORCEINLINE constexpr void eval_bitwise_and(big_integer<Bits>& result,
limb_type l) noexcept {
NIL_CO3_MP_FORCEINLINE constexpr void bitwise_and(big_integer<Bits>& result,
limb_type l) noexcept {
result.limbs()[0] &= l;
result.zero_after(1);
}

template<unsigned Bits>
NIL_CO3_MP_FORCEINLINE constexpr void eval_bitwise_or(big_integer<Bits>& result,
limb_type l) noexcept {
NIL_CO3_MP_FORCEINLINE constexpr void bitwise_or(big_integer<Bits>& result,
limb_type l) noexcept {
result.limbs()[0] |= l;
}

template<unsigned Bits>
NIL_CO3_MP_FORCEINLINE constexpr void eval_bitwise_xor(big_integer<Bits>& result,
limb_type l) noexcept {
NIL_CO3_MP_FORCEINLINE constexpr void bitwise_xor(big_integer<Bits>& result,
limb_type l) noexcept {
result.limbs()[0] ^= l;
}

template<unsigned Bits>
NIL_CO3_MP_FORCEINLINE constexpr void eval_complement(big_integer<Bits>& result,
const big_integer<Bits>& o) noexcept {
NIL_CO3_MP_FORCEINLINE constexpr void complement(big_integer<Bits>& result,
const big_integer<Bits>& o) noexcept {
unsigned os = o.size();
for (unsigned i = 0; i < os; ++i) {
result.limbs()[i] = ~o.limbs()[i];
Expand All @@ -101,9 +96,9 @@ namespace nil::crypto3::multiprecision {
// This function must be called only when s % 8 == 0, i.e. we shift bytes.
template<unsigned Bits>
inline void left_shift_byte(big_integer<Bits>& result, double_limb_type s) {
typedef big_integer<Bits> Int;
typedef big_integer<Bits> big_integer_t;

typename Int::limb_pointer pr = result.limbs();
typename big_integer_t::limb_pointer pr = result.limbs();

std::size_t bytes = static_cast<std::size_t>(s / CHAR_BIT);
if (s >= Bits) {
Expand All @@ -121,12 +116,12 @@ namespace nil::crypto3::multiprecision {
// are normally 64 bit.
template<unsigned Bits>
inline constexpr void left_shift_limb(big_integer<Bits>& result, double_limb_type s) {
typedef big_integer<Bits> Int;
using big_integer_t = big_integer<Bits>;

limb_type offset = static_cast<limb_type>(s / Int::limb_bits);
BOOST_ASSERT(static_cast<limb_type>(s % Int::limb_bits) == 0);
limb_type offset = static_cast<limb_type>(s / big_integer_t::limb_bits);
BOOST_ASSERT(static_cast<limb_type>(s % big_integer_t::limb_bits) == 0);

typename Int::limb_pointer pr = result.limbs();
typename big_integer_t::limb_pointer pr = result.limbs();

if (s >= Bits) {
// Set result to 0.
Expand All @@ -146,24 +141,24 @@ namespace nil::crypto3::multiprecision {
// Left shift will throw away upper Bits.
template<unsigned Bits>
inline constexpr void left_shift_generic(big_integer<Bits>& result, double_limb_type s) {
typedef big_integer<Bits> Int;
using big_integer_t = big_integer<Bits>;

if (s >= Bits) {
// Set result to 0.
result.zero_after(0);
} else {
limb_type offset = static_cast<limb_type>(s / Int::limb_bits);
limb_type shift = static_cast<limb_type>(s % Int::limb_bits);
limb_type offset = static_cast<limb_type>(s / big_integer_t::limb_bits);
limb_type shift = static_cast<limb_type>(s % big_integer_t::limb_bits);

typename Int::limb_pointer pr = result.limbs();
typename big_integer_t::limb_pointer pr = result.limbs();
std::size_t i = 0;
std::size_t rs = result.size();
// This code only works when shift is non-zero, otherwise we invoke undefined
// behaviour!
BOOST_ASSERT(shift);
for (; rs - i >= 2 + offset; ++i) {
pr[rs - 1 - i] = pr[rs - 1 - i - offset] << shift;
pr[rs - 1 - i] |= pr[rs - 2 - i - offset] >> (Int::limb_bits - shift);
pr[rs - 1 - i] |= pr[rs - 2 - i - offset] >> (big_integer_t::limb_bits - shift);
}
if (rs - i >= 1 + offset) {
pr[rs - 1 - i] = pr[rs - 1 - i - offset] << shift;
Expand All @@ -177,7 +172,7 @@ namespace nil::crypto3::multiprecision {

// Shifting left throws away upper Bits.
template<unsigned Bits>
inline constexpr void eval_left_shift(big_integer<Bits>& result, double_limb_type s) noexcept {
inline constexpr void left_shift(big_integer<Bits>& result, double_limb_type s) noexcept {
if (!s) {
return;
}
Expand Down Expand Up @@ -226,9 +221,9 @@ namespace nil::crypto3::multiprecision {

template<unsigned Bits>
inline void right_shift_byte(big_integer<Bits>& result, double_limb_type s) {
typedef big_integer<Bits> Int;
typedef big_integer<Bits> big_integer_t;

limb_type offset = static_cast<limb_type>(s / Int::limb_bits);
limb_type offset = static_cast<limb_type>(s / big_integer_t::limb_bits);
BOOST_ASSERT((s % CHAR_BIT) == 0);
unsigned ors = result.size();
unsigned rs = ors;
Expand All @@ -237,12 +232,12 @@ namespace nil::crypto3::multiprecision {
return;
}
rs -= offset;
typename Int::limb_pointer pr = result.limbs();
typename big_integer_t::limb_pointer pr = result.limbs();
unsigned char* pc = reinterpret_cast<unsigned char*>(pr);
limb_type 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) {
if (shift < big_integer_t::limb_bits) {
pr[ors - offset - 1] &= (static_cast<limb_type>(1u) << shift) - 1;
if (!pr[ors - offset - 1] && (rs > 1)) {
--rs;
Expand All @@ -254,18 +249,18 @@ namespace nil::crypto3::multiprecision {

template<unsigned Bits>
inline constexpr void right_shift_limb(big_integer<Bits>& result, double_limb_type s) {
typedef big_integer<Bits> Int;
typedef big_integer<Bits> big_integer_t;

limb_type offset = static_cast<limb_type>(s / Int::limb_bits);
BOOST_ASSERT((s % Int::limb_bits) == 0);
limb_type offset = static_cast<limb_type>(s / big_integer_t::limb_bits);
BOOST_ASSERT((s % big_integer_t::limb_bits) == 0);
unsigned ors = result.size();
unsigned rs = ors;
if (offset >= rs) {
result.zero_after(0);
return;
}
rs -= offset;
typename Int::limb_pointer pr = result.limbs();
typename big_integer_t::limb_pointer pr = result.limbs();
unsigned i = 0;
for (; i < rs; ++i) {
pr[i] = pr[i + offset];
Expand All @@ -276,9 +271,9 @@ namespace nil::crypto3::multiprecision {

template<unsigned Bits>
inline constexpr void right_shift_generic(big_integer<Bits>& result, double_limb_type s) {
typedef big_integer<Bits> Int;
limb_type offset = static_cast<limb_type>(s / Int::limb_bits);
limb_type shift = static_cast<limb_type>(s % Int::limb_bits);
typedef big_integer<Bits> big_integer_t;
limb_type offset = static_cast<limb_type>(s / big_integer_t::limb_bits);
limb_type shift = static_cast<limb_type>(s % big_integer_t::limb_bits);
unsigned ors = result.size();
unsigned rs = ors;

Expand All @@ -287,7 +282,7 @@ namespace nil::crypto3::multiprecision {
return;
}
rs -= offset;
typename Int::limb_pointer pr = result.limbs();
typename big_integer_t::limb_pointer pr = result.limbs();
if ((pr[ors - 1] >> shift) == 0) {
if (--rs == 0) {
result = limb_type(0);
Expand All @@ -300,7 +295,7 @@ namespace nil::crypto3::multiprecision {
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 + 1] << (big_integer_t::limb_bits - shift);
}
pr[i] = pr[i + offset] >> shift;

Expand All @@ -309,7 +304,7 @@ namespace nil::crypto3::multiprecision {
}

template<unsigned Bits>
inline constexpr void eval_right_shift(big_integer<Bits>& result, double_limb_type s) noexcept {
inline constexpr void right_shift(big_integer<Bits>& result, double_limb_type s) noexcept {
if (!s) {
return;
}
Expand Down Expand Up @@ -352,8 +347,4 @@ namespace nil::crypto3::multiprecision {
right_shift_generic(result, s);
}
}
} // namespace nil::crypto3::multiprecision

#ifdef _MSC_VER
#pragma warning(pop)
#endif
} // namespace nil::crypto3::multiprecision::detail
Loading

0 comments on commit 30fc662

Please sign in to comment.