Files
pirate-librustzcash/src/tests/field.rs
2017-07-08 10:55:43 -06:00

230 lines
5.2 KiB
Rust

use rand::{Rng, SeedableRng, XorShiftRng};
use ::{SqrtField, Field};
pub fn random_frobenius_tests<F: Field, C: AsRef<[u64]>>(characteristic: C, maxpower: usize) {
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
for _ in 0..100 {
for i in 0..(maxpower+1) {
let mut a = F::rand(&mut rng);
let mut b = a;
for _ in 0..i {
a = a.pow(&characteristic);
}
b.frobenius_map(i);
assert_eq!(a, b);
}
}
}
pub fn random_sqrt_tests<F: SqrtField>() {
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
for _ in 0..10000 {
let a = F::rand(&mut rng);
let mut b = a;
b.square();
let b = b.sqrt().unwrap();
let mut negb = b;
negb.negate();
assert!(a == b || a == negb);
}
let mut c = F::one();
for _ in 0..10000 {
let mut b = c;
b.square();
b = b.sqrt().unwrap();
if b != c {
b.negate();
}
assert_eq!(b, c);
c.add_assign(&F::one());
}
}
pub fn random_field_tests<F: Field>() {
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
random_multiplication_tests::<F, _>(&mut rng);
random_addition_tests::<F, _>(&mut rng);
random_subtraction_tests::<F, _>(&mut rng);
random_negation_tests::<F, _>(&mut rng);
random_doubling_tests::<F, _>(&mut rng);
random_squaring_tests::<F, _>(&mut rng);
random_inversion_tests::<F, _>(&mut rng);
random_expansion_tests::<F, _>(&mut rng);
assert!(F::zero().is_zero());
{
let mut z = F::zero();
z.negate();
assert!(z.is_zero());
}
assert!(F::zero().inverse().is_none());
// Multiplication by zero
{
let mut a = F::rand(&mut rng);
a.mul_assign(&F::zero());
assert!(a.is_zero());
}
// Addition by zero
{
let mut a = F::rand(&mut rng);
let copy = a;
a.add_assign(&F::zero());
assert_eq!(a, copy);
}
}
fn random_multiplication_tests<F: Field, R: Rng>(rng: &mut R) {
for _ in 0..10000 {
let a = F::rand(rng);
let b = F::rand(rng);
let c = F::rand(rng);
let mut t0 = a; // (a * b) * c
t0.mul_assign(&b);
t0.mul_assign(&c);
let mut t1 = a; // (a * c) * b
t1.mul_assign(&c);
t1.mul_assign(&b);
let mut t2 = b; // (b * c) * a
t2.mul_assign(&c);
t2.mul_assign(&a);
assert_eq!(t0, t1);
assert_eq!(t1, t2);
}
}
fn random_addition_tests<F: Field, R: Rng>(rng: &mut R) {
for _ in 0..10000 {
let a = F::rand(rng);
let b = F::rand(rng);
let c = F::rand(rng);
let mut t0 = a; // (a + b) + c
t0.add_assign(&b);
t0.add_assign(&c);
let mut t1 = a; // (a + c) + b
t1.add_assign(&c);
t1.add_assign(&b);
let mut t2 = b; // (b + c) + a
t2.add_assign(&c);
t2.add_assign(&a);
assert_eq!(t0, t1);
assert_eq!(t1, t2);
}
}
fn random_subtraction_tests<F: Field, R: Rng>(rng: &mut R) {
for _ in 0..10000 {
let a = F::rand(rng);
let b = F::rand(rng);
let mut t0 = a; // (a - b)
t0.sub_assign(&b);
let mut t1 = b; // (b - a)
t1.sub_assign(&a);
let mut t2 = t0; // (a - b) + (b - a) = 0
t2.add_assign(&t1);
assert!(t2.is_zero());
}
}
fn random_negation_tests<F: Field, R: Rng>(rng: &mut R) {
for _ in 0..10000 {
let a = F::rand(rng);
let mut b = a;
b.negate();
b.add_assign(&a);
assert!(b.is_zero());
}
}
fn random_doubling_tests<F: Field, R: Rng>(rng: &mut R) {
for _ in 0..10000 {
let mut a = F::rand(rng);
let mut b = a;
a.add_assign(&b);
b.double();
assert_eq!(a, b);
}
}
fn random_squaring_tests<F: Field, R: Rng>(rng: &mut R) {
for _ in 0..10000 {
let mut a = F::rand(rng);
let mut b = a;
a.mul_assign(&b);
b.square();
assert_eq!(a, b);
}
}
fn random_inversion_tests<F: Field, R: Rng>(rng: &mut R) {
assert!(F::zero().inverse().is_none());
for _ in 0..10000 {
let mut a = F::rand(rng);
let b = a.inverse().unwrap(); // probablistically nonzero
a.mul_assign(&b);
assert_eq!(a, F::one());
}
}
fn random_expansion_tests<F: Field, R: Rng>(rng: &mut R) {
for _ in 0..10000 {
// Compare (a + b)(c + d) and (a*c + b*c + a*d + b*d)
let a = F::rand(rng);
let b = F::rand(rng);
let c = F::rand(rng);
let d = F::rand(rng);
let mut t0 = a;
t0.add_assign(&b);
let mut t1 = c;
t1.add_assign(&d);
t0.mul_assign(&t1);
let mut t2 = a;
t2.mul_assign(&c);
let mut t3 = b;
t3.mul_assign(&c);
let mut t4 = a;
t4.mul_assign(&d);
let mut t5 = b;
t5.mul_assign(&d);
t2.add_assign(&t3);
t2.add_assign(&t4);
t2.add_assign(&t5);
assert_eq!(t0, t2);
}
}