Move from CurveProjective::add_assign_mixed to traits

This commit is contained in:
Jack Grigg
2019-12-14 17:20:47 +00:00
parent d822e34e63
commit 9c485cc97e
9 changed files with 225 additions and 155 deletions

View File

@@ -70,7 +70,7 @@ pub(crate) mod g1 {
c.bench_function("G1::add_assign_mixed", |b| {
b.iter(|| {
let mut tmp = v[count].0;
tmp.add_assign_mixed(&v[count].1);
tmp.add_assign(&v[count].1);
count = (count + 1) % SAMPLES;
tmp
})
@@ -157,7 +157,7 @@ pub(crate) mod g2 {
c.bench_function("G2::add_assign_mixed", |b| {
b.iter(|| {
let mut tmp = v[count].0;
tmp.add_assign_mixed(&v[count].1);
tmp.add_assign(&v[count].1);
count = (count + 1) % SAMPLES;
tmp
})

View File

@@ -86,7 +86,7 @@ macro_rules! curve_impl {
for i in bits {
res.double();
if i {
res.add_assign_mixed(self)
res.add_assign(self)
}
}
res
@@ -355,6 +355,149 @@ macro_rules! curve_impl {
}
}
impl<'r> ::std::ops::Add<&'r <$projective as CurveProjective>::Affine> for $projective {
type Output = Self;
#[inline]
fn add(self, other: &<$projective as CurveProjective>::Affine) -> Self {
let mut ret = self;
ret.add_assign(other);
ret
}
}
impl ::std::ops::Add<<$projective as CurveProjective>::Affine> for $projective {
type Output = Self;
#[inline]
fn add(self, other: <$projective as CurveProjective>::Affine) -> Self {
self + &other
}
}
impl<'r> ::std::ops::AddAssign<&'r <$projective as CurveProjective>::Affine>
for $projective
{
fn add_assign(&mut self, other: &<$projective as CurveProjective>::Affine) {
if other.is_zero() {
return;
}
if self.is_zero() {
self.x = other.x;
self.y = other.y;
self.z = $basefield::one();
return;
}
// http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-madd-2007-bl
// Z1Z1 = Z1^2
let z1z1 = self.z.square();
// U2 = X2*Z1Z1
let mut u2 = other.x;
u2.mul_assign(&z1z1);
// S2 = Y2*Z1*Z1Z1
let mut s2 = other.y;
s2.mul_assign(&self.z);
s2.mul_assign(&z1z1);
if self.x == u2 && self.y == s2 {
// The two points are equal, so we double.
self.double();
} else {
// If we're adding -a and a together, self.z becomes zero as H becomes zero.
// H = U2-X1
let mut h = u2;
h.sub_assign(&self.x);
// HH = H^2
let hh = h.square();
// I = 4*HH
let i = hh.double().double();
// J = H*I
let mut j = h;
j.mul_assign(&i);
// r = 2*(S2-Y1)
let mut r = s2;
r.sub_assign(&self.y);
r = r.double();
// V = X1*I
let mut v = self.x;
v.mul_assign(&i);
// X3 = r^2 - J - 2*V
self.x = r.square();
self.x.sub_assign(&j);
self.x.sub_assign(&v);
self.x.sub_assign(&v);
// Y3 = r*(V-X3)-2*Y1*J
j.mul_assign(&self.y); // J = 2*Y1*J
j = j.double();
self.y = v;
self.y.sub_assign(&self.x);
self.y.mul_assign(&r);
self.y.sub_assign(&j);
// Z3 = (Z1+H)^2-Z1Z1-HH
self.z.add_assign(&h);
self.z = self.z.square();
self.z.sub_assign(&z1z1);
self.z.sub_assign(&hh);
}
}
}
impl ::std::ops::AddAssign<<$projective as CurveProjective>::Affine> for $projective {
#[inline]
fn add_assign(&mut self, other: <$projective as CurveProjective>::Affine) {
self.add_assign(&other);
}
}
impl<'r> ::std::ops::Sub<&'r <$projective as CurveProjective>::Affine> for $projective {
type Output = Self;
#[inline]
fn sub(self, other: &<$projective as CurveProjective>::Affine) -> Self {
let mut ret = self;
ret.sub_assign(other);
ret
}
}
impl ::std::ops::Sub<<$projective as CurveProjective>::Affine> for $projective {
type Output = Self;
#[inline]
fn sub(self, other: <$projective as CurveProjective>::Affine) -> Self {
self - &other
}
}
impl<'r> ::std::ops::SubAssign<&'r <$projective as CurveProjective>::Affine>
for $projective
{
fn sub_assign(&mut self, other: &<$projective as CurveProjective>::Affine) {
self.add_assign(&other.neg());
}
}
impl ::std::ops::SubAssign<<$projective as CurveProjective>::Affine> for $projective {
#[inline]
fn sub_assign(&mut self, other: <$projective as CurveProjective>::Affine) {
self.sub_assign(&other);
}
}
impl CurveProjective for $projective {
type Engine = Bls12;
type Scalar = $scalarfield;
@@ -507,83 +650,6 @@ macro_rules! curve_impl {
self.y.sub_assign(&c);
}
fn add_assign_mixed(&mut self, other: &Self::Affine) {
if other.is_zero() {
return;
}
if self.is_zero() {
self.x = other.x;
self.y = other.y;
self.z = $basefield::one();
return;
}
// http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-madd-2007-bl
// Z1Z1 = Z1^2
let z1z1 = self.z.square();
// U2 = X2*Z1Z1
let mut u2 = other.x;
u2.mul_assign(&z1z1);
// S2 = Y2*Z1*Z1Z1
let mut s2 = other.y;
s2.mul_assign(&self.z);
s2.mul_assign(&z1z1);
if self.x == u2 && self.y == s2 {
// The two points are equal, so we double.
self.double();
} else {
// If we're adding -a and a together, self.z becomes zero as H becomes zero.
// H = U2-X1
let mut h = u2;
h.sub_assign(&self.x);
// HH = H^2
let hh = h.square();
// I = 4*HH
let i = hh.double().double();
// J = H*I
let mut j = h;
j.mul_assign(&i);
// r = 2*(S2-Y1)
let mut r = s2;
r.sub_assign(&self.y);
r = r.double();
// V = X1*I
let mut v = self.x;
v.mul_assign(&i);
// X3 = r^2 - J - 2*V
self.x = r.square();
self.x.sub_assign(&j);
self.x.sub_assign(&v);
self.x.sub_assign(&v);
// Y3 = r*(V-X3)-2*Y1*J
j.mul_assign(&self.y); // J = 2*Y1*J
j = j.double();
self.y = v;
self.y.sub_assign(&self.x);
self.y.mul_assign(&r);
self.y.sub_assign(&j);
// Z3 = (Z1+H)^2-Z1Z1-HH
self.z.add_assign(&h);
self.z = self.z.square();
self.z.sub_assign(&z1z1);
self.z.sub_assign(&hh);
}
}
fn mul_assign<S: Into<<Self::Scalar as PrimeField>::Repr>>(&mut self, other: S) {
let mut res = Self::zero();
@@ -1334,7 +1400,7 @@ pub mod g1 {
assert_eq!(tmp1, c.into_projective());
let mut tmp2 = a.into_projective();
tmp2.add_assign_mixed(&b);
tmp2.add_assign(&b);
assert_eq!(tmp2.into_affine(), c);
assert_eq!(tmp2, c.into_projective());
}

View File

@@ -21,7 +21,7 @@ pub mod tests;
pub mod bls12_381;
use ff::{Field, PrimeField, ScalarEngine, SqrtField};
use group::{CurveAffine, CurveProjective};
use group::{CurveAffine, CurveOps, CurveOpsOwned, CurveProjective};
use subtle::CtOption;
/// An "engine" is a collection of types (fields, elliptic curve groups, etc.)
@@ -30,7 +30,9 @@ use subtle::CtOption;
pub trait Engine: ScalarEngine {
/// The projective representation of an element in G1.
type G1: CurveProjective<Engine = Self, Base = Self::Fq, Scalar = Self::Fr, Affine = Self::G1Affine>
+ From<Self::G1Affine>;
+ From<Self::G1Affine>
+ CurveOps<Self::G1Affine>
+ CurveOpsOwned<Self::G1Affine>;
/// The affine representation of an element in G1.
type G1Affine: PairingCurveAffine<
@@ -44,7 +46,9 @@ pub trait Engine: ScalarEngine {
/// The projective representation of an element in G2.
type G2: CurveProjective<Engine = Self, Base = Self::Fqe, Scalar = Self::Fr, Affine = Self::G2Affine>
+ From<Self::G2Affine>;
+ From<Self::G2Affine>
+ CurveOps<Self::G2Affine>
+ CurveOpsOwned<Self::G2Affine>;
/// The affine representation of an element in G2.
type G2Affine: PairingCurveAffine<