src/snark patches for windows build
This commit is contained in:
@@ -6,16 +6,17 @@
|
||||
*****************************************************************************/
|
||||
|
||||
#include "algebra/curves/alt_bn128/alt_bn128_g1.hpp"
|
||||
#include "common/assert_except.hpp"
|
||||
|
||||
namespace libsnark {
|
||||
|
||||
#ifdef PROFILE_OP_COUNTS
|
||||
long long alt_bn128_G1::add_cnt = 0;
|
||||
long long alt_bn128_G1::dbl_cnt = 0;
|
||||
int64_t alt_bn128_G1::add_cnt = 0;
|
||||
int64_t alt_bn128_G1::dbl_cnt = 0;
|
||||
#endif
|
||||
|
||||
std::vector<size_t> alt_bn128_G1::wnaf_window_table;
|
||||
std::vector<size_t> alt_bn128_G1::fixed_base_exp_window_table;
|
||||
std::vector<uint64_t> alt_bn128_G1::wnaf_window_table;
|
||||
std::vector<uint64_t> alt_bn128_G1::fixed_base_exp_window_table;
|
||||
alt_bn128_G1 alt_bn128_G1::G1_zero;
|
||||
alt_bn128_G1 alt_bn128_G1::G1_one;
|
||||
|
||||
@@ -256,7 +257,7 @@ alt_bn128_G1 alt_bn128_G1::add(const alt_bn128_G1 &other) const
|
||||
alt_bn128_G1 alt_bn128_G1::mixed_add(const alt_bn128_G1 &other) const
|
||||
{
|
||||
#ifdef DEBUG
|
||||
assert(other.is_special());
|
||||
assert_except(other.is_special());
|
||||
#endif
|
||||
|
||||
// handle special cases having to do with O
|
||||
|
||||
@@ -20,11 +20,11 @@ std::istream& operator>>(std::istream &, alt_bn128_G1&);
|
||||
class alt_bn128_G1 {
|
||||
public:
|
||||
#ifdef PROFILE_OP_COUNTS
|
||||
static long long add_cnt;
|
||||
static long long dbl_cnt;
|
||||
static int64_t add_cnt;
|
||||
static int64_t dbl_cnt;
|
||||
#endif
|
||||
static std::vector<size_t> wnaf_window_table;
|
||||
static std::vector<size_t> fixed_base_exp_window_table;
|
||||
static std::vector<uint64_t> wnaf_window_table;
|
||||
static std::vector<uint64_t> fixed_base_exp_window_table;
|
||||
static alt_bn128_G1 G1_zero;
|
||||
static alt_bn128_G1 G1_one;
|
||||
|
||||
|
||||
@@ -6,16 +6,17 @@
|
||||
*****************************************************************************/
|
||||
|
||||
#include "algebra/curves/alt_bn128/alt_bn128_g2.hpp"
|
||||
#include "common/assert_except.hpp"
|
||||
|
||||
namespace libsnark {
|
||||
|
||||
#ifdef PROFILE_OP_COUNTS
|
||||
long long alt_bn128_G2::add_cnt = 0;
|
||||
long long alt_bn128_G2::dbl_cnt = 0;
|
||||
int64_t alt_bn128_G2::add_cnt = 0;
|
||||
int64_t alt_bn128_G2::dbl_cnt = 0;
|
||||
#endif
|
||||
|
||||
std::vector<size_t> alt_bn128_G2::wnaf_window_table;
|
||||
std::vector<size_t> alt_bn128_G2::fixed_base_exp_window_table;
|
||||
std::vector<uint64_t> alt_bn128_G2::wnaf_window_table;
|
||||
std::vector<uint64_t> alt_bn128_G2::fixed_base_exp_window_table;
|
||||
alt_bn128_G2 alt_bn128_G2::G2_zero;
|
||||
alt_bn128_G2 alt_bn128_G2::G2_one;
|
||||
|
||||
@@ -266,7 +267,7 @@ alt_bn128_G2 alt_bn128_G2::add(const alt_bn128_G2 &other) const
|
||||
alt_bn128_G2 alt_bn128_G2::mixed_add(const alt_bn128_G2 &other) const
|
||||
{
|
||||
#ifdef DEBUG
|
||||
assert(other.is_special());
|
||||
assert_except(other.is_special());
|
||||
#endif
|
||||
|
||||
// handle special cases having to do with O
|
||||
|
||||
@@ -20,11 +20,11 @@ std::istream& operator>>(std::istream &, alt_bn128_G2&);
|
||||
class alt_bn128_G2 {
|
||||
public:
|
||||
#ifdef PROFILE_OP_COUNTS
|
||||
static long long add_cnt;
|
||||
static long long dbl_cnt;
|
||||
static int64_t add_cnt;
|
||||
static int64_t dbl_cnt;
|
||||
#endif
|
||||
static std::vector<size_t> wnaf_window_table;
|
||||
static std::vector<size_t> fixed_base_exp_window_table;
|
||||
static std::vector<uint64_t> wnaf_window_table;
|
||||
static std::vector<uint64_t> fixed_base_exp_window_table;
|
||||
static alt_bn128_G2 G2_zero;
|
||||
static alt_bn128_G2 G2_one;
|
||||
|
||||
|
||||
@@ -324,7 +324,7 @@ alt_bn128_ate_G2_precomp alt_bn128_ate_precompute_G2(const alt_bn128_G2& Q)
|
||||
bool found_one = false;
|
||||
alt_bn128_ate_ell_coeffs c;
|
||||
|
||||
for (long i = loop_count.max_bits(); i >= 0; --i)
|
||||
for (int64_t i = loop_count.max_bits(); i >= 0; --i)
|
||||
{
|
||||
const bool bit = loop_count.test_bit(i);
|
||||
if (!found_one)
|
||||
@@ -378,7 +378,7 @@ alt_bn128_Fq12 alt_bn128_ate_miller_loop(const alt_bn128_ate_G1_precomp &prec_P,
|
||||
const bigint<alt_bn128_Fr::num_limbs> &loop_count = alt_bn128_ate_loop_count;
|
||||
alt_bn128_ate_ell_coeffs c;
|
||||
|
||||
for (long i = loop_count.max_bits(); i >= 0; --i)
|
||||
for (int64_t i = loop_count.max_bits(); i >= 0; --i)
|
||||
{
|
||||
const bool bit = loop_count.test_bit(i);
|
||||
if (!found_one)
|
||||
@@ -432,7 +432,7 @@ alt_bn128_Fq12 alt_bn128_ate_double_miller_loop(const alt_bn128_ate_G1_precomp &
|
||||
size_t idx = 0;
|
||||
|
||||
const bigint<alt_bn128_Fr::num_limbs> &loop_count = alt_bn128_ate_loop_count;
|
||||
for (long i = loop_count.max_bits(); i >= 0; --i)
|
||||
for (int64_t i = loop_count.max_bits(); i >= 0; --i)
|
||||
{
|
||||
const bool bit = loop_count.test_bit(i);
|
||||
if (!found_one)
|
||||
|
||||
@@ -16,7 +16,7 @@ GroupT scalar_mul(const GroupT &base, const bigint<m> &scalar)
|
||||
GroupT result = GroupT::zero();
|
||||
|
||||
bool found_one = false;
|
||||
for (long i = scalar.max_bits() - 1; i >= 0; --i)
|
||||
for (int64_t i = scalar.max_bits() - 1; i >= 0; --i)
|
||||
{
|
||||
if (found_one)
|
||||
{
|
||||
|
||||
@@ -4,13 +4,17 @@
|
||||
* and contributors (see AUTHORS).
|
||||
* @copyright MIT license (see LICENSE file)
|
||||
*****************************************************************************/
|
||||
#include <iostream>
|
||||
#include "common/profiling.hpp"
|
||||
//#include "algebra/curves/edwards/edwards_pp.hpp"
|
||||
#ifdef CURVE_BN128
|
||||
#include "algebra/curves/bn128/bn128_pp.hpp"
|
||||
#endif
|
||||
#include "algebra/curves/alt_bn128/alt_bn128_pp.hpp"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
//#include "algebra/curves/mnt/mnt4/mnt4_pp.hpp"
|
||||
//#include "algebra/curves/mnt/mnt6/mnt6_pp.hpp"
|
||||
#include "algebra/curves/alt_bn128/alt_bn128_pairing.hpp"
|
||||
#include "algebra/curves/alt_bn128/alt_bn128_pairing.cpp"
|
||||
|
||||
using namespace libsnark;
|
||||
|
||||
@@ -45,11 +49,11 @@ void pairing_test()
|
||||
ans1.print();
|
||||
ans2.print();
|
||||
ans3.print();
|
||||
EXPECT_EQ(ans1, ans2);
|
||||
EXPECT_EQ(ans2, ans3);
|
||||
assert(ans1 == ans2);
|
||||
assert(ans2 == ans3);
|
||||
|
||||
EXPECT_NE(ans1, GT_one);
|
||||
EXPECT_EQ((ans1^Fr<ppT>::field_char()), GT_one);
|
||||
assert(ans1 != GT_one);
|
||||
assert((ans1^Fr<ppT>::field_char()) == GT_one);
|
||||
printf("\n\n");
|
||||
}
|
||||
|
||||
@@ -69,7 +73,7 @@ void double_miller_loop_test()
|
||||
const Fqk<ppT> ans_1 = ppT::miller_loop(prec_P1, prec_Q1);
|
||||
const Fqk<ppT> ans_2 = ppT::miller_loop(prec_P2, prec_Q2);
|
||||
const Fqk<ppT> ans_12 = ppT::double_miller_loop(prec_P1, prec_Q1, prec_P2, prec_Q2);
|
||||
EXPECT_EQ(ans_1 * ans_2, ans_12);
|
||||
assert(ans_1 * ans_2 == ans_12);
|
||||
}
|
||||
|
||||
template<typename ppT>
|
||||
@@ -98,17 +102,31 @@ void affine_pairing_test()
|
||||
ans1.print();
|
||||
ans2.print();
|
||||
ans3.print();
|
||||
EXPECT_EQ(ans1, ans2);
|
||||
EXPECT_EQ(ans2, ans3);
|
||||
assert(ans1 == ans2);
|
||||
assert(ans2 == ans3);
|
||||
|
||||
EXPECT_NE(ans1, GT_one);
|
||||
EXPECT_EQ((ans1^Fr<ppT>::field_char()), GT_one);
|
||||
assert(ans1 != GT_one);
|
||||
assert((ans1^Fr<ppT>::field_char()) == GT_one);
|
||||
printf("\n\n");
|
||||
}
|
||||
|
||||
TEST(algebra, bilinearity)
|
||||
int main(void)
|
||||
{
|
||||
start_profiling();
|
||||
edwards_pp::init_public_params();
|
||||
pairing_test<edwards_pp>();
|
||||
double_miller_loop_test<edwards_pp>();
|
||||
|
||||
mnt6_pp::init_public_params();
|
||||
pairing_test<mnt6_pp>();
|
||||
double_miller_loop_test<mnt6_pp>();
|
||||
affine_pairing_test<mnt6_pp>();
|
||||
|
||||
mnt4_pp::init_public_params();
|
||||
pairing_test<mnt4_pp>();
|
||||
double_miller_loop_test<mnt4_pp>();
|
||||
affine_pairing_test<mnt4_pp>();
|
||||
|
||||
alt_bn128_pp::init_public_params();
|
||||
pairing_test<alt_bn128_pp>();
|
||||
double_miller_loop_test<alt_bn128_pp>();
|
||||
|
||||
@@ -5,14 +5,15 @@
|
||||
* @copyright MIT license (see LICENSE file)
|
||||
*****************************************************************************/
|
||||
#include "common/profiling.hpp"
|
||||
//#include "algebra/curves/edwards/edwards_pp.hpp"
|
||||
//#include "algebra/curves/mnt/mnt4/mnt4_pp.hpp"
|
||||
//#include "algebra/curves/mnt/mnt6/mnt6_pp.hpp"
|
||||
#ifdef CURVE_BN128
|
||||
#include "algebra/curves/bn128/bn128_pp.hpp"
|
||||
#endif
|
||||
#include "algebra/curves/alt_bn128/alt_bn128_pp.hpp"
|
||||
#include <sstream>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using namespace libsnark;
|
||||
|
||||
template<typename GroupT>
|
||||
@@ -24,31 +25,31 @@ void test_mixed_add()
|
||||
el = GroupT::zero();
|
||||
el.to_special();
|
||||
result = base.mixed_add(el);
|
||||
EXPECT_EQ(result, base + el);
|
||||
assert(result == base + el);
|
||||
|
||||
base = GroupT::zero();
|
||||
el = GroupT::random_element();
|
||||
el.to_special();
|
||||
result = base.mixed_add(el);
|
||||
EXPECT_EQ(result, base + el);
|
||||
assert(result == base + el);
|
||||
|
||||
base = GroupT::random_element();
|
||||
el = GroupT::zero();
|
||||
el.to_special();
|
||||
result = base.mixed_add(el);
|
||||
EXPECT_EQ(result, base + el);
|
||||
assert(result == base + el);
|
||||
|
||||
base = GroupT::random_element();
|
||||
el = GroupT::random_element();
|
||||
el.to_special();
|
||||
result = base.mixed_add(el);
|
||||
EXPECT_EQ(result, base + el);
|
||||
assert(result == base + el);
|
||||
|
||||
base = GroupT::random_element();
|
||||
el = base;
|
||||
el.to_special();
|
||||
result = base.mixed_add(el);
|
||||
EXPECT_EQ(result, base.dbl());
|
||||
assert(result == base.dbl());
|
||||
}
|
||||
|
||||
template<typename GroupT>
|
||||
@@ -59,53 +60,53 @@ void test_group()
|
||||
bigint<1> randsum = bigint<1>("121160274");
|
||||
|
||||
GroupT zero = GroupT::zero();
|
||||
EXPECT_EQ(zero, zero);
|
||||
assert(zero == zero);
|
||||
GroupT one = GroupT::one();
|
||||
EXPECT_EQ(one, one);
|
||||
assert(one == one);
|
||||
GroupT two = bigint<1>(2l) * GroupT::one();
|
||||
EXPECT_EQ(two, two);
|
||||
assert(two == two);
|
||||
GroupT five = bigint<1>(5l) * GroupT::one();
|
||||
|
||||
GroupT three = bigint<1>(3l) * GroupT::one();
|
||||
GroupT four = bigint<1>(4l) * GroupT::one();
|
||||
|
||||
EXPECT_EQ(two+five, three+four);
|
||||
assert(two+five == three+four);
|
||||
|
||||
GroupT a = GroupT::random_element();
|
||||
GroupT b = GroupT::random_element();
|
||||
|
||||
EXPECT_NE(one, zero);
|
||||
EXPECT_NE(a, zero);
|
||||
EXPECT_NE(a, one);
|
||||
assert(one != zero);
|
||||
assert(a != zero);
|
||||
assert(a != one);
|
||||
|
||||
EXPECT_NE(b, zero);
|
||||
EXPECT_NE(b, one);
|
||||
assert(b != zero);
|
||||
assert(b != one);
|
||||
|
||||
EXPECT_EQ(a.dbl(), a + a);
|
||||
EXPECT_EQ(b.dbl(), b + b);
|
||||
EXPECT_EQ(one.add(two), three);
|
||||
EXPECT_EQ(two.add(one), three);
|
||||
EXPECT_EQ(a + b, b + a);
|
||||
EXPECT_EQ(a - a, zero);
|
||||
EXPECT_EQ(a - b, a + (-b));
|
||||
EXPECT_EQ(a - b, (-b) + a);
|
||||
assert(a.dbl() == a + a);
|
||||
assert(b.dbl() == b + b);
|
||||
assert(one.add(two) == three);
|
||||
assert(two.add(one) == three);
|
||||
assert(a + b == b + a);
|
||||
assert(a - a == zero);
|
||||
assert(a - b == a + (-b));
|
||||
assert(a - b == (-b) + a);
|
||||
|
||||
// handle special cases
|
||||
EXPECT_EQ(zero + (-a), -a);
|
||||
EXPECT_EQ(zero - a, -a);
|
||||
EXPECT_EQ(a - zero, a);
|
||||
EXPECT_EQ(a + zero, a);
|
||||
EXPECT_EQ(zero + a, a);
|
||||
assert(zero + (-a) == -a);
|
||||
assert(zero - a == -a);
|
||||
assert(a - zero == a);
|
||||
assert(a + zero == a);
|
||||
assert(zero + a == a);
|
||||
|
||||
EXPECT_EQ((a + b).dbl(), (a + b) + (b + a));
|
||||
EXPECT_EQ(bigint<1>("2") * (a + b), (a + b) + (b + a));
|
||||
assert((a + b).dbl() == (a + b) + (b + a));
|
||||
assert(bigint<1>("2") * (a + b) == (a + b) + (b + a));
|
||||
|
||||
EXPECT_EQ((rand1 * a) + (rand2 * a), (randsum * a));
|
||||
assert((rand1 * a) + (rand2 * a) == (randsum * a));
|
||||
|
||||
EXPECT_EQ(GroupT::order() * a, zero);
|
||||
EXPECT_EQ(GroupT::order() * one, zero);
|
||||
EXPECT_NE((GroupT::order() * a) - a, zero);
|
||||
EXPECT_NE((GroupT::order() * one) - one, zero);
|
||||
assert(GroupT::order() * a == zero);
|
||||
assert(GroupT::order() * one == zero);
|
||||
assert((GroupT::order() * a) - a != zero);
|
||||
assert((GroupT::order() * one) - one != zero);
|
||||
|
||||
test_mixed_add<GroupT>();
|
||||
}
|
||||
@@ -114,7 +115,7 @@ template<typename GroupT>
|
||||
void test_mul_by_q()
|
||||
{
|
||||
GroupT a = GroupT::random_element();
|
||||
EXPECT_EQ((GroupT::base_field_char()*a), a.mul_by_q());
|
||||
assert((GroupT::base_field_char()*a) == a.mul_by_q());
|
||||
}
|
||||
|
||||
template<typename GroupT>
|
||||
@@ -128,14 +129,36 @@ void test_output()
|
||||
ss << g;
|
||||
GroupT gg;
|
||||
ss >> gg;
|
||||
EXPECT_EQ(g, gg);
|
||||
assert(g == gg);
|
||||
/* use a random point in next iteration */
|
||||
g = GroupT::random_element();
|
||||
}
|
||||
}
|
||||
|
||||
TEST(algebra, groups)
|
||||
int main(void)
|
||||
{
|
||||
/*
|
||||
edwards_pp::init_public_params();
|
||||
test_group<G1<edwards_pp> >();
|
||||
test_output<G1<edwards_pp> >();
|
||||
test_group<G2<edwards_pp> >();
|
||||
test_output<G2<edwards_pp> >();
|
||||
test_mul_by_q<G2<edwards_pp> >();
|
||||
|
||||
mnt4_pp::init_public_params();
|
||||
test_group<G1<mnt4_pp> >();
|
||||
test_output<G1<mnt4_pp> >();
|
||||
test_group<G2<mnt4_pp> >();
|
||||
test_output<G2<mnt4_pp> >();
|
||||
test_mul_by_q<G2<mnt4_pp> >();
|
||||
|
||||
mnt6_pp::init_public_params();
|
||||
test_group<G1<mnt6_pp> >();
|
||||
test_output<G1<mnt6_pp> >();
|
||||
test_group<G2<mnt6_pp> >();
|
||||
test_output<G2<mnt6_pp> >();
|
||||
test_mul_by_q<G2<mnt6_pp> >();
|
||||
*/
|
||||
alt_bn128_pp::init_public_params();
|
||||
test_group<G1<alt_bn128_pp> >();
|
||||
test_output<G1<alt_bn128_pp> >();
|
||||
|
||||
@@ -15,15 +15,16 @@
|
||||
#define BASIC_RADIX2_DOMAIN_TCC_
|
||||
|
||||
#include "algebra/evaluation_domain/domains/basic_radix2_domain_aux.hpp"
|
||||
#include "common/assert_except.hpp"
|
||||
|
||||
namespace libsnark {
|
||||
|
||||
template<typename FieldT>
|
||||
basic_radix2_domain<FieldT>::basic_radix2_domain(const size_t m) : evaluation_domain<FieldT>(m)
|
||||
{
|
||||
assert(m > 1);
|
||||
assert_except(m > 1);
|
||||
const size_t logm = log2(m);
|
||||
assert(logm <= (FieldT::s));
|
||||
assert_except(logm <= (FieldT::s));
|
||||
|
||||
omega = get_root_of_unity<FieldT>(m);
|
||||
}
|
||||
@@ -32,7 +33,7 @@ template<typename FieldT>
|
||||
void basic_radix2_domain<FieldT>::FFT(std::vector<FieldT> &a)
|
||||
{
|
||||
enter_block("Execute FFT");
|
||||
assert(a.size() == this->m);
|
||||
assert_except(a.size() == this->m);
|
||||
_basic_radix2_FFT(a, omega);
|
||||
leave_block("Execute FFT");
|
||||
}
|
||||
@@ -41,7 +42,7 @@ template<typename FieldT>
|
||||
void basic_radix2_domain<FieldT>::iFFT(std::vector<FieldT> &a)
|
||||
{
|
||||
enter_block("Execute inverse FFT");
|
||||
assert(a.size() == this->m);
|
||||
assert_except(a.size() == this->m);
|
||||
_basic_radix2_FFT(a, omega.inverse());
|
||||
|
||||
const FieldT sconst = FieldT(a.size()).inverse();
|
||||
@@ -91,7 +92,7 @@ FieldT basic_radix2_domain<FieldT>::compute_Z(const FieldT &t)
|
||||
template<typename FieldT>
|
||||
void basic_radix2_domain<FieldT>::add_poly_Z(const FieldT &coeff, std::vector<FieldT> &H)
|
||||
{
|
||||
assert(H.size() == this->m+1);
|
||||
assert_except(H.size() == this->m+1);
|
||||
H[this->m] += coeff;
|
||||
H[0] -= coeff;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "algebra/fields/field_utils.hpp"
|
||||
#include "common/profiling.hpp"
|
||||
#include "common/utils.hpp"
|
||||
#include "common/assert_except.hpp"
|
||||
|
||||
namespace libsnark {
|
||||
|
||||
@@ -38,7 +39,7 @@ template<typename FieldT>
|
||||
void _basic_serial_radix2_FFT(std::vector<FieldT> &a, const FieldT &omega)
|
||||
{
|
||||
const size_t n = a.size(), logn = log2(n);
|
||||
assert(n == (1u << logn));
|
||||
assert_except(n == (1u << logn));
|
||||
|
||||
/* swapping in place (from Storer's book) */
|
||||
for (size_t k = 0; k < n; ++k)
|
||||
@@ -74,11 +75,11 @@ void _basic_serial_radix2_FFT(std::vector<FieldT> &a, const FieldT &omega)
|
||||
template<typename FieldT>
|
||||
void _basic_parallel_radix2_FFT_inner(std::vector<FieldT> &a, const FieldT &omega, const size_t log_cpus)
|
||||
{
|
||||
const size_t num_cpus = 1ul<<log_cpus;
|
||||
const size_t num_cpus = UINT64_C(1)<<log_cpus;
|
||||
|
||||
const size_t m = a.size();
|
||||
const size_t log_m = log2(m);
|
||||
assert(m == 1ul<<log_m);
|
||||
assert_except(m == UINT64_C(1)<<log_m);
|
||||
|
||||
if (log_m < log_cpus)
|
||||
{
|
||||
@@ -90,7 +91,7 @@ void _basic_parallel_radix2_FFT_inner(std::vector<FieldT> &a, const FieldT &omeg
|
||||
std::vector<std::vector<FieldT> > tmp(num_cpus);
|
||||
for (size_t j = 0; j < num_cpus; ++j)
|
||||
{
|
||||
tmp[j].resize(1ul<<(log_m-log_cpus), FieldT::zero());
|
||||
tmp[j].resize(UINT64_C(1)<<(log_m-log_cpus), FieldT::zero());
|
||||
}
|
||||
|
||||
#ifdef MULTICORE
|
||||
@@ -102,7 +103,7 @@ void _basic_parallel_radix2_FFT_inner(std::vector<FieldT> &a, const FieldT &omeg
|
||||
const FieldT omega_step = omega^(j<<(log_m - log_cpus));
|
||||
|
||||
FieldT elt = FieldT::one();
|
||||
for (size_t i = 0; i < 1ul<<(log_m - log_cpus); ++i)
|
||||
for (size_t i = 0; i < UINT64_C(1)<<(log_m - log_cpus); ++i)
|
||||
{
|
||||
for (size_t s = 0; s < num_cpus; ++s)
|
||||
{
|
||||
@@ -135,7 +136,7 @@ void _basic_parallel_radix2_FFT_inner(std::vector<FieldT> &a, const FieldT &omeg
|
||||
#endif
|
||||
for (size_t i = 0; i < num_cpus; ++i)
|
||||
{
|
||||
for (size_t j = 0; j < 1ul<<(log_m - log_cpus); ++j)
|
||||
for (size_t j = 0; j < UINT64_C(1)<<(log_m - log_cpus); ++j)
|
||||
{
|
||||
// now: i = idx >> (log_m - log_cpus) and j = idx % (1u << (log_m - log_cpus)), for idx = ((i<<(log_m-log_cpus))+j) % (1u << log_m)
|
||||
a[(j<<log_cpus) + i] = tmp[i][j];
|
||||
@@ -189,7 +190,7 @@ std::vector<FieldT> _basic_radix2_lagrange_coeffs(const size_t m, const FieldT &
|
||||
return std::vector<FieldT>(1, FieldT::one());
|
||||
}
|
||||
|
||||
assert(m == (1u << log2(m)));
|
||||
assert_except(m == (1u << log2(m)));
|
||||
|
||||
const FieldT omega = get_root_of_unity<FieldT>(m);
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
a choice of domain S with size ~m that has been selected so to optimize
|
||||
- computations of Lagrange polynomials, and
|
||||
- FFT/iFFT computations.
|
||||
An evaluation domain also provides other functions, e.g., accessing
|
||||
An evaluation domain also provides other other functions, e.g., accessing
|
||||
individual elements in S or evaluating its vanishing polynomial.
|
||||
|
||||
The descriptions below make use of the definition of a *Lagrange polynomial*,
|
||||
@@ -111,7 +111,7 @@ std::shared_ptr<evaluation_domain<FieldT> > get_evaluation_domain(const size_t m
|
||||
* The inputs are:
|
||||
* - an integer m
|
||||
* - a domain S = (a_{0},...,a_{m-1}) of size m
|
||||
* - a field element t
|
||||
* - a field element element t
|
||||
* - an index idx in {0,...,m-1}
|
||||
* The output is the polynomial L_{idx,S}(z) evaluated at z = t.
|
||||
*/
|
||||
|
||||
@@ -22,15 +22,16 @@
|
||||
#include <cassert>
|
||||
#include "algebra/fields/field_utils.hpp"
|
||||
#include "algebra/evaluation_domain/domains/basic_radix2_domain.hpp"
|
||||
#include "common/assert_except.hpp"
|
||||
|
||||
namespace libsnark {
|
||||
|
||||
template<typename FieldT>
|
||||
std::shared_ptr<evaluation_domain<FieldT> > get_evaluation_domain(const size_t min_size)
|
||||
{
|
||||
assert(min_size > 1);
|
||||
assert_except(min_size > 1);
|
||||
const size_t log_min_size = log2(min_size);
|
||||
assert(log_min_size <= (FieldT::s+1));
|
||||
assert_except(log_min_size <= (FieldT::s+1));
|
||||
|
||||
std::shared_ptr<evaluation_domain<FieldT> > result;
|
||||
if (min_size == (1u << log_min_size))
|
||||
@@ -41,7 +42,7 @@ std::shared_ptr<evaluation_domain<FieldT> > get_evaluation_domain(const size_t m
|
||||
{
|
||||
print_indent(); printf("* Selected domain: extended_radix2\n");
|
||||
}
|
||||
assert(0);
|
||||
assert_except(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -54,9 +55,9 @@ std::shared_ptr<evaluation_domain<FieldT> > get_evaluation_domain(const size_t m
|
||||
}
|
||||
else
|
||||
{
|
||||
const size_t big = 1ul<<(log2(min_size)-1);
|
||||
const size_t big = UINT64_C(1)<<(log2(min_size)-1);
|
||||
const size_t small = min_size - big;
|
||||
const size_t rounded_small = (1ul<<log2(small));
|
||||
const size_t rounded_small = (UINT64_C(1)<<log2(small));
|
||||
if (big == rounded_small)
|
||||
{
|
||||
if (log2(big + rounded_small) < FieldT::s+1)
|
||||
@@ -73,7 +74,7 @@ std::shared_ptr<evaluation_domain<FieldT> > get_evaluation_domain(const size_t m
|
||||
{
|
||||
print_indent(); printf("* Selected domain: extended_radix2\n");
|
||||
}
|
||||
assert(0);
|
||||
assert_except(0);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -82,7 +83,7 @@ std::shared_ptr<evaluation_domain<FieldT> > get_evaluation_domain(const size_t m
|
||||
{
|
||||
print_indent(); printf("* Selected domain: step_radix2\n");
|
||||
}
|
||||
assert(0);
|
||||
assert_except(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,8 +93,8 @@ std::shared_ptr<evaluation_domain<FieldT> > get_evaluation_domain(const size_t m
|
||||
template<typename FieldT>
|
||||
FieldT lagrange_eval(const size_t m, const std::vector<FieldT> &domain, const FieldT &t, const size_t idx)
|
||||
{
|
||||
assert(m == domain.size());
|
||||
assert(idx < m);
|
||||
assert_except(m == domain.size());
|
||||
assert_except(idx < m);
|
||||
|
||||
FieldT num = FieldT::one();
|
||||
FieldT denom = FieldT::one();
|
||||
|
||||
@@ -22,7 +22,7 @@ template<typename FieldT, mp_size_t m>
|
||||
FieldT power(const FieldT &base, const bigint<m> &exponent);
|
||||
|
||||
template<typename FieldT>
|
||||
FieldT power(const FieldT &base, const unsigned long exponent);
|
||||
FieldT power(const FieldT &base, const uint64_t exponent);
|
||||
|
||||
} // libsnark
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ FieldT power(const FieldT &base, const bigint<m> &exponent)
|
||||
|
||||
bool found_one = false;
|
||||
|
||||
for (long i = exponent.max_bits() - 1; i >= 0; --i)
|
||||
for (int64_t i = exponent.max_bits() - 1; i >= 0; --i)
|
||||
{
|
||||
if (found_one)
|
||||
{
|
||||
@@ -43,7 +43,7 @@ FieldT power(const FieldT &base, const bigint<m> &exponent)
|
||||
}
|
||||
|
||||
template<typename FieldT>
|
||||
FieldT power(const FieldT &base, const unsigned long exponent)
|
||||
FieldT power(const FieldT &base, const uint64_t exponent)
|
||||
{
|
||||
return power<FieldT>(base, bigint<1>(exponent));
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ public:
|
||||
mp_limb_t data[n] = {0};
|
||||
|
||||
bigint() = default;
|
||||
bigint(const unsigned long x); /// Initialize from a small integer
|
||||
bigint(const uint64_t x); /// Initalize from a small integer
|
||||
bigint(const char* s); /// Initialize from a string containing an integer in decimal notation
|
||||
bigint(const mpz_t r); /// Initialize from MPZ element
|
||||
|
||||
@@ -46,7 +46,7 @@ public:
|
||||
size_t max_bits() const { return n * GMP_NUMB_BITS; }
|
||||
size_t num_bits() const;
|
||||
|
||||
unsigned long as_ulong() const; /* return the last limb of the integer */
|
||||
uint64_t as_ulong() const; /* return the last limb of the integer */
|
||||
void to_mpz(mpz_t r) const;
|
||||
bool test_bit(const std::size_t bitno) const;
|
||||
|
||||
|
||||
@@ -13,13 +13,14 @@
|
||||
#include <climits>
|
||||
#include <cstring>
|
||||
#include "sodium.h"
|
||||
#include "common/assert_except.hpp"
|
||||
|
||||
namespace libsnark {
|
||||
|
||||
template<mp_size_t n>
|
||||
bigint<n>::bigint(const unsigned long x) /// Initialize from a small integer
|
||||
bigint<n>::bigint(const uint64_t x) /// Initalize from a small integer
|
||||
{
|
||||
static_assert(ULONG_MAX <= GMP_NUMB_MAX, "unsigned long does not fit in a GMP limb");
|
||||
static_assert(UINT64_MAX <= GMP_NUMB_MAX, "uint64_t does not fit in a GMP limb");
|
||||
this->data[0] = x;
|
||||
}
|
||||
|
||||
@@ -31,12 +32,12 @@ bigint<n>::bigint(const char* s) /// Initialize from a string containing an inte
|
||||
|
||||
for (size_t i = 0; i < l; ++i)
|
||||
{
|
||||
assert(s[i] >= '0' && s[i] <= '9');
|
||||
assert_except(s[i] >= '0' && s[i] <= '9');
|
||||
s_copy[i] = s[i] - '0';
|
||||
}
|
||||
|
||||
mp_size_t limbs_written = mpn_set_str(this->data, s_copy, l, 10);
|
||||
assert(limbs_written <= n);
|
||||
assert_except(limbs_written <= n);
|
||||
|
||||
delete[] s_copy;
|
||||
}
|
||||
@@ -53,7 +54,7 @@ bigint<n>::bigint(const mpz_t r) /// Initialize from MPZ element
|
||||
mpz_fdiv_q_2exp(k, k, GMP_NUMB_BITS);
|
||||
}
|
||||
|
||||
assert(mpz_sgn(k) == 0);
|
||||
assert_except(mpz_sgn(k) == 0);
|
||||
mpz_clear(k);
|
||||
}
|
||||
|
||||
@@ -105,7 +106,7 @@ template<mp_size_t n>
|
||||
size_t bigint<n>::num_bits() const
|
||||
{
|
||||
/*
|
||||
for (long i = max_bits(); i >= 0; --i)
|
||||
for (int64_t i = max_bits(); i >= 0; --i)
|
||||
{
|
||||
if (this->test_bit(i))
|
||||
{
|
||||
@@ -115,7 +116,7 @@ size_t bigint<n>::num_bits() const
|
||||
|
||||
return 0;
|
||||
*/
|
||||
for (long i = n-1; i >= 0; --i)
|
||||
for (int64_t i = n-1; i >= 0; --i)
|
||||
{
|
||||
mp_limb_t x = this->data[i];
|
||||
if (x == 0)
|
||||
@@ -124,14 +125,14 @@ size_t bigint<n>::num_bits() const
|
||||
}
|
||||
else
|
||||
{
|
||||
return ((i+1) * GMP_NUMB_BITS) - __builtin_clzl(x);
|
||||
return ((i+1) * GMP_NUMB_BITS) - __builtin_clzll(x);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<mp_size_t n>
|
||||
unsigned long bigint<n>::as_ulong() const
|
||||
uint64_t bigint<n>::as_ulong() const
|
||||
{
|
||||
return this->data[0];
|
||||
}
|
||||
@@ -186,7 +187,7 @@ inline void bigint<n>::div_qr(bigint<n-d+1>& quotient, bigint<d>& remainder,
|
||||
const bigint<n>& dividend, const bigint<d>& divisor)
|
||||
{
|
||||
static_assert(n >= d, "dividend must not be smaller than divisor for bigint::div_qr");
|
||||
assert(divisor.data[d-1] != 0);
|
||||
assert_except(divisor.data[d-1] != 0);
|
||||
mpn_tdiv_qr(quotient.data, remainder.data, 0, dividend.data, n, divisor.data, d);
|
||||
}
|
||||
|
||||
@@ -223,7 +224,7 @@ inline bool bigint<n>::operator>(const bigint<n>& other) const
|
||||
template<mp_size_t n>
|
||||
bigint<n>& bigint<n>::randomize()
|
||||
{
|
||||
assert(GMP_NUMB_BITS == sizeof(mp_limb_t) * 8);
|
||||
assert_except(GMP_NUMB_BITS == sizeof(mp_limb_t) * 8);
|
||||
|
||||
randombytes_buf(this->data, sizeof(mp_limb_t) * n);
|
||||
|
||||
@@ -262,12 +263,12 @@ std::istream& operator>>(std::istream &in, bigint<n> &b)
|
||||
|
||||
for (size_t i = 0; i < l; ++i)
|
||||
{
|
||||
assert(s[i] >= '0' && s[i] <= '9');
|
||||
assert_except(s[i] >= '0' && s[i] <= '9');
|
||||
s_copy[i] = s[i] - '0';
|
||||
}
|
||||
|
||||
mp_size_t limbs_written = mpn_set_str(b.data, s_copy, l, 10);
|
||||
assert(limbs_written <= n);
|
||||
assert_except(limbs_written <= n);
|
||||
|
||||
delete[] s_copy;
|
||||
#endif
|
||||
|
||||
@@ -16,13 +16,13 @@ namespace libsnark {
|
||||
|
||||
// returns root of unity of order n (for n a power of 2), if one exists
|
||||
template<typename FieldT>
|
||||
FieldT get_root_of_unity(const size_t n);
|
||||
FieldT get_root_of_unity(const uint64_t n);
|
||||
|
||||
template<typename FieldT>
|
||||
std::vector<FieldT> pack_int_vector_into_field_element_vector(const std::vector<size_t> &v, const size_t w);
|
||||
std::vector<FieldT> pack_int_vector_into_field_element_vector(const std::vector<uint64_t> &v, const uint64_t w);
|
||||
|
||||
template<typename FieldT>
|
||||
std::vector<FieldT> pack_bit_vector_into_field_element_vector(const bit_vector &v, const size_t chunk_bits);
|
||||
std::vector<FieldT> pack_bit_vector_into_field_element_vector(const bit_vector &v, const uint64_t chunk_bits);
|
||||
|
||||
template<typename FieldT>
|
||||
std::vector<FieldT> pack_bit_vector_into_field_element_vector(const bit_vector &v);
|
||||
@@ -37,7 +37,7 @@ template<typename FieldT>
|
||||
bit_vector convert_field_element_to_bit_vector(const FieldT &el);
|
||||
|
||||
template<typename FieldT>
|
||||
bit_vector convert_field_element_to_bit_vector(const FieldT &el, const size_t bitcount);
|
||||
bit_vector convert_field_element_to_bit_vector(const FieldT &el, const uint64_t bitcount);
|
||||
|
||||
template<typename FieldT>
|
||||
FieldT convert_bit_vector_to_field_element(const bit_vector &v);
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#define FIELD_UTILS_TCC_
|
||||
|
||||
#include "common/utils.hpp"
|
||||
#include "common/assert_except.hpp"
|
||||
|
||||
namespace libsnark {
|
||||
|
||||
@@ -21,14 +22,14 @@ FieldT coset_shift()
|
||||
}
|
||||
|
||||
template<typename FieldT>
|
||||
FieldT get_root_of_unity(const size_t n)
|
||||
FieldT get_root_of_unity(const uint64_t n)
|
||||
{
|
||||
const size_t logn = log2(n);
|
||||
assert(n == (1u << logn));
|
||||
assert(logn <= FieldT::s);
|
||||
const uint64_t logn = log2(n);
|
||||
assert_except(n == (1u << logn));
|
||||
assert_except(logn <= FieldT::s);
|
||||
|
||||
FieldT omega = FieldT::root_of_unity;
|
||||
for (size_t i = FieldT::s; i > logn; --i)
|
||||
for (uint64_t i = FieldT::s; i > logn; --i)
|
||||
{
|
||||
omega *= omega;
|
||||
}
|
||||
@@ -37,21 +38,21 @@ FieldT get_root_of_unity(const size_t n)
|
||||
}
|
||||
|
||||
template<typename FieldT>
|
||||
std::vector<FieldT> pack_int_vector_into_field_element_vector(const std::vector<size_t> &v, const size_t w)
|
||||
std::vector<FieldT> pack_int_vector_into_field_element_vector(const std::vector<uint64_t> &v, const uint64_t w)
|
||||
{
|
||||
const size_t chunk_bits = FieldT::capacity();
|
||||
const size_t repacked_size = div_ceil(v.size() * w, chunk_bits);
|
||||
const uint64_t chunk_bits = FieldT::capacity();
|
||||
const uint64_t repacked_size = div_ceil(v.size() * w, chunk_bits);
|
||||
std::vector<FieldT> result(repacked_size);
|
||||
|
||||
for (size_t i = 0; i < repacked_size; ++i)
|
||||
for (uint64_t i = 0; i < repacked_size; ++i)
|
||||
{
|
||||
bigint<FieldT::num_limbs> b;
|
||||
for (size_t j = 0; j < chunk_bits; ++j)
|
||||
for (uint64_t j = 0; j < chunk_bits; ++j)
|
||||
{
|
||||
const size_t word_index = (i * chunk_bits + j) / w;
|
||||
const size_t pos_in_word = (i * chunk_bits + j) % w;
|
||||
const size_t word_or_0 = (word_index < v.size() ? v[word_index] : 0);
|
||||
const size_t bit = (word_or_0 >> pos_in_word) & 1;
|
||||
const uint64_t word_index = (i * chunk_bits + j) / w;
|
||||
const uint64_t pos_in_word = (i * chunk_bits + j) % w;
|
||||
const uint64_t word_or_0 = (word_index < v.size() ? v[word_index] : 0);
|
||||
const uint64_t bit = (word_or_0 >> pos_in_word) & 1;
|
||||
|
||||
b.data[j / GMP_NUMB_BITS] |= bit << (j % GMP_NUMB_BITS);
|
||||
}
|
||||
@@ -62,11 +63,11 @@ std::vector<FieldT> pack_int_vector_into_field_element_vector(const std::vector<
|
||||
}
|
||||
|
||||
template<typename FieldT>
|
||||
std::vector<FieldT> pack_bit_vector_into_field_element_vector(const bit_vector &v, const size_t chunk_bits)
|
||||
std::vector<FieldT> pack_bit_vector_into_field_element_vector(const bit_vector &v, const uint64_t chunk_bits)
|
||||
{
|
||||
assert(chunk_bits <= FieldT::capacity());
|
||||
assert_except(chunk_bits <= FieldT::capacity());
|
||||
|
||||
const size_t repacked_size = div_ceil(v.size(), chunk_bits);
|
||||
const uint64_t repacked_size = div_ceil(v.size(), chunk_bits);
|
||||
std::vector<FieldT> result(repacked_size);
|
||||
|
||||
for (size_t i = 0; i < repacked_size; ++i)
|
||||
@@ -131,7 +132,7 @@ bit_vector convert_field_element_to_bit_vector(const FieldT &el)
|
||||
}
|
||||
|
||||
template<typename FieldT>
|
||||
bit_vector convert_field_element_to_bit_vector(const FieldT &el, const size_t bitcount)
|
||||
bit_vector convert_field_element_to_bit_vector(const FieldT &el, const uint64_t bitcount)
|
||||
{
|
||||
bit_vector result = convert_field_element_to_bit_vector(el);
|
||||
result.resize(bitcount);
|
||||
@@ -142,7 +143,7 @@ bit_vector convert_field_element_to_bit_vector(const FieldT &el, const size_t bi
|
||||
template<typename FieldT>
|
||||
FieldT convert_bit_vector_to_field_element(const bit_vector &v)
|
||||
{
|
||||
assert(v.size() <= FieldT::size_in_bits());
|
||||
assert_except(v.size() <= FieldT::size_in_bits());
|
||||
|
||||
FieldT res = FieldT::zero();
|
||||
FieldT c = FieldT::one();
|
||||
@@ -164,14 +165,14 @@ void batch_invert(std::vector<FieldT> &vec)
|
||||
|
||||
for (auto el : vec)
|
||||
{
|
||||
assert(!el.is_zero());
|
||||
assert_except(!el.is_zero());
|
||||
prod.emplace_back(acc);
|
||||
acc = acc * el;
|
||||
}
|
||||
|
||||
FieldT acc_inverse = acc.inverse();
|
||||
|
||||
for (long i = vec.size()-1; i >= 0; --i)
|
||||
for (int64_t i = vec.size()-1; i >= 0; --i)
|
||||
{
|
||||
const FieldT old_el = vec[i];
|
||||
vec[i] = acc_inverse * prod[i];
|
||||
|
||||
@@ -34,7 +34,7 @@ std::istream& operator>>(std::istream &, Fp_model<n, modulus> &);
|
||||
* The implementation is mostly a wrapper around GMP's MPN (constant-size integers).
|
||||
* But for the integer sizes of interest for libsnark (3 to 5 limbs of 64 bits each),
|
||||
* we implement performance-critical routines, like addition and multiplication,
|
||||
* using hand-optimized assembly code.
|
||||
* using hand-optimzied assembly code.
|
||||
*/
|
||||
template<mp_size_t n, const bigint<n>& modulus>
|
||||
class Fp_model {
|
||||
@@ -44,15 +44,15 @@ public:
|
||||
static const mp_size_t num_limbs = n;
|
||||
static const constexpr bigint<n>& mod = modulus;
|
||||
#ifdef PROFILE_OP_COUNTS
|
||||
static long long add_cnt;
|
||||
static long long sub_cnt;
|
||||
static long long mul_cnt;
|
||||
static long long sqr_cnt;
|
||||
static long long inv_cnt;
|
||||
static int64_t add_cnt;
|
||||
static int64_t sub_cnt;
|
||||
static int64_t mul_cnt;
|
||||
static int64_t sqr_cnt;
|
||||
static int64_t inv_cnt;
|
||||
#endif
|
||||
static size_t num_bits;
|
||||
static uint64_t num_bits;
|
||||
static bigint<n> euler; // (modulus-1)/2
|
||||
static size_t s; // modulus = 2^s * t + 1
|
||||
static uint64_t s; // modulus = 2^s * t + 1
|
||||
static bigint<n> t; // with t odd
|
||||
static bigint<n> t_minus_1_over_2; // (t-1)/2
|
||||
static Fp_model<n, modulus> nqr; // a quadratic nonresidue
|
||||
@@ -67,9 +67,9 @@ public:
|
||||
|
||||
Fp_model() {};
|
||||
Fp_model(const bigint<n> &b);
|
||||
Fp_model(const long x, const bool is_unsigned=false);
|
||||
Fp_model(const int64_t x, const bool is_unsigned=false);
|
||||
|
||||
void set_ulong(const unsigned long x);
|
||||
void set_ulong(const uint64_t x);
|
||||
|
||||
void mul_reduce(const bigint<n> &other);
|
||||
|
||||
@@ -82,7 +82,7 @@ public:
|
||||
/* Return the last limb of the standard representation of the
|
||||
field element. E.g. on 64-bit architectures Fp(123).as_ulong()
|
||||
and Fp(2^64+123).as_ulong() would both return 123. */
|
||||
unsigned long as_ulong() const;
|
||||
uint64_t as_ulong() const;
|
||||
|
||||
bool operator==(const Fp_model& other) const;
|
||||
bool operator!=(const Fp_model& other) const;
|
||||
@@ -93,7 +93,7 @@ public:
|
||||
Fp_model& operator+=(const Fp_model& other);
|
||||
Fp_model& operator-=(const Fp_model& other);
|
||||
Fp_model& operator*=(const Fp_model& other);
|
||||
Fp_model& operator^=(const unsigned long pow);
|
||||
Fp_model& operator^=(const uint64_t pow);
|
||||
|
||||
template<mp_size_t m>
|
||||
Fp_model& operator^=(const bigint<m> &pow);
|
||||
@@ -107,12 +107,12 @@ public:
|
||||
Fp_model inverse() const;
|
||||
Fp_model sqrt() const; // HAS TO BE A SQUARE (else does not terminate)
|
||||
|
||||
Fp_model operator^(const unsigned long pow) const;
|
||||
Fp_model operator^(const uint64_t pow) const;
|
||||
template<mp_size_t m>
|
||||
Fp_model operator^(const bigint<m> &pow) const;
|
||||
|
||||
static size_t size_in_bits() { return num_bits; }
|
||||
static size_t capacity() { return num_bits - 1; }
|
||||
static uint64_t size_in_bits() { return num_bits; }
|
||||
static uint64_t capacity() { return num_bits - 1; }
|
||||
static bigint<n> field_char() { return modulus; }
|
||||
|
||||
static Fp_model<n, modulus> zero();
|
||||
@@ -125,29 +125,29 @@ public:
|
||||
|
||||
#ifdef PROFILE_OP_COUNTS
|
||||
template<mp_size_t n, const bigint<n>& modulus>
|
||||
long long Fp_model<n, modulus>::add_cnt = 0;
|
||||
int64_t Fp_model<n, modulus>::add_cnt = 0;
|
||||
|
||||
template<mp_size_t n, const bigint<n>& modulus>
|
||||
long long Fp_model<n, modulus>::sub_cnt = 0;
|
||||
int64_t Fp_model<n, modulus>::sub_cnt = 0;
|
||||
|
||||
template<mp_size_t n, const bigint<n>& modulus>
|
||||
long long Fp_model<n, modulus>::mul_cnt = 0;
|
||||
int64_t Fp_model<n, modulus>::mul_cnt = 0;
|
||||
|
||||
template<mp_size_t n, const bigint<n>& modulus>
|
||||
long long Fp_model<n, modulus>::sqr_cnt = 0;
|
||||
int64_t Fp_model<n, modulus>::sqr_cnt = 0;
|
||||
|
||||
template<mp_size_t n, const bigint<n>& modulus>
|
||||
long long Fp_model<n, modulus>::inv_cnt = 0;
|
||||
int64_t Fp_model<n, modulus>::inv_cnt = 0;
|
||||
#endif
|
||||
|
||||
template<mp_size_t n, const bigint<n>& modulus>
|
||||
size_t Fp_model<n, modulus>::num_bits;
|
||||
uint64_t Fp_model<n, modulus>::num_bits;
|
||||
|
||||
template<mp_size_t n, const bigint<n>& modulus>
|
||||
bigint<n> Fp_model<n, modulus>::euler;
|
||||
|
||||
template<mp_size_t n, const bigint<n>& modulus>
|
||||
size_t Fp_model<n, modulus>::s;
|
||||
uint64_t Fp_model<n, modulus>::s;
|
||||
|
||||
template<mp_size_t n, const bigint<n>& modulus>
|
||||
bigint<n> Fp_model<n, modulus>::t;
|
||||
|
||||
@@ -173,13 +173,13 @@ void Fp_model<n,modulus>::mul_reduce(const bigint<n> &other)
|
||||
/* calculate res = res + k * mod * b^i */
|
||||
mp_limb_t carryout = mpn_addmul_1(res+i, modulus.data, n, k);
|
||||
carryout = mpn_add_1(res+n+i, res+n+i, n-i, carryout);
|
||||
assert(carryout == 0);
|
||||
assert_except(carryout == 0);
|
||||
}
|
||||
|
||||
if (mpn_cmp(res+n, modulus.data, n) >= 0)
|
||||
{
|
||||
const mp_limb_t borrow = mpn_sub(res+n, res+n, n, modulus.data, n);
|
||||
assert(borrow == 0);
|
||||
assert_except(borrow == 0);
|
||||
}
|
||||
|
||||
mpn_copyi(this->mont_repr.data, res+n, n);
|
||||
@@ -194,7 +194,7 @@ Fp_model<n,modulus>::Fp_model(const bigint<n> &b)
|
||||
}
|
||||
|
||||
template<mp_size_t n, const bigint<n>& modulus>
|
||||
Fp_model<n,modulus>::Fp_model(const long x, const bool is_unsigned)
|
||||
Fp_model<n,modulus>::Fp_model(const int64_t x, const bool is_unsigned)
|
||||
{
|
||||
if (is_unsigned || x >= 0)
|
||||
{
|
||||
@@ -203,14 +203,14 @@ Fp_model<n,modulus>::Fp_model(const long x, const bool is_unsigned)
|
||||
else
|
||||
{
|
||||
const mp_limb_t borrow = mpn_sub_1(this->mont_repr.data, modulus.data, n, -x);
|
||||
assert(borrow == 0);
|
||||
assert_except(borrow == 0);
|
||||
}
|
||||
|
||||
mul_reduce(Rsquared);
|
||||
}
|
||||
|
||||
template<mp_size_t n, const bigint<n>& modulus>
|
||||
void Fp_model<n,modulus>::set_ulong(const unsigned long x)
|
||||
void Fp_model<n,modulus>::set_ulong(const uint64_t x)
|
||||
{
|
||||
this->mont_repr.clear();
|
||||
this->mont_repr.data[0] = x;
|
||||
@@ -237,7 +237,7 @@ bigint<n> Fp_model<n,modulus>::as_bigint() const
|
||||
}
|
||||
|
||||
template<mp_size_t n, const bigint<n>& modulus>
|
||||
unsigned long Fp_model<n,modulus>::as_ulong() const
|
||||
uint64_t Fp_model<n,modulus>::as_ulong() const
|
||||
{
|
||||
return this->as_bigint().as_ulong();
|
||||
}
|
||||
@@ -391,7 +391,7 @@ Fp_model<n,modulus>& Fp_model<n,modulus>::operator+=(const Fp_model<n,modulus>&
|
||||
if (carry || mpn_cmp(scratch, modulus.data, n) >= 0)
|
||||
{
|
||||
const mp_limb_t borrow = mpn_sub(scratch, scratch, n+1, modulus.data, n);
|
||||
assert(borrow == 0);
|
||||
assert_except(borrow == 0);
|
||||
}
|
||||
|
||||
mpn_copyi(this->mont_repr.data, scratch, n);
|
||||
@@ -483,7 +483,7 @@ Fp_model<n,modulus>& Fp_model<n,modulus>::operator-=(const Fp_model<n,modulus>&
|
||||
}
|
||||
|
||||
const mp_limb_t borrow = mpn_sub(scratch, scratch, n+1, other.mont_repr.data, n);
|
||||
assert(borrow == 0);
|
||||
assert_except(borrow == 0);
|
||||
|
||||
mpn_copyi(this->mont_repr.data, scratch, n);
|
||||
}
|
||||
@@ -502,7 +502,7 @@ Fp_model<n,modulus>& Fp_model<n,modulus>::operator*=(const Fp_model<n,modulus>&
|
||||
}
|
||||
|
||||
template<mp_size_t n, const bigint<n>& modulus>
|
||||
Fp_model<n,modulus>& Fp_model<n,modulus>::operator^=(const unsigned long pow)
|
||||
Fp_model<n,modulus>& Fp_model<n,modulus>::operator^=(const uint64_t pow)
|
||||
{
|
||||
(*this) = power<Fp_model<n, modulus> >(*this, pow);
|
||||
return (*this);
|
||||
@@ -538,7 +538,7 @@ Fp_model<n,modulus> Fp_model<n,modulus>::operator*(const Fp_model<n,modulus>& ot
|
||||
}
|
||||
|
||||
template<mp_size_t n, const bigint<n>& modulus>
|
||||
Fp_model<n,modulus> Fp_model<n,modulus>::operator^(const unsigned long pow) const
|
||||
Fp_model<n,modulus> Fp_model<n,modulus>::operator^(const uint64_t pow) const
|
||||
{
|
||||
Fp_model<n, modulus> r(*this);
|
||||
return (r ^= pow);
|
||||
@@ -626,7 +626,7 @@ Fp_model<n,modulus>& Fp_model<n,modulus>::invert()
|
||||
this->inv_cnt++;
|
||||
#endif
|
||||
|
||||
assert(!this->is_zero());
|
||||
assert_except(!this->is_zero());
|
||||
|
||||
bigint<n> g; /* gp should have room for vn = n limbs */
|
||||
|
||||
@@ -637,7 +637,7 @@ Fp_model<n,modulus>& Fp_model<n,modulus>::invert()
|
||||
|
||||
/* computes gcd(u, v) = g = u*s + v*t, so s*u will be 1 (mod v) */
|
||||
const mp_size_t gn = mpn_gcdext(g.data, s, &sn, this->mont_repr.data, n, v.data, n);
|
||||
assert(gn == 1 && g.data[0] == 1); /* inverse exists */
|
||||
assert_except(gn == 1 && g.data[0] == 1); /* inverse exists */
|
||||
|
||||
mp_limb_t q; /* division result fits into q, as sn <= n+1 */
|
||||
/* sn < 0 indicates negative sn; will fix up later */
|
||||
@@ -658,7 +658,7 @@ Fp_model<n,modulus>& Fp_model<n,modulus>::invert()
|
||||
if (sn < 0)
|
||||
{
|
||||
const mp_limb_t borrow = mpn_sub_n(this->mont_repr.data, modulus.data, this->mont_repr.data, n);
|
||||
assert(borrow == 0);
|
||||
assert_except(borrow == 0);
|
||||
}
|
||||
|
||||
mul_reduce(Rcubed);
|
||||
@@ -684,13 +684,13 @@ Fp_model<n, modulus> Fp_model<n,modulus>::random_element() /// returns random el
|
||||
r.mont_repr.randomize();
|
||||
|
||||
/* clear all bits higher than MSB of modulus */
|
||||
size_t bitno = GMP_NUMB_BITS * n - 1;
|
||||
uint64_t bitno = GMP_NUMB_BITS * n - 1;
|
||||
while (modulus.test_bit(bitno) == false)
|
||||
{
|
||||
const std::size_t part = bitno/GMP_NUMB_BITS;
|
||||
const std::size_t bit = bitno - (GMP_NUMB_BITS*part);
|
||||
const uint64_t part = bitno/GMP_NUMB_BITS;
|
||||
const uint64_t bit = bitno - (GMP_NUMB_BITS*part);
|
||||
|
||||
r.mont_repr.data[part] &= ~(1ul<<bit);
|
||||
r.mont_repr.data[part] &= ~(1ull<<bit);
|
||||
|
||||
bitno--;
|
||||
}
|
||||
@@ -710,7 +710,7 @@ Fp_model<n,modulus> Fp_model<n,modulus>::sqrt() const
|
||||
|
||||
Fp_model<n,modulus> one = Fp_model<n,modulus>::one();
|
||||
|
||||
size_t v = Fp_model<n,modulus>::s;
|
||||
uint64_t v = Fp_model<n,modulus>::s;
|
||||
Fp_model<n,modulus> z = Fp_model<n,modulus>::nqr_to_t;
|
||||
Fp_model<n,modulus> w = (*this)^Fp_model<n,modulus>::t_minus_1_over_2;
|
||||
Fp_model<n,modulus> x = (*this) * w;
|
||||
@@ -734,7 +734,7 @@ Fp_model<n,modulus> Fp_model<n,modulus>::sqrt() const
|
||||
|
||||
while (b != one)
|
||||
{
|
||||
size_t m = 0;
|
||||
uint64_t m = 0;
|
||||
Fp_model<n,modulus> b2m = b;
|
||||
while (b2m != one)
|
||||
{
|
||||
|
||||
@@ -66,7 +66,7 @@ public:
|
||||
Fp12_2over3over2_model squared_karatsuba() const;
|
||||
Fp12_2over3over2_model squared_complex() const;
|
||||
Fp12_2over3over2_model inverse() const;
|
||||
Fp12_2over3over2_model Frobenius_map(unsigned long power) const;
|
||||
Fp12_2over3over2_model Frobenius_map(uint64_t power) const;
|
||||
Fp12_2over3over2_model unitary_inverse() const;
|
||||
Fp12_2over3over2_model cyclotomic_squared() const;
|
||||
|
||||
@@ -78,7 +78,7 @@ public:
|
||||
Fp12_2over3over2_model cyclotomic_exp(const bigint<m> &exponent) const;
|
||||
|
||||
static bigint<n> base_field_char() { return modulus; }
|
||||
static size_t extension_degree() { return 12; }
|
||||
static uint64_t extension_degree() { return 12; }
|
||||
|
||||
friend std::ostream& operator<< <n, modulus>(std::ostream &out, const Fp12_2over3over2_model<n, modulus> &el);
|
||||
friend std::istream& operator>> <n, modulus>(std::istream &in, Fp12_2over3over2_model<n, modulus> &el);
|
||||
|
||||
@@ -156,7 +156,7 @@ Fp12_2over3over2_model<n,modulus> Fp12_2over3over2_model<n,modulus>::inverse() c
|
||||
}
|
||||
|
||||
template<mp_size_t n, const bigint<n>& modulus>
|
||||
Fp12_2over3over2_model<n,modulus> Fp12_2over3over2_model<n,modulus>::Frobenius_map(unsigned long power) const
|
||||
Fp12_2over3over2_model<n,modulus> Fp12_2over3over2_model<n,modulus>::Frobenius_map(uint64_t power) const
|
||||
{
|
||||
return Fp12_2over3over2_model<n,modulus>(c0.Frobenius_map(power),
|
||||
Frobenius_coeffs_c1[power % 12] * c1.Frobenius_map(power));
|
||||
@@ -339,16 +339,16 @@ Fp12_2over3over2_model<n, modulus> Fp12_2over3over2_model<n,modulus>::cyclotomic
|
||||
Fp12_2over3over2_model<n,modulus> res = Fp12_2over3over2_model<n,modulus>::one();
|
||||
|
||||
bool found_one = false;
|
||||
for (long i = m-1; i >= 0; --i)
|
||||
for (int64_t i = m-1; i >= 0; --i)
|
||||
{
|
||||
for (long j = GMP_NUMB_BITS - 1; j >= 0; --j)
|
||||
for (int64_t j = GMP_NUMB_BITS - 1; j >= 0; --j)
|
||||
{
|
||||
if (found_one)
|
||||
{
|
||||
res = res.cyclotomic_squared();
|
||||
}
|
||||
|
||||
if (exponent.data[i] & (1ul<<j))
|
||||
if (exponent.data[i] & (UINT64_C(1)<<j))
|
||||
{
|
||||
found_one = true;
|
||||
res = res * (*this);
|
||||
@@ -390,7 +390,7 @@ std::istream& operator>>(std::istream& in, std::vector<Fp12_2over3over2_model<n,
|
||||
{
|
||||
v.clear();
|
||||
|
||||
size_t s;
|
||||
uint64_t s;
|
||||
in >> s;
|
||||
|
||||
char b;
|
||||
|
||||
@@ -37,7 +37,7 @@ public:
|
||||
typedef Fp_model<n, modulus> my_Fp;
|
||||
|
||||
static bigint<2*n> euler; // (modulus^2-1)/2
|
||||
static size_t s; // modulus^2 = 2^s * t + 1
|
||||
static uint64_t s; // modulus^2 = 2^s * t + 1
|
||||
static bigint<2*n> t; // with t odd
|
||||
static bigint<2*n> t_minus_1_over_2; // (t-1)/2
|
||||
static my_Fp non_residue; // X^4-non_residue irreducible over Fp; used for constructing Fp2 = Fp[X] / (X^2 - non_residue)
|
||||
@@ -66,7 +66,7 @@ public:
|
||||
Fp2_model operator-() const;
|
||||
Fp2_model squared() const; // default is squared_complex
|
||||
Fp2_model inverse() const;
|
||||
Fp2_model Frobenius_map(unsigned long power) const;
|
||||
Fp2_model Frobenius_map(uint64_t power) const;
|
||||
Fp2_model sqrt() const; // HAS TO BE A SQUARE (else does not terminate)
|
||||
Fp2_model squared_karatsuba() const;
|
||||
Fp2_model squared_complex() const;
|
||||
@@ -74,7 +74,7 @@ public:
|
||||
template<mp_size_t m>
|
||||
Fp2_model operator^(const bigint<m> &other) const;
|
||||
|
||||
static size_t size_in_bits() { return 2*my_Fp::size_in_bits(); }
|
||||
static uint64_t size_in_bits() { return 2*my_Fp::size_in_bits(); }
|
||||
static bigint<n> base_field_char() { return modulus; }
|
||||
|
||||
friend std::ostream& operator<< <n, modulus>(std::ostream &out, const Fp2_model<n, modulus> &el);
|
||||
@@ -94,7 +94,7 @@ template<mp_size_t n, const bigint<n>& modulus>
|
||||
bigint<2*n> Fp2_model<n, modulus>::euler;
|
||||
|
||||
template<mp_size_t n, const bigint<n>& modulus>
|
||||
size_t Fp2_model<n, modulus>::s;
|
||||
uint64_t Fp2_model<n, modulus>::s;
|
||||
|
||||
template<mp_size_t n, const bigint<n>& modulus>
|
||||
bigint<2*n> Fp2_model<n, modulus>::t;
|
||||
|
||||
@@ -136,7 +136,7 @@ Fp2_model<n,modulus> Fp2_model<n,modulus>::inverse() const
|
||||
}
|
||||
|
||||
template<mp_size_t n, const bigint<n>& modulus>
|
||||
Fp2_model<n,modulus> Fp2_model<n,modulus>::Frobenius_map(unsigned long power) const
|
||||
Fp2_model<n,modulus> Fp2_model<n,modulus>::Frobenius_map(uint64_t power) const
|
||||
{
|
||||
return Fp2_model<n,modulus>(c0,
|
||||
Frobenius_coeffs_c1[power % 2] * c1);
|
||||
@@ -151,7 +151,7 @@ Fp2_model<n,modulus> Fp2_model<n,modulus>::sqrt() const
|
||||
|
||||
Fp2_model<n,modulus> one = Fp2_model<n,modulus>::one();
|
||||
|
||||
size_t v = Fp2_model<n,modulus>::s;
|
||||
unsigned long long v = Fp2_model<n,modulus>::s;
|
||||
Fp2_model<n,modulus> z = Fp2_model<n,modulus>::nqr_to_t;
|
||||
Fp2_model<n,modulus> w = (*this)^Fp2_model<n,modulus>::t_minus_1_over_2;
|
||||
Fp2_model<n,modulus> x = (*this) * w;
|
||||
@@ -175,7 +175,7 @@ Fp2_model<n,modulus> Fp2_model<n,modulus>::sqrt() const
|
||||
|
||||
while (b != one)
|
||||
{
|
||||
size_t m = 0;
|
||||
unsigned long long m = 0;
|
||||
Fp2_model<n,modulus> b2m = b;
|
||||
while (b2m != one)
|
||||
{
|
||||
@@ -239,7 +239,7 @@ std::istream& operator>>(std::istream& in, std::vector<Fp2_model<n, modulus> > &
|
||||
{
|
||||
v.clear();
|
||||
|
||||
size_t s;
|
||||
unsigned long long s;
|
||||
in >> s;
|
||||
|
||||
char b;
|
||||
|
||||
@@ -63,7 +63,7 @@ public:
|
||||
Fp6_3over2_model operator-() const;
|
||||
Fp6_3over2_model squared() const;
|
||||
Fp6_3over2_model inverse() const;
|
||||
Fp6_3over2_model Frobenius_map(unsigned long power) const;
|
||||
Fp6_3over2_model Frobenius_map(uint64_t power) const;
|
||||
|
||||
static my_Fp2 mul_by_non_residue(const my_Fp2 &elt);
|
||||
|
||||
@@ -71,7 +71,7 @@ public:
|
||||
Fp6_3over2_model operator^(const bigint<m> &other) const;
|
||||
|
||||
static bigint<n> base_field_char() { return modulus; }
|
||||
static size_t extension_degree() { return 6; }
|
||||
static uint64_t extension_degree() { return 6; }
|
||||
|
||||
friend std::ostream& operator<< <n, modulus>(std::ostream &out, const Fp6_3over2_model<n, modulus> &el);
|
||||
friend std::istream& operator>> <n, modulus>(std::istream &in, Fp6_3over2_model<n, modulus> &el);
|
||||
|
||||
@@ -149,7 +149,7 @@ Fp6_3over2_model<n,modulus> Fp6_3over2_model<n,modulus>::inverse() const
|
||||
}
|
||||
|
||||
template<mp_size_t n, const bigint<n>& modulus>
|
||||
Fp6_3over2_model<n,modulus> Fp6_3over2_model<n,modulus>::Frobenius_map(unsigned long power) const
|
||||
Fp6_3over2_model<n,modulus> Fp6_3over2_model<n,modulus>::Frobenius_map(uint64_t power) const
|
||||
{
|
||||
return Fp6_3over2_model<n,modulus>(c0.Frobenius_map(power),
|
||||
Frobenius_coeffs_c1[power % 6] * c1.Frobenius_map(power),
|
||||
@@ -194,7 +194,7 @@ std::istream& operator>>(std::istream& in, std::vector<Fp6_3over2_model<n, modul
|
||||
{
|
||||
v.clear();
|
||||
|
||||
size_t s;
|
||||
uint64_t s;
|
||||
in >> s;
|
||||
|
||||
char b;
|
||||
|
||||
@@ -7,13 +7,11 @@
|
||||
|
||||
#include "algebra/fields/bigint.hpp"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using namespace libsnark;
|
||||
|
||||
TEST(algebra, bigint)
|
||||
void test_bigint()
|
||||
{
|
||||
static_assert(ULONG_MAX == 0xFFFFFFFFFFFFFFFFul, "unsigned long not 64-bit");
|
||||
static_assert(UINT64_MAX == 0xFFFFFFFFFFFFFFFFul, "uint64_t not 64-bit");
|
||||
static_assert(GMP_NUMB_BITS == 64, "GMP limb not 64-bit");
|
||||
|
||||
const char *b1_decimal = "76749407";
|
||||
@@ -22,76 +20,88 @@ TEST(algebra, bigint)
|
||||
const char *b2_binary = "0000000000000000000000000000010101111101101000000110100001011010"
|
||||
"1101101010001001000001101000101000100110011001110001111110100010";
|
||||
|
||||
bigint<1> b0 = bigint<1>(0ul);
|
||||
bigint<1> b0 = bigint<1>(UINT64_C(0));
|
||||
bigint<1> b1 = bigint<1>(b1_decimal);
|
||||
bigint<2> b2 = bigint<2>(b2_decimal);
|
||||
|
||||
EXPECT_EQ(b0.as_ulong(), 0ul);
|
||||
EXPECT_TRUE(b0.is_zero());
|
||||
EXPECT_EQ(b1.as_ulong(), 76749407ul);
|
||||
EXPECT_FALSE(b1.is_zero());
|
||||
EXPECT_EQ(b2.as_ulong(), 15747124762497195938ul);
|
||||
EXPECT_FALSE(b2.is_zero());
|
||||
EXPECT_NE(b0, b1);
|
||||
EXPECT_FALSE(b0 == b1);
|
||||
assert(b0.as_ulong() == UINT64_C(0));
|
||||
assert(b0.is_zero());
|
||||
assert(b1.as_ulong() == UINT64_C(76749407));
|
||||
assert(!(b1.is_zero()));
|
||||
assert(b2.as_ulong() == UINT64_C(15747124762497195938));
|
||||
assert(!(b2.is_zero()));
|
||||
assert(b0 != b1);
|
||||
assert(!(b0 == b1));
|
||||
|
||||
EXPECT_EQ(b2.max_bits(), 128);
|
||||
EXPECT_EQ(b2.num_bits(), 99);
|
||||
assert(b2.max_bits() == 128);
|
||||
assert(b2.num_bits() == 99);
|
||||
for (size_t i = 0; i < 128; i++) {
|
||||
EXPECT_EQ(b2.test_bit(i), (b2_binary[127-i] == '1'));
|
||||
assert(b2.test_bit(i) == (b2_binary[127-i] == '1'));
|
||||
}
|
||||
|
||||
bigint<3> b3 = b2 * b1;
|
||||
|
||||
EXPECT_EQ(b3, bigint<3>(b3_decimal));
|
||||
EXPECT_FALSE(b3.is_zero());
|
||||
assert(b3 == bigint<3>(b3_decimal));
|
||||
assert(!(b3.is_zero()));
|
||||
|
||||
bigint<3> b3a { b3 };
|
||||
EXPECT_EQ(b3a, bigint<3>(b3_decimal));
|
||||
EXPECT_EQ(b3a, b3);
|
||||
EXPECT_FALSE(b3a.is_zero());
|
||||
assert(b3a == bigint<3>(b3_decimal));
|
||||
assert(b3a == b3);
|
||||
assert(!(b3a.is_zero()));
|
||||
|
||||
mpz_t m3;
|
||||
mpz_init(m3);
|
||||
b3.to_mpz(m3);
|
||||
bigint<3> b3b { m3 };
|
||||
EXPECT_EQ(b3b, b3);
|
||||
assert(b3b == b3);
|
||||
|
||||
bigint<2> quotient;
|
||||
bigint<2> remainder;
|
||||
bigint<3>::div_qr(quotient, remainder, b3, b2);
|
||||
EXPECT_LT(quotient.num_bits(), GMP_NUMB_BITS);
|
||||
EXPECT_EQ(quotient.as_ulong(), b1.as_ulong());
|
||||
assert(quotient.num_bits() < GMP_NUMB_BITS);
|
||||
assert(quotient.as_ulong() == b1.as_ulong());
|
||||
bigint<1> b1inc = bigint<1>("76749408");
|
||||
bigint<1> b1a = quotient.shorten(b1inc, "test");
|
||||
EXPECT_EQ(b1a, b1);
|
||||
EXPECT_TRUE(remainder.is_zero());
|
||||
assert(b1a == b1);
|
||||
assert(remainder.is_zero());
|
||||
remainder.limit(b2, "test");
|
||||
|
||||
EXPECT_THROW((void)(quotient.shorten(b1, "test")), std::domain_error);
|
||||
EXPECT_THROW(remainder.limit(remainder, "test"), std::domain_error);
|
||||
try {
|
||||
(void)(quotient.shorten(b1, "test"));
|
||||
assert(false);
|
||||
} catch (std::domain_error) {}
|
||||
try {
|
||||
remainder.limit(remainder, "test");
|
||||
assert(false);
|
||||
} catch (std::domain_error) {}
|
||||
|
||||
bigint<1> br = bigint<1>("42");
|
||||
b3 += br;
|
||||
EXPECT_NE(b3, b3a);
|
||||
EXPECT_GT(b3, b3a);
|
||||
EXPECT_FALSE(b3a > b3);
|
||||
assert(b3 != b3a);
|
||||
assert(b3 > b3a);
|
||||
assert(!(b3a > b3));
|
||||
|
||||
bigint<3>::div_qr(quotient, remainder, b3, b2);
|
||||
EXPECT_LT(quotient.num_bits(), GMP_NUMB_BITS);
|
||||
EXPECT_EQ(quotient.as_ulong(), b1.as_ulong());
|
||||
EXPECT_LT(remainder.num_bits(), GMP_NUMB_BITS);
|
||||
EXPECT_EQ(remainder.as_ulong(), 42);
|
||||
assert(quotient.num_bits() < GMP_NUMB_BITS);
|
||||
assert(quotient.as_ulong() == b1.as_ulong());
|
||||
assert(remainder.num_bits() < GMP_NUMB_BITS);
|
||||
assert(remainder.as_ulong() == 42);
|
||||
|
||||
b3a.clear();
|
||||
EXPECT_TRUE(b3a.is_zero());
|
||||
EXPECT_EQ(b3a.num_bits(), 0);
|
||||
EXPECT_FALSE(b3.is_zero());
|
||||
assert(b3a.is_zero());
|
||||
assert(b3a.num_bits() == 0);
|
||||
assert(!(b3.is_zero()));
|
||||
|
||||
bigint<4> bx = bigint<4>().randomize();
|
||||
bigint<4> by = bigint<4>().randomize();
|
||||
EXPECT_FALSE(bx == by);
|
||||
assert(!(bx == by));
|
||||
|
||||
// TODO: test serialization
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
test_bigint();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
* @copyright MIT license (see LICENSE file)
|
||||
*****************************************************************************/
|
||||
#include "common/profiling.hpp"
|
||||
#include "algebra/curves/edwards/edwards_pp.hpp"
|
||||
#include "algebra/curves/mnt/mnt4/mnt4_pp.hpp"
|
||||
#include "algebra/curves/mnt/mnt6/mnt6_pp.hpp"
|
||||
#ifdef CURVE_BN128
|
||||
#include "algebra/curves/bn128/bn128_pp.hpp"
|
||||
#endif
|
||||
@@ -12,8 +15,6 @@
|
||||
#include "algebra/fields/fp6_3over2.hpp"
|
||||
#include "algebra/fields/fp12_2over3over2.hpp"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using namespace libsnark;
|
||||
|
||||
template<typename FieldT>
|
||||
@@ -28,25 +29,25 @@ void test_field()
|
||||
FieldT a = FieldT::random_element();
|
||||
FieldT a_ser;
|
||||
a_ser = reserialize<FieldT>(a);
|
||||
EXPECT_EQ(a_ser, a);
|
||||
assert(a_ser == a);
|
||||
|
||||
FieldT b = FieldT::random_element();
|
||||
FieldT c = FieldT::random_element();
|
||||
FieldT d = FieldT::random_element();
|
||||
|
||||
EXPECT_NE(a, zero);
|
||||
EXPECT_NE(a, one);
|
||||
assert(a != zero);
|
||||
assert(a != one);
|
||||
|
||||
EXPECT_EQ(a * a, a.squared());
|
||||
EXPECT_EQ((a + b).squared(), a.squared() + a*b + b*a + b.squared());
|
||||
EXPECT_EQ((a + b)*(c + d), a*c + a*d + b*c + b*d);
|
||||
EXPECT_EQ(a - b, a + (-b));
|
||||
EXPECT_EQ(a - b, (-b) + a);
|
||||
assert(a * a == a.squared());
|
||||
assert((a + b).squared() == a.squared() + a*b + b*a + b.squared());
|
||||
assert((a + b)*(c + d) == a*c + a*d + b*c + b*d);
|
||||
assert(a - b == a + (-b));
|
||||
assert(a - b == (-b) + a);
|
||||
|
||||
EXPECT_EQ((a ^ rand1) * (a ^ rand2), (a^randsum));
|
||||
assert((a ^ rand1) * (a ^ rand2) == (a^randsum));
|
||||
|
||||
EXPECT_EQ(a * a.inverse(), one);
|
||||
EXPECT_EQ((a + b) * c.inverse(), a * c.inverse() + (b.inverse() * c).inverse());
|
||||
assert(a * a.inverse() == one);
|
||||
assert((a + b) * c.inverse() == a * c.inverse() + (b.inverse() * c).inverse());
|
||||
|
||||
}
|
||||
|
||||
@@ -57,7 +58,7 @@ void test_sqrt()
|
||||
{
|
||||
FieldT a = FieldT::random_element();
|
||||
FieldT asq = a.squared();
|
||||
EXPECT_TRUE(asq.sqrt() == a || asq.sqrt() == -a);
|
||||
assert(asq.sqrt() == a || asq.sqrt() == -a);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,21 +66,21 @@ template<typename FieldT>
|
||||
void test_two_squarings()
|
||||
{
|
||||
FieldT a = FieldT::random_element();
|
||||
EXPECT_EQ(a.squared(), a * a);
|
||||
EXPECT_EQ(a.squared(), a.squared_complex());
|
||||
EXPECT_EQ(a.squared(), a.squared_karatsuba());
|
||||
assert(a.squared() == a * a);
|
||||
assert(a.squared() == a.squared_complex());
|
||||
assert(a.squared() == a.squared_karatsuba());
|
||||
}
|
||||
|
||||
template<typename FieldT>
|
||||
void test_Frobenius()
|
||||
{
|
||||
FieldT a = FieldT::random_element();
|
||||
EXPECT_EQ(a.Frobenius_map(0), a);
|
||||
assert(a.Frobenius_map(0) == a);
|
||||
FieldT a_q = a ^ FieldT::base_field_char();
|
||||
for (size_t power = 1; power < 10; ++power)
|
||||
{
|
||||
const FieldT a_qi = a.Frobenius_map(power);
|
||||
EXPECT_EQ(a_qi, a_q);
|
||||
assert(a_qi == a_q);
|
||||
|
||||
a_q = a_q ^ FieldT::base_field_char();
|
||||
}
|
||||
@@ -88,10 +89,49 @@ void test_Frobenius()
|
||||
template<typename FieldT>
|
||||
void test_unitary_inverse()
|
||||
{
|
||||
EXPECT_EQ(FieldT::extension_degree() % 2, 0);
|
||||
assert(FieldT::extension_degree() % 2 == 0);
|
||||
FieldT a = FieldT::random_element();
|
||||
FieldT aqcubed_minus1 = a.Frobenius_map(FieldT::extension_degree()/2) * a.inverse();
|
||||
EXPECT_EQ(aqcubed_minus1.inverse(), aqcubed_minus1.unitary_inverse());
|
||||
assert(aqcubed_minus1.inverse() == aqcubed_minus1.unitary_inverse());
|
||||
}
|
||||
|
||||
template<typename FieldT>
|
||||
void test_cyclotomic_squaring();
|
||||
|
||||
template<>
|
||||
void test_cyclotomic_squaring<Fqk<edwards_pp> >()
|
||||
{
|
||||
typedef Fqk<edwards_pp> FieldT;
|
||||
assert(FieldT::extension_degree() % 2 == 0);
|
||||
FieldT a = FieldT::random_element();
|
||||
FieldT a_unitary = a.Frobenius_map(FieldT::extension_degree()/2) * a.inverse();
|
||||
// beta = a^((q^(k/2)-1)*(q+1))
|
||||
FieldT beta = a_unitary.Frobenius_map(1) * a_unitary;
|
||||
assert(beta.cyclotomic_squared() == beta.squared());
|
||||
}
|
||||
|
||||
template<>
|
||||
void test_cyclotomic_squaring<Fqk<mnt4_pp> >()
|
||||
{
|
||||
typedef Fqk<mnt4_pp> FieldT;
|
||||
assert(FieldT::extension_degree() % 2 == 0);
|
||||
FieldT a = FieldT::random_element();
|
||||
FieldT a_unitary = a.Frobenius_map(FieldT::extension_degree()/2) * a.inverse();
|
||||
// beta = a^(q^(k/2)-1)
|
||||
FieldT beta = a_unitary;
|
||||
assert(beta.cyclotomic_squared() == beta.squared());
|
||||
}
|
||||
|
||||
template<>
|
||||
void test_cyclotomic_squaring<Fqk<mnt6_pp> >()
|
||||
{
|
||||
typedef Fqk<mnt6_pp> FieldT;
|
||||
assert(FieldT::extension_degree() % 2 == 0);
|
||||
FieldT a = FieldT::random_element();
|
||||
FieldT a_unitary = a.Frobenius_map(FieldT::extension_degree()/2) * a.inverse();
|
||||
// beta = a^((q^(k/2)-1)*(q+1))
|
||||
FieldT beta = a_unitary.Frobenius_map(1) * a_unitary;
|
||||
assert(beta.cyclotomic_squared() == beta.squared());
|
||||
}
|
||||
|
||||
template<typename ppT>
|
||||
@@ -157,16 +197,16 @@ void test_Fp4_tom_cook()
|
||||
c2 = - (FieldT(5)*(FieldT(4).inverse()))* v0 + (FieldT(2)*(FieldT(3).inverse()))*(v1 + v2) - FieldT(24).inverse()*(v3 + v4) + FieldT(4)*v6 + beta*v6;
|
||||
c3 = FieldT(12).inverse() * (FieldT(5)*v0 - FieldT(7)*v1) - FieldT(24).inverse()*(v2 - FieldT(7)*v3 + v4 + v5) + FieldT(15)*v6;
|
||||
|
||||
EXPECT_EQ(res, correct_res);
|
||||
assert(res == correct_res);
|
||||
|
||||
// {v0, v3, v4, v5}
|
||||
const FieldT u = (FieldT::one() - beta).inverse();
|
||||
EXPECT_EQ(v0, u * c0 + beta * u * c2 - beta * u * FieldT(2).inverse() * v1 - beta * u * FieldT(2).inverse() * v2 + beta * v6);
|
||||
EXPECT_EQ(v3, - FieldT(15) * u * c0 - FieldT(30) * u * c1 - FieldT(3) * (FieldT(4) + beta) * u * c2 - FieldT(6) * (FieldT(4) + beta) * u * c3 + (FieldT(24) - FieldT(3) * beta * FieldT(2).inverse()) * u * v1 + (-FieldT(8) + beta * FieldT(2).inverse()) * u * v2
|
||||
assert(v0 == u * c0 + beta * u * c2 - beta * u * FieldT(2).inverse() * v1 - beta * u * FieldT(2).inverse() * v2 + beta * v6);
|
||||
assert(v3 == - FieldT(15) * u * c0 - FieldT(30) * u * c1 - FieldT(3) * (FieldT(4) + beta) * u * c2 - FieldT(6) * (FieldT(4) + beta) * u * c3 + (FieldT(24) - FieldT(3) * beta * FieldT(2).inverse()) * u * v1 + (-FieldT(8) + beta * FieldT(2).inverse()) * u * v2
|
||||
- FieldT(3) * (-FieldT(16) + beta) * v6);
|
||||
EXPECT_EQ(v4, - FieldT(15) * u * c0 + FieldT(30) * u * c1 - FieldT(3) * (FieldT(4) + beta) * u * c2 + FieldT(6) * (FieldT(4) + beta) * u * c3 + (FieldT(24) - FieldT(3) * beta * FieldT(2).inverse()) * u * v2 + (-FieldT(8) + beta * FieldT(2).inverse()) * u * v1
|
||||
assert(v4 == - FieldT(15) * u * c0 + FieldT(30) * u * c1 - FieldT(3) * (FieldT(4) + beta) * u * c2 + FieldT(6) * (FieldT(4) + beta) * u * c3 + (FieldT(24) - FieldT(3) * beta * FieldT(2).inverse()) * u * v2 + (-FieldT(8) + beta * FieldT(2).inverse()) * u * v1
|
||||
- FieldT(3) * (-FieldT(16) + beta) * v6);
|
||||
EXPECT_EQ(v5, - FieldT(80) * u * c0 - FieldT(240) * u * c1 - FieldT(8) * (FieldT(9) + beta) * u * c2 - FieldT(24) * (FieldT(9) + beta) * u * c3 - FieldT(2) * (-FieldT(81) + beta) * u * v1 + (-FieldT(81) + beta) * u * v2
|
||||
assert(v5 == - FieldT(80) * u * c0 - FieldT(240) * u * c1 - FieldT(8) * (FieldT(9) + beta) * u * c2 - FieldT(24) * (FieldT(9) + beta) * u * c3 - FieldT(2) * (-FieldT(81) + beta) * u * v1 + (-FieldT(81) + beta) * u * v2
|
||||
- FieldT(8) * (-FieldT(81) + beta) * v6);
|
||||
|
||||
// c0 + beta c2 - (beta v1)/2 - (beta v2)/ 2 - (-1 + beta) beta v6,
|
||||
@@ -176,8 +216,22 @@ void test_Fp4_tom_cook()
|
||||
}
|
||||
}
|
||||
|
||||
TEST(algebra, fields)
|
||||
int main(void)
|
||||
{
|
||||
edwards_pp::init_public_params();
|
||||
test_all_fields<edwards_pp>();
|
||||
test_cyclotomic_squaring<Fqk<edwards_pp> >();
|
||||
|
||||
mnt4_pp::init_public_params();
|
||||
test_all_fields<mnt4_pp>();
|
||||
test_Fp4_tom_cook<mnt4_Fq4>();
|
||||
test_two_squarings<Fqe<mnt4_pp> >();
|
||||
test_cyclotomic_squaring<Fqk<mnt4_pp> >();
|
||||
|
||||
mnt6_pp::init_public_params();
|
||||
test_all_fields<mnt6_pp>();
|
||||
test_cyclotomic_squaring<Fqk<mnt6_pp> >();
|
||||
|
||||
alt_bn128_pp::init_public_params();
|
||||
test_field<alt_bn128_Fq6>();
|
||||
test_Frobenius<alt_bn128_Fq6>();
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
|
||||
/*
|
||||
Split out from multiexp to prevent cyclical
|
||||
dependencies. I.e. previously multiexp depended on
|
||||
knowledge_commitment, which depended on sparse_vector, which
|
||||
depended on multiexp (to do accumulate).
|
||||
dependencies. I.e. previously multiexp dependend on
|
||||
knowledge_commitment, which dependend on sparse_vector, which
|
||||
dependend on multiexp (to do accumulate).
|
||||
|
||||
Will probably go away in more general exp refactoring.
|
||||
*/
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#ifndef KC_MULTIEXP_TCC_
|
||||
#define KC_MULTIEXP_TCC_
|
||||
|
||||
#include "common/assert_except.hpp"
|
||||
|
||||
namespace libsnark {
|
||||
|
||||
template<typename T1, typename T2, mp_size_t n>
|
||||
@@ -50,7 +52,7 @@ knowledge_commitment<T1, T2> kc_multi_exp_with_mixed_addition(const knowledge_co
|
||||
while (index_it != vec.indices.end() && *index_it < max_idx)
|
||||
{
|
||||
const size_t scalar_position = (*index_it) - min_idx;
|
||||
assert(scalar_position < scalar_length);
|
||||
assert_except(scalar_position < scalar_length);
|
||||
|
||||
const FieldT scalar = *(scalar_start + scalar_position);
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#include "common/profiling.hpp"
|
||||
#include "common/utils.hpp"
|
||||
#include "common/assert_except.hpp"
|
||||
#include "algebra/scalar_multiplication/wnaf.hpp"
|
||||
|
||||
namespace libsnark {
|
||||
@@ -40,7 +41,7 @@ public:
|
||||
#if defined(__x86_64__) && defined(USE_ASM)
|
||||
if (n == 3)
|
||||
{
|
||||
long res;
|
||||
int64_t res;
|
||||
__asm__
|
||||
("// check for overflow \n\t"
|
||||
"mov $0, %[res] \n\t"
|
||||
@@ -58,7 +59,7 @@ public:
|
||||
}
|
||||
else if (n == 4)
|
||||
{
|
||||
long res;
|
||||
int64_t res;
|
||||
__asm__
|
||||
("// check for overflow \n\t"
|
||||
"mov $0, %[res] \n\t"
|
||||
@@ -77,7 +78,7 @@ public:
|
||||
}
|
||||
else if (n == 5)
|
||||
{
|
||||
long res;
|
||||
int64_t res;
|
||||
__asm__
|
||||
("// check for overflow \n\t"
|
||||
"mov $0, %[res] \n\t"
|
||||
@@ -119,7 +120,7 @@ T naive_exp(typename std::vector<T>::const_iterator vec_start,
|
||||
bigint<FieldT::num_limbs> scalar_bigint = scalar_it->as_bigint();
|
||||
result = result + opt_window_wnaf_exp(*vec_it, scalar_bigint, scalar_bigint.num_bits());
|
||||
}
|
||||
assert(scalar_it == scalar_end);
|
||||
assert_except(scalar_it == scalar_end);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -139,7 +140,7 @@ T naive_plain_exp(typename std::vector<T>::const_iterator vec_start,
|
||||
{
|
||||
result = result + (*scalar_it) * (*vec_it);
|
||||
}
|
||||
assert(scalar_it == scalar_end);
|
||||
assert_except(scalar_it == scalar_end);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -185,15 +186,15 @@ T multi_exp_inner(typename std::vector<T>::const_iterator vec_start,
|
||||
opt_q.emplace_back(ordered_exponent<n>(i, scalar_it->as_bigint()));
|
||||
}
|
||||
std::make_heap(opt_q.begin(),opt_q.end());
|
||||
assert(scalar_it == scalar_end);
|
||||
assert_except(scalar_it == scalar_end);
|
||||
|
||||
if (vec_len != odd_vec_len)
|
||||
{
|
||||
g.emplace_back(T::zero());
|
||||
opt_q.emplace_back(ordered_exponent<n>(odd_vec_len - 1, bigint<n>(0ul)));
|
||||
opt_q.emplace_back(ordered_exponent<n>(odd_vec_len - 1, bigint<n>(UINT64_C(0))));
|
||||
}
|
||||
assert(g.size() % 2 == 1);
|
||||
assert(opt_q.size() == g.size());
|
||||
assert_except(g.size() % 2 == 1);
|
||||
assert_except(opt_q.size() == g.size());
|
||||
|
||||
T opt_result = T::zero();
|
||||
|
||||
@@ -214,7 +215,7 @@ T multi_exp_inner(typename std::vector<T>::const_iterator vec_start,
|
||||
const size_t bbits = b.r.num_bits();
|
||||
const size_t limit = (abits-bbits >= 20 ? 20 : abits-bbits);
|
||||
|
||||
if (bbits < 1ul<<limit)
|
||||
if (bbits < UINT64_C(1)<<limit)
|
||||
{
|
||||
/*
|
||||
In this case, exponentiating to the power of a is cheaper than
|
||||
@@ -329,7 +330,7 @@ T multi_exp_with_mixed_addition(typename std::vector<T>::const_iterator vec_star
|
||||
const size_t chunks,
|
||||
const bool use_multiexp)
|
||||
{
|
||||
assert(std::distance(vec_start, vec_end) == std::distance(scalar_start, scalar_end));
|
||||
assert_except(std::distance(vec_start, vec_end) == std::distance(scalar_start, scalar_end));
|
||||
enter_block("Process scalar vector");
|
||||
auto value_it = vec_start;
|
||||
auto scalar_it = scalar_start;
|
||||
@@ -389,7 +390,7 @@ size_t get_exp_window_size(const size_t num_scalars)
|
||||
#endif
|
||||
}
|
||||
size_t window = 1;
|
||||
for (long i = T::fixed_base_exp_window_table.size()-1; i >= 0; --i)
|
||||
for (int64_t i = T::fixed_base_exp_window_table.size()-1; i >= 0; --i)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (!inhibit_profiling_info)
|
||||
@@ -420,9 +421,9 @@ window_table<T> get_window_table(const size_t scalar_size,
|
||||
const size_t window,
|
||||
const T &g)
|
||||
{
|
||||
const size_t in_window = 1ul<<window;
|
||||
const size_t in_window = UINT64_C(1)<<window;
|
||||
const size_t outerc = (scalar_size+window-1)/window;
|
||||
const size_t last_in_window = 1ul<<(scalar_size - (outerc-1)*window);
|
||||
const size_t last_in_window = UINT64_C(1)<<(scalar_size - (outerc-1)*window);
|
||||
#ifdef DEBUG
|
||||
if (!inhibit_profiling_info)
|
||||
{
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace libsnark {
|
||||
* Find the wNAF representation of the given scalar relative to the given window size.
|
||||
*/
|
||||
template<mp_size_t n>
|
||||
std::vector<long> find_wnaf(const size_t window_size, const bigint<n> &scalar);
|
||||
std::vector<int64_t> find_wnaf(const size_t window_size, const bigint<n> &scalar);
|
||||
|
||||
/**
|
||||
* In additive notation, use wNAF exponentiation (with the given window size) to compute scalar * base.
|
||||
|
||||
@@ -17,15 +17,15 @@
|
||||
namespace libsnark {
|
||||
|
||||
template<mp_size_t n>
|
||||
std::vector<long> find_wnaf(const size_t window_size, const bigint<n> &scalar)
|
||||
std::vector<int64_t> find_wnaf(const size_t window_size, const bigint<n> &scalar)
|
||||
{
|
||||
const size_t length = scalar.max_bits(); // upper bound
|
||||
std::vector<long> res(length+1);
|
||||
std::vector<int64_t> res(length+1);
|
||||
bigint<n> c = scalar;
|
||||
long j = 0;
|
||||
int64_t j = 0;
|
||||
while (!c.is_zero())
|
||||
{
|
||||
long u;
|
||||
int64_t u;
|
||||
if ((c.data[0] & 1) == 1)
|
||||
{
|
||||
u = c.data[0] % (1u << (window_size+1));
|
||||
@@ -59,11 +59,11 @@ std::vector<long> find_wnaf(const size_t window_size, const bigint<n> &scalar)
|
||||
template<typename T, mp_size_t n>
|
||||
T fixed_window_wnaf_exp(const size_t window_size, const T &base, const bigint<n> &scalar)
|
||||
{
|
||||
std::vector<long> naf = find_wnaf(window_size, scalar);
|
||||
std::vector<T> table(1ul<<(window_size-1));
|
||||
std::vector<int64_t> naf = find_wnaf(window_size, scalar);
|
||||
std::vector<T> table(UINT64_C(1)<<(window_size-1));
|
||||
T tmp = base;
|
||||
T dbl = base.dbl();
|
||||
for (size_t i = 0; i < 1ul<<(window_size-1); ++i)
|
||||
for (size_t i = 0; i < UINT64_C(1)<<(window_size-1); ++i)
|
||||
{
|
||||
table[i] = tmp;
|
||||
tmp = tmp + dbl;
|
||||
@@ -71,7 +71,7 @@ T fixed_window_wnaf_exp(const size_t window_size, const T &base, const bigint<n>
|
||||
|
||||
T res = T::zero();
|
||||
bool found_nonzero = false;
|
||||
for (long i = naf.size()-1; i >= 0; --i)
|
||||
for (int64_t i = naf.size()-1; i >= 0; --i)
|
||||
{
|
||||
if (found_nonzero)
|
||||
{
|
||||
@@ -99,7 +99,7 @@ template<typename T, mp_size_t n>
|
||||
T opt_window_wnaf_exp(const T &base, const bigint<n> &scalar, const size_t scalar_bits)
|
||||
{
|
||||
size_t best = 0;
|
||||
for (long i = T::wnaf_window_table.size() - 1; i >= 0; --i)
|
||||
for (int64_t i = T::wnaf_window_table.size() - 1; i >= 0; --i)
|
||||
{
|
||||
if (scalar_bits >= T::wnaf_window_table[i])
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user