mirror of
https://github.com/arnaucube/ark-curves-cherry-picked.git
synced 2026-01-08 06:51:32 +01:00
Optimizations to field and curve arithmetic
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
<Fp6ConfigWrapper<Fq6Config>>::mul_base_field_by_nonresidue(&a)
|
||||
*<Fp6ConfigWrapper<Fq6Config>>::mul_base_field_by_nonresidue_in_place(&mut a)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
<Fp6ConfigWrapper<Fq6Config>>::mul_base_field_by_nonresidue(&a)
|
||||
*<Fp6ConfigWrapper<Fq6Config>>::mul_base_field_by_nonresidue_in_place(&mut a)
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user