Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiprecision refactoring #98

Merged
merged 18 commits into from
Dec 10, 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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ endif()
# Add dummy target for the more efficient reusing of precompiled headers
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/generated-dummy.cpp)
add_library(crypto3_precompiled_headers STATIC ${CMAKE_CURRENT_BINARY_DIR}/generated-dummy.cpp)
set_target_properties(crypto3_precompiled_headers PROPERTIES
LINKER_LANGUAGE CXX
CXX_STANDARD 20
CXX_STANDARD_REQUIRED TRUE
)

file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/generated-dummy-23.cpp)
add_library(crypto3_precompiled_headers_23 STATIC ${CMAKE_CURRENT_BINARY_DIR}/generated-dummy-23.cpp)
Expand Down
3 changes: 2 additions & 1 deletion crypto3/benchmarks/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ macro(define_benchmark benchmark)

set_target_properties(${full_name}
PROPERTIES
CXX_STANDARD 17
CXX_STANDARD 20
CXX_STANDARD_REQUIRED TRUE)

if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
Expand All @@ -60,6 +60,7 @@ set(BENCHMARK_NAMES
"math/polynomial_dfs"

"multiprecision/modular_adaptor_fixed"
"multiprecision/big_int"

"zk/lpc"
"zk/pedersen"
Expand Down
292 changes: 292 additions & 0 deletions crypto3/benchmarks/multiprecision/big_int.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,292 @@
//---------------------------------------------------------------------------//
// Copyright (c) 2024 Martun Karapetyan <[email protected]>
// Copyright (c) 2024 Vasiliy Olekhov <[email protected]>
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//---------------------------------------------------------------------------//

#define BOOST_TEST_MODULE big_int_benchmark_test

#include <boost/test/unit_test.hpp>
#include <boost/test/data/test_case.hpp>
#include <boost/test/data/monomorphic.hpp>

#include <cstddef>
#include <iostream>

#include <nil/crypto3/multiprecision/big_uint.hpp>
#include <nil/crypto3/multiprecision/literals.hpp>
#include <nil/crypto3/multiprecision/big_mod.hpp>

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

using namespace nil::crypto3::multiprecision::literals;

constexpr std::size_t Bits = 256;
using standart_number = nil::crypto3::multiprecision::big_uint<Bits>;

constexpr standart_number modulus_odd = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f_big_uint256;
constexpr standart_number modulus_even = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e_big_uint256;

using modular_number_ct_odd = nil::crypto3::multiprecision::montgomery_big_mod<modulus_odd>;
using modular_number_ct_even = nil::crypto3::multiprecision::big_mod<modulus_even>;
using modular_number_rt_montgomery = nil::crypto3::multiprecision::montgomery_big_mod_rt<Bits>;
using modular_number_rt = nil::crypto3::multiprecision::big_mod_rt<Bits>;

constexpr standart_number x = 0xb5d724ce6f44c3c587867bbcb417e9eb6fa05e7e2ef029166568f14eb3161387_big_uint256;
constexpr modular_number_ct_odd x_mod_ct_odd = x;
constexpr modular_number_ct_even x_mod_ct_even = x;
constexpr modular_number_rt_montgomery x_mod_rt_odd{x, modulus_odd};
constexpr modular_number_rt x_mod_rt_even{x, modulus_even};

constexpr standart_number y = 0xad6e1fcc680392abfb075838eafa513811112f14c593e0efacb6e9d0d7770b4_big_uint256;
constexpr modular_number_ct_odd y_mod_ct_odd = y;
constexpr modular_number_ct_even y_mod_ct_even = y;
constexpr modular_number_rt_montgomery y_mod_rt_odd{y, modulus_odd};
constexpr modular_number_rt y_mod_rt_even{y, modulus_even};

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();
auto mod_ops = x_mod_rt_odd.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;
});

std::cout << raw_base << std::endl;
}

BOOST_AUTO_TEST_CASE(big_mod_sub_perf_test) {
auto x_modular = x_mod_rt_odd;

nil::crypto3::bench::run_benchmark<>(
"[odd modulus][runtime] big_mod_subtract",
[&]() {
x_modular -= y_mod_rt_odd;
return x_modular;
});

// Print something so the whole computation is not optimized out.
std::cout << x_modular << std::endl;
}

BOOST_AUTO_TEST_CASE(big_mod_add_perf_test) {
auto x_modular = x_mod_rt_odd;

nil::crypto3::bench::run_benchmark<>(
"[odd modulus][runtime] big_mod_add",
[&]() {
x_modular += y_mod_rt_odd;
return x_modular;
});

// Print something so the whole computation is not optimized out.
std::cout << x_modular << std::endl;
}

BOOST_AUTO_TEST_CASE(big_mod_mul_perf_test) {
auto x_modular = x_mod_rt_odd;

nil::crypto3::bench::run_benchmark<>(
"[odd modulus][runtime] big_mod_multiply",
[&]() {
x_modular *= y_mod_rt_odd;
return x_modular;
});

// Print something so the whole computation is not optimized out.
std::cout << x_modular << std::endl;
}

BOOST_AUTO_TEST_SUITE_END()

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();
auto mod_ops = x_mod_ct_odd.ops();

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;
});

std::cout << raw_base << std::endl;
}

BOOST_AUTO_TEST_CASE(big_mod_sub_perf_test) {
auto x_modular = x_mod_ct_odd;

nil::crypto3::bench::run_benchmark<>(
"[odd modulus][compile time] big_mod_subtract",
[&]() {
x_modular -= y_mod_ct_odd;
return x_modular;
});

// Print something so the whole computation is not optimized out.
std::cout << x_modular << std::endl;
}

BOOST_AUTO_TEST_CASE(big_mod_add_perf_test) {
auto x_modular = x_mod_ct_odd;

nil::crypto3::bench::run_benchmark<>(
"[odd modulus][compile time] big_mod_add",
[&]() {
x_modular += y_mod_ct_odd;
return x_modular;
});

// Print something so the whole computation is not optimized out.
std::cout << x_modular << std::endl;
}

BOOST_AUTO_TEST_CASE(big_mod_mul_perf_test) {
auto x_modular = x_mod_ct_odd;

nil::crypto3::bench::run_benchmark<>(
"[odd modulus][compile time] big_mod_multiply",
[&]() {
x_modular *= y_mod_ct_odd;
return x_modular;
});

// Print something so the whole computation is not optimized out.
std::cout << x_modular << std::endl;
}

BOOST_AUTO_TEST_SUITE_END()

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();
auto mod_ops = x_mod_rt_even.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;
});

std::cout << raw_base << std::endl;
}

BOOST_AUTO_TEST_CASE(big_mod_sub_perf_test) {
auto x_modular = x_mod_rt_even;

nil::crypto3::bench::run_benchmark<>(
"[even modulus][runtime] big_mod_subtract",
[&]() {
x_modular -= y_mod_rt_even;
return x_modular;
});

// Print something so the whole computation is not optimized out.
std::cout << x_modular << std::endl;
}

BOOST_AUTO_TEST_CASE(big_mod_add_perf_test) {
auto x_modular = x_mod_rt_even;

nil::crypto3::bench::run_benchmark<>(
"[even modulus][runtime] big_mod_add",
[&]() {
x_modular += y_mod_rt_even;
return x_modular;
});

// Print something so the whole computation is not optimized out.
std::cout << x_modular << std::endl;
}

BOOST_AUTO_TEST_CASE(big_mod_mul_perf_test) {
auto x_modular = x_mod_rt_even;

nil::crypto3::bench::run_benchmark<>(
"[even modulus][runtime] big_mod_multiply",
[&]() {
x_modular *= y_mod_rt_even;
return x_modular;
});

// Print something so the whole computation is not optimized out.
std::cout << x_modular << std::endl;
}

BOOST_AUTO_TEST_SUITE_END()

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();
auto mod_ops = x_mod_ct_even.ops();

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;
});

std::cout << raw_base << std::endl;
}

BOOST_AUTO_TEST_CASE(big_mod_sub_perf_test) {
auto x_modular = x_mod_ct_even;

nil::crypto3::bench::run_benchmark<>(
"[even modulus][compile time] big_mod_subtract",
[&]() {
x_modular -= y_mod_ct_even;
return x_modular;
});

// Print something so the whole computation is not optimized out.
std::cout << x_modular << std::endl;
}

BOOST_AUTO_TEST_CASE(big_mod_add_perf_test) {
auto x_modular = x_mod_ct_even;

nil::crypto3::bench::run_benchmark<>(
"[even modulus][compile time] big_mod_add",
[&]() {
x_modular += y_mod_ct_even;
return x_modular;
});

// Print something so the whole computation is not optimized out.
std::cout << x_modular << std::endl;
}

BOOST_AUTO_TEST_CASE(big_mod_mul_perf_test) {
auto x_modular = x_mod_ct_even;

nil::crypto3::bench::run_benchmark<>(
"[even modulus][compile time] big_mod_multiply",
[&]() {
x_modular *= y_mod_ct_even;
return x_modular;
});

// Print something so the whole computation is not optimized out.
std::cout << x_modular << std::endl;
}

BOOST_AUTO_TEST_SUITE_END()
Loading
Loading