Merge pull request #45 from mir-protocol/remove-exp-self

Change `Field::exp` to using a `u64` power.
This commit is contained in:
wborgeaud 2021-05-19 20:28:47 +02:00 committed by GitHub
commit 965c4e4da5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 31 additions and 53 deletions

View File

@ -28,7 +28,7 @@ pub trait QuadraticFieldExtension:
fn frobenius(&self) -> Self {
let [a0, a1] = self.to_canonical_representation();
let k = (Self::BaseField::ORDER - 1) / 2;
let z = Self::W.exp_usize(k as usize);
let z = Self::W.exp(k);
Self::from_canonical_representation([a0, a1 * z])
}
@ -233,19 +233,6 @@ mod tests {
};
use crate::field::field::Field;
fn exp_naive<F: Field>(x: F, power: u64) -> F {
let mut current = x;
let mut product = F::ONE;
for j in 0..64 {
if (power >> j & 1) != 0 {
product *= current;
}
current = current.square();
}
product
}
#[test]
fn test_add_neg_sub_mul() {
type F = QuadraticCrandallField;
@ -286,7 +273,7 @@ mod tests {
type F = QuadraticCrandallField;
let x = F::rand();
assert_eq!(
exp_naive(x, <F as QuadraticFieldExtension>::BaseField::ORDER),
x.exp(<F as QuadraticFieldExtension>::BaseField::ORDER),
x.frobenius()
);
}
@ -297,7 +284,7 @@ mod tests {
type F = QuadraticCrandallField;
let x = F::rand();
assert_eq!(
exp_naive(exp_naive(x, 18446744071293632512), 18446744071293632514),
x.exp(18446744071293632512).exp(18446744071293632514),
F::ONE
);
}
@ -308,12 +295,12 @@ mod tests {
// F::ORDER = 2^29 * 2762315674048163 * 229454332791453 + 1
assert_eq!(
F::MULTIPLICATIVE_GROUP_GENERATOR
.exp_usize(2762315674048163)
.exp_usize(229454332791453),
.exp(2762315674048163)
.exp(229454332791453),
F::POWER_OF_TWO_GENERATOR
);
assert_eq!(
F::POWER_OF_TWO_GENERATOR.exp_usize(
F::POWER_OF_TWO_GENERATOR.exp(
1 << (F::TWO_ADICITY - <F as QuadraticFieldExtension>::BaseField::TWO_ADICITY)
),
<F as QuadraticFieldExtension>::BaseField::POWER_OF_TWO_GENERATOR.into()

View File

@ -26,7 +26,7 @@ pub trait QuarticFieldExtension: Field + From<<Self as QuarticFieldExtension>::B
fn frobenius(&self) -> Self {
let [a0, a1, a2, a3] = self.to_canonical_representation();
let k = (Self::BaseField::ORDER - 1) / 4;
let z0 = Self::W.exp_usize(k as usize);
let z0 = Self::W.exp(k);
let mut z = Self::BaseField::ONE;
let b0 = a0 * z;
z *= z0;
@ -373,9 +373,8 @@ mod tests {
F::POWER_OF_TWO_GENERATOR
);
assert_eq!(
F::POWER_OF_TWO_GENERATOR.exp_usize(
1 << (F::TWO_ADICITY - <F as QuarticFieldExtension>::BaseField::TWO_ADICITY)
),
F::POWER_OF_TWO_GENERATOR
.exp(1 << (F::TWO_ADICITY - <F as QuarticFieldExtension>::BaseField::TWO_ADICITY)),
<F as QuarticFieldExtension>::BaseField::POWER_OF_TWO_GENERATOR.into()
);
}

View File

@ -157,12 +157,12 @@ pub trait Field:
bits_u64(self.to_canonical_u64())
}
fn exp(&self, power: Self) -> Self {
fn exp(&self, power: u64) -> Self {
let mut current = *self;
let mut product = Self::ONE;
for j in 0..power.bits() {
if (power.to_canonical_u64() >> j & 1) != 0 {
for j in 0..bits_u64(power) {
if (power >> j & 1) != 0 {
product *= current;
}
current = current.square();
@ -171,32 +171,25 @@ pub trait Field:
}
fn exp_u32(&self, power: u32) -> Self {
self.exp(Self::from_canonical_u32(power))
}
fn exp_usize(&self, power: usize) -> Self {
self.exp(Self::from_canonical_usize(power))
self.exp(power as u64)
}
/// Returns whether `x^power` is a permutation of this field.
fn is_monomial_permutation(power: Self) -> bool {
if power.is_zero() {
return false;
fn is_monomial_permutation(power: u64) -> bool {
match power {
0 => false,
1 => true,
_ => (Self::ORDER - 1).gcd(&power) == 1,
}
if power.is_one() {
return true;
}
(Self::ORDER - 1).gcd(&power.to_canonical_u64()) == 1
}
fn kth_root(&self, k: Self) -> Self {
fn kth_root(&self, k: u64) -> Self {
let p = Self::ORDER;
let p_minus_1 = p - 1;
debug_assert!(
Self::is_monomial_permutation(k),
"Not a permutation of this field"
);
let k = k.to_canonical_u64();
// By Fermat's little theorem, x^p = x and x^(p - 1) = 1, so x^(p + n(p - 1)) = x for any n.
// Our assumption that the k'th root operation is a permutation implies gcd(p - 1, k) = 1,
@ -208,7 +201,7 @@ pub trait Field:
let numerator = p as u128 + n as u128 * p_minus_1 as u128;
if numerator % k as u128 == 0 {
let power = (numerator / k as u128) as u64 % p_minus_1;
return self.exp(Self::from_canonical_u64(power));
return self.exp(power);
}
}
panic!(
@ -218,11 +211,11 @@ pub trait Field:
}
fn kth_root_u32(&self, k: u32) -> Self {
self.kth_root(Self::from_canonical_u32(k))
self.kth_root(k as u64)
}
fn cube_root(&self) -> Self {
self.kth_root_u32(3)
self.kth_root(3)
}
fn powers(&self) -> Powers<Self> {

View File

@ -298,7 +298,6 @@ macro_rules! test_arithmetic {
assert_eq!(F::TWO.kth_root_u32(1), <F>::TWO);
for power in 1..10 {
let power = F::from_canonical_u32(power);
if F::is_monomial_permutation(power) {
let x = F::rand();
assert_eq!(x.exp(power).kth_root(power), x);

View File

@ -187,7 +187,7 @@ fn fri_verifier_query_round<F: Field + Extendable<D>, const D: usize>(
// `subgroup_x` is `subgroup[x_index]`, i.e., the actual field element in the domain.
let log_n = log2_strict(n);
let mut subgroup_x = F::MULTIPLICATIVE_GROUP_GENERATOR
* F::primitive_root_of_unity(log_n).exp_usize(reverse_bits(x_index, log_n));
* F::primitive_root_of_unity(log_n).exp(reverse_bits(x_index, log_n) as u64);
for (i, &arity_bits) in config.reduction_arity_bits.iter().enumerate() {
let arity = 1 << arity_bits;
let next_domain_size = domain_size >> arity_bits;

View File

@ -120,7 +120,7 @@ impl WirePartitions {
.map(|chunk| {
let values = chunk
.par_iter()
.map(|&x| k_is[x / degree] * subgroup_generator.exp_usize(x % degree))
.map(|&x| k_is[x / degree] * subgroup_generator.exp((x % degree) as u64))
.collect::<Vec<_>>();
PolynomialValues::new(values)
})

View File

@ -47,7 +47,7 @@ pub fn evaluate_gate_constraints_recursively<F: Field>(
/// Evaluate the polynomial which vanishes on any multiplicative subgroup of a given order `n`.
pub(crate) fn eval_zero_poly<F: Field>(n: usize, x: F) -> F {
// Z(x) = x^n - 1
x.exp_usize(n) - F::ONE
x.exp(n as u64) - F::ONE
}
/// Evaluate the Lagrange basis `L_1` with `L_1(1) = 1`, and `L_1(x) = 0` for other members of an

View File

@ -90,7 +90,7 @@ impl<F: Field> ListPolynomialCommitment<F> {
assert_eq!(self.blinding, config.blinding[0]);
for p in points {
assert_ne!(
p.exp_usize(self.degree),
p.exp(self.degree as u64),
F::Extension::ONE,
"Opening point is in the subgroup."
);
@ -175,7 +175,7 @@ impl<F: Field> ListPolynomialCommitment<F> {
}
for p in points {
assert_ne!(
p.exp_usize(degree),
p.exp(degree as u64),
F::Extension::ONE,
"Opening point is in the subgroup."
);
@ -374,7 +374,7 @@ mod tests {
.map(|_| PolynomialCoeffs::new(F::rand_vec(degree)))
.collect();
let mut points = F::Extension::rand_vec(num_points);
while points.iter().any(|&x| x.exp_usize(degree).is_one()) {
while points.iter().any(|&x| x.exp(degree as u64).is_one()) {
points = F::Extension::rand_vec(num_points);
}

View File

@ -91,8 +91,8 @@ impl<F: Field> PolynomialCoeffs<F> {
// Equals to the evaluation of `a` on `{g.w^i}`.
let mut a_eval = fft(a);
// Compute the denominators `1/(g^n.w^(n*i) - 1)` using batch inversion.
let denominator_g = g.exp_usize(n);
let root_n = root.exp_usize(n);
let denominator_g = g.exp(n as u64);
let root_n = root.exp(n as u64);
let mut root_pow = F::ONE;
let denominators = (0..a_eval.len())
.map(|i| {

View File

@ -434,7 +434,7 @@ mod tests {
PolynomialCoeffs::new(xn_min_one_vec)
};
let a = g.exp_usize(rng.gen_range(0, n));
let a = g.exp(rng.gen_range(0, n as u64));
let denom = PolynomialCoeffs::new(vec![-a, F::ONE]);
let now = Instant::now();
xn_minus_one.div_rem(&denom);