mirror of
https://github.com/Qortal/pirate-librustzcash.git
synced 2025-07-30 20:11:23 +00:00
Merge branch 'develop'
This commit is contained in:
@@ -21,8 +21,10 @@ byteorder = "1"
|
||||
ff = { version = "0.6", path = "../ff", features = ["derive"] }
|
||||
group = { version = "0.6", path = "../group" }
|
||||
rand_core = "0.5"
|
||||
subtle = "2.2.1"
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = "0.3"
|
||||
rand_xorshift = "0.2"
|
||||
|
||||
[features]
|
||||
@@ -30,5 +32,9 @@ unstable-features = ["expose-arith"]
|
||||
expose-arith = []
|
||||
default = []
|
||||
|
||||
[[bench]]
|
||||
name = "pairing_benches"
|
||||
harness = false
|
||||
|
||||
[badges]
|
||||
maintenance = { status = "actively-developed" }
|
||||
|
@@ -1,13 +1,14 @@
|
||||
mod g1 {
|
||||
pub(crate) mod g1 {
|
||||
use criterion::{criterion_group, Criterion};
|
||||
use rand_core::SeedableRng;
|
||||
use rand_xorshift::XorShiftRng;
|
||||
use std::ops::AddAssign;
|
||||
|
||||
use ff::Field;
|
||||
use group::CurveProjective;
|
||||
use pairing::bls12_381::*;
|
||||
|
||||
#[bench]
|
||||
fn bench_g1_mul_assign(b: &mut ::test::Bencher) {
|
||||
fn bench_g1_mul_assign(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -20,16 +21,17 @@ mod g1 {
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.mul_assign(v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
c.bench_function("G1::mul_assign", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.mul_assign(v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_g1_add_assign(b: &mut ::test::Bencher) {
|
||||
fn bench_g1_add_assign(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -42,16 +44,17 @@ mod g1 {
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.add_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
c.bench_function("G1::add_assign", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.add_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_g1_add_assign_mixed(b: &mut ::test::Bencher) {
|
||||
fn bench_g1_add_assign_mixed(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -64,25 +67,35 @@ mod g1 {
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.add_assign_mixed(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
c.bench_function("G1::add_assign_mixed", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.add_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
criterion_group!(
|
||||
benches,
|
||||
bench_g1_add_assign,
|
||||
bench_g1_add_assign_mixed,
|
||||
bench_g1_mul_assign,
|
||||
);
|
||||
}
|
||||
|
||||
mod g2 {
|
||||
pub(crate) mod g2 {
|
||||
use criterion::{criterion_group, Criterion};
|
||||
use rand_core::SeedableRng;
|
||||
use rand_xorshift::XorShiftRng;
|
||||
use std::ops::AddAssign;
|
||||
|
||||
use ff::Field;
|
||||
use group::CurveProjective;
|
||||
use pairing::bls12_381::*;
|
||||
|
||||
#[bench]
|
||||
fn bench_g2_mul_assign(b: &mut ::test::Bencher) {
|
||||
fn bench_g2_mul_assign(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -95,16 +108,17 @@ mod g2 {
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.mul_assign(v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
c.bench_function("G2::mul_assign", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.mul_assign(v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_g2_add_assign(b: &mut ::test::Bencher) {
|
||||
fn bench_g2_add_assign(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -117,16 +131,17 @@ mod g2 {
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.add_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
c.bench_function("G2::add_assign", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.add_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_g2_add_assign_mixed(b: &mut ::test::Bencher) {
|
||||
fn bench_g2_add_assign_mixed(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -139,11 +154,20 @@ mod g2 {
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.add_assign_mixed(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
c.bench_function("G2::add_assign_mixed", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.add_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
criterion_group!(
|
||||
benches,
|
||||
bench_g2_add_assign,
|
||||
bench_g2_add_assign_mixed,
|
||||
bench_g2_mul_assign,
|
||||
);
|
||||
}
|
||||
|
@@ -1,11 +1,12 @@
|
||||
use criterion::{criterion_group, Criterion};
|
||||
use rand_core::SeedableRng;
|
||||
use rand_xorshift::XorShiftRng;
|
||||
use std::ops::{AddAssign, MulAssign, Neg, SubAssign};
|
||||
|
||||
use ff::{Field, PrimeField, PrimeFieldRepr, SqrtField};
|
||||
use pairing::bls12_381::*;
|
||||
|
||||
#[bench]
|
||||
fn bench_fq_repr_add_nocarry(b: &mut ::test::Bencher) {
|
||||
fn bench_fq_repr_add_nocarry(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -27,16 +28,17 @@ fn bench_fq_repr_add_nocarry(b: &mut ::test::Bencher) {
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.add_nocarry(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
c.bench_function("FqRepr::add_nocarry", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.add_nocarry(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_fq_repr_sub_noborrow(b: &mut ::test::Bencher) {
|
||||
fn bench_fq_repr_sub_noborrow(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -57,16 +59,17 @@ fn bench_fq_repr_sub_noborrow(b: &mut ::test::Bencher) {
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.sub_noborrow(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
c.bench_function("FqRepr::sub_noborrow", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.sub_noborrow(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_fq_repr_num_bits(b: &mut ::test::Bencher) {
|
||||
fn bench_fq_repr_num_bits(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -79,15 +82,16 @@ fn bench_fq_repr_num_bits(b: &mut ::test::Bencher) {
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
let tmp = v[count].num_bits();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
c.bench_function("FqRepr::num_bits", |b| {
|
||||
b.iter(|| {
|
||||
let tmp = v[count].num_bits();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_fq_repr_mul2(b: &mut ::test::Bencher) {
|
||||
fn bench_fq_repr_mul2(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -100,16 +104,17 @@ fn bench_fq_repr_mul2(b: &mut ::test::Bencher) {
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count];
|
||||
tmp.mul2();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
c.bench_function("FqRepr::mul2", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count];
|
||||
tmp.mul2();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_fq_repr_div2(b: &mut ::test::Bencher) {
|
||||
fn bench_fq_repr_div2(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -122,16 +127,17 @@ fn bench_fq_repr_div2(b: &mut ::test::Bencher) {
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count];
|
||||
tmp.div2();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
c.bench_function("FqRepr::div2", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count];
|
||||
tmp.div2();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_fq_add_assign(b: &mut ::test::Bencher) {
|
||||
fn bench_fq_add_assign(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -144,16 +150,17 @@ fn bench_fq_add_assign(b: &mut ::test::Bencher) {
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.add_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
c.bench_function("Fq::add_assign", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.add_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_fq_sub_assign(b: &mut ::test::Bencher) {
|
||||
fn bench_fq_sub_assign(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -166,16 +173,17 @@ fn bench_fq_sub_assign(b: &mut ::test::Bencher) {
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.sub_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
c.bench_function("Fq::sub_assign", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.sub_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_fq_mul_assign(b: &mut ::test::Bencher) {
|
||||
fn bench_fq_mul_assign(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -188,16 +196,17 @@ fn bench_fq_mul_assign(b: &mut ::test::Bencher) {
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.mul_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
c.bench_function("Fq::mul_assign", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.mul_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_fq_square(b: &mut ::test::Bencher) {
|
||||
fn bench_fq_square(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -208,16 +217,16 @@ fn bench_fq_square(b: &mut ::test::Bencher) {
|
||||
let v: Vec<Fq> = (0..SAMPLES).map(|_| Fq::random(&mut rng)).collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count];
|
||||
tmp.square();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
c.bench_function("Fq::square", |b| {
|
||||
b.iter(|| {
|
||||
let tmp = v[count].square();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_fq_inverse(b: &mut ::test::Bencher) {
|
||||
fn bench_fq_invert(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -228,14 +237,15 @@ fn bench_fq_inverse(b: &mut ::test::Bencher) {
|
||||
let v: Vec<Fq> = (0..SAMPLES).map(|_| Fq::random(&mut rng)).collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
count = (count + 1) % SAMPLES;
|
||||
v[count].inverse()
|
||||
c.bench_function("Fq::invert", |b| {
|
||||
b.iter(|| {
|
||||
count = (count + 1) % SAMPLES;
|
||||
v[count].invert()
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_fq_negate(b: &mut ::test::Bencher) {
|
||||
fn bench_fq_neg(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -246,16 +256,16 @@ fn bench_fq_negate(b: &mut ::test::Bencher) {
|
||||
let v: Vec<Fq> = (0..SAMPLES).map(|_| Fq::random(&mut rng)).collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count];
|
||||
tmp.negate();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
c.bench_function("Fq::neg", |b| {
|
||||
b.iter(|| {
|
||||
let tmp = v[count].neg();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_fq_sqrt(b: &mut ::test::Bencher) {
|
||||
fn bench_fq_sqrt(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -264,22 +274,19 @@ fn bench_fq_sqrt(b: &mut ::test::Bencher) {
|
||||
]);
|
||||
|
||||
let v: Vec<Fq> = (0..SAMPLES)
|
||||
.map(|_| {
|
||||
let mut tmp = Fq::random(&mut rng);
|
||||
tmp.square();
|
||||
tmp
|
||||
})
|
||||
.map(|_| Fq::random(&mut rng).square())
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
count = (count + 1) % SAMPLES;
|
||||
v[count].sqrt()
|
||||
c.bench_function("Fq::sqrt", |b| {
|
||||
b.iter(|| {
|
||||
count = (count + 1) % SAMPLES;
|
||||
v[count].sqrt()
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_fq_into_repr(b: &mut ::test::Bencher) {
|
||||
fn bench_fq_into_repr(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -290,14 +297,15 @@ fn bench_fq_into_repr(b: &mut ::test::Bencher) {
|
||||
let v: Vec<Fq> = (0..SAMPLES).map(|_| Fq::random(&mut rng)).collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
count = (count + 1) % SAMPLES;
|
||||
v[count].into_repr()
|
||||
c.bench_function("Fq::into_repr", |b| {
|
||||
b.iter(|| {
|
||||
count = (count + 1) % SAMPLES;
|
||||
v[count].into_repr()
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_fq_from_repr(b: &mut ::test::Bencher) {
|
||||
fn bench_fq_from_repr(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -310,8 +318,28 @@ fn bench_fq_from_repr(b: &mut ::test::Bencher) {
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
count = (count + 1) % SAMPLES;
|
||||
Fq::from_repr(v[count])
|
||||
c.bench_function("Fq::from_repr", |b| {
|
||||
b.iter(|| {
|
||||
count = (count + 1) % SAMPLES;
|
||||
Fq::from_repr(v[count])
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
criterion_group!(
|
||||
benches,
|
||||
bench_fq_repr_add_nocarry,
|
||||
bench_fq_repr_sub_noborrow,
|
||||
bench_fq_repr_num_bits,
|
||||
bench_fq_repr_mul2,
|
||||
bench_fq_repr_div2,
|
||||
bench_fq_add_assign,
|
||||
bench_fq_sub_assign,
|
||||
bench_fq_mul_assign,
|
||||
bench_fq_square,
|
||||
bench_fq_invert,
|
||||
bench_fq_neg,
|
||||
bench_fq_sqrt,
|
||||
bench_fq_into_repr,
|
||||
bench_fq_from_repr,
|
||||
);
|
||||
|
@@ -1,11 +1,12 @@
|
||||
use criterion::{criterion_group, Criterion};
|
||||
use rand_core::SeedableRng;
|
||||
use rand_xorshift::XorShiftRng;
|
||||
use std::ops::{AddAssign, MulAssign, SubAssign};
|
||||
|
||||
use ff::Field;
|
||||
use pairing::bls12_381::*;
|
||||
|
||||
#[bench]
|
||||
fn bench_fq12_add_assign(b: &mut ::test::Bencher) {
|
||||
fn bench_fq12_add_assign(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -18,16 +19,17 @@ fn bench_fq12_add_assign(b: &mut ::test::Bencher) {
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.add_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
c.bench_function("Fq12::add_assign", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.add_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_fq12_sub_assign(b: &mut ::test::Bencher) {
|
||||
fn bench_fq12_sub_assign(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -40,16 +42,17 @@ fn bench_fq12_sub_assign(b: &mut ::test::Bencher) {
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.sub_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
c.bench_function("Fq12::sub_assign", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.sub_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_fq12_mul_assign(b: &mut ::test::Bencher) {
|
||||
fn bench_fq12_mul_assign(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -62,16 +65,17 @@ fn bench_fq12_mul_assign(b: &mut ::test::Bencher) {
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.mul_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
c.bench_function("Fq12::mul_assign", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.mul_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_fq12_squaring(b: &mut ::test::Bencher) {
|
||||
fn bench_fq12_squaring(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -82,16 +86,16 @@ fn bench_fq12_squaring(b: &mut ::test::Bencher) {
|
||||
let v: Vec<Fq12> = (0..SAMPLES).map(|_| Fq12::random(&mut rng)).collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count];
|
||||
tmp.square();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
c.bench_function("Fq12::square", |b| {
|
||||
b.iter(|| {
|
||||
let tmp = v[count].square();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_fq12_inverse(b: &mut ::test::Bencher) {
|
||||
fn bench_fq12_invert(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -102,9 +106,20 @@ fn bench_fq12_inverse(b: &mut ::test::Bencher) {
|
||||
let v: Vec<Fq12> = (0..SAMPLES).map(|_| Fq12::random(&mut rng)).collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
let tmp = v[count].inverse();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
c.bench_function("Fq12::invert", |b| {
|
||||
b.iter(|| {
|
||||
let tmp = v[count].invert();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
criterion_group!(
|
||||
benches,
|
||||
bench_fq12_add_assign,
|
||||
bench_fq12_sub_assign,
|
||||
bench_fq12_mul_assign,
|
||||
bench_fq12_squaring,
|
||||
bench_fq12_invert,
|
||||
);
|
||||
|
@@ -1,11 +1,12 @@
|
||||
use criterion::{criterion_group, Criterion};
|
||||
use rand_core::SeedableRng;
|
||||
use rand_xorshift::XorShiftRng;
|
||||
use std::ops::{AddAssign, MulAssign, SubAssign};
|
||||
|
||||
use ff::{Field, SqrtField};
|
||||
use pairing::bls12_381::*;
|
||||
|
||||
#[bench]
|
||||
fn bench_fq2_add_assign(b: &mut ::test::Bencher) {
|
||||
fn bench_fq2_add_assign(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -18,16 +19,17 @@ fn bench_fq2_add_assign(b: &mut ::test::Bencher) {
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.add_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
c.bench_function("Fq2::add_assign", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.add_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_fq2_sub_assign(b: &mut ::test::Bencher) {
|
||||
fn bench_fq2_sub_assign(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -40,16 +42,17 @@ fn bench_fq2_sub_assign(b: &mut ::test::Bencher) {
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.sub_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
c.bench_function("Fq2::sub_assign", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.sub_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_fq2_mul_assign(b: &mut ::test::Bencher) {
|
||||
fn bench_fq2_mul_assign(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -62,16 +65,17 @@ fn bench_fq2_mul_assign(b: &mut ::test::Bencher) {
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.mul_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
c.bench_function("Fq2::mul_assign", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.mul_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_fq2_squaring(b: &mut ::test::Bencher) {
|
||||
fn bench_fq2_squaring(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -82,16 +86,16 @@ fn bench_fq2_squaring(b: &mut ::test::Bencher) {
|
||||
let v: Vec<Fq2> = (0..SAMPLES).map(|_| Fq2::random(&mut rng)).collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count];
|
||||
tmp.square();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
c.bench_function("Fq2::square", |b| {
|
||||
b.iter(|| {
|
||||
let tmp = v[count].square();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_fq2_inverse(b: &mut ::test::Bencher) {
|
||||
fn bench_fq2_invert(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -102,15 +106,16 @@ fn bench_fq2_inverse(b: &mut ::test::Bencher) {
|
||||
let v: Vec<Fq2> = (0..SAMPLES).map(|_| Fq2::random(&mut rng)).collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
let tmp = v[count].inverse();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
c.bench_function("Fq2::invert", |b| {
|
||||
b.iter(|| {
|
||||
let tmp = v[count].invert();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_fq2_sqrt(b: &mut ::test::Bencher) {
|
||||
fn bench_fq2_sqrt(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -121,9 +126,21 @@ fn bench_fq2_sqrt(b: &mut ::test::Bencher) {
|
||||
let v: Vec<Fq2> = (0..SAMPLES).map(|_| Fq2::random(&mut rng)).collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
let tmp = v[count].sqrt();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
c.bench_function("Fq2::sqrt", |b| {
|
||||
b.iter(|| {
|
||||
let tmp = v[count].sqrt();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
criterion_group!(
|
||||
benches,
|
||||
bench_fq2_add_assign,
|
||||
bench_fq2_sub_assign,
|
||||
bench_fq2_mul_assign,
|
||||
bench_fq2_squaring,
|
||||
bench_fq2_invert,
|
||||
bench_fq2_sqrt,
|
||||
);
|
||||
|
@@ -1,11 +1,12 @@
|
||||
use criterion::{criterion_group, Criterion};
|
||||
use rand_core::SeedableRng;
|
||||
use rand_xorshift::XorShiftRng;
|
||||
use std::ops::{AddAssign, MulAssign, Neg, SubAssign};
|
||||
|
||||
use ff::{Field, PrimeField, PrimeFieldRepr, SqrtField};
|
||||
use pairing::bls12_381::*;
|
||||
|
||||
#[bench]
|
||||
fn bench_fr_repr_add_nocarry(b: &mut ::test::Bencher) {
|
||||
fn bench_fr_repr_add_nocarry(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -27,16 +28,17 @@ fn bench_fr_repr_add_nocarry(b: &mut ::test::Bencher) {
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.add_nocarry(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
c.bench_function("FrRepr::add_nocarry", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.add_nocarry(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_fr_repr_sub_noborrow(b: &mut ::test::Bencher) {
|
||||
fn bench_fr_repr_sub_noborrow(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -57,16 +59,17 @@ fn bench_fr_repr_sub_noborrow(b: &mut ::test::Bencher) {
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.sub_noborrow(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
c.bench_function("FrRepr::sub_noborrow", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.sub_noborrow(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_fr_repr_num_bits(b: &mut ::test::Bencher) {
|
||||
fn bench_fr_repr_num_bits(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -79,15 +82,16 @@ fn bench_fr_repr_num_bits(b: &mut ::test::Bencher) {
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
let tmp = v[count].num_bits();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
c.bench_function("FrRepr::num_bits", |b| {
|
||||
b.iter(|| {
|
||||
let tmp = v[count].num_bits();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_fr_repr_mul2(b: &mut ::test::Bencher) {
|
||||
fn bench_fr_repr_mul2(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -100,16 +104,17 @@ fn bench_fr_repr_mul2(b: &mut ::test::Bencher) {
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count];
|
||||
tmp.mul2();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
c.bench_function("FrRepr::mul2", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count];
|
||||
tmp.mul2();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_fr_repr_div2(b: &mut ::test::Bencher) {
|
||||
fn bench_fr_repr_div2(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -122,16 +127,17 @@ fn bench_fr_repr_div2(b: &mut ::test::Bencher) {
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count];
|
||||
tmp.div2();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
c.bench_function("FrRepr::div2", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count];
|
||||
tmp.div2();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_fr_add_assign(b: &mut ::test::Bencher) {
|
||||
fn bench_fr_add_assign(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -144,16 +150,17 @@ fn bench_fr_add_assign(b: &mut ::test::Bencher) {
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.add_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
c.bench_function("Fr::add_assign", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.add_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_fr_sub_assign(b: &mut ::test::Bencher) {
|
||||
fn bench_fr_sub_assign(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -166,16 +173,17 @@ fn bench_fr_sub_assign(b: &mut ::test::Bencher) {
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.sub_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
c.bench_function("Fr::sub_assign", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.sub_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_fr_mul_assign(b: &mut ::test::Bencher) {
|
||||
fn bench_fr_mul_assign(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -188,16 +196,17 @@ fn bench_fr_mul_assign(b: &mut ::test::Bencher) {
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.mul_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
c.bench_function("Fr::mul_assign", |b| {
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count].0;
|
||||
tmp.mul_assign(&v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_fr_square(b: &mut ::test::Bencher) {
|
||||
fn bench_fr_square(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -208,16 +217,16 @@ fn bench_fr_square(b: &mut ::test::Bencher) {
|
||||
let v: Vec<Fr> = (0..SAMPLES).map(|_| Fr::random(&mut rng)).collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count];
|
||||
tmp.square();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
c.bench_function("Fr::square", |b| {
|
||||
b.iter(|| {
|
||||
let tmp = v[count].square();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_fr_inverse(b: &mut ::test::Bencher) {
|
||||
fn bench_fr_invert(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -228,14 +237,15 @@ fn bench_fr_inverse(b: &mut ::test::Bencher) {
|
||||
let v: Vec<Fr> = (0..SAMPLES).map(|_| Fr::random(&mut rng)).collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
count = (count + 1) % SAMPLES;
|
||||
v[count].inverse()
|
||||
c.bench_function("Fr::invert", |b| {
|
||||
b.iter(|| {
|
||||
count = (count + 1) % SAMPLES;
|
||||
v[count].invert()
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_fr_negate(b: &mut ::test::Bencher) {
|
||||
fn bench_fr_neg(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -246,16 +256,16 @@ fn bench_fr_negate(b: &mut ::test::Bencher) {
|
||||
let v: Vec<Fr> = (0..SAMPLES).map(|_| Fr::random(&mut rng)).collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
let mut tmp = v[count];
|
||||
tmp.negate();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
c.bench_function("Fr::neg", |b| {
|
||||
b.iter(|| {
|
||||
let tmp = v[count].neg();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_fr_sqrt(b: &mut ::test::Bencher) {
|
||||
fn bench_fr_sqrt(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -264,22 +274,19 @@ fn bench_fr_sqrt(b: &mut ::test::Bencher) {
|
||||
]);
|
||||
|
||||
let v: Vec<Fr> = (0..SAMPLES)
|
||||
.map(|_| {
|
||||
let mut tmp = Fr::random(&mut rng);
|
||||
tmp.square();
|
||||
tmp
|
||||
})
|
||||
.map(|_| Fr::random(&mut rng).square())
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
count = (count + 1) % SAMPLES;
|
||||
v[count].sqrt()
|
||||
c.bench_function("Fr::sqrt", |b| {
|
||||
b.iter(|| {
|
||||
count = (count + 1) % SAMPLES;
|
||||
v[count].sqrt()
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_fr_into_repr(b: &mut ::test::Bencher) {
|
||||
fn bench_fr_into_repr(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -290,14 +297,15 @@ fn bench_fr_into_repr(b: &mut ::test::Bencher) {
|
||||
let v: Vec<Fr> = (0..SAMPLES).map(|_| Fr::random(&mut rng)).collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
count = (count + 1) % SAMPLES;
|
||||
v[count].into_repr()
|
||||
c.bench_function("Fr::into_repr", |b| {
|
||||
b.iter(|| {
|
||||
count = (count + 1) % SAMPLES;
|
||||
v[count].into_repr()
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_fr_from_repr(b: &mut ::test::Bencher) {
|
||||
fn bench_fr_from_repr(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -310,8 +318,28 @@ fn bench_fr_from_repr(b: &mut ::test::Bencher) {
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
count = (count + 1) % SAMPLES;
|
||||
Fr::from_repr(v[count])
|
||||
c.bench_function("Fr::from_repr", |b| {
|
||||
b.iter(|| {
|
||||
count = (count + 1) % SAMPLES;
|
||||
Fr::from_repr(v[count])
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
criterion_group!(
|
||||
benches,
|
||||
bench_fr_repr_add_nocarry,
|
||||
bench_fr_repr_sub_noborrow,
|
||||
bench_fr_repr_num_bits,
|
||||
bench_fr_repr_mul2,
|
||||
bench_fr_repr_div2,
|
||||
bench_fr_add_assign,
|
||||
bench_fr_sub_assign,
|
||||
bench_fr_mul_assign,
|
||||
bench_fr_square,
|
||||
bench_fr_invert,
|
||||
bench_fr_neg,
|
||||
bench_fr_sqrt,
|
||||
bench_fr_into_repr,
|
||||
bench_fr_from_repr,
|
||||
);
|
||||
|
@@ -1,9 +1,10 @@
|
||||
mod ec;
|
||||
mod fq;
|
||||
mod fq12;
|
||||
mod fq2;
|
||||
mod fr;
|
||||
pub(crate) mod ec;
|
||||
pub(crate) mod fq;
|
||||
pub(crate) mod fq12;
|
||||
pub(crate) mod fq2;
|
||||
pub(crate) mod fr;
|
||||
|
||||
use criterion::{criterion_group, Criterion};
|
||||
use rand_core::SeedableRng;
|
||||
use rand_xorshift::XorShiftRng;
|
||||
|
||||
@@ -11,8 +12,7 @@ use group::CurveProjective;
|
||||
use pairing::bls12_381::*;
|
||||
use pairing::{Engine, PairingCurveAffine};
|
||||
|
||||
#[bench]
|
||||
fn bench_pairing_g1_preparation(b: &mut ::test::Bencher) {
|
||||
fn bench_pairing_g1_preparation(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -23,15 +23,16 @@ fn bench_pairing_g1_preparation(b: &mut ::test::Bencher) {
|
||||
let v: Vec<G1> = (0..SAMPLES).map(|_| G1::random(&mut rng)).collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
let tmp = G1Affine::from(v[count]).prepare();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
c.bench_function("G1 preparation", |b| {
|
||||
b.iter(|| {
|
||||
let tmp = G1Affine::from(v[count]).prepare();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_pairing_g2_preparation(b: &mut ::test::Bencher) {
|
||||
fn bench_pairing_g2_preparation(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -42,15 +43,16 @@ fn bench_pairing_g2_preparation(b: &mut ::test::Bencher) {
|
||||
let v: Vec<G2> = (0..SAMPLES).map(|_| G2::random(&mut rng)).collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
let tmp = G2Affine::from(v[count]).prepare();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
c.bench_function("G2 preparation", |b| {
|
||||
b.iter(|| {
|
||||
let tmp = G2Affine::from(v[count]).prepare();
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_pairing_miller_loop(b: &mut ::test::Bencher) {
|
||||
fn bench_pairing_miller_loop(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -68,15 +70,16 @@ fn bench_pairing_miller_loop(b: &mut ::test::Bencher) {
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
let tmp = Bls12::miller_loop(&[(&v[count].0, &v[count].1)]);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
c.bench_function("Miller loop", |b| {
|
||||
b.iter(|| {
|
||||
let tmp = Bls12::miller_loop(&[(&v[count].0, &v[count].1)]);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_pairing_final_exponentiation(b: &mut ::test::Bencher) {
|
||||
fn bench_pairing_final_exponentiation(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -95,15 +98,16 @@ fn bench_pairing_final_exponentiation(b: &mut ::test::Bencher) {
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
let tmp = Bls12::final_exponentiation(&v[count]);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
c.bench_function("Final exponentiation", |b| {
|
||||
b.iter(|| {
|
||||
let tmp = Bls12::final_exponentiation(&v[count]);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_pairing_full(b: &mut ::test::Bencher) {
|
||||
fn bench_pairing_full(c: &mut Criterion) {
|
||||
const SAMPLES: usize = 1000;
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -116,9 +120,20 @@ fn bench_pairing_full(b: &mut ::test::Bencher) {
|
||||
.collect();
|
||||
|
||||
let mut count = 0;
|
||||
b.iter(|| {
|
||||
let tmp = Bls12::pairing(v[count].0, v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
c.bench_function("Full pairing", |b| {
|
||||
b.iter(|| {
|
||||
let tmp = Bls12::pairing(v[count].0, v[count].1);
|
||||
count = (count + 1) % SAMPLES;
|
||||
tmp
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
criterion_group!(
|
||||
benches,
|
||||
bench_pairing_g1_preparation,
|
||||
bench_pairing_g2_preparation,
|
||||
bench_pairing_miller_loop,
|
||||
bench_pairing_final_exponentiation,
|
||||
bench_pairing_full,
|
||||
);
|
||||
|
@@ -1,10 +1,12 @@
|
||||
#![feature(test)]
|
||||
|
||||
extern crate ff;
|
||||
extern crate group;
|
||||
extern crate pairing;
|
||||
extern crate rand_core;
|
||||
extern crate rand_xorshift;
|
||||
extern crate test;
|
||||
|
||||
use criterion::criterion_main;
|
||||
mod bls12_381;
|
||||
|
||||
criterion_main!(
|
||||
bls12_381::benches,
|
||||
bls12_381::ec::g1::benches,
|
||||
bls12_381::ec::g2::benches,
|
||||
bls12_381::fq::benches,
|
||||
bls12_381::fq12::benches,
|
||||
bls12_381::fq2::benches,
|
||||
bls12_381::fr::benches,
|
||||
);
|
||||
|
@@ -54,10 +54,8 @@ macro_rules! curve_impl {
|
||||
// are equal when (X * Z^2) = (X' * Z'^2)
|
||||
// and (Y * Z^3) = (Y' * Z'^3).
|
||||
|
||||
let mut z1 = self.z;
|
||||
z1.square();
|
||||
let mut z2 = other.z;
|
||||
z2.square();
|
||||
let mut z1 = self.z.square();
|
||||
let mut z2 = other.z.square();
|
||||
|
||||
let mut tmp1 = self.x;
|
||||
tmp1.mul_assign(&z2);
|
||||
@@ -88,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
|
||||
@@ -99,16 +97,14 @@ macro_rules! curve_impl {
|
||||
///
|
||||
/// If and only if `greatest` is set will the lexicographically
|
||||
/// largest y-coordinate be selected.
|
||||
fn get_point_from_x(x: $basefield, greatest: bool) -> Option<$affine> {
|
||||
fn get_point_from_x(x: $basefield, greatest: bool) -> CtOption<$affine> {
|
||||
// Compute x^3 + b
|
||||
let mut x3b = x;
|
||||
x3b.square();
|
||||
let mut x3b = x.square();
|
||||
x3b.mul_assign(&x);
|
||||
x3b.add_assign(&$affine::get_coeff_b());
|
||||
|
||||
x3b.sqrt().map(|y| {
|
||||
let mut negy = y;
|
||||
negy.negate();
|
||||
let negy = y.neg();
|
||||
|
||||
$affine {
|
||||
x: x,
|
||||
@@ -123,11 +119,9 @@ macro_rules! curve_impl {
|
||||
true
|
||||
} else {
|
||||
// Check that the point is on the curve
|
||||
let mut y2 = self.y;
|
||||
y2.square();
|
||||
let y2 = self.y.square();
|
||||
|
||||
let mut x3b = self.x;
|
||||
x3b.square();
|
||||
let mut x3b = self.x.square();
|
||||
x3b.mul_assign(&self.x);
|
||||
x3b.add_assign(&Self::get_coeff_b());
|
||||
|
||||
@@ -140,6 +134,19 @@ macro_rules! curve_impl {
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::ops::Neg for $affine {
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn neg(self) -> Self {
|
||||
let mut ret = self;
|
||||
if !ret.is_zero() {
|
||||
ret.y = ret.y.neg();
|
||||
}
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
impl CurveAffine for $affine {
|
||||
type Engine = Bls12;
|
||||
type Scalar = $scalarfield;
|
||||
@@ -169,12 +176,6 @@ macro_rules! curve_impl {
|
||||
self.mul_bits(bits)
|
||||
}
|
||||
|
||||
fn negate(&mut self) {
|
||||
if !self.is_zero() {
|
||||
self.y.negate();
|
||||
}
|
||||
}
|
||||
|
||||
fn into_projective(&self) -> $projective {
|
||||
(*self).into()
|
||||
}
|
||||
@@ -194,6 +195,309 @@ macro_rules! curve_impl {
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::ops::Neg for $projective {
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn neg(self) -> Self {
|
||||
let mut ret = self;
|
||||
if !ret.is_zero() {
|
||||
ret.y = ret.y.neg();
|
||||
}
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> ::std::ops::Add<&'r $projective> for $projective {
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn add(self, other: &Self) -> Self {
|
||||
let mut ret = self;
|
||||
ret.add_assign(other);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::ops::Add for $projective {
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn add(self, other: Self) -> Self {
|
||||
self + &other
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> ::std::ops::AddAssign<&'r $projective> for $projective {
|
||||
fn add_assign(&mut self, other: &Self) {
|
||||
if self.is_zero() {
|
||||
*self = *other;
|
||||
return;
|
||||
}
|
||||
|
||||
if other.is_zero() {
|
||||
return;
|
||||
}
|
||||
|
||||
// http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl
|
||||
|
||||
// Z1Z1 = Z1^2
|
||||
let z1z1 = self.z.square();
|
||||
|
||||
// Z2Z2 = Z2^2
|
||||
let z2z2 = other.z.square();
|
||||
|
||||
// U1 = X1*Z2Z2
|
||||
let mut u1 = self.x;
|
||||
u1.mul_assign(&z2z2);
|
||||
|
||||
// U2 = X2*Z1Z1
|
||||
let mut u2 = other.x;
|
||||
u2.mul_assign(&z1z1);
|
||||
|
||||
// S1 = Y1*Z2*Z2Z2
|
||||
let mut s1 = self.y;
|
||||
s1.mul_assign(&other.z);
|
||||
s1.mul_assign(&z2z2);
|
||||
|
||||
// S2 = Y2*Z1*Z1Z1
|
||||
let mut s2 = other.y;
|
||||
s2.mul_assign(&self.z);
|
||||
s2.mul_assign(&z1z1);
|
||||
|
||||
if u1 == u2 && s1 == 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-U1
|
||||
let mut h = u2;
|
||||
h.sub_assign(&u1);
|
||||
|
||||
// I = (2*H)^2
|
||||
let i = h.double().square();
|
||||
|
||||
// J = H*I
|
||||
let mut j = h;
|
||||
j.mul_assign(&i);
|
||||
|
||||
// r = 2*(S2-S1)
|
||||
let mut r = s2;
|
||||
r.sub_assign(&s1);
|
||||
r = r.double();
|
||||
|
||||
// V = U1*I
|
||||
let mut v = u1;
|
||||
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*S1*J
|
||||
self.y = v;
|
||||
self.y.sub_assign(&self.x);
|
||||
self.y.mul_assign(&r);
|
||||
s1.mul_assign(&j); // S1 = S1 * J * 2
|
||||
s1 = s1.double();
|
||||
self.y.sub_assign(&s1);
|
||||
|
||||
// Z3 = ((Z1+Z2)^2 - Z1Z1 - Z2Z2)*H
|
||||
self.z.add_assign(&other.z);
|
||||
self.z = self.z.square();
|
||||
self.z.sub_assign(&z1z1);
|
||||
self.z.sub_assign(&z2z2);
|
||||
self.z.mul_assign(&h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::ops::AddAssign for $projective {
|
||||
#[inline]
|
||||
fn add_assign(&mut self, other: Self) {
|
||||
self.add_assign(&other);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> ::std::ops::Sub<&'r $projective> for $projective {
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn sub(self, other: &Self) -> Self {
|
||||
let mut ret = self;
|
||||
ret.sub_assign(other);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::ops::Sub for $projective {
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
fn sub(self, other: Self) -> Self {
|
||||
self - &other
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> ::std::ops::SubAssign<&'r $projective> for $projective {
|
||||
fn sub_assign(&mut self, other: &Self) {
|
||||
self.add_assign(&other.neg());
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::ops::SubAssign for $projective {
|
||||
#[inline]
|
||||
fn sub_assign(&mut self, other: Self) {
|
||||
self.sub_assign(&other);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -205,8 +509,9 @@ macro_rules! curve_impl {
|
||||
let x = $basefield::random(rng);
|
||||
let greatest = rng.next_u32() % 2 != 0;
|
||||
|
||||
if let Some(p) = $affine::get_point_from_x(x, greatest) {
|
||||
let p = p.scale_by_cofactor();
|
||||
let p = $affine::get_point_from_x(x, greatest);
|
||||
if p.is_some().into() {
|
||||
let p = p.unwrap().scale_by_cofactor();
|
||||
|
||||
if !p.is_zero() {
|
||||
return p;
|
||||
@@ -257,7 +562,7 @@ macro_rules! curve_impl {
|
||||
}
|
||||
|
||||
// Invert `tmp`.
|
||||
tmp = tmp.inverse().unwrap(); // Guaranteed to be nonzero.
|
||||
tmp = tmp.invert().unwrap(); // Guaranteed to be nonzero.
|
||||
|
||||
// Second pass: iterate backwards to compute inverses
|
||||
for (g, s) in v
|
||||
@@ -284,8 +589,7 @@ macro_rules! curve_impl {
|
||||
|
||||
// Perform affine transformations
|
||||
for g in v.iter_mut().filter(|g| !g.is_normalized()) {
|
||||
let mut z = g.z; // 1/z
|
||||
z.square(); // 1/z^2
|
||||
let mut z = g.z.square(); // 1/z^2
|
||||
g.x.mul_assign(&z); // x/z^2
|
||||
z.mul_assign(&g.z); // 1/z^3
|
||||
g.y.mul_assign(&z); // y/z^3
|
||||
@@ -306,37 +610,32 @@ macro_rules! curve_impl {
|
||||
// http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l
|
||||
|
||||
// A = X1^2
|
||||
let mut a = self.x;
|
||||
a.square();
|
||||
let a = self.x.square();
|
||||
|
||||
// B = Y1^2
|
||||
let mut b = self.y;
|
||||
b.square();
|
||||
let b = self.y.square();
|
||||
|
||||
// C = B^2
|
||||
let mut c = b;
|
||||
c.square();
|
||||
let mut c = b.square();
|
||||
|
||||
// D = 2*((X1+B)2-A-C)
|
||||
let mut d = self.x;
|
||||
d.add_assign(&b);
|
||||
d.square();
|
||||
d = d.square();
|
||||
d.sub_assign(&a);
|
||||
d.sub_assign(&c);
|
||||
d.double();
|
||||
d = d.double();
|
||||
|
||||
// E = 3*A
|
||||
let mut e = a;
|
||||
e.double();
|
||||
let mut e = a.double();
|
||||
e.add_assign(&a);
|
||||
|
||||
// F = E^2
|
||||
let mut f = e;
|
||||
f.square();
|
||||
let f = e.square();
|
||||
|
||||
// Z3 = 2*Y1*Z1
|
||||
self.z.mul_assign(&self.y);
|
||||
self.z.double();
|
||||
self.z = self.z.double();
|
||||
|
||||
// X3 = F-2*D
|
||||
self.x = f;
|
||||
@@ -347,190 +646,10 @@ macro_rules! curve_impl {
|
||||
self.y = d;
|
||||
self.y.sub_assign(&self.x);
|
||||
self.y.mul_assign(&e);
|
||||
c.double();
|
||||
c.double();
|
||||
c.double();
|
||||
c = c.double().double().double();
|
||||
self.y.sub_assign(&c);
|
||||
}
|
||||
|
||||
fn add_assign(&mut self, other: &Self) {
|
||||
if self.is_zero() {
|
||||
*self = *other;
|
||||
return;
|
||||
}
|
||||
|
||||
if other.is_zero() {
|
||||
return;
|
||||
}
|
||||
|
||||
// http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl
|
||||
|
||||
// Z1Z1 = Z1^2
|
||||
let mut z1z1 = self.z;
|
||||
z1z1.square();
|
||||
|
||||
// Z2Z2 = Z2^2
|
||||
let mut z2z2 = other.z;
|
||||
z2z2.square();
|
||||
|
||||
// U1 = X1*Z2Z2
|
||||
let mut u1 = self.x;
|
||||
u1.mul_assign(&z2z2);
|
||||
|
||||
// U2 = X2*Z1Z1
|
||||
let mut u2 = other.x;
|
||||
u2.mul_assign(&z1z1);
|
||||
|
||||
// S1 = Y1*Z2*Z2Z2
|
||||
let mut s1 = self.y;
|
||||
s1.mul_assign(&other.z);
|
||||
s1.mul_assign(&z2z2);
|
||||
|
||||
// S2 = Y2*Z1*Z1Z1
|
||||
let mut s2 = other.y;
|
||||
s2.mul_assign(&self.z);
|
||||
s2.mul_assign(&z1z1);
|
||||
|
||||
if u1 == u2 && s1 == 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-U1
|
||||
let mut h = u2;
|
||||
h.sub_assign(&u1);
|
||||
|
||||
// I = (2*H)^2
|
||||
let mut i = h;
|
||||
i.double();
|
||||
i.square();
|
||||
|
||||
// J = H*I
|
||||
let mut j = h;
|
||||
j.mul_assign(&i);
|
||||
|
||||
// r = 2*(S2-S1)
|
||||
let mut r = s2;
|
||||
r.sub_assign(&s1);
|
||||
r.double();
|
||||
|
||||
// V = U1*I
|
||||
let mut v = u1;
|
||||
v.mul_assign(&i);
|
||||
|
||||
// X3 = r^2 - J - 2*V
|
||||
self.x = r;
|
||||
self.x.square();
|
||||
self.x.sub_assign(&j);
|
||||
self.x.sub_assign(&v);
|
||||
self.x.sub_assign(&v);
|
||||
|
||||
// Y3 = r*(V - X3) - 2*S1*J
|
||||
self.y = v;
|
||||
self.y.sub_assign(&self.x);
|
||||
self.y.mul_assign(&r);
|
||||
s1.mul_assign(&j); // S1 = S1 * J * 2
|
||||
s1.double();
|
||||
self.y.sub_assign(&s1);
|
||||
|
||||
// Z3 = ((Z1+Z2)^2 - Z1Z1 - Z2Z2)*H
|
||||
self.z.add_assign(&other.z);
|
||||
self.z.square();
|
||||
self.z.sub_assign(&z1z1);
|
||||
self.z.sub_assign(&z2z2);
|
||||
self.z.mul_assign(&h);
|
||||
}
|
||||
}
|
||||
|
||||
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 mut z1z1 = self.z;
|
||||
z1z1.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 mut hh = h;
|
||||
hh.square();
|
||||
|
||||
// I = 4*HH
|
||||
let mut i = hh;
|
||||
i.double();
|
||||
i.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.double();
|
||||
|
||||
// V = X1*I
|
||||
let mut v = self.x;
|
||||
v.mul_assign(&i);
|
||||
|
||||
// X3 = r^2 - J - 2*V
|
||||
self.x = r;
|
||||
self.x.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.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.square();
|
||||
self.z.sub_assign(&z1z1);
|
||||
self.z.sub_assign(&hh);
|
||||
}
|
||||
}
|
||||
|
||||
fn negate(&mut self) {
|
||||
if !self.is_zero() {
|
||||
self.y.negate()
|
||||
}
|
||||
}
|
||||
|
||||
fn mul_assign<S: Into<<Self::Scalar as PrimeField>::Repr>>(&mut self, other: S) {
|
||||
let mut res = Self::zero();
|
||||
|
||||
@@ -544,7 +663,7 @@ macro_rules! curve_impl {
|
||||
}
|
||||
|
||||
if i {
|
||||
res.add_assign(self);
|
||||
res.add_assign(&*self);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -595,9 +714,8 @@ macro_rules! curve_impl {
|
||||
}
|
||||
} else {
|
||||
// Z is nonzero, so it must have an inverse in a field.
|
||||
let zinv = p.z.inverse().unwrap();
|
||||
let mut zinv_powered = zinv;
|
||||
zinv_powered.square();
|
||||
let zinv = p.z.invert().unwrap();
|
||||
let mut zinv_powered = zinv.square();
|
||||
|
||||
// X/Z^2
|
||||
let mut x = p.x;
|
||||
@@ -627,6 +745,8 @@ pub mod g1 {
|
||||
use group::{CurveAffine, CurveProjective, EncodedPoint, GroupDecodingError};
|
||||
use rand_core::RngCore;
|
||||
use std::fmt;
|
||||
use std::ops::{AddAssign, MulAssign, Neg, SubAssign};
|
||||
use subtle::CtOption;
|
||||
|
||||
curve_impl!(
|
||||
"G1",
|
||||
@@ -831,7 +951,12 @@ pub mod g1 {
|
||||
let x = Fq::from_repr(x)
|
||||
.map_err(|e| GroupDecodingError::CoordinateDecodingError("x coordinate", e))?;
|
||||
|
||||
G1Affine::get_point_from_x(x, greatest).ok_or(GroupDecodingError::NotOnCurve)
|
||||
let ret = G1Affine::get_point_from_x(x, greatest);
|
||||
if ret.is_some().into() {
|
||||
Ok(ret.unwrap())
|
||||
} else {
|
||||
Err(GroupDecodingError::NotOnCurve)
|
||||
}
|
||||
}
|
||||
}
|
||||
fn from_affine(affine: G1Affine) -> Self {
|
||||
@@ -848,8 +973,7 @@ pub mod g1 {
|
||||
affine.x.into_repr().write_be(&mut writer).unwrap();
|
||||
}
|
||||
|
||||
let mut negy = affine.y;
|
||||
negy.negate();
|
||||
let negy = affine.y.neg();
|
||||
|
||||
// Set the third most significant bit if the correct y-coordinate
|
||||
// is lexicographically largest.
|
||||
@@ -940,15 +1064,15 @@ pub mod g1 {
|
||||
let mut i = 0;
|
||||
loop {
|
||||
// y^2 = x^3 + b
|
||||
let mut rhs = x;
|
||||
rhs.square();
|
||||
let mut rhs = x.square();
|
||||
rhs.mul_assign(&x);
|
||||
rhs.add_assign(&G1Affine::get_coeff_b());
|
||||
|
||||
if let Some(y) = rhs.sqrt() {
|
||||
let y = rhs.sqrt();
|
||||
if y.is_some().into() {
|
||||
let y = y.unwrap();
|
||||
let yrepr = y.into_repr();
|
||||
let mut negy = y;
|
||||
negy.negate();
|
||||
let negy = y.neg();
|
||||
let negyrepr = negy.into_repr();
|
||||
|
||||
let p = G1Affine {
|
||||
@@ -1276,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());
|
||||
}
|
||||
@@ -1296,6 +1420,8 @@ pub mod g2 {
|
||||
use group::{CurveAffine, CurveProjective, EncodedPoint, GroupDecodingError};
|
||||
use rand_core::RngCore;
|
||||
use std::fmt;
|
||||
use std::ops::{AddAssign, MulAssign, Neg, SubAssign};
|
||||
use subtle::CtOption;
|
||||
|
||||
curve_impl!(
|
||||
"G2",
|
||||
@@ -1524,7 +1650,12 @@ pub mod g2 {
|
||||
})?,
|
||||
};
|
||||
|
||||
G2Affine::get_point_from_x(x, greatest).ok_or(GroupDecodingError::NotOnCurve)
|
||||
let ret = G2Affine::get_point_from_x(x, greatest);
|
||||
if ret.is_some().into() {
|
||||
Ok(ret.unwrap())
|
||||
} else {
|
||||
Err(GroupDecodingError::NotOnCurve)
|
||||
}
|
||||
}
|
||||
}
|
||||
fn from_affine(affine: G2Affine) -> Self {
|
||||
@@ -1542,8 +1673,7 @@ pub mod g2 {
|
||||
affine.x.c0.into_repr().write_be(&mut writer).unwrap();
|
||||
}
|
||||
|
||||
let mut negy = affine.y;
|
||||
negy.negate();
|
||||
let negy = affine.y.neg();
|
||||
|
||||
// Set the third most significant bit if the correct y-coordinate
|
||||
// is lexicographically largest.
|
||||
@@ -1646,14 +1776,14 @@ pub mod g2 {
|
||||
let mut i = 0;
|
||||
loop {
|
||||
// y^2 = x^3 + b
|
||||
let mut rhs = x;
|
||||
rhs.square();
|
||||
let mut rhs = x.square();
|
||||
rhs.mul_assign(&x);
|
||||
rhs.add_assign(&G2Affine::get_coeff_b());
|
||||
|
||||
if let Some(y) = rhs.sqrt() {
|
||||
let mut negy = y;
|
||||
negy.negate();
|
||||
let y = rhs.sqrt();
|
||||
if y.is_some().into() {
|
||||
let y = y.unwrap();
|
||||
let negy = y.neg();
|
||||
|
||||
let p = G2Affine {
|
||||
x,
|
||||
|
@@ -1,5 +1,9 @@
|
||||
use super::fq2::Fq2;
|
||||
use ff::{Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr};
|
||||
use std::ops::{AddAssign, MulAssign, SubAssign};
|
||||
|
||||
#[cfg(test)]
|
||||
use std::ops::Neg;
|
||||
|
||||
// B coefficient of BLS12-381 curve, 4.
|
||||
pub const B_COEFF: Fq = Fq(FqRepr([
|
||||
@@ -454,14 +458,14 @@ fn test_b_coeff() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::cognitive_complexity)]
|
||||
fn test_frob_coeffs() {
|
||||
let mut nqr = Fq::one();
|
||||
nqr.negate();
|
||||
let nqr = Fq::one().neg();
|
||||
|
||||
assert_eq!(FROBENIUS_COEFF_FQ2_C1[0], Fq::one());
|
||||
assert_eq!(
|
||||
FROBENIUS_COEFF_FQ2_C1[1],
|
||||
nqr.pow([
|
||||
nqr.pow_vartime([
|
||||
0xdcff7fffffffd555,
|
||||
0xf55ffff58a9ffff,
|
||||
0xb39869507b587b12,
|
||||
@@ -479,7 +483,7 @@ fn test_frob_coeffs() {
|
||||
assert_eq!(FROBENIUS_COEFF_FQ6_C1[0], Fq2::one());
|
||||
assert_eq!(
|
||||
FROBENIUS_COEFF_FQ6_C1[1],
|
||||
nqr.pow([
|
||||
nqr.pow_vartime([
|
||||
0x9354ffffffffe38e,
|
||||
0xa395554e5c6aaaa,
|
||||
0xcd104635a790520c,
|
||||
@@ -490,7 +494,7 @@ fn test_frob_coeffs() {
|
||||
);
|
||||
assert_eq!(
|
||||
FROBENIUS_COEFF_FQ6_C1[2],
|
||||
nqr.pow([
|
||||
nqr.pow_vartime([
|
||||
0xb78e0000097b2f68,
|
||||
0xd44f23b47cbd64e3,
|
||||
0x5cb9668120b069a9,
|
||||
@@ -507,7 +511,7 @@ fn test_frob_coeffs() {
|
||||
);
|
||||
assert_eq!(
|
||||
FROBENIUS_COEFF_FQ6_C1[3],
|
||||
nqr.pow([
|
||||
nqr.pow_vartime([
|
||||
0xdbc6fcd6f35b9e06,
|
||||
0x997dead10becd6aa,
|
||||
0x9dbbd24c17206460,
|
||||
@@ -530,7 +534,7 @@ fn test_frob_coeffs() {
|
||||
);
|
||||
assert_eq!(
|
||||
FROBENIUS_COEFF_FQ6_C1[4],
|
||||
nqr.pow([
|
||||
nqr.pow_vartime([
|
||||
0x4649add3c71c6d90,
|
||||
0x43caa6528972a865,
|
||||
0xcda8445bbaaa0fbb,
|
||||
@@ -559,7 +563,7 @@ fn test_frob_coeffs() {
|
||||
);
|
||||
assert_eq!(
|
||||
FROBENIUS_COEFF_FQ6_C1[5],
|
||||
nqr.pow([
|
||||
nqr.pow_vartime([
|
||||
0xf896f792732eb2be,
|
||||
0x49c86a6d1dc593a1,
|
||||
0xe5b31e94581f91c3,
|
||||
@@ -596,7 +600,7 @@ fn test_frob_coeffs() {
|
||||
assert_eq!(FROBENIUS_COEFF_FQ6_C2[0], Fq2::one());
|
||||
assert_eq!(
|
||||
FROBENIUS_COEFF_FQ6_C2[1],
|
||||
nqr.pow([
|
||||
nqr.pow_vartime([
|
||||
0x26a9ffffffffc71c,
|
||||
0x1472aaa9cb8d5555,
|
||||
0x9a208c6b4f20a418,
|
||||
@@ -607,7 +611,7 @@ fn test_frob_coeffs() {
|
||||
);
|
||||
assert_eq!(
|
||||
FROBENIUS_COEFF_FQ6_C2[2],
|
||||
nqr.pow([
|
||||
nqr.pow_vartime([
|
||||
0x6f1c000012f65ed0,
|
||||
0xa89e4768f97ac9c7,
|
||||
0xb972cd024160d353,
|
||||
@@ -624,7 +628,7 @@ fn test_frob_coeffs() {
|
||||
);
|
||||
assert_eq!(
|
||||
FROBENIUS_COEFF_FQ6_C2[3],
|
||||
nqr.pow([
|
||||
nqr.pow_vartime([
|
||||
0xb78df9ade6b73c0c,
|
||||
0x32fbd5a217d9ad55,
|
||||
0x3b77a4982e40c8c1,
|
||||
@@ -647,7 +651,7 @@ fn test_frob_coeffs() {
|
||||
);
|
||||
assert_eq!(
|
||||
FROBENIUS_COEFF_FQ6_C2[4],
|
||||
nqr.pow([
|
||||
nqr.pow_vartime([
|
||||
0x8c935ba78e38db20,
|
||||
0x87954ca512e550ca,
|
||||
0x9b5088b775541f76,
|
||||
@@ -676,7 +680,7 @@ fn test_frob_coeffs() {
|
||||
);
|
||||
assert_eq!(
|
||||
FROBENIUS_COEFF_FQ6_C2[5],
|
||||
nqr.pow([
|
||||
nqr.pow_vartime([
|
||||
0xf12def24e65d657c,
|
||||
0x9390d4da3b8b2743,
|
||||
0xcb663d28b03f2386,
|
||||
@@ -713,7 +717,7 @@ fn test_frob_coeffs() {
|
||||
assert_eq!(FROBENIUS_COEFF_FQ12_C1[0], Fq2::one());
|
||||
assert_eq!(
|
||||
FROBENIUS_COEFF_FQ12_C1[1],
|
||||
nqr.pow([
|
||||
nqr.pow_vartime([
|
||||
0x49aa7ffffffff1c7,
|
||||
0x51caaaa72e35555,
|
||||
0xe688231ad3c82906,
|
||||
@@ -724,7 +728,7 @@ fn test_frob_coeffs() {
|
||||
);
|
||||
assert_eq!(
|
||||
FROBENIUS_COEFF_FQ12_C1[2],
|
||||
nqr.pow([
|
||||
nqr.pow_vartime([
|
||||
0xdbc7000004bd97b4,
|
||||
0xea2791da3e5eb271,
|
||||
0x2e5cb340905834d4,
|
||||
@@ -741,7 +745,7 @@ fn test_frob_coeffs() {
|
||||
);
|
||||
assert_eq!(
|
||||
FROBENIUS_COEFF_FQ12_C1[3],
|
||||
nqr.pow(vec![
|
||||
nqr.pow_vartime(vec![
|
||||
0x6de37e6b79adcf03,
|
||||
0x4cbef56885f66b55,
|
||||
0x4edde9260b903230,
|
||||
@@ -764,7 +768,7 @@ fn test_frob_coeffs() {
|
||||
);
|
||||
assert_eq!(
|
||||
FROBENIUS_COEFF_FQ12_C1[4],
|
||||
nqr.pow(vec![
|
||||
nqr.pow_vartime(vec![
|
||||
0xa324d6e9e38e36c8,
|
||||
0xa1e5532944b95432,
|
||||
0x66d4222ddd5507dd,
|
||||
@@ -793,7 +797,7 @@ fn test_frob_coeffs() {
|
||||
);
|
||||
assert_eq!(
|
||||
FROBENIUS_COEFF_FQ12_C1[5],
|
||||
nqr.pow(vec![
|
||||
nqr.pow_vartime(vec![
|
||||
0xfc4b7bc93997595f,
|
||||
0xa4e435368ee2c9d0,
|
||||
0xf2d98f4a2c0fc8e1,
|
||||
@@ -828,7 +832,7 @@ fn test_frob_coeffs() {
|
||||
);
|
||||
assert_eq!(
|
||||
FROBENIUS_COEFF_FQ12_C1[6],
|
||||
nqr.pow(vec![
|
||||
nqr.pow_vartime(vec![
|
||||
0x21219610a012ba3c,
|
||||
0xa5c19ad35375325,
|
||||
0x4e9df1e497674396,
|
||||
@@ -869,7 +873,7 @@ fn test_frob_coeffs() {
|
||||
);
|
||||
assert_eq!(
|
||||
FROBENIUS_COEFF_FQ12_C1[7],
|
||||
nqr.pow(vec![
|
||||
nqr.pow_vartime(vec![
|
||||
0x742754a1f22fdb,
|
||||
0x2a1955c2dec3a702,
|
||||
0x9747b28c796d134e,
|
||||
@@ -916,7 +920,7 @@ fn test_frob_coeffs() {
|
||||
);
|
||||
assert_eq!(
|
||||
FROBENIUS_COEFF_FQ12_C1[8],
|
||||
nqr.pow(vec![
|
||||
nqr.pow_vartime(vec![
|
||||
0x802f5720d0b25710,
|
||||
0x6714f0a258b85c7c,
|
||||
0x31394c90afdf16e,
|
||||
@@ -969,7 +973,7 @@ fn test_frob_coeffs() {
|
||||
);
|
||||
assert_eq!(
|
||||
FROBENIUS_COEFF_FQ12_C1[9],
|
||||
nqr.pow(vec![
|
||||
nqr.pow_vartime(vec![
|
||||
0x4af4accf7de0b977,
|
||||
0x742485e21805b4ee,
|
||||
0xee388fbc4ac36dec,
|
||||
@@ -1028,7 +1032,7 @@ fn test_frob_coeffs() {
|
||||
);
|
||||
assert_eq!(
|
||||
FROBENIUS_COEFF_FQ12_C1[10],
|
||||
nqr.pow(vec![
|
||||
nqr.pow_vartime(vec![
|
||||
0xe5953a4f96cdda44,
|
||||
0x336b2d734cbc32bb,
|
||||
0x3f79bfe3cd7410e,
|
||||
@@ -1093,7 +1097,7 @@ fn test_frob_coeffs() {
|
||||
);
|
||||
assert_eq!(
|
||||
FROBENIUS_COEFF_FQ12_C1[11],
|
||||
nqr.pow(vec![
|
||||
nqr.pow_vartime(vec![
|
||||
0x107db680942de533,
|
||||
0x6262b24d2052393b,
|
||||
0x6136df824159ebc,
|
||||
@@ -1166,8 +1170,7 @@ fn test_frob_coeffs() {
|
||||
|
||||
#[test]
|
||||
fn test_neg_one() {
|
||||
let mut o = Fq::one();
|
||||
o.negate();
|
||||
let o = Fq::one().neg();
|
||||
|
||||
assert_eq!(NEGATIVE_ONE, o);
|
||||
}
|
||||
@@ -1928,7 +1931,7 @@ fn test_fq_mul_assign() {
|
||||
|
||||
#[test]
|
||||
fn test_fq_squaring() {
|
||||
let mut a = Fq(FqRepr([
|
||||
let a = Fq(FqRepr([
|
||||
0xffffffffffffffff,
|
||||
0xffffffffffffffff,
|
||||
0xffffffffffffffff,
|
||||
@@ -1937,9 +1940,8 @@ fn test_fq_squaring() {
|
||||
0x19ffffffffffffff,
|
||||
]));
|
||||
assert!(a.is_valid());
|
||||
a.square();
|
||||
assert_eq!(
|
||||
a,
|
||||
a.square(),
|
||||
Fq::from_repr(FqRepr([
|
||||
0x1cfb28fe7dfbbb86,
|
||||
0x24cbe1731577a59,
|
||||
@@ -1959,20 +1961,13 @@ fn test_fq_squaring() {
|
||||
for _ in 0..1000000 {
|
||||
// Ensure that (a * a) = a^2
|
||||
let a = Fq::random(&mut rng);
|
||||
|
||||
let mut tmp = a;
|
||||
tmp.square();
|
||||
|
||||
let mut tmp2 = a;
|
||||
tmp2.mul_assign(&a);
|
||||
|
||||
assert_eq!(tmp, tmp2);
|
||||
assert_eq!(a.square(), a * a);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fq_inverse() {
|
||||
assert!(Fq::zero().inverse().is_none());
|
||||
fn test_fq_invert() {
|
||||
assert!(bool::from(Fq::zero().invert().is_none()));
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
@@ -1984,7 +1979,7 @@ fn test_fq_inverse() {
|
||||
for _ in 0..1000 {
|
||||
// Ensure that a * a^-1 = 1
|
||||
let mut a = Fq::random(&mut rng);
|
||||
let ainv = a.inverse().unwrap();
|
||||
let ainv = a.invert().unwrap();
|
||||
a.mul_assign(&ainv);
|
||||
assert_eq!(a, one);
|
||||
}
|
||||
@@ -1999,19 +1994,15 @@ fn test_fq_double() {
|
||||
|
||||
for _ in 0..1000 {
|
||||
// Ensure doubling a is equivalent to adding a to itself.
|
||||
let mut a = Fq::random(&mut rng);
|
||||
let mut b = a;
|
||||
b.add_assign(&a);
|
||||
a.double();
|
||||
assert_eq!(a, b);
|
||||
let a = Fq::random(&mut rng);
|
||||
assert_eq!(a.double(), a + a);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fq_negate() {
|
||||
fn test_fq_neg() {
|
||||
{
|
||||
let mut a = Fq::zero();
|
||||
a.negate();
|
||||
let a = Fq::zero().neg();
|
||||
|
||||
assert!(a.is_zero());
|
||||
}
|
||||
@@ -2024,8 +2015,7 @@ fn test_fq_negate() {
|
||||
for _ in 0..1000 {
|
||||
// Ensure (a - (-a)) = 0.
|
||||
let mut a = Fq::random(&mut rng);
|
||||
let mut b = a;
|
||||
b.negate();
|
||||
let b = a.neg();
|
||||
a.add_assign(&b);
|
||||
|
||||
assert!(a.is_zero());
|
||||
@@ -2043,7 +2033,7 @@ fn test_fq_pow() {
|
||||
// Exponentiate by various small numbers and ensure it consists with repeated
|
||||
// multiplication.
|
||||
let a = Fq::random(&mut rng);
|
||||
let target = a.pow(&[i]);
|
||||
let target = a.pow_vartime(&[i]);
|
||||
let mut c = Fq::one();
|
||||
for _ in 0..i {
|
||||
c.mul_assign(&a);
|
||||
@@ -2055,7 +2045,7 @@ fn test_fq_pow() {
|
||||
// Exponentiating by the modulus should have no effect in a prime field.
|
||||
let a = Fq::random(&mut rng);
|
||||
|
||||
assert_eq!(a, a.pow(Fq::char()));
|
||||
assert_eq!(a, a.pow_vartime(Fq::char()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2073,10 +2063,8 @@ fn test_fq_sqrt() {
|
||||
for _ in 0..1000 {
|
||||
// Ensure sqrt(a^2) = a or -a
|
||||
let a = Fq::random(&mut rng);
|
||||
let mut nega = a;
|
||||
nega.negate();
|
||||
let mut b = a;
|
||||
b.square();
|
||||
let nega = a.neg();
|
||||
let b = a.square();
|
||||
|
||||
let b = b.sqrt().unwrap();
|
||||
|
||||
@@ -2087,10 +2075,9 @@ fn test_fq_sqrt() {
|
||||
// Ensure sqrt(a)^2 = a for random a
|
||||
let a = Fq::random(&mut rng);
|
||||
|
||||
if let Some(mut tmp) = a.sqrt() {
|
||||
tmp.square();
|
||||
|
||||
assert_eq!(a, tmp);
|
||||
let tmp = a.sqrt();
|
||||
if tmp.is_some().into() {
|
||||
assert_eq!(a, tmp.unwrap().square());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2209,7 +2196,7 @@ fn test_fq_root_of_unity() {
|
||||
Fq::from_repr(FqRepr::from(2)).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Fq::multiplicative_generator().pow([
|
||||
Fq::multiplicative_generator().pow_vartime([
|
||||
0xdcff7fffffffd555,
|
||||
0xf55ffff58a9ffff,
|
||||
0xb39869507b587b12,
|
||||
@@ -2219,8 +2206,8 @@ fn test_fq_root_of_unity() {
|
||||
]),
|
||||
Fq::root_of_unity()
|
||||
);
|
||||
assert_eq!(Fq::root_of_unity().pow([1 << Fq::S]), Fq::one());
|
||||
assert!(Fq::multiplicative_generator().sqrt().is_none());
|
||||
assert_eq!(Fq::root_of_unity().pow_vartime([1 << Fq::S]), Fq::one());
|
||||
assert!(bool::from(Fq::multiplicative_generator().sqrt().is_none()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -2246,40 +2233,3 @@ fn test_fq_ordering() {
|
||||
fn fq_repr_tests() {
|
||||
crate::tests::repr::random_repr_tests::<Fq>();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fq_legendre() {
|
||||
use ff::LegendreSymbol::*;
|
||||
use ff::SqrtField;
|
||||
|
||||
assert_eq!(QuadraticResidue, Fq::one().legendre());
|
||||
assert_eq!(Zero, Fq::zero().legendre());
|
||||
|
||||
assert_eq!(
|
||||
QuadraticNonResidue,
|
||||
Fq::from_repr(FqRepr::from(2)).unwrap().legendre()
|
||||
);
|
||||
assert_eq!(
|
||||
QuadraticResidue,
|
||||
Fq::from_repr(FqRepr::from(4)).unwrap().legendre()
|
||||
);
|
||||
|
||||
let e = FqRepr([
|
||||
0x52a112f249778642,
|
||||
0xd0bedb989b7991f,
|
||||
0xdad3b6681aa63c05,
|
||||
0xf2efc0bb4721b283,
|
||||
0x6057a98f18c24733,
|
||||
0x1022c2fd122889e4,
|
||||
]);
|
||||
assert_eq!(QuadraticNonResidue, Fq::from_repr(e).unwrap().legendre());
|
||||
let e = FqRepr([
|
||||
0x6dae594e53a96c74,
|
||||
0x19b16ca9ba64b37b,
|
||||
0x5c764661a59bfc68,
|
||||
0xaa346e9b31c60a,
|
||||
0x346059f9d87a9fa9,
|
||||
0x1d61ac6bfd5c88b,
|
||||
]);
|
||||
assert_eq!(QuadraticResidue, Fq::from_repr(e).unwrap().legendre());
|
||||
}
|
||||
|
@@ -3,9 +3,11 @@ use super::fq2::Fq2;
|
||||
use super::fq6::Fq6;
|
||||
use ff::Field;
|
||||
use rand_core::RngCore;
|
||||
use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
|
||||
use subtle::{Choice, ConditionallySelectable, CtOption};
|
||||
|
||||
/// An element of Fq12, represented by c0 + c1 * w.
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
|
||||
pub struct Fq12 {
|
||||
pub c0: Fq6,
|
||||
pub c1: Fq6,
|
||||
@@ -19,7 +21,7 @@ impl ::std::fmt::Display for Fq12 {
|
||||
|
||||
impl Fq12 {
|
||||
pub fn conjugate(&mut self) {
|
||||
self.c1.negate();
|
||||
self.c1 = self.c1.neg();
|
||||
}
|
||||
|
||||
pub fn mul_by_014(&mut self, c0: &Fq2, c1: &Fq2, c4: &Fq2) {
|
||||
@@ -39,6 +41,132 @@ impl Fq12 {
|
||||
}
|
||||
}
|
||||
|
||||
impl ConditionallySelectable for Fq12 {
|
||||
fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
|
||||
Fq12 {
|
||||
c0: Fq6::conditional_select(&a.c0, &b.c0, choice),
|
||||
c1: Fq6::conditional_select(&a.c1, &b.c1, choice),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Neg for Fq12 {
|
||||
type Output = Self;
|
||||
|
||||
fn neg(self) -> Self {
|
||||
Fq12 {
|
||||
c0: self.c0.neg(),
|
||||
c1: self.c1.neg(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> Add<&'r Fq12> for Fq12 {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, other: &Self) -> Self {
|
||||
Fq12 {
|
||||
c0: self.c0 + other.c0,
|
||||
c1: self.c1 + other.c1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for Fq12 {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, other: Self) -> Self {
|
||||
self.add(&other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> AddAssign<&'r Fq12> for Fq12 {
|
||||
fn add_assign(&mut self, other: &'r Self) {
|
||||
self.c0.add_assign(&other.c0);
|
||||
self.c1.add_assign(&other.c1);
|
||||
}
|
||||
}
|
||||
|
||||
impl AddAssign for Fq12 {
|
||||
fn add_assign(&mut self, other: Self) {
|
||||
self.add_assign(&other);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> Sub<&'r Fq12> for Fq12 {
|
||||
type Output = Self;
|
||||
|
||||
fn sub(self, other: &Self) -> Self {
|
||||
Fq12 {
|
||||
c0: self.c0 - other.c0,
|
||||
c1: self.c1 - other.c1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub for Fq12 {
|
||||
type Output = Self;
|
||||
|
||||
fn sub(self, other: Self) -> Self {
|
||||
self.sub(&other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> SubAssign<&'r Fq12> for Fq12 {
|
||||
fn sub_assign(&mut self, other: &'r Self) {
|
||||
self.c0.sub_assign(&other.c0);
|
||||
self.c1.sub_assign(&other.c1);
|
||||
}
|
||||
}
|
||||
|
||||
impl SubAssign for Fq12 {
|
||||
fn sub_assign(&mut self, other: Self) {
|
||||
self.sub_assign(&other);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> Mul<&'r Fq12> for Fq12 {
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, other: &Self) -> Self {
|
||||
let mut ret = self;
|
||||
ret.mul_assign(other);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul for Fq12 {
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, other: Self) -> Self {
|
||||
self.mul(&other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> MulAssign<&'r Fq12> for Fq12 {
|
||||
fn mul_assign(&mut self, other: &Self) {
|
||||
let mut aa = self.c0;
|
||||
aa.mul_assign(&other.c0);
|
||||
let mut bb = self.c1;
|
||||
bb.mul_assign(&other.c1);
|
||||
let mut o = other.c0;
|
||||
o.add_assign(&other.c1);
|
||||
self.c1.add_assign(&self.c0);
|
||||
self.c1.mul_assign(&o);
|
||||
self.c1.sub_assign(&aa);
|
||||
self.c1.sub_assign(&bb);
|
||||
self.c0 = bb;
|
||||
self.c0.mul_by_nonresidue();
|
||||
self.c0.add_assign(&aa);
|
||||
}
|
||||
}
|
||||
|
||||
impl MulAssign for Fq12 {
|
||||
fn mul_assign(&mut self, other: Self) {
|
||||
self.mul_assign(&other);
|
||||
}
|
||||
}
|
||||
|
||||
impl Field for Fq12 {
|
||||
fn random<R: RngCore + ?std::marker::Sized>(rng: &mut R) -> Self {
|
||||
Fq12 {
|
||||
@@ -65,24 +193,11 @@ impl Field for Fq12 {
|
||||
self.c0.is_zero() && self.c1.is_zero()
|
||||
}
|
||||
|
||||
fn double(&mut self) {
|
||||
self.c0.double();
|
||||
self.c1.double();
|
||||
}
|
||||
|
||||
fn negate(&mut self) {
|
||||
self.c0.negate();
|
||||
self.c1.negate();
|
||||
}
|
||||
|
||||
fn add_assign(&mut self, other: &Self) {
|
||||
self.c0.add_assign(&other.c0);
|
||||
self.c1.add_assign(&other.c1);
|
||||
}
|
||||
|
||||
fn sub_assign(&mut self, other: &Self) {
|
||||
self.c0.sub_assign(&other.c0);
|
||||
self.c1.sub_assign(&other.c1);
|
||||
fn double(&self) -> Self {
|
||||
Fq12 {
|
||||
c0: self.c0.double(),
|
||||
c1: self.c1.double(),
|
||||
}
|
||||
}
|
||||
|
||||
fn frobenius_map(&mut self, power: usize) {
|
||||
@@ -94,7 +209,7 @@ impl Field for Fq12 {
|
||||
self.c1.c2.mul_assign(&FROBENIUS_COEFF_FQ12_C1[power % 12]);
|
||||
}
|
||||
|
||||
fn square(&mut self) {
|
||||
fn square(&self) -> Self {
|
||||
let mut ab = self.c0;
|
||||
ab.mul_assign(&self.c1);
|
||||
let mut c0c1 = self.c0;
|
||||
@@ -104,44 +219,22 @@ impl Field for Fq12 {
|
||||
c0.add_assign(&self.c0);
|
||||
c0.mul_assign(&c0c1);
|
||||
c0.sub_assign(&ab);
|
||||
self.c1 = ab;
|
||||
self.c1.add_assign(&ab);
|
||||
let mut c1 = ab;
|
||||
c1.add_assign(&ab);
|
||||
ab.mul_by_nonresidue();
|
||||
c0.sub_assign(&ab);
|
||||
self.c0 = c0;
|
||||
Fq12 { c0, c1 }
|
||||
}
|
||||
|
||||
fn mul_assign(&mut self, other: &Self) {
|
||||
let mut aa = self.c0;
|
||||
aa.mul_assign(&other.c0);
|
||||
let mut bb = self.c1;
|
||||
bb.mul_assign(&other.c1);
|
||||
let mut o = other.c0;
|
||||
o.add_assign(&other.c1);
|
||||
self.c1.add_assign(&self.c0);
|
||||
self.c1.mul_assign(&o);
|
||||
self.c1.sub_assign(&aa);
|
||||
self.c1.sub_assign(&bb);
|
||||
self.c0 = bb;
|
||||
self.c0.mul_by_nonresidue();
|
||||
self.c0.add_assign(&aa);
|
||||
}
|
||||
|
||||
fn inverse(&self) -> Option<Self> {
|
||||
let mut c0s = self.c0;
|
||||
c0s.square();
|
||||
let mut c1s = self.c1;
|
||||
c1s.square();
|
||||
fn invert(&self) -> CtOption<Self> {
|
||||
let mut c0s = self.c0.square();
|
||||
let mut c1s = self.c1.square();
|
||||
c1s.mul_by_nonresidue();
|
||||
c0s.sub_assign(&c1s);
|
||||
|
||||
c0s.inverse().map(|t| {
|
||||
let mut tmp = Fq12 { c0: t, c1: t };
|
||||
tmp.c0.mul_assign(&self.c0);
|
||||
tmp.c1.mul_assign(&self.c1);
|
||||
tmp.c1.negate();
|
||||
|
||||
tmp
|
||||
c0s.invert().map(|t| Fq12 {
|
||||
c0: t.mul(&self.c0),
|
||||
c1: t.mul(&self.c1).neg(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@@ -1,11 +1,12 @@
|
||||
use super::fq::{Fq, FROBENIUS_COEFF_FQ2_C1, NEGATIVE_ONE};
|
||||
use ff::{Field, SqrtField};
|
||||
use rand_core::RngCore;
|
||||
|
||||
use std::cmp::Ordering;
|
||||
use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
|
||||
use subtle::{Choice, ConditionallySelectable, CtOption};
|
||||
|
||||
/// An element of Fq2, represented by c0 + c1 * u.
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
|
||||
pub struct Fq2 {
|
||||
pub c0: Fq,
|
||||
pub c1: Fq,
|
||||
@@ -46,16 +47,139 @@ impl Fq2 {
|
||||
|
||||
/// Norm of Fq2 as extension field in i over Fq
|
||||
pub fn norm(&self) -> Fq {
|
||||
let mut t0 = self.c0;
|
||||
let mut t1 = self.c1;
|
||||
t0.square();
|
||||
t1.square();
|
||||
let t0 = self.c0.square();
|
||||
let mut t1 = self.c1.square();
|
||||
t1.add_assign(&t0);
|
||||
|
||||
t1
|
||||
}
|
||||
}
|
||||
|
||||
impl ConditionallySelectable for Fq2 {
|
||||
fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
|
||||
Fq2 {
|
||||
c0: Fq::conditional_select(&a.c0, &b.c0, choice),
|
||||
c1: Fq::conditional_select(&a.c1, &b.c1, choice),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Neg for Fq2 {
|
||||
type Output = Self;
|
||||
|
||||
fn neg(self) -> Self {
|
||||
Fq2 {
|
||||
c0: self.c0.neg(),
|
||||
c1: self.c1.neg(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> Add<&'r Fq2> for Fq2 {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, other: &Self) -> Self {
|
||||
Fq2 {
|
||||
c0: self.c0 + other.c0,
|
||||
c1: self.c1 + other.c1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for Fq2 {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, other: Self) -> Self {
|
||||
self.add(&other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> AddAssign<&'r Fq2> for Fq2 {
|
||||
fn add_assign(&mut self, other: &'r Self) {
|
||||
self.c0.add_assign(&other.c0);
|
||||
self.c1.add_assign(&other.c1);
|
||||
}
|
||||
}
|
||||
|
||||
impl AddAssign for Fq2 {
|
||||
fn add_assign(&mut self, other: Self) {
|
||||
self.add_assign(&other);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> Sub<&'r Fq2> for Fq2 {
|
||||
type Output = Self;
|
||||
|
||||
fn sub(self, other: &Self) -> Self {
|
||||
Fq2 {
|
||||
c0: self.c0 - other.c0,
|
||||
c1: self.c1 - other.c1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub for Fq2 {
|
||||
type Output = Self;
|
||||
|
||||
fn sub(self, other: Self) -> Self {
|
||||
self.sub(&other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> SubAssign<&'r Fq2> for Fq2 {
|
||||
fn sub_assign(&mut self, other: &'r Self) {
|
||||
self.c0.sub_assign(&other.c0);
|
||||
self.c1.sub_assign(&other.c1);
|
||||
}
|
||||
}
|
||||
|
||||
impl SubAssign for Fq2 {
|
||||
fn sub_assign(&mut self, other: Self) {
|
||||
self.sub_assign(&other);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> Mul<&'r Fq2> for Fq2 {
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, other: &Self) -> Self {
|
||||
let mut ret = self;
|
||||
ret.mul_assign(other);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul for Fq2 {
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, other: Self) -> Self {
|
||||
self.mul(&other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> MulAssign<&'r Fq2> for Fq2 {
|
||||
fn mul_assign(&mut self, other: &Self) {
|
||||
let mut aa = self.c0;
|
||||
aa.mul_assign(&other.c0);
|
||||
let mut bb = self.c1;
|
||||
bb.mul_assign(&other.c1);
|
||||
let mut o = other.c0;
|
||||
o.add_assign(&other.c1);
|
||||
self.c1.add_assign(&self.c0);
|
||||
self.c1.mul_assign(&o);
|
||||
self.c1.sub_assign(&aa);
|
||||
self.c1.sub_assign(&bb);
|
||||
self.c0 = aa;
|
||||
self.c0.sub_assign(&bb);
|
||||
}
|
||||
}
|
||||
|
||||
impl MulAssign for Fq2 {
|
||||
fn mul_assign(&mut self, other: Self) {
|
||||
self.mul_assign(&other);
|
||||
}
|
||||
}
|
||||
|
||||
impl Field for Fq2 {
|
||||
fn random<R: RngCore + ?std::marker::Sized>(rng: &mut R) -> Self {
|
||||
Fq2 {
|
||||
@@ -82,73 +206,35 @@ impl Field for Fq2 {
|
||||
self.c0.is_zero() && self.c1.is_zero()
|
||||
}
|
||||
|
||||
fn square(&mut self) {
|
||||
fn square(&self) -> Self {
|
||||
let mut ab = self.c0;
|
||||
ab.mul_assign(&self.c1);
|
||||
let mut c0c1 = self.c0;
|
||||
c0c1.add_assign(&self.c1);
|
||||
let mut c0 = self.c1;
|
||||
c0.negate();
|
||||
let mut c0 = self.c1.neg();
|
||||
c0.add_assign(&self.c0);
|
||||
c0.mul_assign(&c0c1);
|
||||
c0.sub_assign(&ab);
|
||||
self.c1 = ab;
|
||||
self.c1.add_assign(&ab);
|
||||
let mut c1 = ab;
|
||||
c1.add_assign(&ab);
|
||||
c0.add_assign(&ab);
|
||||
self.c0 = c0;
|
||||
Fq2 { c0, c1 }
|
||||
}
|
||||
|
||||
fn double(&mut self) {
|
||||
self.c0.double();
|
||||
self.c1.double();
|
||||
fn double(&self) -> Self {
|
||||
Fq2 {
|
||||
c0: self.c0.double(),
|
||||
c1: self.c1.double(),
|
||||
}
|
||||
}
|
||||
|
||||
fn negate(&mut self) {
|
||||
self.c0.negate();
|
||||
self.c1.negate();
|
||||
}
|
||||
|
||||
fn add_assign(&mut self, other: &Self) {
|
||||
self.c0.add_assign(&other.c0);
|
||||
self.c1.add_assign(&other.c1);
|
||||
}
|
||||
|
||||
fn sub_assign(&mut self, other: &Self) {
|
||||
self.c0.sub_assign(&other.c0);
|
||||
self.c1.sub_assign(&other.c1);
|
||||
}
|
||||
|
||||
fn mul_assign(&mut self, other: &Self) {
|
||||
let mut aa = self.c0;
|
||||
aa.mul_assign(&other.c0);
|
||||
let mut bb = self.c1;
|
||||
bb.mul_assign(&other.c1);
|
||||
let mut o = other.c0;
|
||||
o.add_assign(&other.c1);
|
||||
self.c1.add_assign(&self.c0);
|
||||
self.c1.mul_assign(&o);
|
||||
self.c1.sub_assign(&aa);
|
||||
self.c1.sub_assign(&bb);
|
||||
self.c0 = aa;
|
||||
self.c0.sub_assign(&bb);
|
||||
}
|
||||
|
||||
fn inverse(&self) -> Option<Self> {
|
||||
let mut t1 = self.c1;
|
||||
t1.square();
|
||||
let mut t0 = self.c0;
|
||||
t0.square();
|
||||
fn invert(&self) -> CtOption<Self> {
|
||||
let t1 = self.c1.square();
|
||||
let mut t0 = self.c0.square();
|
||||
t0.add_assign(&t1);
|
||||
t0.inverse().map(|t| {
|
||||
let mut tmp = Fq2 {
|
||||
c0: self.c0,
|
||||
c1: self.c1,
|
||||
};
|
||||
tmp.c0.mul_assign(&t);
|
||||
tmp.c1.mul_assign(&t);
|
||||
tmp.c1.negate();
|
||||
|
||||
tmp
|
||||
t0.invert().map(|t| Fq2 {
|
||||
c0: self.c0.mul(&t),
|
||||
c1: self.c1.mul(&t).neg(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -158,18 +244,16 @@ impl Field for Fq2 {
|
||||
}
|
||||
|
||||
impl SqrtField for Fq2 {
|
||||
fn legendre(&self) -> ::ff::LegendreSymbol {
|
||||
self.norm().legendre()
|
||||
}
|
||||
|
||||
fn sqrt(&self) -> Option<Self> {
|
||||
/// WARNING: THIS IS NOT ACTUALLY CONSTANT TIME YET!
|
||||
/// THIS WILL BE REPLACED BY THE bls12_381 CRATE, WHICH IS CONSTANT TIME!
|
||||
fn sqrt(&self) -> CtOption<Self> {
|
||||
// Algorithm 9, https://eprint.iacr.org/2012/685.pdf
|
||||
|
||||
if self.is_zero() {
|
||||
Some(Self::zero())
|
||||
CtOption::new(Self::zero(), Choice::from(1))
|
||||
} else {
|
||||
// a1 = self^((q - 3) / 4)
|
||||
let mut a1 = self.pow([
|
||||
let mut a1 = self.pow_vartime([
|
||||
0xee7fbfffffffeaaa,
|
||||
0x7aaffffac54ffff,
|
||||
0xd9cc34a83dac3d89,
|
||||
@@ -177,8 +261,7 @@ impl SqrtField for Fq2 {
|
||||
0x92c6e9ed90d2eb35,
|
||||
0x680447a8e5ff9a6,
|
||||
]);
|
||||
let mut alpha = a1;
|
||||
alpha.square();
|
||||
let mut alpha = a1.square();
|
||||
alpha.mul_assign(self);
|
||||
let mut a0 = alpha;
|
||||
a0.frobenius_map(1);
|
||||
@@ -190,7 +273,7 @@ impl SqrtField for Fq2 {
|
||||
};
|
||||
|
||||
if a0 == neg1 {
|
||||
None
|
||||
CtOption::new(Self::zero(), Choice::from(0))
|
||||
} else {
|
||||
a1.mul_assign(self);
|
||||
|
||||
@@ -202,7 +285,7 @@ impl SqrtField for Fq2 {
|
||||
} else {
|
||||
alpha.add_assign(&Fq2::one());
|
||||
// alpha = alpha^((q - 1) / 2)
|
||||
alpha = alpha.pow([
|
||||
alpha = alpha.pow_vartime([
|
||||
0xdcff7fffffffd555,
|
||||
0xf55ffff58a9ffff,
|
||||
0xb39869507b587b12,
|
||||
@@ -213,7 +296,7 @@ impl SqrtField for Fq2 {
|
||||
a1.mul_assign(&alpha);
|
||||
}
|
||||
|
||||
Some(a1)
|
||||
CtOption::new(a1, Choice::from(1))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -226,7 +309,7 @@ fn test_fq2_ordering() {
|
||||
c1: Fq::zero(),
|
||||
};
|
||||
|
||||
let mut b = a.clone();
|
||||
let mut b = a;
|
||||
|
||||
assert!(a.cmp(&b) == Ordering::Equal);
|
||||
b.c0.add_assign(&Fq::one());
|
||||
@@ -273,34 +356,30 @@ fn test_fq2_squaring() {
|
||||
use super::fq::FqRepr;
|
||||
use ff::PrimeField;
|
||||
|
||||
let mut a = Fq2 {
|
||||
let a = Fq2 {
|
||||
c0: Fq::one(),
|
||||
c1: Fq::one(),
|
||||
}; // u + 1
|
||||
a.square();
|
||||
assert_eq!(
|
||||
a,
|
||||
a.square(),
|
||||
Fq2 {
|
||||
c0: Fq::zero(),
|
||||
c1: Fq::from_repr(FqRepr::from(2)).unwrap(),
|
||||
}
|
||||
); // 2u
|
||||
|
||||
let mut a = Fq2 {
|
||||
let a = Fq2 {
|
||||
c0: Fq::zero(),
|
||||
c1: Fq::one(),
|
||||
}; // u
|
||||
a.square();
|
||||
assert_eq!(a, {
|
||||
let mut neg1 = Fq::one();
|
||||
neg1.negate();
|
||||
assert_eq!(a.square(), {
|
||||
Fq2 {
|
||||
c0: neg1,
|
||||
c0: Fq::one().neg(),
|
||||
c1: Fq::zero(),
|
||||
}
|
||||
}); // -1
|
||||
|
||||
let mut a = Fq2 {
|
||||
let a = Fq2 {
|
||||
c0: Fq::from_repr(FqRepr([
|
||||
0x9c2c6309bbf8b598,
|
||||
0x4eef5c946536f602,
|
||||
@@ -320,9 +399,8 @@ fn test_fq2_squaring() {
|
||||
]))
|
||||
.unwrap(),
|
||||
};
|
||||
a.square();
|
||||
assert_eq!(
|
||||
a,
|
||||
a.square(),
|
||||
Fq2 {
|
||||
c0: Fq::from_repr(FqRepr([
|
||||
0xf262c28c538bcf68,
|
||||
@@ -417,11 +495,11 @@ fn test_fq2_mul() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fq2_inverse() {
|
||||
fn test_fq2_invert() {
|
||||
use super::fq::FqRepr;
|
||||
use ff::PrimeField;
|
||||
|
||||
assert!(Fq2::zero().inverse().is_none());
|
||||
assert!(bool::from(Fq2::zero().invert().is_none()));
|
||||
|
||||
let a = Fq2 {
|
||||
c0: Fq::from_repr(FqRepr([
|
||||
@@ -443,7 +521,7 @@ fn test_fq2_inverse() {
|
||||
]))
|
||||
.unwrap(),
|
||||
};
|
||||
let a = a.inverse().unwrap();
|
||||
let a = a.invert().unwrap();
|
||||
assert_eq!(
|
||||
a,
|
||||
Fq2 {
|
||||
@@ -614,7 +692,7 @@ fn test_fq2_negation() {
|
||||
use super::fq::FqRepr;
|
||||
use ff::PrimeField;
|
||||
|
||||
let mut a = Fq2 {
|
||||
let a = Fq2 {
|
||||
c0: Fq::from_repr(FqRepr([
|
||||
0x2d0078036923ffc7,
|
||||
0x11e59ea221a3b6d2,
|
||||
@@ -633,8 +711,8 @@ fn test_fq2_negation() {
|
||||
0x12d1137b8a6a837,
|
||||
]))
|
||||
.unwrap(),
|
||||
};
|
||||
a.negate();
|
||||
}
|
||||
.neg();
|
||||
assert_eq!(
|
||||
a,
|
||||
Fq2 {
|
||||
@@ -665,7 +743,7 @@ fn test_fq2_doubling() {
|
||||
use super::fq::FqRepr;
|
||||
use ff::PrimeField;
|
||||
|
||||
let mut a = Fq2 {
|
||||
let a = Fq2 {
|
||||
c0: Fq::from_repr(FqRepr([
|
||||
0x2d0078036923ffc7,
|
||||
0x11e59ea221a3b6d2,
|
||||
@@ -685,9 +763,8 @@ fn test_fq2_doubling() {
|
||||
]))
|
||||
.unwrap(),
|
||||
};
|
||||
a.double();
|
||||
assert_eq!(
|
||||
a,
|
||||
a.double(),
|
||||
Fq2 {
|
||||
c0: Fq::from_repr(FqRepr([
|
||||
0x5a00f006d247ff8e,
|
||||
@@ -914,19 +991,6 @@ fn test_fq2_sqrt() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fq2_legendre() {
|
||||
use ff::LegendreSymbol::*;
|
||||
|
||||
assert_eq!(Zero, Fq2::zero().legendre());
|
||||
// i^2 = -1
|
||||
let mut m1 = Fq2::one();
|
||||
m1.negate();
|
||||
assert_eq!(QuadraticResidue, m1.legendre());
|
||||
m1.mul_by_nonresidue();
|
||||
assert_eq!(QuadraticNonResidue, m1.legendre());
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
use rand_core::SeedableRng;
|
||||
#[cfg(test)]
|
||||
|
@@ -2,9 +2,11 @@ use super::fq::{FROBENIUS_COEFF_FQ6_C1, FROBENIUS_COEFF_FQ6_C2};
|
||||
use super::fq2::Fq2;
|
||||
use ff::Field;
|
||||
use rand_core::RngCore;
|
||||
use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
|
||||
use subtle::{Choice, ConditionallySelectable, CtOption};
|
||||
|
||||
/// An element of Fq6, represented by c0 + c1 * v + c2 * v^(2).
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
|
||||
pub struct Fq6 {
|
||||
pub c0: Fq2,
|
||||
pub c1: Fq2,
|
||||
@@ -99,101 +101,115 @@ impl Fq6 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Field for Fq6 {
|
||||
fn random<R: RngCore + ?std::marker::Sized>(rng: &mut R) -> Self {
|
||||
impl ConditionallySelectable for Fq6 {
|
||||
fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
|
||||
Fq6 {
|
||||
c0: Fq2::random(rng),
|
||||
c1: Fq2::random(rng),
|
||||
c2: Fq2::random(rng),
|
||||
c0: Fq2::conditional_select(&a.c0, &b.c0, choice),
|
||||
c1: Fq2::conditional_select(&a.c1, &b.c1, choice),
|
||||
c2: Fq2::conditional_select(&a.c2, &b.c2, choice),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn zero() -> Self {
|
||||
impl Neg for Fq6 {
|
||||
type Output = Self;
|
||||
|
||||
fn neg(self) -> Self {
|
||||
Fq6 {
|
||||
c0: Fq2::zero(),
|
||||
c1: Fq2::zero(),
|
||||
c2: Fq2::zero(),
|
||||
c0: self.c0.neg(),
|
||||
c1: self.c1.neg(),
|
||||
c2: self.c2.neg(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn one() -> Self {
|
||||
impl<'r> Add<&'r Fq6> for Fq6 {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, other: &Self) -> Self {
|
||||
Fq6 {
|
||||
c0: Fq2::one(),
|
||||
c1: Fq2::zero(),
|
||||
c2: Fq2::zero(),
|
||||
c0: self.c0 + other.c0,
|
||||
c1: self.c1 + other.c1,
|
||||
c2: self.c2 + other.c2,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_zero(&self) -> bool {
|
||||
self.c0.is_zero() && self.c1.is_zero() && self.c2.is_zero()
|
||||
impl Add for Fq6 {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, other: Self) -> Self {
|
||||
self.add(&other)
|
||||
}
|
||||
}
|
||||
|
||||
fn double(&mut self) {
|
||||
self.c0.double();
|
||||
self.c1.double();
|
||||
self.c2.double();
|
||||
}
|
||||
|
||||
fn negate(&mut self) {
|
||||
self.c0.negate();
|
||||
self.c1.negate();
|
||||
self.c2.negate();
|
||||
}
|
||||
|
||||
fn add_assign(&mut self, other: &Self) {
|
||||
impl<'r> AddAssign<&'r Fq6> for Fq6 {
|
||||
fn add_assign(&mut self, other: &'r Self) {
|
||||
self.c0.add_assign(&other.c0);
|
||||
self.c1.add_assign(&other.c1);
|
||||
self.c2.add_assign(&other.c2);
|
||||
}
|
||||
}
|
||||
|
||||
fn sub_assign(&mut self, other: &Self) {
|
||||
impl AddAssign for Fq6 {
|
||||
fn add_assign(&mut self, other: Self) {
|
||||
self.add_assign(&other);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> Sub<&'r Fq6> for Fq6 {
|
||||
type Output = Self;
|
||||
|
||||
fn sub(self, other: &Self) -> Self {
|
||||
Fq6 {
|
||||
c0: self.c0 - other.c0,
|
||||
c1: self.c1 - other.c1,
|
||||
c2: self.c2 - other.c2,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub for Fq6 {
|
||||
type Output = Self;
|
||||
|
||||
fn sub(self, other: Self) -> Self {
|
||||
self.sub(&other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> SubAssign<&'r Fq6> for Fq6 {
|
||||
fn sub_assign(&mut self, other: &'r Self) {
|
||||
self.c0.sub_assign(&other.c0);
|
||||
self.c1.sub_assign(&other.c1);
|
||||
self.c2.sub_assign(&other.c2);
|
||||
}
|
||||
}
|
||||
|
||||
fn frobenius_map(&mut self, power: usize) {
|
||||
self.c0.frobenius_map(power);
|
||||
self.c1.frobenius_map(power);
|
||||
self.c2.frobenius_map(power);
|
||||
|
||||
self.c1.mul_assign(&FROBENIUS_COEFF_FQ6_C1[power % 6]);
|
||||
self.c2.mul_assign(&FROBENIUS_COEFF_FQ6_C2[power % 6]);
|
||||
impl SubAssign for Fq6 {
|
||||
fn sub_assign(&mut self, other: Self) {
|
||||
self.sub_assign(&other);
|
||||
}
|
||||
}
|
||||
|
||||
fn square(&mut self) {
|
||||
let mut s0 = self.c0;
|
||||
s0.square();
|
||||
let mut ab = self.c0;
|
||||
ab.mul_assign(&self.c1);
|
||||
let mut s1 = ab;
|
||||
s1.double();
|
||||
let mut s2 = self.c0;
|
||||
s2.sub_assign(&self.c1);
|
||||
s2.add_assign(&self.c2);
|
||||
s2.square();
|
||||
let mut bc = self.c1;
|
||||
bc.mul_assign(&self.c2);
|
||||
let mut s3 = bc;
|
||||
s3.double();
|
||||
let mut s4 = self.c2;
|
||||
s4.square();
|
||||
impl<'r> Mul<&'r Fq6> for Fq6 {
|
||||
type Output = Self;
|
||||
|
||||
self.c0 = s3;
|
||||
self.c0.mul_by_nonresidue();
|
||||
self.c0.add_assign(&s0);
|
||||
|
||||
self.c1 = s4;
|
||||
self.c1.mul_by_nonresidue();
|
||||
self.c1.add_assign(&s1);
|
||||
|
||||
self.c2 = s1;
|
||||
self.c2.add_assign(&s2);
|
||||
self.c2.add_assign(&s3);
|
||||
self.c2.sub_assign(&s0);
|
||||
self.c2.sub_assign(&s4);
|
||||
fn mul(self, other: &Self) -> Self {
|
||||
let mut ret = self;
|
||||
ret.mul_assign(other);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul for Fq6 {
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, other: Self) -> Self {
|
||||
self.mul(&other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> MulAssign<&'r Fq6> for Fq6 {
|
||||
fn mul_assign(&mut self, other: &Self) {
|
||||
let mut a_a = self.c0;
|
||||
let mut b_b = self.c1;
|
||||
@@ -244,27 +260,108 @@ impl Field for Fq6 {
|
||||
self.c1 = t2;
|
||||
self.c2 = t3;
|
||||
}
|
||||
}
|
||||
|
||||
fn inverse(&self) -> Option<Self> {
|
||||
impl MulAssign for Fq6 {
|
||||
fn mul_assign(&mut self, other: Self) {
|
||||
self.mul_assign(&other);
|
||||
}
|
||||
}
|
||||
|
||||
impl Field for Fq6 {
|
||||
fn random<R: RngCore + ?std::marker::Sized>(rng: &mut R) -> Self {
|
||||
Fq6 {
|
||||
c0: Fq2::random(rng),
|
||||
c1: Fq2::random(rng),
|
||||
c2: Fq2::random(rng),
|
||||
}
|
||||
}
|
||||
|
||||
fn zero() -> Self {
|
||||
Fq6 {
|
||||
c0: Fq2::zero(),
|
||||
c1: Fq2::zero(),
|
||||
c2: Fq2::zero(),
|
||||
}
|
||||
}
|
||||
|
||||
fn one() -> Self {
|
||||
Fq6 {
|
||||
c0: Fq2::one(),
|
||||
c1: Fq2::zero(),
|
||||
c2: Fq2::zero(),
|
||||
}
|
||||
}
|
||||
|
||||
fn is_zero(&self) -> bool {
|
||||
self.c0.is_zero() && self.c1.is_zero() && self.c2.is_zero()
|
||||
}
|
||||
|
||||
fn double(&self) -> Self {
|
||||
Fq6 {
|
||||
c0: self.c0.double(),
|
||||
c1: self.c1.double(),
|
||||
c2: self.c2.double(),
|
||||
}
|
||||
}
|
||||
|
||||
fn frobenius_map(&mut self, power: usize) {
|
||||
self.c0.frobenius_map(power);
|
||||
self.c1.frobenius_map(power);
|
||||
self.c2.frobenius_map(power);
|
||||
|
||||
self.c1.mul_assign(&FROBENIUS_COEFF_FQ6_C1[power % 6]);
|
||||
self.c2.mul_assign(&FROBENIUS_COEFF_FQ6_C2[power % 6]);
|
||||
}
|
||||
|
||||
fn square(&self) -> Self {
|
||||
let s0 = self.c0.square();
|
||||
let mut ab = self.c0;
|
||||
ab.mul_assign(&self.c1);
|
||||
let s1 = ab.double();
|
||||
let mut s2 = self.c0;
|
||||
s2.sub_assign(&self.c1);
|
||||
s2.add_assign(&self.c2);
|
||||
s2 = s2.square();
|
||||
let mut bc = self.c1;
|
||||
bc.mul_assign(&self.c2);
|
||||
let s3 = bc.double();
|
||||
let s4 = self.c2.square();
|
||||
|
||||
let mut c0 = s3;
|
||||
c0.mul_by_nonresidue();
|
||||
c0.add_assign(&s0);
|
||||
|
||||
let mut c1 = s4;
|
||||
c1.mul_by_nonresidue();
|
||||
c1.add_assign(&s1);
|
||||
|
||||
let mut c2 = s1;
|
||||
c2.add_assign(&s2);
|
||||
c2.add_assign(&s3);
|
||||
c2.sub_assign(&s0);
|
||||
c2.sub_assign(&s4);
|
||||
|
||||
Fq6 { c0, c1, c2 }
|
||||
}
|
||||
|
||||
fn invert(&self) -> CtOption<Self> {
|
||||
let mut c0 = self.c2;
|
||||
c0.mul_by_nonresidue();
|
||||
c0.mul_assign(&self.c1);
|
||||
c0.negate();
|
||||
c0 = c0.neg();
|
||||
{
|
||||
let mut c0s = self.c0;
|
||||
c0s.square();
|
||||
let c0s = self.c0.square();
|
||||
c0.add_assign(&c0s);
|
||||
}
|
||||
let mut c1 = self.c2;
|
||||
c1.square();
|
||||
let mut c1 = self.c2.square();
|
||||
c1.mul_by_nonresidue();
|
||||
{
|
||||
let mut c01 = self.c0;
|
||||
c01.mul_assign(&self.c1);
|
||||
c1.sub_assign(&c01);
|
||||
}
|
||||
let mut c2 = self.c1;
|
||||
c2.square();
|
||||
let mut c2 = self.c1.square();
|
||||
{
|
||||
let mut c02 = self.c0;
|
||||
c02.mul_assign(&self.c2);
|
||||
@@ -281,21 +378,18 @@ impl Field for Fq6 {
|
||||
tmp2.mul_assign(&c0);
|
||||
tmp1.add_assign(&tmp2);
|
||||
|
||||
match tmp1.inverse() {
|
||||
Some(t) => {
|
||||
let mut tmp = Fq6 {
|
||||
c0: t,
|
||||
c1: t,
|
||||
c2: t,
|
||||
};
|
||||
tmp.c0.mul_assign(&c0);
|
||||
tmp.c1.mul_assign(&c1);
|
||||
tmp.c2.mul_assign(&c2);
|
||||
tmp1.invert().map(|t| {
|
||||
let mut tmp = Fq6 {
|
||||
c0: t,
|
||||
c1: t,
|
||||
c2: t,
|
||||
};
|
||||
tmp.c0.mul_assign(&c0);
|
||||
tmp.c1.mul_assign(&c1);
|
||||
tmp.c2.mul_assign(&c2);
|
||||
|
||||
Some(tmp)
|
||||
}
|
||||
None => None,
|
||||
}
|
||||
tmp
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,4 +1,5 @@
|
||||
use ff::{Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr};
|
||||
use std::ops::{AddAssign, MulAssign, SubAssign};
|
||||
|
||||
#[derive(PrimeField)]
|
||||
#[PrimeFieldModulus = "52435875175126190479447740508185965837690552500527637822603658699938581184513"]
|
||||
@@ -9,6 +10,8 @@ pub struct Fr(FrRepr);
|
||||
use rand_core::SeedableRng;
|
||||
#[cfg(test)]
|
||||
use rand_xorshift::XorShiftRng;
|
||||
#[cfg(test)]
|
||||
use std::ops::Neg;
|
||||
|
||||
#[test]
|
||||
fn test_fr_repr_ordering() {
|
||||
@@ -275,30 +278,6 @@ fn test_fr_repr_sub_noborrow() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fr_legendre() {
|
||||
use ff::LegendreSymbol::*;
|
||||
use ff::SqrtField;
|
||||
|
||||
assert_eq!(QuadraticResidue, Fr::one().legendre());
|
||||
assert_eq!(Zero, Fr::zero().legendre());
|
||||
|
||||
let e = FrRepr([
|
||||
0x0dbc5349cd5664da,
|
||||
0x8ac5b6296e3ae29d,
|
||||
0x127cb819feceaa3b,
|
||||
0x3a6b21fb03867191,
|
||||
]);
|
||||
assert_eq!(QuadraticResidue, Fr::from_repr(e).unwrap().legendre());
|
||||
let e = FrRepr([
|
||||
0x96341aefd047c045,
|
||||
0x9b5f4254500a4d65,
|
||||
0x1ee08223b68ac240,
|
||||
0x31d9cd545c0ec7c6,
|
||||
]);
|
||||
assert_eq!(QuadraticNonResidue, Fr::from_repr(e).unwrap().legendre());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fr_repr_add_nocarry() {
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
@@ -690,16 +669,15 @@ fn test_fr_mul_assign() {
|
||||
|
||||
#[test]
|
||||
fn test_fr_squaring() {
|
||||
let mut a = Fr(FrRepr([
|
||||
let a = Fr(FrRepr([
|
||||
0xffffffffffffffff,
|
||||
0xffffffffffffffff,
|
||||
0xffffffffffffffff,
|
||||
0x73eda753299d7d47,
|
||||
]));
|
||||
assert!(a.is_valid());
|
||||
a.square();
|
||||
assert_eq!(
|
||||
a,
|
||||
a.square(),
|
||||
Fr::from_repr(FrRepr([
|
||||
0xc0d698e7bde077b8,
|
||||
0xb79a310579e76ec2,
|
||||
@@ -717,20 +695,13 @@ fn test_fr_squaring() {
|
||||
for _ in 0..1000000 {
|
||||
// Ensure that (a * a) = a^2
|
||||
let a = Fr::random(&mut rng);
|
||||
|
||||
let mut tmp = a;
|
||||
tmp.square();
|
||||
|
||||
let mut tmp2 = a;
|
||||
tmp2.mul_assign(&a);
|
||||
|
||||
assert_eq!(tmp, tmp2);
|
||||
assert_eq!(a.square(), a * a);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fr_inverse() {
|
||||
assert!(Fr::zero().inverse().is_none());
|
||||
fn test_fr_invert() {
|
||||
assert!(bool::from(Fr::zero().invert().is_none()));
|
||||
|
||||
let mut rng = XorShiftRng::from_seed([
|
||||
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
|
||||
@@ -742,7 +713,7 @@ fn test_fr_inverse() {
|
||||
for _ in 0..1000 {
|
||||
// Ensure that a * a^-1 = 1
|
||||
let mut a = Fr::random(&mut rng);
|
||||
let ainv = a.inverse().unwrap();
|
||||
let ainv = a.invert().unwrap();
|
||||
a.mul_assign(&ainv);
|
||||
assert_eq!(a, one);
|
||||
}
|
||||
@@ -757,19 +728,15 @@ fn test_fr_double() {
|
||||
|
||||
for _ in 0..1000 {
|
||||
// Ensure doubling a is equivalent to adding a to itself.
|
||||
let mut a = Fr::random(&mut rng);
|
||||
let mut b = a;
|
||||
b.add_assign(&a);
|
||||
a.double();
|
||||
assert_eq!(a, b);
|
||||
let a = Fr::random(&mut rng);
|
||||
assert_eq!(a.double(), a + a);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fr_negate() {
|
||||
fn test_fr_neg() {
|
||||
{
|
||||
let mut a = Fr::zero();
|
||||
a.negate();
|
||||
let a = Fr::zero().neg();
|
||||
|
||||
assert!(a.is_zero());
|
||||
}
|
||||
@@ -782,8 +749,7 @@ fn test_fr_negate() {
|
||||
for _ in 0..1000 {
|
||||
// Ensure (a - (-a)) = 0.
|
||||
let mut a = Fr::random(&mut rng);
|
||||
let mut b = a;
|
||||
b.negate();
|
||||
let b = a.neg();
|
||||
a.add_assign(&b);
|
||||
|
||||
assert!(a.is_zero());
|
||||
@@ -801,7 +767,7 @@ fn test_fr_pow() {
|
||||
// Exponentiate by various small numbers and ensure it consists with repeated
|
||||
// multiplication.
|
||||
let a = Fr::random(&mut rng);
|
||||
let target = a.pow(&[i]);
|
||||
let target = a.pow_vartime(&[i]);
|
||||
let mut c = Fr::one();
|
||||
for _ in 0..i {
|
||||
c.mul_assign(&a);
|
||||
@@ -813,7 +779,7 @@ fn test_fr_pow() {
|
||||
// Exponentiating by the modulus should have no effect in a prime field.
|
||||
let a = Fr::random(&mut rng);
|
||||
|
||||
assert_eq!(a, a.pow(Fr::char()));
|
||||
assert_eq!(a, a.pow_vartime(Fr::char()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -831,10 +797,8 @@ fn test_fr_sqrt() {
|
||||
for _ in 0..1000 {
|
||||
// Ensure sqrt(a^2) = a or -a
|
||||
let a = Fr::random(&mut rng);
|
||||
let mut nega = a;
|
||||
nega.negate();
|
||||
let mut b = a;
|
||||
b.square();
|
||||
let nega = a.neg();
|
||||
let b = a.square();
|
||||
|
||||
let b = b.sqrt().unwrap();
|
||||
|
||||
@@ -845,10 +809,9 @@ fn test_fr_sqrt() {
|
||||
// Ensure sqrt(a)^2 = a for random a
|
||||
let a = Fr::random(&mut rng);
|
||||
|
||||
if let Some(mut tmp) = a.sqrt() {
|
||||
tmp.square();
|
||||
|
||||
assert_eq!(a, tmp);
|
||||
let tmp = a.sqrt();
|
||||
if tmp.is_some().into() {
|
||||
assert_eq!(a, tmp.unwrap().square());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1001,7 +964,7 @@ fn test_fr_root_of_unity() {
|
||||
Fr::from_repr(FrRepr::from(7)).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Fr::multiplicative_generator().pow([
|
||||
Fr::multiplicative_generator().pow_vartime([
|
||||
0xfffe5bfeffffffff,
|
||||
0x9a1d80553bda402,
|
||||
0x299d7d483339d808,
|
||||
@@ -1009,8 +972,8 @@ fn test_fr_root_of_unity() {
|
||||
]),
|
||||
Fr::root_of_unity()
|
||||
);
|
||||
assert_eq!(Fr::root_of_unity().pow([1 << Fr::S]), Fr::one());
|
||||
assert!(Fr::multiplicative_generator().sqrt().is_none());
|
||||
assert_eq!(Fr::root_of_unity().pow_vartime([1 << Fr::S]), Fr::one());
|
||||
assert!(bool::from(Fr::multiplicative_generator().sqrt().is_none()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@@ -25,6 +25,8 @@ use super::{Engine, PairingCurveAffine};
|
||||
|
||||
use ff::{BitIterator, Field, ScalarEngine};
|
||||
use group::CurveAffine;
|
||||
use std::ops::{AddAssign, MulAssign, Neg, SubAssign};
|
||||
use subtle::CtOption;
|
||||
|
||||
// The BLS parameter x for BLS12-381 is -0xd201000000010000
|
||||
const BLS_X: u64 = 0xd201000000010000;
|
||||
@@ -96,7 +98,7 @@ impl Engine for Bls12 {
|
||||
}
|
||||
}
|
||||
|
||||
f.square();
|
||||
f = f.square();
|
||||
}
|
||||
|
||||
for &mut (p, ref mut coeffs) in &mut pairs {
|
||||
@@ -110,62 +112,58 @@ impl Engine for Bls12 {
|
||||
f
|
||||
}
|
||||
|
||||
fn final_exponentiation(r: &Fq12) -> Option<Fq12> {
|
||||
fn final_exponentiation(r: &Fq12) -> CtOption<Fq12> {
|
||||
let mut f1 = *r;
|
||||
f1.conjugate();
|
||||
|
||||
match r.inverse() {
|
||||
Some(mut f2) => {
|
||||
let mut r = f1;
|
||||
r.mul_assign(&f2);
|
||||
f2 = r;
|
||||
r.frobenius_map(2);
|
||||
r.mul_assign(&f2);
|
||||
r.invert().map(|mut f2| {
|
||||
let mut r = f1;
|
||||
r.mul_assign(&f2);
|
||||
f2 = r;
|
||||
r.frobenius_map(2);
|
||||
r.mul_assign(&f2);
|
||||
|
||||
fn exp_by_x(f: &mut Fq12, x: u64) {
|
||||
*f = f.pow(&[x]);
|
||||
if BLS_X_IS_NEGATIVE {
|
||||
f.conjugate();
|
||||
}
|
||||
fn exp_by_x(f: &mut Fq12, x: u64) {
|
||||
*f = f.pow_vartime(&[x]);
|
||||
if BLS_X_IS_NEGATIVE {
|
||||
f.conjugate();
|
||||
}
|
||||
|
||||
let mut x = BLS_X;
|
||||
let mut y0 = r;
|
||||
y0.square();
|
||||
let mut y1 = y0;
|
||||
exp_by_x(&mut y1, x);
|
||||
x >>= 1;
|
||||
let mut y2 = y1;
|
||||
exp_by_x(&mut y2, x);
|
||||
x <<= 1;
|
||||
let mut y3 = r;
|
||||
y3.conjugate();
|
||||
y1.mul_assign(&y3);
|
||||
y1.conjugate();
|
||||
y1.mul_assign(&y2);
|
||||
y2 = y1;
|
||||
exp_by_x(&mut y2, x);
|
||||
y3 = y2;
|
||||
exp_by_x(&mut y3, x);
|
||||
y1.conjugate();
|
||||
y3.mul_assign(&y1);
|
||||
y1.conjugate();
|
||||
y1.frobenius_map(3);
|
||||
y2.frobenius_map(2);
|
||||
y1.mul_assign(&y2);
|
||||
y2 = y3;
|
||||
exp_by_x(&mut y2, x);
|
||||
y2.mul_assign(&y0);
|
||||
y2.mul_assign(&r);
|
||||
y1.mul_assign(&y2);
|
||||
y2 = y3;
|
||||
y2.frobenius_map(1);
|
||||
y1.mul_assign(&y2);
|
||||
|
||||
Some(y1)
|
||||
}
|
||||
None => None,
|
||||
}
|
||||
|
||||
let mut x = BLS_X;
|
||||
let y0 = r.square();
|
||||
let mut y1 = y0;
|
||||
exp_by_x(&mut y1, x);
|
||||
x >>= 1;
|
||||
let mut y2 = y1;
|
||||
exp_by_x(&mut y2, x);
|
||||
x <<= 1;
|
||||
let mut y3 = r;
|
||||
y3.conjugate();
|
||||
y1.mul_assign(&y3);
|
||||
y1.conjugate();
|
||||
y1.mul_assign(&y2);
|
||||
y2 = y1;
|
||||
exp_by_x(&mut y2, x);
|
||||
y3 = y2;
|
||||
exp_by_x(&mut y3, x);
|
||||
y1.conjugate();
|
||||
y3.mul_assign(&y1);
|
||||
y1.conjugate();
|
||||
y1.frobenius_map(3);
|
||||
y2.frobenius_map(2);
|
||||
y1.mul_assign(&y2);
|
||||
y2 = y3;
|
||||
exp_by_x(&mut y2, x);
|
||||
y2.mul_assign(&y0);
|
||||
y2.mul_assign(&r);
|
||||
y1.mul_assign(&y2);
|
||||
y2 = y3;
|
||||
y2.frobenius_map(1);
|
||||
y1.mul_assign(&y2);
|
||||
|
||||
y1
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,41 +182,35 @@ impl G2Prepared {
|
||||
|
||||
fn doubling_step(r: &mut G2) -> (Fq2, Fq2, Fq2) {
|
||||
// Adaptation of Algorithm 26, https://eprint.iacr.org/2010/354.pdf
|
||||
let mut tmp0 = r.x;
|
||||
tmp0.square();
|
||||
let mut tmp0 = r.x.square();
|
||||
|
||||
let mut tmp1 = r.y;
|
||||
tmp1.square();
|
||||
let mut tmp1 = r.y.square();
|
||||
|
||||
let mut tmp2 = tmp1;
|
||||
tmp2.square();
|
||||
let mut tmp2 = tmp1.square();
|
||||
|
||||
let mut tmp3 = tmp1;
|
||||
tmp3.add_assign(&r.x);
|
||||
tmp3.square();
|
||||
tmp3 = tmp3.square();
|
||||
tmp3.sub_assign(&tmp0);
|
||||
tmp3.sub_assign(&tmp2);
|
||||
tmp3.double();
|
||||
tmp3 = tmp3.double();
|
||||
|
||||
let mut tmp4 = tmp0;
|
||||
tmp4.double();
|
||||
let mut tmp4 = tmp0.double();
|
||||
tmp4.add_assign(&tmp0);
|
||||
|
||||
let mut tmp6 = r.x;
|
||||
tmp6.add_assign(&tmp4);
|
||||
|
||||
let mut tmp5 = tmp4;
|
||||
tmp5.square();
|
||||
let tmp5 = tmp4.square();
|
||||
|
||||
let mut zsquared = r.z;
|
||||
zsquared.square();
|
||||
let zsquared = r.z.square();
|
||||
|
||||
r.x = tmp5;
|
||||
r.x.sub_assign(&tmp3);
|
||||
r.x.sub_assign(&tmp3);
|
||||
|
||||
r.z.add_assign(&r.y);
|
||||
r.z.square();
|
||||
r.z = r.z.square();
|
||||
r.z.sub_assign(&tmp1);
|
||||
r.z.sub_assign(&zsquared);
|
||||
|
||||
@@ -226,47 +218,41 @@ impl G2Prepared {
|
||||
r.y.sub_assign(&r.x);
|
||||
r.y.mul_assign(&tmp4);
|
||||
|
||||
tmp2.double();
|
||||
tmp2.double();
|
||||
tmp2.double();
|
||||
tmp2 = tmp2.double().double().double();
|
||||
|
||||
r.y.sub_assign(&tmp2);
|
||||
|
||||
tmp3 = tmp4;
|
||||
tmp3.mul_assign(&zsquared);
|
||||
tmp3.double();
|
||||
tmp3.negate();
|
||||
tmp3 = tmp3.double().neg();
|
||||
|
||||
tmp6.square();
|
||||
tmp6 = tmp6.square();
|
||||
tmp6.sub_assign(&tmp0);
|
||||
tmp6.sub_assign(&tmp5);
|
||||
|
||||
tmp1.double();
|
||||
tmp1.double();
|
||||
tmp1 = tmp1.double().double();
|
||||
|
||||
tmp6.sub_assign(&tmp1);
|
||||
|
||||
tmp0 = r.z;
|
||||
tmp0.mul_assign(&zsquared);
|
||||
tmp0.double();
|
||||
tmp0 = tmp0.double();
|
||||
|
||||
(tmp0, tmp3, tmp6)
|
||||
}
|
||||
|
||||
fn addition_step(r: &mut G2, q: &G2Affine) -> (Fq2, Fq2, Fq2) {
|
||||
// Adaptation of Algorithm 27, https://eprint.iacr.org/2010/354.pdf
|
||||
let mut zsquared = r.z;
|
||||
zsquared.square();
|
||||
let zsquared = r.z.square();
|
||||
|
||||
let mut ysquared = q.y;
|
||||
ysquared.square();
|
||||
let ysquared = q.y.square();
|
||||
|
||||
let mut t0 = zsquared;
|
||||
t0.mul_assign(&q.x);
|
||||
|
||||
let mut t1 = q.y;
|
||||
t1.add_assign(&r.z);
|
||||
t1.square();
|
||||
t1 = t1.square();
|
||||
t1.sub_assign(&ysquared);
|
||||
t1.sub_assign(&zsquared);
|
||||
t1.mul_assign(&zsquared);
|
||||
@@ -274,12 +260,9 @@ impl G2Prepared {
|
||||
let mut t2 = t0;
|
||||
t2.sub_assign(&r.x);
|
||||
|
||||
let mut t3 = t2;
|
||||
t3.square();
|
||||
let t3 = t2.square();
|
||||
|
||||
let mut t4 = t3;
|
||||
t4.double();
|
||||
t4.double();
|
||||
let t4 = t3.double().double();
|
||||
|
||||
let mut t5 = t4;
|
||||
t5.mul_assign(&t2);
|
||||
@@ -294,14 +277,13 @@ impl G2Prepared {
|
||||
let mut t7 = t4;
|
||||
t7.mul_assign(&r.x);
|
||||
|
||||
r.x = t6;
|
||||
r.x.square();
|
||||
r.x = t6.square();
|
||||
r.x.sub_assign(&t5);
|
||||
r.x.sub_assign(&t7);
|
||||
r.x.sub_assign(&t7);
|
||||
|
||||
r.z.add_assign(&t2);
|
||||
r.z.square();
|
||||
r.z = r.z.square();
|
||||
r.z.sub_assign(&zsquared);
|
||||
r.z.sub_assign(&t3);
|
||||
|
||||
@@ -314,29 +296,26 @@ impl G2Prepared {
|
||||
|
||||
t0 = r.y;
|
||||
t0.mul_assign(&t5);
|
||||
t0.double();
|
||||
t0 = t0.double();
|
||||
|
||||
r.y = t8;
|
||||
r.y.sub_assign(&t0);
|
||||
|
||||
t10.square();
|
||||
t10 = t10.square();
|
||||
t10.sub_assign(&ysquared);
|
||||
|
||||
let mut ztsquared = r.z;
|
||||
ztsquared.square();
|
||||
let ztsquared = r.z.square();
|
||||
|
||||
t10.sub_assign(&ztsquared);
|
||||
|
||||
t9.double();
|
||||
t9 = t9.double();
|
||||
t9.sub_assign(&t10);
|
||||
|
||||
t10 = r.z;
|
||||
t10.double();
|
||||
t10 = r.z.double();
|
||||
|
||||
t6.negate();
|
||||
t6 = t6.neg();
|
||||
|
||||
t1 = t6;
|
||||
t1.double();
|
||||
t1 = t6.double();
|
||||
|
||||
(t10, t1, t9)
|
||||
}
|
||||
|
@@ -189,12 +189,14 @@ fn test_g1_uncompressed_invalid_vectors() {
|
||||
let mut x = Fq::one();
|
||||
|
||||
loop {
|
||||
let mut x3b = x;
|
||||
x3b.square();
|
||||
let mut x3b = x.square();
|
||||
x3b.mul_assign(&x);
|
||||
x3b.add_assign(&Fq::from_repr(FqRepr::from(4)).unwrap()); // TODO: perhaps expose coeff_b through API?
|
||||
|
||||
if let Some(y) = x3b.sqrt() {
|
||||
let y = x3b.sqrt();
|
||||
if y.is_some().into() {
|
||||
let y = y.unwrap();
|
||||
|
||||
// We know this is on the curve, but it's likely not going to be in the correct subgroup.
|
||||
x.into_repr().write_be(&mut o.as_mut()[0..]).unwrap();
|
||||
y.into_repr().write_be(&mut o.as_mut()[48..]).unwrap();
|
||||
@@ -326,15 +328,17 @@ fn test_g2_uncompressed_invalid_vectors() {
|
||||
let mut x = Fq2::one();
|
||||
|
||||
loop {
|
||||
let mut x3b = x;
|
||||
x3b.square();
|
||||
let mut x3b = x.square();
|
||||
x3b.mul_assign(&x);
|
||||
x3b.add_assign(&Fq2 {
|
||||
c0: Fq::from_repr(FqRepr::from(4)).unwrap(),
|
||||
c1: Fq::from_repr(FqRepr::from(4)).unwrap(),
|
||||
}); // TODO: perhaps expose coeff_b through API?
|
||||
|
||||
if let Some(y) = x3b.sqrt() {
|
||||
let y = x3b.sqrt();
|
||||
if y.is_some().into() {
|
||||
let y = y.unwrap();
|
||||
|
||||
// We know this is on the curve, but it's likely not going to be in the correct subgroup.
|
||||
x.c1.into_repr().write_be(&mut o.as_mut()[0..]).unwrap();
|
||||
x.c0.into_repr().write_be(&mut o.as_mut()[48..]).unwrap();
|
||||
@@ -422,12 +426,11 @@ fn test_g1_compressed_invalid_vectors() {
|
||||
let mut x = Fq::one();
|
||||
|
||||
loop {
|
||||
let mut x3b = x;
|
||||
x3b.square();
|
||||
let mut x3b = x.square();
|
||||
x3b.mul_assign(&x);
|
||||
x3b.add_assign(&Fq::from_repr(FqRepr::from(4)).unwrap()); // TODO: perhaps expose coeff_b through API?
|
||||
|
||||
if let Some(_) = x3b.sqrt() {
|
||||
if x3b.sqrt().is_some().into() {
|
||||
x.add_assign(&Fq::one());
|
||||
} else {
|
||||
x.into_repr().write_be(&mut o.as_mut()[0..]).unwrap();
|
||||
@@ -447,12 +450,11 @@ fn test_g1_compressed_invalid_vectors() {
|
||||
let mut x = Fq::one();
|
||||
|
||||
loop {
|
||||
let mut x3b = x;
|
||||
x3b.square();
|
||||
let mut x3b = x.square();
|
||||
x3b.mul_assign(&x);
|
||||
x3b.add_assign(&Fq::from_repr(FqRepr::from(4)).unwrap()); // TODO: perhaps expose coeff_b through API?
|
||||
|
||||
if let Some(_) = x3b.sqrt() {
|
||||
if x3b.sqrt().is_some().into() {
|
||||
// We know this is on the curve, but it's likely not going to be in the correct subgroup.
|
||||
x.into_repr().write_be(&mut o.as_mut()[0..]).unwrap();
|
||||
o.as_mut()[0] |= 0b1000_0000;
|
||||
@@ -553,15 +555,14 @@ fn test_g2_compressed_invalid_vectors() {
|
||||
};
|
||||
|
||||
loop {
|
||||
let mut x3b = x;
|
||||
x3b.square();
|
||||
let mut x3b = x.square();
|
||||
x3b.mul_assign(&x);
|
||||
x3b.add_assign(&Fq2 {
|
||||
c0: Fq::from_repr(FqRepr::from(4)).unwrap(),
|
||||
c1: Fq::from_repr(FqRepr::from(4)).unwrap(),
|
||||
}); // TODO: perhaps expose coeff_b through API?
|
||||
|
||||
if let Some(_) = x3b.sqrt() {
|
||||
if x3b.sqrt().is_some().into() {
|
||||
x.add_assign(&Fq2::one());
|
||||
} else {
|
||||
x.c1.into_repr().write_be(&mut o.as_mut()[0..]).unwrap();
|
||||
@@ -585,15 +586,14 @@ fn test_g2_compressed_invalid_vectors() {
|
||||
};
|
||||
|
||||
loop {
|
||||
let mut x3b = x;
|
||||
x3b.square();
|
||||
let mut x3b = x.square();
|
||||
x3b.mul_assign(&x);
|
||||
x3b.add_assign(&Fq2 {
|
||||
c0: Fq::from_repr(FqRepr::from(4)).unwrap(),
|
||||
c1: Fq::from_repr(FqRepr::from(4)).unwrap(),
|
||||
}); // TODO: perhaps expose coeff_b through API?
|
||||
|
||||
if let Some(_) = x3b.sqrt() {
|
||||
if x3b.sqrt().is_some().into() {
|
||||
// We know this is on the curve, but it's likely not going to be in the correct subgroup.
|
||||
x.c1.into_repr().write_be(&mut o.as_mut()[0..]).unwrap();
|
||||
x.c0.into_repr().write_be(&mut o.as_mut()[48..]).unwrap();
|
||||
|
@@ -21,19 +21,18 @@ 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.)
|
||||
/// with well-defined relationships. In particular, the G1/G2 curve groups are
|
||||
/// of prime order `r`, and are equipped with a bilinear pairing function.
|
||||
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>;
|
||||
type G1: CurveProjective<Engine = Self, Base = Self::Fq, Scalar = Self::Fr, Affine = Self::G1Affine>
|
||||
+ From<Self::G1Affine>
|
||||
+ CurveOps<Self::G1Affine>
|
||||
+ CurveOpsOwned<Self::G1Affine>;
|
||||
|
||||
/// The affine representation of an element in G1.
|
||||
type G1Affine: PairingCurveAffine<
|
||||
@@ -46,12 +45,10 @@ pub trait Engine: ScalarEngine {
|
||||
> + From<Self::G1>;
|
||||
|
||||
/// 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>;
|
||||
type G2: CurveProjective<Engine = Self, Base = Self::Fqe, Scalar = Self::Fr, Affine = Self::G2Affine>
|
||||
+ From<Self::G2Affine>
|
||||
+ CurveOps<Self::G2Affine>
|
||||
+ CurveOpsOwned<Self::G2Affine>;
|
||||
|
||||
/// The affine representation of an element in G2.
|
||||
type G2Affine: PairingCurveAffine<
|
||||
@@ -83,7 +80,7 @@ pub trait Engine: ScalarEngine {
|
||||
>;
|
||||
|
||||
/// Perform final exponentiation of the result of a miller loop.
|
||||
fn final_exponentiation(_: &Self::Fqk) -> Option<Self::Fqk>;
|
||||
fn final_exponentiation(_: &Self::Fqk) -> CtOption<Self::Fqk>;
|
||||
|
||||
/// Performs a complete pairing operation `(p, q)`.
|
||||
fn pairing<G1, G2>(p: G1, q: G2) -> Self::Fqk
|
||||
|
@@ -1,6 +1,7 @@
|
||||
use group::{CurveAffine, CurveProjective};
|
||||
use rand_core::SeedableRng;
|
||||
use rand_xorshift::XorShiftRng;
|
||||
use std::ops::MulAssign;
|
||||
|
||||
use crate::{Engine, Field, PairingCurveAffine, PrimeField};
|
||||
|
||||
@@ -129,7 +130,7 @@ fn random_bilinearity_tests<E: Engine>() {
|
||||
let mut cd = c;
|
||||
cd.mul_assign(&d);
|
||||
|
||||
let abcd = E::pairing(a, b).pow(cd.into_repr());
|
||||
let abcd = E::pairing(a, b).pow_vartime(cd.into_repr());
|
||||
|
||||
assert_eq!(acbd, adbc);
|
||||
assert_eq!(acbd, abcd);
|
||||
|
@@ -1,4 +1,4 @@
|
||||
use ff::{Field, LegendreSymbol, PrimeField, SqrtField};
|
||||
use ff::{Field, PrimeField, SqrtField};
|
||||
use rand_core::{RngCore, SeedableRng};
|
||||
use rand_xorshift::XorShiftRng;
|
||||
|
||||
@@ -9,12 +9,12 @@ pub fn random_frobenius_tests<F: Field, C: AsRef<[u64]>>(characteristic: C, maxp
|
||||
]);
|
||||
|
||||
for _ in 0..100 {
|
||||
for i in 0..(maxpower + 1) {
|
||||
for i in 0..=maxpower {
|
||||
let mut a = F::random(&mut rng);
|
||||
let mut b = a;
|
||||
|
||||
for _ in 0..i {
|
||||
a = a.pow(&characteristic);
|
||||
a = a.pow_vartime(&characteristic);
|
||||
}
|
||||
b.frobenius_map(i);
|
||||
|
||||
@@ -31,27 +31,22 @@ pub fn random_sqrt_tests<F: SqrtField>() {
|
||||
|
||||
for _ in 0..10000 {
|
||||
let a = F::random(&mut rng);
|
||||
let mut b = a;
|
||||
b.square();
|
||||
assert_eq!(b.legendre(), LegendreSymbol::QuadraticResidue);
|
||||
let b = a.square();
|
||||
|
||||
let b = b.sqrt().unwrap();
|
||||
let mut negb = b;
|
||||
negb.negate();
|
||||
let negb = b.neg();
|
||||
|
||||
assert!(a == b || a == negb);
|
||||
}
|
||||
|
||||
let mut c = F::one();
|
||||
for _ in 0..10000 {
|
||||
let mut b = c;
|
||||
b.square();
|
||||
assert_eq!(b.legendre(), LegendreSymbol::QuadraticResidue);
|
||||
let mut b = c.square();
|
||||
|
||||
b = b.sqrt().unwrap();
|
||||
|
||||
if b != c {
|
||||
b.negate();
|
||||
b = b.neg();
|
||||
}
|
||||
|
||||
assert_eq!(b, c);
|
||||
@@ -77,12 +72,11 @@ pub fn random_field_tests<F: Field>() {
|
||||
|
||||
assert!(F::zero().is_zero());
|
||||
{
|
||||
let mut z = F::zero();
|
||||
z.negate();
|
||||
let z = F::zero().neg();
|
||||
assert!(z.is_zero());
|
||||
}
|
||||
|
||||
assert!(F::zero().inverse().is_none());
|
||||
assert!(bool::from(F::zero().invert().is_none()));
|
||||
|
||||
// Multiplication by zero
|
||||
{
|
||||
@@ -204,8 +198,7 @@ fn random_subtraction_tests<F: Field, R: RngCore>(rng: &mut R) {
|
||||
fn random_negation_tests<F: Field, R: RngCore>(rng: &mut R) {
|
||||
for _ in 0..10000 {
|
||||
let a = F::random(rng);
|
||||
let mut b = a;
|
||||
b.negate();
|
||||
let mut b = a.neg();
|
||||
b.add_assign(&a);
|
||||
|
||||
assert!(b.is_zero());
|
||||
@@ -214,32 +207,24 @@ fn random_negation_tests<F: Field, R: RngCore>(rng: &mut R) {
|
||||
|
||||
fn random_doubling_tests<F: Field, R: RngCore>(rng: &mut R) {
|
||||
for _ in 0..10000 {
|
||||
let mut a = F::random(rng);
|
||||
let mut b = a;
|
||||
a.add_assign(&b);
|
||||
b.double();
|
||||
|
||||
assert_eq!(a, b);
|
||||
let a = F::random(rng);
|
||||
assert_eq!(a + a, a.double());
|
||||
}
|
||||
}
|
||||
|
||||
fn random_squaring_tests<F: Field, R: RngCore>(rng: &mut R) {
|
||||
for _ in 0..10000 {
|
||||
let mut a = F::random(rng);
|
||||
let mut b = a;
|
||||
a.mul_assign(&b);
|
||||
b.square();
|
||||
|
||||
assert_eq!(a, b);
|
||||
let a = F::random(rng);
|
||||
assert_eq!(a * a, a.square());
|
||||
}
|
||||
}
|
||||
|
||||
fn random_inversion_tests<F: Field, R: RngCore>(rng: &mut R) {
|
||||
assert!(F::zero().inverse().is_none());
|
||||
assert!(bool::from(F::zero().invert().is_none()));
|
||||
|
||||
for _ in 0..10000 {
|
||||
let mut a = F::random(rng);
|
||||
let b = a.inverse().unwrap(); // probablistically nonzero
|
||||
let b = a.invert().unwrap(); // probablistically nonzero
|
||||
a.mul_assign(&b);
|
||||
|
||||
assert_eq!(a, F::one());
|
||||
|
@@ -68,7 +68,7 @@ fn random_shl_tests<P: PrimeField>() {
|
||||
for _ in 0..100 {
|
||||
let r = P::random(&mut rng).into_repr();
|
||||
|
||||
for shift in 0..(r.num_bits() + 1) {
|
||||
for shift in 0..=r.num_bits() {
|
||||
let mut r1 = r;
|
||||
let mut r2 = r;
|
||||
|
||||
@@ -92,7 +92,7 @@ fn random_shr_tests<P: PrimeField>() {
|
||||
for _ in 0..100 {
|
||||
let r = P::random(&mut rng).into_repr();
|
||||
|
||||
for shift in 0..(r.num_bits() + 1) {
|
||||
for shift in 0..=r.num_bits() {
|
||||
let mut r1 = r;
|
||||
let mut r2 = r;
|
||||
|
||||
|
Reference in New Issue
Block a user