Browse Source

Optimizations to field and curve arithmetic

cherry-pick
Pratyush Mishra 2 years ago
parent
commit
68f500da01
13 changed files with 82 additions and 39 deletions
  1. +28
    -4
      bls12_377/src/fields/fq2.rs
  2. +6
    -4
      bls12_377/src/fields/fq6.rs
  3. +1
    -1
      bls12_377/src/fields/tests.rs
  4. +17
    -2
      bls12_381/src/fields/fq2.rs
  5. +5
    -6
      bls12_381/src/fields/fq6.rs
  6. +3
    -3
      bls12_381/src/fields/tests.rs
  7. +2
    -2
      bn254/src/fields/fq2.rs
  8. +7
    -3
      bn254/src/fields/fq6.rs
  9. +1
    -1
      bn254/src/fields/tests.rs
  10. +2
    -4
      bw6_761/src/fields/fq3.rs
  11. +6
    -5
      cp6_782/src/fields/fq3.rs
  12. +2
    -2
      mnt6_298/src/fields/tests.rs
  13. +2
    -2
      mnt6_753/src/fields/tests.rs

+ 28
- 4
bls12_377/src/fields/fq2.rs

@ -21,10 +21,34 @@ impl Fp2Config for Fq2Config {
]; ];
#[inline(always)] #[inline(always)]
fn mul_fp_by_nonresidue(fe: &Self::Fp) -> Self::Fp {
let original = fe;
let mut fe = -fe.double();
fn mul_fp_by_nonresidue_in_place(fe: &mut Self::Fp) -> &mut Self::Fp {
let original = *fe;
fe.neg_in_place();
fe.double_in_place(); fe.double_in_place();
fe - original
fe.double_in_place();
*fe -= original;
fe
}
#[inline(always)]
fn sub_and_mul_fp_by_nonresidue(y: &mut Self::Fp, x: &Self::Fp) {
let mut original = *y;
original += x;
y.double_in_place().double_in_place();
*y += original;
}
#[inline(always)]
fn add_and_mul_fp_by_nonresidue_plus_one(y: &mut Self::Fp, x: &Self::Fp) {
y.double_in_place().double_in_place().neg_in_place();
*y += x;
}
fn add_and_mul_fp_by_nonresidue_in_place(y: &mut Self::Fp, x: &Self::Fp) {
let mut original = *y;
original.double_in_place().double_in_place();
original += &*y;
*y = *x;
*y -= original;
} }
} }

+ 6
- 4
bls12_377/src/fields/fq6.rs

@ -68,10 +68,12 @@ impl Fp6Config for Fq6Config {
]; ];
#[inline(always)] #[inline(always)]
fn mul_fp2_by_nonresidue(fe: &Fq2) -> Fq2 {
fn mul_fp2_by_nonresidue_in_place(fe: &mut Fq2) -> &mut Fq2 {
// Karatsuba multiplication with constant other = u. // Karatsuba multiplication with constant other = u.
let c0 = Fq2Config::mul_fp_by_nonresidue(&fe.c1);
let c1 = fe.c0;
Fq2::new(c0, c1)
let old_c0 = fe.c0;
fe.c0 = fe.c1;
Fq2Config::mul_fp_by_nonresidue_in_place(&mut fe.c0);
fe.c1 = old_c0;
fe
} }
} }

+ 1
- 1
bls12_377/src/fields/tests.rs

@ -136,7 +136,7 @@ fn test_fq2_legendre() {
// i^2 = -1 // i^2 = -1
let mut m1 = -Fq2::one(); let mut m1 = -Fq2::one();
assert_eq!(QuadraticResidue, m1.legendre()); assert_eq!(QuadraticResidue, m1.legendre());
m1 = Fq6Config::mul_fp2_by_nonresidue(&m1);
Fq6Config::mul_fp2_by_nonresidue_in_place(&mut m1);
assert_eq!(QuadraticNonResidue, m1.legendre()); assert_eq!(QuadraticNonResidue, m1.legendre());
} }

+ 17
- 2
bls12_381/src/fields/fq2.rs

@ -21,7 +21,22 @@ impl Fp2Config for Fq2Config {
]; ];
#[inline(always)] #[inline(always)]
fn mul_fp_by_nonresidue(fp: &Self::Fp) -> Self::Fp {
-(*fp)
fn mul_fp_by_nonresidue_in_place(fp: &mut Self::Fp) -> &mut Self::Fp {
fp.neg_in_place()
}
#[inline(always)]
fn sub_and_mul_fp_by_nonresidue(y: &mut Self::Fp, x: &Self::Fp) {
*y += x;
}
#[inline(always)]
fn add_and_mul_fp_by_nonresidue_plus_one(y: &mut Self::Fp, x: &Self::Fp) {
*y = *x;
}
fn add_and_mul_fp_by_nonresidue_in_place(y: &mut Self::Fp, x: &Self::Fp) {
y.neg_in_place();
*y += x;
} }
} }

+ 5
- 6
bls12_381/src/fields/fq6.rs

@ -82,11 +82,10 @@ impl Fp6Config for Fq6Config {
/// Multiply this element by the quadratic nonresidue 1 + u. /// Multiply this element by the quadratic nonresidue 1 + u.
/// Make this generic. /// Make this generic.
fn mul_fp2_by_nonresidue(fe: &Fq2) -> Fq2 {
let mut copy = *fe;
let t0 = copy.c0;
copy.c0 -= &fe.c1;
copy.c1 += &t0;
copy
fn mul_fp2_by_nonresidue_in_place(fe: &mut Fq2) -> &mut Fq2 {
let t0 = fe.c0;
fe.c0 -= &fe.c1;
fe.c1 += &t0;
fe
} }
} }

+ 3
- 3
bls12_381/src/fields/tests.rs

@ -1718,7 +1718,7 @@ fn test_fq2_legendre() {
// i^2 = -1 // i^2 = -1
let mut m1 = -Fq2::one(); let mut m1 = -Fq2::one();
assert_eq!(QuadraticResidue, m1.legendre()); assert_eq!(QuadraticResidue, m1.legendre());
m1 = Fq6Config::mul_fp2_by_nonresidue(&m1);
Fq6Config::mul_fp2_by_nonresidue_in_place(&mut m1);
assert_eq!(QuadraticNonResidue, m1.legendre()); assert_eq!(QuadraticNonResidue, m1.legendre());
} }
@ -1731,7 +1731,7 @@ fn test_fq2_mul_nonresidue() {
for _ in 0..1000 { for _ in 0..1000 {
let mut a = Fq2::rand(&mut rng); let mut a = Fq2::rand(&mut rng);
let mut b = a; let mut b = a;
a = Fq6Config::mul_fp2_by_nonresidue(&a);
Fq6Config::mul_fp2_by_nonresidue_in_place(&mut a);
b.mul_assign(&nqr); b.mul_assign(&nqr);
assert_eq!(a, b); assert_eq!(a, b);
@ -1747,7 +1747,7 @@ fn test_fq6_mul_nonresidue() {
for _ in 0..1000 { for _ in 0..1000 {
let mut a = Fq6::rand(&mut rng); let mut a = Fq6::rand(&mut rng);
let mut b = a; let mut b = a;
a = Fq12Config::mul_fp6_by_nonresidue(&a);
Fq12Config::mul_fp6_by_nonresidue_in_place(&mut a);
b.mul_assign(&nqr); b.mul_assign(&nqr);
assert_eq!(a, b); assert_eq!(a, b);

+ 2
- 2
bn254/src/fields/fq2.rs

@ -21,7 +21,7 @@ impl Fp2Config for Fq2Config {
]; ];
#[inline(always)] #[inline(always)]
fn mul_fp_by_nonresidue(fe: &Self::Fp) -> Self::Fp {
-(*fe)
fn mul_fp_by_nonresidue_in_place(fe: &mut Self::Fp) -> &mut Self::Fp {
fe.neg_in_place()
} }
} }

+ 7
- 3
bn254/src/fields/fq6.rs

@ -90,12 +90,16 @@ impl Fp6Config for Fq6Config {
]; ];
#[inline(always)] #[inline(always)]
fn mul_fp2_by_nonresidue(fe: &Fq2) -> Fq2 {
fn mul_fp2_by_nonresidue_in_place(fe: &mut Fq2) -> &mut Fq2 {
// (c0+u*c1)*(9+u) = (9*c0-c1)+u*(9*c1+c0) // (c0+u*c1)*(9+u) = (9*c0-c1)+u*(9*c1+c0)
let mut f = *fe; let mut f = *fe;
f.double_in_place().double_in_place().double_in_place(); f.double_in_place().double_in_place().double_in_place();
let c0 = f.c0 + fe.c0 + Fq2Config::mul_fp_by_nonresidue(&fe.c1);
let mut c0 = fe.c1;
Fq2Config::mul_fp_by_nonresidue_in_place(&mut c0);
c0 += &f.c0;
c0 += &fe.c0;
let c1 = f.c1 + fe.c1 + fe.c0; let c1 = f.c1 + fe.c1 + fe.c0;
Fq2::new(c0, c1)
*fe = Fq2::new(c0, c1);
fe
} }
} }

+ 1
- 1
bn254/src/fields/tests.rs

@ -139,7 +139,7 @@ fn test_fq2_legendre() {
// i^2 = -1 // i^2 = -1
let mut m1 = -Fq2::one(); let mut m1 = -Fq2::one();
assert_eq!(QuadraticResidue, m1.legendre()); assert_eq!(QuadraticResidue, m1.legendre());
m1 = Fq6Config::mul_fp2_by_nonresidue(&m1);
Fq6Config::mul_fp2_by_nonresidue_in_place(&mut m1);
assert_eq!(QuadraticNonResidue, m1.legendre()); assert_eq!(QuadraticNonResidue, m1.legendre());
} }

+ 2
- 4
bw6_761/src/fields/fq3.rs

@ -82,9 +82,7 @@ impl Fp3Config for Fq3Config {
]; ];
#[inline(always)] #[inline(always)]
fn mul_fp_by_nonresidue(fe: &Self::Fp) -> Self::Fp {
let original = -(*fe);
let double = original + &original;
double + &double
fn mul_fp_by_nonresidue_in_place(fe: &mut Self::Fp) -> &mut Self::Fp {
fe.double_in_place().double_in_place()
} }
} }

+ 6
- 5
cp6_782/src/fields/fq3.rs

@ -77,11 +77,12 @@ impl Fp3Config for Fq3Config {
]; ];
#[inline(always)] #[inline(always)]
fn mul_fp_by_nonresidue(fe: &Self::Fp) -> Self::Fp {
fn mul_fp_by_nonresidue_in_place(fe: &mut Self::Fp) -> &mut Self::Fp {
let original = *fe; let original = *fe;
let mut four_fe = fe.double();
four_fe.double_in_place();
let eight_fe = four_fe.double();
eight_fe + &four_fe + &original
fe.double_in_place();
*fe += original;
fe.double_in_place().double_in_place();
*fe += original;
fe
} }
} }

+ 2
- 2
mnt6_298/src/fields/tests.rs

@ -12,9 +12,9 @@ test_field!(fq6; Fq6);
#[test] #[test]
fn test_fq3_more() { fn test_fq3_more() {
let mut rng = test_rng(); let mut rng = test_rng();
let a: Fq3 = rng.gen();
let mut a: Fq3 = rng.gen();
assert_eq!( assert_eq!(
a * Fq6Config::NONRESIDUE, a * Fq6Config::NONRESIDUE,
<Fp6ConfigWrapper<Fq6Config>>::mul_base_field_by_nonresidue(&a)
*<Fp6ConfigWrapper<Fq6Config>>::mul_base_field_by_nonresidue_in_place(&mut a)
); );
} }

+ 2
- 2
mnt6_753/src/fields/tests.rs

@ -11,9 +11,9 @@ test_field!(fq6; Fq6);
#[test] #[test]
fn test_fq3_more() { fn test_fq3_more() {
let mut rng = test_rng(); let mut rng = test_rng();
let a: Fq3 = rng.gen();
let mut a: Fq3 = rng.gen();
assert_eq!( assert_eq!(
a * Fq6Config::NONRESIDUE, a * Fq6Config::NONRESIDUE,
<Fp6ConfigWrapper<Fq6Config>>::mul_base_field_by_nonresidue(&a)
*<Fp6ConfigWrapper<Fq6Config>>::mul_base_field_by_nonresidue_in_place(&mut a)
); );
} }

Loading…
Cancel
Save