diff --git a/crypto3/libs/multiprecision/include/nil/crypto3/multiprecision/big_integer/big_integer_impl.hpp b/crypto3/libs/multiprecision/include/nil/crypto3/multiprecision/big_integer/big_integer_impl.hpp index a51f07d10..16e917eec 100644 --- a/crypto3/libs/multiprecision/include/nil/crypto3/multiprecision/big_integer/big_integer_impl.hpp +++ b/crypto3/libs/multiprecision/include/nil/crypto3/multiprecision/big_integer/big_integer_impl.hpp @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include diff --git a/crypto3/libs/multiprecision/include/nil/crypto3/multiprecision/big_integer/modular/modular_big_integer_impl.hpp b/crypto3/libs/multiprecision/include/nil/crypto3/multiprecision/big_integer/modular/modular_big_integer_impl.hpp index 67c10fd13..8a11dce4a 100644 --- a/crypto3/libs/multiprecision/include/nil/crypto3/multiprecision/big_integer/modular/modular_big_integer_impl.hpp +++ b/crypto3/libs/multiprecision/include/nil/crypto3/multiprecision/big_integer/modular/modular_big_integer_impl.hpp @@ -13,6 +13,7 @@ // IWYU pragma: private; include "nil/crypto3/multiprecision/big_integer/modular/modular_big_integer.hpp" +#include #include #include #include @@ -38,12 +39,10 @@ namespace nil::crypto3::multiprecision { // Constructors protected: - inline constexpr modular_big_integer_impl(const big_integer_t x, + template + inline constexpr modular_big_integer_impl(const big_integer& x, modular_ops_storage_t&& modular_ops_storage) : m_modular_ops_storage(std::move(modular_ops_storage)) { - // TODO(ioxid): do we need this? - // NIL_CO3_MP_ASSERT_MSG(Bits == msb(mod()) + 1, - // "modulus precision should match used big_integer"); ops().adjust_modular(m_raw_base, x); } @@ -51,7 +50,6 @@ namespace nil::crypto3::multiprecision { // Comparison constexpr bool compare_eq(const modular_big_integer_impl& o) const { - // TODO(ioxid): ensure modulus comparison is done in compile time when possible return ops().compare_eq(o.ops()) && m_raw_base == o.m_raw_base; } @@ -101,24 +99,20 @@ namespace nil::crypto3::multiprecision { using typename base_type::big_integer_t; - constexpr modular_big_integer_ct_impl() : base_type({}, {}) {} - - constexpr modular_big_integer_ct_impl(const big_integer_t& b) : base_type(b, {}) { - this->ops().adjust_modular(this->m_raw_base, b); - } + constexpr modular_big_integer_ct_impl() : base_type(big_integer_t(0u), {}) {} template - constexpr explicit modular_big_integer_ct_impl(const big_integer& b) - : base_type(b, {}) { + constexpr modular_big_integer_ct_impl(const big_integer& b) : base_type(b, {}) { this->ops().adjust_modular(this->m_raw_base, b); } + // TODO(ioxid): this is buggy, need to remove it asap // A method for converting a signed integer to a modular adaptor. We are not supposed to // have this, but in the code we already have conversion for an 'int' into modular type. // In the future we must remove. template && std::is_signed_v, int> = 0> - constexpr modular_big_integer_ct_impl(SI b) : base_type(0u, {}) { + constexpr modular_big_integer_ct_impl(SI b) : base_type(big_integer_t(0u), {}) { if (b >= 0) { this->m_raw_base = static_cast>(b); } else { @@ -133,7 +127,8 @@ namespace nil::crypto3::multiprecision { template && std::is_unsigned_v, int> = 0> - constexpr modular_big_integer_ct_impl(UI b) : base_type(b, {}) {} + constexpr modular_big_integer_ct_impl(UI b) + : base_type(big_integer(b), {}) {} template inline constexpr modular_big_integer_ct_impl with_replaced_base( @@ -153,7 +148,8 @@ namespace nil::crypto3::multiprecision { template && std::is_signed_v, int> = 0> - constexpr modular_big_integer_rt_impl(SI b, const big_integer_t& m) : base_type(0u, m) { + constexpr modular_big_integer_rt_impl(SI b, const big_integer_t& m) + : base_type(big_integer_t(0u), m) { if (b >= 0) { this->m_raw_base = b; } else { @@ -166,14 +162,15 @@ namespace nil::crypto3::multiprecision { this->ops().adjust_modular(this->m_raw_base); } - template && std::is_unsigned_v, int> = 0> - constexpr modular_big_integer_rt_impl(UI b, const big_integer_t& m) : base_type(b, m) {} - template constexpr modular_big_integer_rt_impl(const big_integer& b, const big_integer_t& m) : base_type(b, m) {} + template && std::is_unsigned_v, int> = 0> + constexpr modular_big_integer_rt_impl(UI b, const big_integer_t& m) + : base_type(big_integer(b), m) {} + template inline constexpr modular_big_integer_rt_impl with_replaced_base( const big_integer& b) const { @@ -359,7 +356,6 @@ namespace nil::crypto3::multiprecision { template inline constexpr std::size_t hash_value( const detail::modular_big_integer_impl& val) noexcept { - // TODO(ioxid): also hash modulus for runtime type return hash_value(val.raw_base()); } diff --git a/crypto3/libs/multiprecision/include/nil/crypto3/multiprecision/big_integer/modular/modular_ops_storage.hpp b/crypto3/libs/multiprecision/include/nil/crypto3/multiprecision/big_integer/modular/modular_ops_storage.hpp index 967a5f88c..25a505790 100644 --- a/crypto3/libs/multiprecision/include/nil/crypto3/multiprecision/big_integer/modular/modular_ops_storage.hpp +++ b/crypto3/libs/multiprecision/include/nil/crypto3/multiprecision/big_integer/modular/modular_ops_storage.hpp @@ -22,6 +22,9 @@ namespace nil::crypto3::multiprecision::detail { using big_integer_t = std::decay_t; using modular_ops_t = modular_ops_template; + static_assert(big_integer_t::Bits == msb(Modulus) + 1, + "modulus bit width should match used precision"); + constexpr modular_ops_storage_ct() {} static constexpr const modular_ops_t &ops() { return m_modular_ops; } diff --git a/crypto3/libs/multiprecision/include/nil/crypto3/multiprecision/big_integer/signed_big_integer.hpp b/crypto3/libs/multiprecision/include/nil/crypto3/multiprecision/big_integer/signed_big_integer.hpp index 2942eb9ed..ed3c1418d 100644 --- a/crypto3/libs/multiprecision/include/nil/crypto3/multiprecision/big_integer/signed_big_integer.hpp +++ b/crypto3/libs/multiprecision/include/nil/crypto3/multiprecision/big_integer/signed_big_integer.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -11,6 +12,9 @@ #include "nil/crypto3/multiprecision/big_integer/detail/assert.hpp" #include "nil/crypto3/multiprecision/big_integer/detail/config.hpp" +// TODO(ioxid): boost is used for +// boost::hash_combine + namespace nil::crypto3::multiprecision { template class signed_big_integer { @@ -378,7 +382,13 @@ namespace nil::crypto3::multiprecision { return a; } - // TODO(ioxid): hash + template + inline constexpr std::size_t hash_value(const signed_big_integer& val) noexcept { + std::size_t result = 0; + boost::hash_combine(result, hash_value(val.abs())); + boost::hash_combine(result, val.negative()); + return result; + } // IO diff --git a/crypto3/libs/multiprecision/test/big_integer_modular.cpp b/crypto3/libs/multiprecision/test/big_integer_modular.cpp index 2919818cd..ac951668d 100644 --- a/crypto3/libs/multiprecision/test/big_integer_modular.cpp +++ b/crypto3/libs/multiprecision/test/big_integer_modular.cpp @@ -9,13 +9,15 @@ using namespace nil::crypto3::multiprecision; using namespace nil::crypto3::multiprecision::literals; +NIL_CO3_MP_DEFINE_BIG_INTEGER_LITERAL(2) NIL_CO3_MP_DEFINE_BIG_INTEGER_LITERAL(32) NIL_CO3_MP_DEFINE_BIG_INTEGER_LITERAL(36) +NIL_CO3_MP_DEFINE_BIG_INTEGER_LITERAL(57) NIL_CO3_MP_DEFINE_BIG_INTEGER_LITERAL(60) using namespace nil::crypto3::multiprecision::literals; -constexpr auto mod = 0x123456789ABCDEF_big_integer64; +constexpr auto mod = 0x123456789ABCDEF_big_integer57; using modular_big_int = montgomery_modular_big_integer; BOOST_AUTO_TEST_SUITE(smoke) @@ -25,45 +27,45 @@ BOOST_AUTO_TEST_CASE(construct_constexpr) { } BOOST_AUTO_TEST_CASE(construct_modular_ct_trivial_montgomery) { - static constexpr auto mod = 0x3_big_integer64; - auto_modular_big_integer a = auto_modular_big_integer(0x5_big_integer64); + static constexpr auto mod = 0x3_big_integer2; + auto_modular_big_integer a = auto_modular_big_integer(0x5_big_integer); BOOST_CHECK_EQUAL(a.str(), "0x2 mod 0x3"); } BOOST_AUTO_TEST_CASE(construct_modular_rt_trivial_montgomery) { - modular_big_integer_rt<64> a{0x5_big_integer64, 0x3_big_integer64}; + modular_big_integer_rt<2> a{0x5_big_integer, 0x3_big_integer}; BOOST_CHECK_EQUAL(a.str(), "0x2 mod 0x3"); } BOOST_AUTO_TEST_CASE(construct_modular_ct_small_montgomery) { - static constexpr auto mod = 0x79_big_integer64; - auto_modular_big_integer a = auto_modular_big_integer(0x1234_big_integer64); + static constexpr auto mod = 0x79_big_integer7; + auto_modular_big_integer a = auto_modular_big_integer(0x1234_big_integer); BOOST_CHECK_EQUAL(a.str(), "0x3E mod 0x79"); } BOOST_AUTO_TEST_CASE(construct_modular_rt_small_montgomery) { - modular_big_integer_rt<64> a{0x1234_big_integer64, 0x79_big_integer64}; + modular_big_integer_rt<7> a{0x1234_big_integer, 0x79_big_integer}; BOOST_CHECK_EQUAL(a.str(), "0x3E mod 0x79"); } BOOST_AUTO_TEST_CASE(construct_modular_ct_small) { - static constexpr auto mod = 0x78_big_integer64; - auto_modular_big_integer a = auto_modular_big_integer(0x1234_big_integer64); + static constexpr auto mod = 0x78_big_integer7; + auto_modular_big_integer a = auto_modular_big_integer(0x1234_big_integer); BOOST_CHECK_EQUAL(a.str(), "0x64 mod 0x78"); } BOOST_AUTO_TEST_CASE(construct_modular_rt_small) { - modular_big_integer_rt<64> a{0x1234_big_integer64, 0x78_big_integer64}; + modular_big_integer_rt<7> a{0x1234_big_integer, 0x78_big_integer}; BOOST_CHECK_EQUAL(a.str(), "0x64 mod 0x78"); } BOOST_AUTO_TEST_CASE(to_string_trivial) { - BOOST_CHECK_EQUAL((static_cast(0x1_big_integer64)).str(), + BOOST_CHECK_EQUAL((static_cast(0x1_big_integer)).str(), "0x1 mod 0x123456789ABCDEF"); } BOOST_AUTO_TEST_CASE(to_string_small) { - BOOST_CHECK_EQUAL((static_cast(0x20_big_integer64)).str(), + BOOST_CHECK_EQUAL((static_cast(0x20_big_integer)).str(), "0x20 mod 0x123456789ABCDEF"); }