8#include <gtest/gtest.h>
19 return { nonmont.
data[0], nonmont.data[1], nonmont.data[2], nonmont.data[3] };
22template <
class F> F from_raw(
const uint256_t&
a)
25 r.self_to_montgomery_form();
29template <
class S,
class F>
uint256_t by_invert(
const F&
a)
32 constexpr uint64_t p_inv_mod_2k = S::p_inv_mod_2k_from_montgomery_r_inv(F::Params::r_inv);
33 return bb::bernstein_yang::invert_vartime<S>(to_raw(
a), p, p_inv_mod_2k);
37template <
class S,
class F>
void check_inverse_matches_modexp(
size_t n)
39 for (
size_t i = 0; i < n; ++i) {
40 F
a = F::random_element();
44 F got = from_raw<F>(by_invert<S>(
a));
45 EXPECT_EQ(got *
a, F::one()) <<
"iteration " << i;
50template <
class F>
void check_native_matches_wasm(
size_t n)
52 for (
size_t i = 0; i < n; ++i) {
53 F
a = F::random_element();
57 EXPECT_EQ(by_invert<Native>(
a), by_invert<Wasm>(
a)) <<
"iteration " << i;
61template <
class S,
class F>
void check_edge_cases()
64 EXPECT_EQ(from_raw<F>(by_invert<S>(F::one())), F::one());
67 F neg_one = -F::one();
68 EXPECT_EQ(from_raw<F>(by_invert<S>(neg_one)), neg_one);
71 F two = F::one() + F::one();
73 F top_limb_only{ 0, 0, 0, 1 };
74 top_limb_only.self_to_montgomery_form();
75 for (
const F&
a : { two, neg_two, top_limb_only }) {
76 F inv = from_raw<F>(by_invert<S>(
a));
77 EXPECT_EQ(inv *
a, F::one());
81 for (
int i = 0; i < 64; ++i) {
82 F
a = F::random_element();
86 F inv = from_raw<F>(by_invert<S>(
a));
87 F inv_inv = from_raw<F>(by_invert<S>(inv));
88 EXPECT_EQ(inv_inv,
a);
94TEST(Wasm9x29, MatchesModexp_BN254_Fr)
96 check_inverse_matches_modexp<Wasm, bb::fr>(500);
98TEST(Wasm9x29, MatchesModexp_BN254_Fq)
100 check_inverse_matches_modexp<Wasm, bb::fq>(500);
103TEST(Native5x64, MatchesModexp_BN254_Fr)
105 check_inverse_matches_modexp<Native, bb::fr>(500);
107TEST(Native5x64, MatchesModexp_BN254_Fq)
109 check_inverse_matches_modexp<Native, bb::fq>(500);
112TEST(Wasm9x29, EdgeCases_BN254_Fr)
114 check_edge_cases<Wasm, bb::fr>();
116TEST(Wasm9x29, EdgeCases_BN254_Fq)
118 check_edge_cases<Wasm, bb::fq>();
120TEST(Native5x64, EdgeCases_BN254_Fr)
122 check_edge_cases<Native, bb::fr>();
124TEST(Native5x64, EdgeCases_BN254_Fq)
126 check_edge_cases<Native, bb::fq>();
129TEST(BernsteinYang, NativeMatchesWasm_BN254_Fr)
131 check_native_matches_wasm<bb::fr>(500);
133TEST(BernsteinYang, NativeMatchesWasm_BN254_Fq)
135 check_native_matches_wasm<bb::fq>(500);
141TEST(BernsteinYang, FermatFallback_Secp256k1_Fr)
146TEST(BernsteinYang, FermatFallback_Secp256r1_Fr)
TEST(Wasm9x29, MatchesModexp_BN254_Fr)
BB_INLINE constexpr field from_montgomery_form_reduced() const noexcept
static constexpr field one()
constexpr field invert() const noexcept
static field random_element(numeric::RNG *engine=nullptr) noexcept