Skip to content

Commit

Permalink
multiprecision: make more methods private
Browse files Browse the repository at this point in the history
  • Loading branch information
ioxid committed Dec 18, 2024
1 parent fc3e337 commit 4ab0dc5
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 77 deletions.
56 changes: 28 additions & 28 deletions crypto3/benchmarks/multiprecision/big_int.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
#include <nil/crypto3/multiprecision/literals.hpp>
#include <nil/crypto3/multiprecision/big_mod.hpp>

#include <nil/crypto3/multiprecision/detail/big_mod/test_support.hpp>

#include <nil/crypto3/bench/benchmark.hpp>

using namespace nil::crypto3::multiprecision::literals;
Expand Down Expand Up @@ -51,15 +53,14 @@ BOOST_AUTO_TEST_SUITE(runtime_odd_tests)

// This directly calls montgomery mul from modular_ops.hpp.
BOOST_AUTO_TEST_CASE(montgomery_mul_perf_test) {
auto raw_base = x_mod_rt_odd.raw_base();
const auto &mod_ops = x_mod_rt_odd.ops();
auto raw_base = nil::crypto3::multiprecision::detail::get_raw_base(x_mod_rt_odd);
const auto &mod_ops = x_mod_rt_odd.ops_storage().ops();

nil::crypto3::bench::run_benchmark<>(
"[odd modulus][runtime] montgomery mul (direct call)",
[&]() {
mod_ops.mul(raw_base, y_mod_rt_odd.raw_base());
return raw_base;
});
"[odd modulus][runtime] montgomery mul (direct call)", [&]() {
mod_ops.mul(raw_base, nil::crypto3::multiprecision::detail::get_raw_base(y_mod_rt_odd));
return raw_base;
});

std::cout << raw_base << std::endl;
}
Expand Down Expand Up @@ -112,15 +113,14 @@ BOOST_AUTO_TEST_SUITE(compile_time_odd_tests)

// This directly calls montgomery mul from modular_ops.hpp.
BOOST_AUTO_TEST_CASE(montgomery_mul_perf_test) {
auto raw_base = x_mod_ct_odd.raw_base();
const auto &mod_ops = x_mod_ct_odd.ops();
auto raw_base = nil::crypto3::multiprecision::detail::get_raw_base(x_mod_ct_odd);
const auto &mod_ops = x_mod_ct_odd.ops_storage().ops(); // NOLINT

nil::crypto3::bench::run_benchmark<>(
"[odd modulus][compile time] montgomery mul (direct call)",
[&]() {
mod_ops.mul(raw_base, y_mod_ct_odd.raw_base());
return raw_base;
});
"[odd modulus][compile time] montgomery mul (direct call)", [&]() {
mod_ops.mul(raw_base, nil::crypto3::multiprecision::detail::get_raw_base(y_mod_ct_odd));
return raw_base;
});

std::cout << raw_base << std::endl;
}
Expand Down Expand Up @@ -173,15 +173,15 @@ BOOST_AUTO_TEST_SUITE(runtime_even_tests)

// This directly calls barrett mul from modular_ops.hpp.
BOOST_AUTO_TEST_CASE(barrett_mul_perf_test) {
auto raw_base = x_mod_rt_even.raw_base();
const auto &mod_ops = x_mod_rt_even.ops();
auto raw_base = nil::crypto3::multiprecision::detail::get_raw_base(x_mod_rt_even);
const auto &mod_ops = x_mod_rt_even.ops_storage().ops();

nil::crypto3::bench::run_benchmark<>(
"[even modulus][runtime] barrett mul (direct call)",
[&]() {
mod_ops.mul(raw_base, y_mod_rt_even.raw_base());
return raw_base;
});
"[even modulus][runtime] barrett mul (direct call)", [&]() {
mod_ops.mul(raw_base,
nil::crypto3::multiprecision::detail::get_raw_base(y_mod_rt_even));
return raw_base;
});

std::cout << raw_base << std::endl;
}
Expand Down Expand Up @@ -234,15 +234,15 @@ BOOST_AUTO_TEST_SUITE(compile_time_even_tests)

// This directly calls mul from modular_ops.hpp.
BOOST_AUTO_TEST_CASE(barrett_mul_perf_test) {
auto raw_base = x_mod_ct_even.raw_base();
const auto &mod_ops = x_mod_ct_even.ops();
auto raw_base = nil::crypto3::multiprecision::detail::get_raw_base(x_mod_ct_even);
const auto &mod_ops = x_mod_ct_even.ops_storage().ops(); // NOLINT

nil::crypto3::bench::run_benchmark<>(
"[even modulus][compile time] barrett mul (direct call)",
[&]() {
mod_ops.mul(raw_base, y_mod_ct_even.raw_base());
return raw_base;
});
"[even modulus][compile time] barrett mul (direct call)", [&]() {
mod_ops.mul(raw_base,
nil::crypto3::multiprecision::detail::get_raw_base(y_mod_ct_even));
return raw_base;
});

std::cout << raw_base << std::endl;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <cstddef>
#include <functional>
#include <ios>
#include <limits>
#include <ostream>
#include <string>
#include <type_traits>
Expand All @@ -25,6 +26,7 @@

#include "nil/crypto3/multiprecision/detail/big_mod/modular_ops.hpp"
#include "nil/crypto3/multiprecision/detail/big_mod/modular_ops_storage.hpp"
#include "nil/crypto3/multiprecision/detail/big_mod/test_support.hpp" // IWYU pragma: keep (for get_raw_base)
#include "nil/crypto3/multiprecision/detail/big_mod/type_traits.hpp" // IWYU pragma: export
#include "nil/crypto3/multiprecision/detail/big_uint/big_uint_impl.hpp"
#include "nil/crypto3/multiprecision/detail/integer_ops_base.hpp" // IWYU pragma: keep (used for is_zero)
Expand Down Expand Up @@ -76,7 +78,7 @@ namespace nil::crypto3::multiprecision {

constexpr big_uint_t base() const {
big_uint_t result;
ops().adjust_regular(result, m_raw_base);
ops().adjust_regular(result, raw_base());
return result;
}

Expand Down Expand Up @@ -133,7 +135,7 @@ namespace nil::crypto3::multiprecision {
constexpr void negate() { ops().negate(m_raw_base); }

constexpr auto& operator++() noexcept {
ops().increment(raw_base());
ops().increment(m_raw_base);
return *this;
}

Expand All @@ -146,7 +148,7 @@ namespace nil::crypto3::multiprecision {
constexpr auto operator+() const noexcept { return *this; }

constexpr auto& operator--() noexcept {
ops().decrement(raw_base());
ops().decrement(m_raw_base);
return *this;
}

Expand Down Expand Up @@ -188,15 +190,15 @@ namespace nil::crypto3::multiprecision {
BOOST_ASSERT(a.ops().compare_eq(b.ops())); \
} \
big_mod_impl result = a; \
a.ops().METHOD_(result.raw_base(), convert_to_raw_base(b, a.ops())); \
a.ops().METHOD_(result.m_raw_base, convert_to_raw_base(b, a.ops())); \
return result; \
} \
\
template<typename T, std::enable_if_t<detail::is_integral_v<T>, int> = 0> \
friend constexpr auto operator OP_(const T& a, const big_mod_impl& b) noexcept { \
big_mod_impl result(b.ops_storage()); \
result.raw_base() = convert_to_raw_base(a, b.ops()); \
b.ops().METHOD_(result.raw_base(), b.raw_base()); \
result.m_raw_base = convert_to_raw_base(a, b.ops()); \
b.ops().METHOD_(result.m_raw_base, b.raw_base()); \
return result; \
} \
\
Expand All @@ -207,7 +209,7 @@ namespace nil::crypto3::multiprecision {
if constexpr (detail::is_big_mod_v<T>) { \
BOOST_ASSERT(a.ops().compare_eq(b.ops())); \
} \
a.ops().METHOD_(a.raw_base(), convert_to_raw_base(b, a.ops())); \
a.ops().METHOD_(a.m_raw_base, convert_to_raw_base(b, a.ops())); \
return a; \
}

Expand All @@ -217,27 +219,47 @@ namespace nil::crypto3::multiprecision {

#undef NIL_CO3_MP_BIG_MOD_OPERATOR_IMPL

template<typename T,
std::enable_if_t<detail::is_integral_v<T> && !std::numeric_limits<T>::is_signed,
int> = 0>
friend constexpr big_mod_impl pow_unsigned(big_mod_impl b, const T& e) {
b.ops().pow(b.m_raw_base, b.raw_base(), e);
return b;
}

// Hash

friend constexpr std::size_t hash_value(const big_mod_impl& val) noexcept {
return hash_value(val.raw_base());
// mod() is ignored because we don't allow comparing numbers with different moduli
// anyway
}

// IO

friend std::ostream& operator<<(std::ostream& os, const big_mod_impl& value) {
os << value.str(os.flags());
return os;
}

// Accessing raw base value. Should only be used internally by multiprecision library.

constexpr auto& raw_base() { return m_raw_base; }
constexpr const auto& raw_base() const { return m_raw_base; }

// Accessing operations. Can be used to efficiently initialize a new big_mod_rt instance by
// copying operations storage from an existing big_mod_rt instance.

constexpr const auto& ops_storage() const { return m_modular_ops_storage; }

private:
constexpr const auto& ops() const { return m_modular_ops_storage.ops(); }
constexpr const auto& raw_base() const { return m_raw_base; }

// Data

protected:
modular_ops_storage_t m_modular_ops_storage;
big_uint_t m_raw_base;

// Friends

template<typename big_mod_t>
friend constexpr const auto& detail::get_raw_base(const big_mod_t& a);
};

template<const auto& modulus, template<std::size_t> typename modular_ops_template>
Expand All @@ -249,23 +271,6 @@ namespace nil::crypto3::multiprecision {
using big_mod_rt_impl =
big_mod_impl<Bits, detail::modular_ops_storage_rt<Bits, modular_ops_template>>;

// Hash

template<const auto& modulus, template<std::size_t> typename modular_ops_template>
constexpr std::size_t hash_value(
const big_mod_ct_impl<modulus, modular_ops_template>& val) noexcept {
return hash_value(val.raw_base());
}

template<std::size_t Bits, template<std::size_t> typename modular_ops_template>
constexpr std::size_t hash_value(
const big_mod_rt_impl<Bits, modular_ops_template>& val) noexcept {
std::size_t result = 0;
boost::hash_combine(result, val.base());
boost::hash_combine(result, val.mod());
return result;
}

// For generic code

template<typename big_mod_t, std::enable_if_t<detail::is_big_mod_v<big_mod_t>, int> = 0>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ namespace nil::crypto3::multiprecision::detail {
detail::is_integral_v<T> && !std::numeric_limits<T>::is_signed,
int> = 0>
constexpr void pow(big_uint<Bits2> &result, const big_uint<Bits3> &a, T exp) const {
/// input parameter should be less than modulus
BOOST_ASSERT(a < mod());

if (is_zero(exp)) {
Expand Down Expand Up @@ -572,10 +573,6 @@ namespace nil::crypto3::multiprecision::detail {
/// input parameter should be less than modulus
BOOST_ASSERT(a < this->mod());

big_uint_t R_mod_m = m_one;

big_uint_t base(a);

if (is_zero(exp)) {
result = m_one;
return;
Expand All @@ -585,18 +582,20 @@ namespace nil::crypto3::multiprecision::detail {
return;
}

big_uint_t base(a), res = m_one;

while (true) {
bool lsb = bit_test(exp, 0u);
exp >>= 1u;
if (lsb) {
mul(R_mod_m, base);
mul(res, base);
if (is_zero(exp)) {
break;
}
}
mul(base, base);
}
result = R_mod_m;
result = res;
}

// Adjust to/from modular form
Expand Down Expand Up @@ -637,18 +636,18 @@ namespace nil::crypto3::multiprecision::detail {
ops.adjust_modular(raw_base, b);
}

template<std::size_t Bits, typename SI, typename modular_ops_t,
typename std::enable_if_t<std::is_integral_v<SI> && std::is_signed_v<SI>, int> = 0>
constexpr void init_raw_base(big_uint<Bits> &raw_base, SI b, const modular_ops_t &ops) {
template<std::size_t Bits, typename T, typename modular_ops_t,
typename std::enable_if_t<std::is_integral_v<T> && std::is_signed_v<T>, int> = 0>
constexpr void init_raw_base(big_uint<Bits> &raw_base, T b, const modular_ops_t &ops) {
ops.adjust_modular(raw_base, detail::as_big_uint(detail::unsigned_abs(b)));
if (b < 0) {
ops.negate(raw_base);
}
}

template<std::size_t Bits, typename UI, typename modular_ops_t,
typename std::enable_if_t<std::is_integral_v<UI> && std::is_unsigned_v<UI>, int> = 0>
constexpr void init_raw_base(big_uint<Bits> &raw_base, UI b, const modular_ops_t &ops) {
template<std::size_t Bits, typename T, typename modular_ops_t,
typename std::enable_if_t<std::is_integral_v<T> && std::is_unsigned_v<T>, int> = 0>
constexpr void init_raw_base(big_uint<Bits> &raw_base, T b, const modular_ops_t &ops) {
ops.adjust_modular(raw_base, detail::as_big_uint(b));
}
} // namespace nil::crypto3::multiprecision::detail
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,7 @@ namespace nil::crypto3::multiprecision {
!std::numeric_limits<T>::is_signed,
int> = 0>
constexpr big_mod_t pow(const big_mod_t &b, const T &e) {
big_mod_t result(b.ops_storage());
result.ops().pow(result.raw_base(), b.raw_base(), e);
return result;
return pow_unsigned(b, e);
}

template<typename big_mod_t, typename T,
Expand All @@ -37,8 +35,8 @@ namespace nil::crypto3::multiprecision {
int> = 0>
constexpr big_mod_t pow(const big_mod_t &b, const T &e) {
if (e < 0) {
return pow(inverse(b), detail::unsigned_abs(e));
return pow_unsigned(inverse(b), detail::unsigned_abs(e));
}
return pow(b, static_cast<std::make_unsigned_t<T>>(e));
return pow_unsigned(b, static_cast<std::make_unsigned_t<T>>(e));
}
} // namespace nil::crypto3::multiprecision
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#pragma once

#include "nil/crypto3/multiprecision/detail/big_mod/type_traits.hpp"

namespace nil::crypto3::multiprecision::detail {
// This should be used in tests or benchmarks only
template<typename big_mod_t>
constexpr const auto& get_raw_base(const big_mod_t& a) {
static_assert(detail::is_big_mod_v<big_mod_t>);
return a.raw_base();
}
} // namespace nil::crypto3::multiprecision::detail
Original file line number Diff line number Diff line change
Expand Up @@ -471,8 +471,6 @@ namespace nil::crypto3::multiprecision {
return copy;
}

NIL_CO3_MP_FORCEINLINE constexpr void decrement() noexcept {}

constexpr auto operator+() const noexcept { return *this; }

constexpr auto& operator--() noexcept {
Expand Down

0 comments on commit 4ab0dc5

Please sign in to comment.