From 68f500da0161d9f48edc753bc6356829f9e9c895 Mon Sep 17 00:00:00 2001 From: Pratyush Mishra Date: Mon, 12 Sep 2022 22:03:00 -0700 Subject: [PATCH] Optimizations to field and curve arithmetic --- bls12_377/src/fields/fq2.rs | 32 ++++++++++++++++++++++++++++---- bls12_377/src/fields/fq6.rs | 10 ++++++---- bls12_377/src/fields/tests.rs | 2 +- bls12_381/src/fields/fq2.rs | 19 +++++++++++++++++-- bls12_381/src/fields/fq6.rs | 11 +++++------ bls12_381/src/fields/tests.rs | 6 +++--- bn254/src/fields/fq2.rs | 4 ++-- bn254/src/fields/fq6.rs | 10 +++++++--- bn254/src/fields/tests.rs | 2 +- bw6_761/src/fields/fq3.rs | 6 ++---- cp6_782/src/fields/fq3.rs | 11 ++++++----- mnt6_298/src/fields/tests.rs | 4 ++-- mnt6_753/src/fields/tests.rs | 4 ++-- 13 files changed, 82 insertions(+), 39 deletions(-) diff --git a/bls12_377/src/fields/fq2.rs b/bls12_377/src/fields/fq2.rs index a6b2aa5..52f7e18 100644 --- a/bls12_377/src/fields/fq2.rs +++ b/bls12_377/src/fields/fq2.rs @@ -21,10 +21,34 @@ impl Fp2Config for Fq2Config { ]; #[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 - 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; } } diff --git a/bls12_377/src/fields/fq6.rs b/bls12_377/src/fields/fq6.rs index 834227a..bafab30 100644 --- a/bls12_377/src/fields/fq6.rs +++ b/bls12_377/src/fields/fq6.rs @@ -68,10 +68,12 @@ impl Fp6Config for Fq6Config { ]; #[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. - 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 } } diff --git a/bls12_377/src/fields/tests.rs b/bls12_377/src/fields/tests.rs index 9e7486c..44c22ec 100644 --- a/bls12_377/src/fields/tests.rs +++ b/bls12_377/src/fields/tests.rs @@ -136,7 +136,7 @@ fn test_fq2_legendre() { // i^2 = -1 let mut m1 = -Fq2::one(); 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()); } diff --git a/bls12_381/src/fields/fq2.rs b/bls12_381/src/fields/fq2.rs index 4963080..3abfb61 100644 --- a/bls12_381/src/fields/fq2.rs +++ b/bls12_381/src/fields/fq2.rs @@ -21,7 +21,22 @@ impl Fp2Config for Fq2Config { ]; #[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; } } diff --git a/bls12_381/src/fields/fq6.rs b/bls12_381/src/fields/fq6.rs index 0fd53d1..f7e4437 100644 --- a/bls12_381/src/fields/fq6.rs +++ b/bls12_381/src/fields/fq6.rs @@ -82,11 +82,10 @@ impl Fp6Config for Fq6Config { /// Multiply this element by the quadratic nonresidue 1 + u. /// 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 } } diff --git a/bls12_381/src/fields/tests.rs b/bls12_381/src/fields/tests.rs index ddeb3bd..5eaa19a 100644 --- a/bls12_381/src/fields/tests.rs +++ b/bls12_381/src/fields/tests.rs @@ -1718,7 +1718,7 @@ fn test_fq2_legendre() { // i^2 = -1 let mut m1 = -Fq2::one(); 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()); } @@ -1731,7 +1731,7 @@ fn test_fq2_mul_nonresidue() { for _ in 0..1000 { let mut a = Fq2::rand(&mut rng); let mut b = a; - a = Fq6Config::mul_fp2_by_nonresidue(&a); + Fq6Config::mul_fp2_by_nonresidue_in_place(&mut a); b.mul_assign(&nqr); assert_eq!(a, b); @@ -1747,7 +1747,7 @@ fn test_fq6_mul_nonresidue() { for _ in 0..1000 { let mut a = Fq6::rand(&mut rng); let mut b = a; - a = Fq12Config::mul_fp6_by_nonresidue(&a); + Fq12Config::mul_fp6_by_nonresidue_in_place(&mut a); b.mul_assign(&nqr); assert_eq!(a, b); diff --git a/bn254/src/fields/fq2.rs b/bn254/src/fields/fq2.rs index e0c80a5..b670e8c 100644 --- a/bn254/src/fields/fq2.rs +++ b/bn254/src/fields/fq2.rs @@ -21,7 +21,7 @@ impl Fp2Config for Fq2Config { ]; #[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() } } diff --git a/bn254/src/fields/fq6.rs b/bn254/src/fields/fq6.rs index ef30442..5f44380 100644 --- a/bn254/src/fields/fq6.rs +++ b/bn254/src/fields/fq6.rs @@ -90,12 +90,16 @@ impl Fp6Config for Fq6Config { ]; #[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) let mut f = *fe; 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; - Fq2::new(c0, c1) + *fe = Fq2::new(c0, c1); + fe } } diff --git a/bn254/src/fields/tests.rs b/bn254/src/fields/tests.rs index 56fb769..1515b67 100644 --- a/bn254/src/fields/tests.rs +++ b/bn254/src/fields/tests.rs @@ -139,7 +139,7 @@ fn test_fq2_legendre() { // i^2 = -1 let mut m1 = -Fq2::one(); 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()); } diff --git a/bw6_761/src/fields/fq3.rs b/bw6_761/src/fields/fq3.rs index fe18682..e7d2f14 100644 --- a/bw6_761/src/fields/fq3.rs +++ b/bw6_761/src/fields/fq3.rs @@ -82,9 +82,7 @@ impl Fp3Config for Fq3Config { ]; #[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() } } diff --git a/cp6_782/src/fields/fq3.rs b/cp6_782/src/fields/fq3.rs index 3511abe..a017113 100644 --- a/cp6_782/src/fields/fq3.rs +++ b/cp6_782/src/fields/fq3.rs @@ -77,11 +77,12 @@ impl Fp3Config for Fq3Config { ]; #[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 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 } } diff --git a/mnt6_298/src/fields/tests.rs b/mnt6_298/src/fields/tests.rs index 7d202e7..e28440d 100644 --- a/mnt6_298/src/fields/tests.rs +++ b/mnt6_298/src/fields/tests.rs @@ -12,9 +12,9 @@ test_field!(fq6; Fq6); #[test] fn test_fq3_more() { let mut rng = test_rng(); - let a: Fq3 = rng.gen(); + let mut a: Fq3 = rng.gen(); assert_eq!( a * Fq6Config::NONRESIDUE, - >::mul_base_field_by_nonresidue(&a) + *>::mul_base_field_by_nonresidue_in_place(&mut a) ); } diff --git a/mnt6_753/src/fields/tests.rs b/mnt6_753/src/fields/tests.rs index 46a6396..de96429 100644 --- a/mnt6_753/src/fields/tests.rs +++ b/mnt6_753/src/fields/tests.rs @@ -11,9 +11,9 @@ test_field!(fq6; Fq6); #[test] fn test_fq3_more() { let mut rng = test_rng(); - let a: Fq3 = rng.gen(); + let mut a: Fq3 = rng.gen(); assert_eq!( a * Fq6Config::NONRESIDUE, - >::mul_base_field_by_nonresidue(&a) + *>::mul_base_field_by_nonresidue_in_place(&mut a) ); }