Skip to content
This repository was archived by the owner on Feb 17, 2025. It is now read-only.

Implementation of no-carry montgomery multiplication. #293

Merged
merged 3 commits into from
Jul 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crypto3.nix
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ in stdenv.mkDerivation {
(if runTests then "-DCMAKE_ENABLE_TESTS=TRUE" else "")
(if enableDebug then "-DCMAKE_BUILD_TYPE=Debug" else "-DCMAKE_BUILD_TYPE=Release")
(if enableDebug then "-DCMAKE_CXX_FLAGS=-ggdb" else "")
(if enableDebug then "-DCMAKE_CXX_FLAGS=-O0" else "")
];

doCheck = runTests; # tests are inside crypto3-tests derivation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ namespace nil {
template<typename PowerType,
typename = typename std::enable_if<boost::is_integral<PowerType>::value>::type>
constexpr element_fp pow(const PowerType pwr) const {
return element_fp(boost::multiprecision::powm(data, boost::multiprecision::uint128_t(pwr)));
return element_fp(boost::multiprecision::powm(data, boost::multiprecision::uint128_modular_t(pwr)));
}

template<typename Backend, boost::multiprecision::expression_template_option ExpressionTemplates>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,9 @@ namespace nil {
h2 += (((t1 >> 24)) & 0x3ffffffffff) | hibit;

/* h *= r */
uint128_t d0 = uint128_t(h0) * r0 + uint128_t(h1) * s2 + uint128_t(h2) * s1;
uint128_t d1 = uint128_t(h0) * r1 + uint128_t(h1) * r0 + uint128_t(h2) * s2;
uint128_t d2 = uint128_t(h0) * r2 + uint128_t(h1) * r1 + uint128_t(h2) * r0;
uint128_modular_t d0 = uint128_modular_t(h0) * r0 + uint128_modular_t(h1) * s2 + uint128_modular_t(h2) * s1;
uint128_modular_t d1 = uint128_modular_t(h0) * r1 + uint128_modular_t(h1) * r0 + uint128_modular_t(h2) * s2;
uint128_modular_t d2 = uint128_modular_t(h0) * r2 + uint128_modular_t(h1) * r1 + uint128_modular_t(h2) * r0;

/* (partial) h %= p */
word_type c = carry_shift(d0, 44);
Expand Down
4 changes: 2 additions & 2 deletions libs/multiprecision/example/mixed_integer_arithmetic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ int main()
boost::uint64_t i = (std::numeric_limits<boost::uint64_t>::max)();
boost::uint64_t j = 1;

uint128_t ui128;
uint128_modular_t ui128;
uint256_t ui256;
//
// Start by performing arithmetic on 64-bit integers to yield 128-bit results:
Expand All @@ -32,7 +32,7 @@ int main()
//
// The try squaring a 128-bit integer to yield a 256-bit result:
//
ui128 = (std::numeric_limits<uint128_t>::max)();
ui128 = (std::numeric_limits<uint128_modular_t>::max)();
std::cout << std::hex << std::showbase << multiply(ui256, ui128, ui128) << std::endl;

return 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,18 +99,15 @@ namespace boost {

template<unsigned Bits>
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
boost::multiprecision::is_unsigned_number<cpp_int_modular_backend<Bits>>::value &&
!boost::multiprecision::backends::is_trivial_cpp_int_modular<cpp_int_modular_backend<Bits>>::value &&
!boost::multiprecision::backends::is_trivial_cpp_int_modular<cpp_int_modular_backend<Bits>>::value>::
type
!boost::multiprecision::backends::is_trivial_cpp_int_modular<cpp_int_modular_backend<Bits>>::value>::type
eval_complement(cpp_int_modular_backend<Bits>& result, const cpp_int_modular_backend<Bits>& o) noexcept {

unsigned os = o.size();
for (unsigned i = 0; i < os; ++i)
result.limbs()[i] = ~o.limbs()[i];
result.normalize();
}
#ifndef TVM

// Left shift will throw away upper bits.
// This function must be called only when s % 8 == 0, i.e. we shift bytes.
template<unsigned Bits>
Expand All @@ -129,7 +126,6 @@ namespace boost {
std::memset(pc, 0, bytes);
}
}
#endif

// Left shift will throw away upper bits.
// This function must be called only when s % limb_bits == 0, i.e. we shift limbs, which are normally 64 bit.
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,11 @@ namespace boost {
}
}

template<typename Backend1, typename Backend2>
BOOST_MP_CXX14_CONSTEXPR void mod_mul(Backend1 &result, const Backend2 &y) const {
template<typename Backend1>
BOOST_MP_CXX14_CONSTEXPR void mod_mul(Backend1 &result, const Backend1 &y) const {
if (is_odd_mod) {
m_mod_obj.montgomery_mul(result, y);
m_mod_obj.montgomery_mul(result, y,
std::integral_constant<bool, is_trivial_cpp_int_modular<Backend1>::value>());
} else {
m_mod_obj.regular_mul(result, y);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,14 @@ BOOST_AUTO_TEST_CASE(modular_adaptor_montgomery_mult_perf_test) {
auto mod_object = x_modular.mod_data().get_mod_obj();
auto base_data = x_modular.base_data();
for (int i = 0; i < SAMPLES; ++i) {
mod_object.montgomery_mul(base_data, res_modular.base_data());
mod_object.montgomery_mul(base_data, res_modular.base_data(),
std::integral_constant<bool, boost::multiprecision::backends::is_trivial_cpp_int_modular<Backend>::value>());
}

std::cout << base_data << std::endl;
auto elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(
std::chrono::high_resolution_clock::now() - start);
std::cout << "Multiplication time: " << std::fixed << std::setprecision(3)
std::cout << "Multiplication time (when montgomery_mul is called directly): " << std::fixed << std::setprecision(3)
<< std::dec << elapsed.count() / SAMPLES << " ns" << std::endl;
}

Expand Down Expand Up @@ -162,7 +163,7 @@ BOOST_AUTO_TEST_CASE(modular_adaptor_backend_mult_perf_test) {

auto elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(
std::chrono::high_resolution_clock::now() - start);
std::cout << "Multiplication time: " << std::fixed << std::setprecision(3)
std::cout << "Multiplication time (when called from modular adaptor): " << std::fixed << std::setprecision(3)
<< elapsed.count() / SAMPLES << " ns" << std::endl;

// Print something so the whole computation is not optimized out.
Expand Down
2 changes: 1 addition & 1 deletion libs/multiprecision/test/constexpr_test_cpp_int_2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ decltype(std::declval<F>()(std::declval<V>())) non_constexpr_invoke(F f, V v) {

int main() {
typedef boost::multiprecision::int128_t int_backend;
typedef boost::multiprecision::uint128_t unsigned_backend;
typedef boost::multiprecision::uint128_modular_t unsigned_backend;

{
constexpr int_backend a(22);
Expand Down
2 changes: 1 addition & 1 deletion libs/multiprecision/test/constexpr_test_cpp_int_4.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ decltype(std::declval<F>()(std::declval<V>())) non_constexpr_invoke(F f, V v) {

int main() {
typedef boost::multiprecision::checked_int128_t int_backend;
typedef boost::multiprecision::checked_uint128_t unsigned_backend;
typedef boost::multiprecision::checked_uint128_modular_t unsigned_backend;

{
constexpr int_backend a(22);
Expand Down
5 changes: 5 additions & 0 deletions libs/multiprecision/test/modular_adaptor_fixed.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,10 +118,14 @@ bool base_operations_test(std::array<Number, test_set_len> test_set) {
standard_number a_powm_b_s = powm(a_cppint, b_cppint, e_cppint);
standard_number a_bit_set_s = a_cppint;
bit_set(a_bit_set_s, 1);
a_bit_set_s %= e_cppint;
standard_number a_bit_unset_s = a_cppint;
a_bit_unset_s %= e_cppint;
bit_unset(a_bit_unset_s, 2);
standard_number a_bit_flip_s = a_cppint;
bit_flip(a_bit_flip_s, 3);
a_bit_flip_s %= e_cppint;

int b_msb_s = msb(b_cppint);
int b_lsb_s = lsb(b_cppint);

Expand All @@ -142,6 +146,7 @@ bool base_operations_test(std::array<Number, test_set_len> test_set) {
bit_unset(a_bit_unset, 2);
modular_number a_bit_flip = a;
bit_flip(a_bit_flip, 3);

int b_msb = msb(b_cppint);
int b_lsb = lsb(b_cppint);

Expand Down
2 changes: 1 addition & 1 deletion libs/multiprecision/test/test_cpp_int_conv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ int main() {

i3 = -1234567;

uint128_t i5(i3);
uint128_modular_t i5(i3);
BOOST_TEST(i5 == -1234567);

int128_t i6(i4);
Expand Down
36 changes: 18 additions & 18 deletions libs/multiprecision/test/test_nothrow_cpp_int.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
BOOST_STATIC_ASSERT(boost::is_nothrow_move_constructible<boost::multiprecision::cpp_int>::value);
BOOST_STATIC_ASSERT(boost::is_nothrow_move_constructible<boost::multiprecision::int128_t>::value);
BOOST_STATIC_ASSERT(boost::is_nothrow_move_constructible<boost::multiprecision::checked_int128_t>::value);
BOOST_STATIC_ASSERT(boost::is_nothrow_move_constructible<boost::multiprecision::uint128_t>::value);
BOOST_STATIC_ASSERT(boost::is_nothrow_move_constructible<boost::multiprecision::checked_uint128_t>::value);
BOOST_STATIC_ASSERT(boost::is_nothrow_move_constructible<boost::multiprecision::uint128_modular_t>::value);
BOOST_STATIC_ASSERT(boost::is_nothrow_move_constructible<boost::multiprecision::checked_uint128_modular_t>::value);
BOOST_STATIC_ASSERT(boost::is_nothrow_move_constructible<boost::multiprecision::int512_t>::value);
BOOST_STATIC_ASSERT(boost::is_nothrow_move_constructible<boost::multiprecision::checked_int512_t>::value);
BOOST_STATIC_ASSERT(boost::is_nothrow_move_constructible<boost::multiprecision::uint512_t>::value);
Expand All @@ -36,8 +36,8 @@ BOOST_STATIC_ASSERT(boost::is_nothrow_move_constructible<boost::multiprecision::
BOOST_STATIC_ASSERT(boost::is_nothrow_move_assignable<boost::multiprecision::cpp_int>::value);
BOOST_STATIC_ASSERT(boost::is_nothrow_move_assignable<boost::multiprecision::int128_t>::value);
BOOST_STATIC_ASSERT(boost::is_nothrow_move_assignable<boost::multiprecision::checked_int128_t>::value);
BOOST_STATIC_ASSERT(boost::is_nothrow_move_assignable<boost::multiprecision::uint128_t>::value);
BOOST_STATIC_ASSERT(boost::is_nothrow_move_assignable<boost::multiprecision::checked_uint128_t>::value);
BOOST_STATIC_ASSERT(boost::is_nothrow_move_assignable<boost::multiprecision::uint128_modular_t>::value);
BOOST_STATIC_ASSERT(boost::is_nothrow_move_assignable<boost::multiprecision::checked_uint128_modular_t>::value);
BOOST_STATIC_ASSERT(boost::is_nothrow_move_assignable<boost::multiprecision::int512_t>::value);
BOOST_STATIC_ASSERT(boost::is_nothrow_move_assignable<boost::multiprecision::checked_int512_t>::value);
BOOST_STATIC_ASSERT(boost::is_nothrow_move_assignable<boost::multiprecision::uint512_t>::value);
Expand All @@ -52,8 +52,8 @@ BOOST_STATIC_ASSERT(boost::is_nothrow_move_assignable<boost::multiprecision::che
BOOST_STATIC_ASSERT(boost::has_nothrow_constructor<boost::multiprecision::cpp_int>::value);
BOOST_STATIC_ASSERT(boost::has_nothrow_constructor<boost::multiprecision::int128_t>::value);
BOOST_STATIC_ASSERT(boost::has_nothrow_constructor<boost::multiprecision::checked_int128_t>::value);
BOOST_STATIC_ASSERT(boost::has_nothrow_constructor<boost::multiprecision::uint128_t>::value);
BOOST_STATIC_ASSERT(boost::has_nothrow_constructor<boost::multiprecision::checked_uint128_t>::value);
BOOST_STATIC_ASSERT(boost::has_nothrow_constructor<boost::multiprecision::uint128_modular_t>::value);
BOOST_STATIC_ASSERT(boost::has_nothrow_constructor<boost::multiprecision::checked_uint128_modular_t>::value);
BOOST_STATIC_ASSERT(boost::has_nothrow_constructor<boost::multiprecision::int512_t>::value);
BOOST_STATIC_ASSERT(boost::has_nothrow_constructor<boost::multiprecision::checked_int512_t>::value);
BOOST_STATIC_ASSERT(boost::has_nothrow_constructor<boost::multiprecision::uint512_t>::value);
Expand All @@ -66,8 +66,8 @@ BOOST_STATIC_ASSERT(boost::has_nothrow_constructor<boost::multiprecision::checke
BOOST_STATIC_ASSERT(!boost::has_nothrow_copy<boost::multiprecision::cpp_int>::value);
BOOST_STATIC_ASSERT(boost::has_nothrow_copy<boost::multiprecision::int128_t>::value);
BOOST_STATIC_ASSERT(boost::has_nothrow_copy<boost::multiprecision::checked_int128_t>::value);
BOOST_STATIC_ASSERT(boost::has_nothrow_copy<boost::multiprecision::uint128_t>::value);
BOOST_STATIC_ASSERT(boost::has_nothrow_copy<boost::multiprecision::checked_uint128_t>::value);
BOOST_STATIC_ASSERT(boost::has_nothrow_copy<boost::multiprecision::uint128_modular_t>::value);
BOOST_STATIC_ASSERT(boost::has_nothrow_copy<boost::multiprecision::checked_uint128_modular_t>::value);
BOOST_STATIC_ASSERT(boost::has_nothrow_copy<boost::multiprecision::int512_t>::value);
BOOST_STATIC_ASSERT(boost::has_nothrow_copy<boost::multiprecision::checked_int512_t>::value);
BOOST_STATIC_ASSERT(boost::has_nothrow_copy<boost::multiprecision::uint512_t>::value);
Expand All @@ -80,8 +80,8 @@ BOOST_STATIC_ASSERT(boost::has_nothrow_copy<boost::multiprecision::checked_uint5
BOOST_STATIC_ASSERT(!boost::has_nothrow_assign<boost::multiprecision::cpp_int>::value);
BOOST_STATIC_ASSERT(boost::has_nothrow_assign<boost::multiprecision::int128_t>::value);
BOOST_STATIC_ASSERT(boost::has_nothrow_assign<boost::multiprecision::checked_int128_t>::value);
BOOST_STATIC_ASSERT(boost::has_nothrow_assign<boost::multiprecision::uint128_t>::value);
BOOST_STATIC_ASSERT(boost::has_nothrow_assign<boost::multiprecision::checked_uint128_t>::value);
BOOST_STATIC_ASSERT(boost::has_nothrow_assign<boost::multiprecision::uint128_modular_t>::value);
BOOST_STATIC_ASSERT(boost::has_nothrow_assign<boost::multiprecision::checked_uint128_modular_t>::value);
BOOST_STATIC_ASSERT(boost::has_nothrow_assign<boost::multiprecision::int512_t>::value);
BOOST_STATIC_ASSERT(boost::has_nothrow_assign<boost::multiprecision::checked_int512_t>::value);
BOOST_STATIC_ASSERT(boost::has_nothrow_assign<boost::multiprecision::uint512_t>::value);
Expand All @@ -97,9 +97,9 @@ BOOST_STATIC_ASSERT(
BOOST_STATIC_ASSERT(noexcept(
boost::multiprecision::checked_int128_t(std::declval<boost::multiprecision::signed_limb_type>())));
BOOST_STATIC_ASSERT(
noexcept(boost::multiprecision::uint128_t(std::declval<boost::multiprecision::signed_limb_type>())));
noexcept(boost::multiprecision::uint128_modular_t(std::declval<boost::multiprecision::signed_limb_type>())));
BOOST_STATIC_ASSERT(!noexcept(
boost::multiprecision::checked_uint128_t(std::declval<boost::multiprecision::signed_limb_type>())));
boost::multiprecision::checked_uint128_modular_t(std::declval<boost::multiprecision::signed_limb_type>())));
BOOST_STATIC_ASSERT(
noexcept(boost::multiprecision::int512_t(std::declval<boost::multiprecision::signed_limb_type>())));
BOOST_STATIC_ASSERT(noexcept(
Expand All @@ -118,9 +118,9 @@ BOOST_STATIC_ASSERT(
BOOST_STATIC_ASSERT(
noexcept(boost::multiprecision::checked_int128_t(std::declval<boost::multiprecision::limb_type>())));
BOOST_STATIC_ASSERT(
noexcept(boost::multiprecision::uint128_t(std::declval<boost::multiprecision::limb_type>())));
noexcept(boost::multiprecision::uint128_modular_t(std::declval<boost::multiprecision::limb_type>())));
BOOST_STATIC_ASSERT(
noexcept(boost::multiprecision::checked_uint128_t(std::declval<boost::multiprecision::limb_type>())));
noexcept(boost::multiprecision::checked_uint128_modular_t(std::declval<boost::multiprecision::limb_type>())));
BOOST_STATIC_ASSERT(
noexcept(boost::multiprecision::int512_t(std::declval<boost::multiprecision::limb_type>())));
BOOST_STATIC_ASSERT(
Expand All @@ -138,9 +138,9 @@ BOOST_STATIC_ASSERT(noexcept(std::declval<boost::multiprecision::int128_t>() =
std::declval<boost::multiprecision::signed_limb_type>()));
BOOST_STATIC_ASSERT(noexcept(std::declval<boost::multiprecision::checked_int128_t>() =
std::declval<boost::multiprecision::signed_limb_type>()));
BOOST_STATIC_ASSERT(noexcept(std::declval<boost::multiprecision::uint128_t>() =
BOOST_STATIC_ASSERT(noexcept(std::declval<boost::multiprecision::uint128_modular_t>() =
std::declval<boost::multiprecision::signed_limb_type>()));
BOOST_STATIC_ASSERT(!noexcept(std::declval<boost::multiprecision::checked_uint128_t>() =
BOOST_STATIC_ASSERT(!noexcept(std::declval<boost::multiprecision::checked_uint128_modular_t>() =
std::declval<boost::multiprecision::signed_limb_type>()));
BOOST_STATIC_ASSERT(noexcept(std::declval<boost::multiprecision::int512_t>() =
std::declval<boost::multiprecision::signed_limb_type>()));
Expand All @@ -160,8 +160,8 @@ BOOST_STATIC_ASSERT(noexcept(
BOOST_STATIC_ASSERT(noexcept(std::declval<boost::multiprecision::checked_int128_t>() =
std::declval<boost::multiprecision::limb_type>()));
BOOST_STATIC_ASSERT(noexcept(
std::declval<boost::multiprecision::uint128_t>() = std::declval<boost::multiprecision::limb_type>()));
BOOST_STATIC_ASSERT(noexcept(std::declval<boost::multiprecision::checked_uint128_t>() =
std::declval<boost::multiprecision::uint128_modular_t>() = std::declval<boost::multiprecision::limb_type>()));
BOOST_STATIC_ASSERT(noexcept(std::declval<boost::multiprecision::checked_uint128_modular_t>() =
std::declval<boost::multiprecision::limb_type>()));
BOOST_STATIC_ASSERT(noexcept(
std::declval<boost::multiprecision::int512_t>() = std::declval<boost::multiprecision::limb_type>()));
Expand Down
4 changes: 2 additions & 2 deletions libs/multiprecision/test/test_nothrow_cpp_rational.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ typedef boost::multiprecision::number<
boost::multiprecision::rational_adaptor<boost::multiprecision::int128_t::backend_type>>
rat128_t;
typedef boost::multiprecision::number<
boost::multiprecision::rational_adaptor<boost::multiprecision::uint128_t::backend_type>>
boost::multiprecision::rational_adaptor<boost::multiprecision::uint128_modular_t::backend_type>>
urat128_t;
typedef boost::multiprecision::number<
boost::multiprecision::rational_adaptor<boost::multiprecision::int512_t::backend_type>>
Expand All @@ -28,7 +28,7 @@ typedef boost::multiprecision::number<
boost::multiprecision::rational_adaptor<boost::multiprecision::checked_int128_t::backend_type>>
checked_rat128_t;
typedef boost::multiprecision::number<
boost::multiprecision::rational_adaptor<boost::multiprecision::checked_uint128_t::backend_type>>
boost::multiprecision::rational_adaptor<boost::multiprecision::checked_uint128_modular_t::backend_type>>
checked_urat128_t;
typedef boost::multiprecision::number<
boost::multiprecision::rational_adaptor<boost::multiprecision::checked_int512_t::backend_type>>
Expand Down
Loading