2016-07-01 12:50:55 -07:00
|
|
|
use rand::{Rng,SeedableRng,StdRng};
|
2016-08-28 10:30:40 -07:00
|
|
|
use super::FieldElement;
|
2016-07-01 12:50:55 -07:00
|
|
|
|
2016-08-28 10:30:40 -07:00
|
|
|
fn can_invert<F: FieldElement>() {
|
|
|
|
let mut a = F::one();
|
2016-07-01 12:50:55 -07:00
|
|
|
|
2016-08-28 10:30:40 -07:00
|
|
|
for _ in 0..10000 {
|
2016-08-28 21:04:46 -07:00
|
|
|
assert_eq!(a * a.inverse().unwrap(), F::one());
|
2016-07-01 12:50:55 -07:00
|
|
|
|
2016-08-28 10:30:40 -07:00
|
|
|
a = a + F::one();
|
2016-07-01 12:50:55 -07:00
|
|
|
}
|
|
|
|
|
2016-08-28 10:30:40 -07:00
|
|
|
a = -F::one();
|
|
|
|
for _ in 0..10000 {
|
2016-08-28 21:04:46 -07:00
|
|
|
assert_eq!(a * a.inverse().unwrap(), F::one());
|
2016-07-01 12:50:55 -07:00
|
|
|
|
2016-08-28 10:30:40 -07:00
|
|
|
a = a - F::one();
|
2016-07-01 12:50:55 -07:00
|
|
|
}
|
2016-08-28 21:04:46 -07:00
|
|
|
|
|
|
|
assert_eq!(F::zero().inverse(), None);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn rand_element_eval<F: FieldElement, R: Rng>(rng: &mut R) {
|
|
|
|
for _ in 0..100 {
|
|
|
|
let a = F::random(rng);
|
|
|
|
let b = F::random(rng);
|
|
|
|
let c = F::random(rng);
|
|
|
|
let d = F::random(rng);
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
(a + b) * (c + d),
|
|
|
|
(a * c) + (b * c) + (a * d) + (b * d)
|
|
|
|
);
|
|
|
|
}
|
2016-07-01 12:50:55 -07:00
|
|
|
}
|
|
|
|
|
2016-08-28 10:30:40 -07:00
|
|
|
fn rand_element_squaring<F: FieldElement, R: Rng>(rng: &mut R) {
|
2016-07-01 12:50:55 -07:00
|
|
|
for _ in 0..100 {
|
|
|
|
let a = F::random(rng);
|
|
|
|
|
2016-08-28 10:30:40 -07:00
|
|
|
assert!(a * a == a.squared());
|
2016-07-01 12:50:55 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
let mut cur = F::zero();
|
|
|
|
for _ in 0..100 {
|
2016-08-28 10:30:40 -07:00
|
|
|
assert_eq!(cur.squared(), cur * cur);
|
2016-07-01 12:50:55 -07:00
|
|
|
|
2016-08-28 10:30:40 -07:00
|
|
|
cur = cur + F::one();
|
2016-07-01 12:50:55 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-28 10:30:40 -07:00
|
|
|
fn rand_element_addition_and_negation<F: FieldElement, R: Rng>(rng: &mut R) {
|
2016-08-28 21:04:46 -07:00
|
|
|
for _ in 0..100 {
|
|
|
|
let a = F::random(rng);
|
|
|
|
|
|
|
|
assert_eq!(a + (-a), F::zero());
|
|
|
|
}
|
|
|
|
|
2016-08-28 10:30:40 -07:00
|
|
|
for _ in 0..100 {
|
2016-07-01 12:50:55 -07:00
|
|
|
let mut a = F::random(rng);
|
|
|
|
let r = F::random(rng);
|
2016-08-28 10:30:40 -07:00
|
|
|
let mut b = a + r;
|
2016-07-01 12:50:55 -07:00
|
|
|
|
|
|
|
for _ in 0..10 {
|
|
|
|
let r = F::random(rng);
|
2016-08-28 10:30:40 -07:00
|
|
|
a = a + r;
|
|
|
|
b = b + r;
|
|
|
|
|
|
|
|
let r = F::random(rng);
|
|
|
|
a = a - r;
|
|
|
|
b = b - r;
|
2016-07-01 12:50:55 -07:00
|
|
|
|
|
|
|
let r = F::random(rng);
|
2016-08-28 10:30:40 -07:00
|
|
|
a = a + (-(-r));
|
|
|
|
b = b + (-(-r));
|
2016-07-01 12:50:55 -07:00
|
|
|
|
|
|
|
let r = F::random(rng);
|
2016-08-28 10:30:40 -07:00
|
|
|
a = a - r;
|
|
|
|
b = b + (-r);
|
|
|
|
|
|
|
|
let r = F::random(rng);
|
|
|
|
a = a + (-r);
|
|
|
|
b = b - r;
|
2016-07-01 12:50:55 -07:00
|
|
|
}
|
|
|
|
|
2016-08-28 10:30:40 -07:00
|
|
|
b = b - r;
|
|
|
|
assert_eq!(a, b);
|
2016-07-01 12:50:55 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-28 10:30:40 -07:00
|
|
|
fn rand_element_inverse<F: FieldElement, R: Rng>(rng: &mut R) {
|
|
|
|
for _ in 0..10000 {
|
2016-07-01 12:50:55 -07:00
|
|
|
let a = F::random(rng);
|
2016-08-28 21:04:46 -07:00
|
|
|
assert!(a.inverse().unwrap() * a == F::one());
|
2016-07-01 12:50:55 -07:00
|
|
|
let b = F::random(rng);
|
2016-08-28 21:04:46 -07:00
|
|
|
assert_eq!((a * b) * (a.inverse().unwrap()), b);
|
2016-07-01 12:50:55 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-28 10:30:40 -07:00
|
|
|
fn rand_element_multiplication<F: FieldElement, R: Rng>(rng: &mut R) {
|
2016-07-01 12:50:55 -07:00
|
|
|
// If field is not associative under multiplication, 1/8 of all triplets a, b, c
|
|
|
|
// will fail the test (a*b)*c = a*(b*c).
|
|
|
|
|
|
|
|
for _ in 0..250 {
|
|
|
|
let a = F::random(rng);
|
|
|
|
let b = F::random(rng);
|
|
|
|
let c = F::random(rng);
|
|
|
|
|
2016-08-28 10:30:40 -07:00
|
|
|
assert_eq!((a * b) * c, a * (b * c));
|
2016-07-01 12:50:55 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-28 10:30:40 -07:00
|
|
|
pub fn field_trials<F: FieldElement>() {
|
2016-07-01 12:50:55 -07:00
|
|
|
can_invert::<F>();
|
|
|
|
|
2016-08-28 10:30:40 -07:00
|
|
|
assert_eq!(-F::zero(), F::zero());
|
|
|
|
assert_eq!(-F::one() + F::one(), F::zero());
|
|
|
|
assert_eq!(F::zero() - F::zero(), F::zero());
|
|
|
|
|
2016-07-01 12:50:55 -07:00
|
|
|
let seed: [usize; 4] = [103245, 191922, 1293, 192103];
|
|
|
|
let mut rng = StdRng::from_seed(&seed);
|
|
|
|
|
|
|
|
rand_element_squaring::<F, StdRng>(&mut rng);
|
|
|
|
rand_element_addition_and_negation::<F, StdRng>(&mut rng);
|
|
|
|
rand_element_multiplication::<F, StdRng>(&mut rng);
|
|
|
|
rand_element_inverse::<F, StdRng>(&mut rng);
|
2016-08-28 21:04:46 -07:00
|
|
|
rand_element_eval::<F, StdRng>(&mut rng);
|
2016-07-01 12:50:55 -07:00
|
|
|
}
|