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

Add frobenius_map_in_place #557

Merged
merged 2 commits into from
Dec 24, 2022
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@
- `MNT4Parameters` → `MNT4Config`
- `MNT6Parameters` → `MNT6Config`
- `GLVParameters` → `GLVConfig`
- [\#557](https://github.com/arkworks-rs/algebra/pull/557) (`ark-ff`) Change `frobenius_map` to return the result, instead of mutating the input. Add `frobenius_map_in_place` for the old behavior.

### Features

Expand Down
6 changes: 3 additions & 3 deletions ec/src/models/bls12/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ pub trait Bls12Config: 'static + Sized {
// f2 = f^(p^6 - 1)
f2 = r;
// r = f^((p^6 - 1)(p^2))
r.frobenius_map(2);
r.frobenius_map_in_place(2);

// r = f^((p^6 - 1)(p^2) + (p^6 - 1))
// r = f^((p^6 - 1)(p^2 + 1))
Expand All @@ -131,7 +131,7 @@ pub trait Bls12Config: 'static + Sized {
// t[2].Expt(&t[1])
Bls12::<Self>::exp_by_x(&y1, &mut y2);
// t[1].Frobenius(&t[1])
y1.frobenius_map(1);
y1.frobenius_map_in_place(1);
// t[1].Mul(&t[1], &t[2])
y1 *= &y2;
// result.Mul(&result, &t[0])
Expand All @@ -142,7 +142,7 @@ pub trait Bls12Config: 'static + Sized {
Bls12::<Self>::exp_by_x(&y0, &mut y2);
// t[0].FrobeniusSquare(&t[1])
y0 = y1;
y0.frobenius_map(2);
y0.frobenius_map_in_place(2);
// t[1].InverseUnitary(&t[1])
y1.cyclotomic_inverse_in_place();
// t[1].Mul(&t[1], &t[2])
Expand Down
4 changes: 2 additions & 2 deletions ec/src/models/bn/g2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,9 +177,9 @@ fn mul_by_char<P: BnConfig>(r: G2Affine<P>) -> G2Affine<P> {
// multiply by field characteristic

let mut s = r;
s.x.frobenius_map(1);
s.x.frobenius_map_in_place(1);
s.x *= &P::TWIST_MUL_BY_Q_X;
s.y.frobenius_map(1);
s.y.frobenius_map_in_place(1);
s.y *= &P::TWIST_MUL_BY_Q_Y;

s
Expand Down
8 changes: 4 additions & 4 deletions ec/src/models/bn/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ impl<P: BnConfig> Pairing for Bn<P> {
// f2 = f^(p^6 - 1)
f2 = r;
// r = f^((p^6 - 1)(p^2))
r.frobenius_map(2);
r.frobenius_map_in_place(2);

// r = f^((p^6 - 1)(p^2) + (p^6 - 1))
// r = f^((p^6 - 1)(p^2 + 1))
Expand Down Expand Up @@ -206,13 +206,13 @@ impl<P: BnConfig> Pairing for Bn<P> {
let y10 = y8 * &y4;
let y11 = y10 * &r;
let mut y12 = y9;
y12.frobenius_map(1);
y12.frobenius_map_in_place(1);
let y13 = y12 * &y11;
y8.frobenius_map(2);
y8.frobenius_map_in_place(2);
let y14 = y8 * &y13;
r.cyclotomic_inverse_in_place();
let mut y15 = r * &y9;
y15.frobenius_map(3);
y15.frobenius_map_in_place(3);
let y16 = y15 * &y14;

PairingOutput(y16)
Expand Down
20 changes: 10 additions & 10 deletions ec/src/models/bw6/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ pub trait BW6Config: 'static + Eq + Sized {
f_2.cyclotomic_inverse_in_place();
}

f_2.frobenius_map(1);
f_2.frobenius_map_in_place(1);

MillerLoopOutput(f_1 * &f_2)
}
Expand Down Expand Up @@ -180,7 +180,7 @@ impl<P: BW6Config> BW6<P> {
let elt_q3_over_elt = elt_q3 * elt_inv;
// alpha = elt^((q^3-1) * q)
let mut alpha = elt_q3_over_elt;
alpha.frobenius_map(1);
alpha.frobenius_map_in_place(1);
// beta = elt^((q^3-1)*(q+1)
alpha * &elt_q3_over_elt
}
Expand All @@ -198,28 +198,28 @@ impl<P: BW6Config> BW6<P> {
// steps 1,2,3
let f0 = *f;
let mut f0p = f0;
f0p.frobenius_map(1);
f0p.frobenius_map_in_place(1);
let f1 = Self::exp_by_x(f0);
let mut f1p = f1;
f1p.frobenius_map(1);
f1p.frobenius_map_in_place(1);
let f2 = Self::exp_by_x(f1);
let mut f2p = f2;
f2p.frobenius_map(1);
f2p.frobenius_map_in_place(1);
let f3 = Self::exp_by_x(f2);
let mut f3p = f3;
f3p.frobenius_map(1);
f3p.frobenius_map_in_place(1);
let f4 = Self::exp_by_x(f3);
let mut f4p = f4;
f4p.frobenius_map(1);
f4p.frobenius_map_in_place(1);
let f5 = Self::exp_by_x(f4);
let mut f5p = f5;
f5p.frobenius_map(1);
f5p.frobenius_map_in_place(1);
let f6 = Self::exp_by_x(f5);
let mut f6p = f6;
f6p.frobenius_map(1);
f6p.frobenius_map_in_place(1);
let f7 = Self::exp_by_x(f6);
let mut f7p = f7;
f7p.frobenius_map(1);
f7p.frobenius_map_in_place(1);

// step 4
let f8p = Self::exp_by_x(f7p);
Expand Down
2 changes: 1 addition & 1 deletion ec/src/models/mnt4/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ impl<P: MNT4Config> MNT4<P> {
let elt_inv_clone = *elt_inv;

let mut elt_q = *elt;
elt_q.frobenius_map(1);
elt_q.frobenius_map_in_place(1);

let w1_part = elt_q.cyclotomic_exp(&P::FINAL_EXPONENT_LAST_CHUNK_1);
let w0_part = if P::FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG {
Expand Down
4 changes: 2 additions & 2 deletions ec/src/models/mnt6/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ impl<P: MNT6Config> MNT6<P> {
let elt_q3_over_elt = elt_q3 * elt_inv;
// alpha = elt^((q^3-1) * q)
let mut alpha = elt_q3_over_elt;
alpha.frobenius_map(1);
alpha.frobenius_map_in_place(1);
// beta = elt^((q^3-1)*(q+1)
alpha * &elt_q3_over_elt
}
Expand All @@ -189,7 +189,7 @@ impl<P: MNT6Config> MNT6<P> {
let elt_inv_clone = *elt_inv;

let mut elt_q = *elt;
elt_q.frobenius_map(1);
elt_q.frobenius_map_in_place(1);

let w1_part = elt_q.cyclotomic_exp(&P::FINAL_EXPONENT_LAST_CHUNK_1);
let w0_part = if P::FINAL_EXPONENT_LAST_CHUNK_W0_IS_NEG {
Expand Down
16 changes: 12 additions & 4 deletions ff/src/fields/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,11 +261,19 @@ pub trait Field:
sum
}

/// Exponentiates this element by a power of the base prime modulus via
/// the Frobenius automorphism.
fn frobenius_map(&mut self, power: usize);
/// Sets `self` to `self^s`, where `s = Self::BasePrimeField::MODULUS^power`.
/// This is also called the Frobenius automorphism.
fn frobenius_map_in_place(&mut self, power: usize);

/// Returns `self^s`, where `s = Self::BasePrimeField::MODULUS^power`.
/// This is also called the Frobenius automorphism.
fn frobenius_map(&self, power: usize) -> Self {
let mut this = *self;
this.frobenius_map_in_place(power);
this
}

/// Exponentiates this element by a number represented with `u64` limbs,
/// Returns `self^exp`, where `exp` is an integer represented with `u64` limbs,
/// least significant limb first.
#[must_use]
fn pow<S: AsRef<[u64]>>(&self, exp: S) -> Self {
Expand Down
12 changes: 6 additions & 6 deletions ff/src/fields/models/cubic_extension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,9 @@ impl<P: CubicExtConfig> CubicExtField<P> {
// indexed w.r.t. to BasePrimeField, we need to calculate the correct index.
let index_multiplier = P::BaseField::extension_degree() as usize;
let mut self_to_p = *self;
self_to_p.frobenius_map(index_multiplier);
self_to_p.frobenius_map_in_place(index_multiplier);
let mut self_to_p2 = *self;
self_to_p2.frobenius_map(2 * index_multiplier);
self_to_p2.frobenius_map_in_place(2 * index_multiplier);
self_to_p *= &(self_to_p2 * self);
assert!(self_to_p.c1.is_zero() && self_to_p.c2.is_zero());
self_to_p.c0
Expand Down Expand Up @@ -328,10 +328,10 @@ impl<P: CubicExtConfig> Field for CubicExtField<P> {
}
}

fn frobenius_map(&mut self, power: usize) {
self.c0.frobenius_map(power);
self.c1.frobenius_map(power);
self.c2.frobenius_map(power);
fn frobenius_map_in_place(&mut self, power: usize) {
self.c0.frobenius_map_in_place(power);
self.c1.frobenius_map_in_place(power);
self.c2.frobenius_map_in_place(power);

P::mul_base_field_by_frob_coeff(&mut self.c1, &mut self.c2, power);
}
Expand Down
2 changes: 1 addition & 1 deletion ff/src/fields/models/fp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ impl<P: FpConfig<N>, const N: usize> Field for Fp<P, N> {

/// The Frobenius map has no effect in a prime field.
#[inline]
fn frobenius_map(&mut self, _: usize) {}
fn frobenius_map_in_place(&mut self, _: usize) {}

#[inline]
fn legendre(&self) -> LegendreSymbol {
Expand Down
10 changes: 5 additions & 5 deletions ff/src/fields/models/quadratic_extension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,9 @@ impl<P: QuadExtConfig> QuadExtField<P> {
/// let norm = c.norm();
/// // We now compute the norm using the `a * a.conjugate()` approach.
/// // A Frobenius map sends an element of `Fp2` to one of its p_th powers:
/// // `a.frobenius_map(1) -> a^p` and `a^p` is also `a`'s Galois conjugate.
/// // `a.frobenius_map_in_place(1) -> a^p` and `a^p` is also `a`'s Galois conjugate.
/// let mut c_conjugate = c;
/// c_conjugate.frobenius_map(1);
/// c_conjugate.frobenius_map_in_place(1);
/// let norm2 = c * c_conjugate;
/// // Computing the norm of an `Fp2` element should result in an element
/// // in BaseField `Fp`, i.e. `c1 == 0`
Expand Down Expand Up @@ -354,9 +354,9 @@ impl<P: QuadExtConfig> Field for QuadExtField<P> {
}
}

fn frobenius_map(&mut self, power: usize) {
self.c0.frobenius_map(power);
self.c1.frobenius_map(power);
fn frobenius_map_in_place(&mut self, power: usize) {
self.c0.frobenius_map_in_place(power);
self.c1.frobenius_map_in_place(power);
P::mul_base_field_by_frob_coeff(&mut self.c1, power);
}

Expand Down
4 changes: 2 additions & 2 deletions test-curves/src/bls12_381/g2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,8 @@ pub fn p_power_endomorphism(p: &Affine<Config>) -> Affine<Config> {
// as implemented in the code as follows.

let mut res = *p;
res.x.frobenius_map(1);
res.y.frobenius_map(1);
res.x.frobenius_map_in_place(1);
res.y.frobenius_map_in_place(1);

let tmp_x = res.x;
res.x.c0 = -P_POWER_ENDOMORPHISM_COEFF_0.c1 * tmp_x.c1;
Expand Down
7 changes: 5 additions & 2 deletions test-templates/src/fields.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,16 @@ macro_rules! __test_field {
let a = <$field>::rand(&mut rng);

let mut a_0 = a;
a_0.frobenius_map(0);
a_0.frobenius_map_in_place(0);
assert_eq!(a, a_0);
assert_eq!(a, a.frobenius_map(0));

let mut a_q = a.pow(&characteristic);
for power in 1..max_power {
assert_eq!(a_q, a.frobenius_map(power));

let mut a_qi = a;
a_qi.frobenius_map(power);
a_qi.frobenius_map_in_place(power);
assert_eq!(a_qi, a_q, "failed on power {}", power);

a_q = a_q.pow(&characteristic);
Expand Down