diff --git a/mvpoly/src/lib.rs b/mvpoly/src/lib.rs index 3f57e5f84a..9724acf190 100644 --- a/mvpoly/src/lib.rs +++ b/mvpoly/src/lib.rs @@ -5,6 +5,7 @@ use kimchi::circuits::expr::{ConstantExpr, Expr}; use rand::RngCore; pub mod monomials; +pub mod pbt; pub mod prime; pub mod utils; @@ -17,6 +18,7 @@ pub trait MVPoly: + ark_ff::One + ark_ff::Zero + std::fmt::Debug + + Clone // Comparison operators + PartialEq + Eq @@ -106,4 +108,6 @@ pub trait MVPoly: u1: F, u2: F, ) -> HashMap; + + fn modify_monomial_with_scalar(&mut self, scalar: F); } diff --git a/mvpoly/src/monomials.rs b/mvpoly/src/monomials.rs index 32fddbb01b..ff4e5c12f4 100644 --- a/mvpoly/src/monomials.rs +++ b/mvpoly/src/monomials.rs @@ -564,6 +564,10 @@ impl MVPoly for Sparse From> diff --git a/mvpoly/src/pbt.rs b/mvpoly/src/pbt.rs new file mode 100644 index 0000000000..b6e06b2062 --- /dev/null +++ b/mvpoly/src/pbt.rs @@ -0,0 +1,371 @@ +//! This module contains a list of property tests for the `MVPoly` trait. +//! +//! Any type that implements the `MVPoly` trait should pass these tests. +//! +//! For instance, one can call the `test_mul_by_one` as follows: +//! +//! ```rust +//! use mvpoly::MVPoly; +//! use mvpoly::prime::Dense; +//! use mina_curves::pasta::Fp; +//! +//! #[test] +//! fn test_mul_by_one() { +//! mvpoly::pbt::test_mul_by_one::>(); +//! mvpoly::pbt::test_mul_by_one::>(); +//! } +//! ``` + +use crate::MVPoly; +use ark_ff::PrimeField; +use rand::Rng; +use std::ops::Neg; + +pub fn test_mul_by_one>() { + let mut rng = o1_utils::tests::make_test_rng(None); + let p1 = unsafe { T::random(&mut rng, None) }; + let one = T::one(); + let p2 = p1.clone() * one.clone(); + assert_eq!(p1.clone(), p2); + let p3 = one * p1.clone(); + assert_eq!(p1.clone(), p3); +} + +pub fn test_mul_by_zero>() { + let mut rng = o1_utils::tests::make_test_rng(None); + let p1 = unsafe { T::random(&mut rng, None) }; + let zero = T::zero(); + let p2 = p1.clone() * zero.clone(); + assert_eq!(zero, p2); + let p3 = zero.clone() * p1.clone(); + assert_eq!(zero.clone(), p3); +} + +pub fn test_add_zero>() { + let mut rng = o1_utils::tests::make_test_rng(None); + let p1 = unsafe { T::random(&mut rng, None) }; + let zero = T::zero(); + let p2 = p1.clone() + zero.clone(); + assert_eq!(p1.clone(), p2); + let p3 = zero.clone() + p1.clone(); + assert_eq!(p1.clone(), p3); +} + +pub fn test_double_is_add_twice< + F: PrimeField, + const N: usize, + const D: usize, + T: MVPoly, +>() { + let mut rng = o1_utils::tests::make_test_rng(None); + let p1 = unsafe { T::random(&mut rng, None) }; + let p2 = p1.clone() + p1.clone(); + let p3 = p1.clone().double(); + assert_eq!(p2, p3); +} + +pub fn test_sub_zero>() { + let mut rng = o1_utils::tests::make_test_rng(None); + let p1 = unsafe { T::random(&mut rng, None) }; + let zero = T::zero(); + let p2 = p1.clone() - zero.clone(); + assert_eq!(p1.clone(), p2); +} + +pub fn test_neg>() { + let mut rng = o1_utils::tests::make_test_rng(None); + let p1 = unsafe { T::random(&mut rng, None) }; + let p2 = -p1.clone(); + // Test that p1 + (-p1) = 0 + let sum = p1.clone() + p2.clone(); + assert_eq!(sum, T::zero()); + // Test that -(-p1) = p1 + let p3 = -p2; + assert_eq!(p1, p3); + // Test negation of zero + let zero = T::zero(); + let neg_zero = -zero.clone(); + assert_eq!(zero, neg_zero); +} + +pub fn test_eval_pbt_add>() { + let mut rng = o1_utils::tests::make_test_rng(None); + let random_evaluation: [F; N] = std::array::from_fn(|_| F::rand(&mut rng)); + let p1 = unsafe { T::random(&mut rng, None) }; + let p2 = unsafe { T::random(&mut rng, None) }; + let p3 = p1.clone() + p2.clone(); + let eval_p1 = p1.eval(&random_evaluation); + let eval_p2 = p2.eval(&random_evaluation); + let eval_p3 = p3.eval(&random_evaluation); + assert_eq!(eval_p3, eval_p1 + eval_p2); +} + +pub fn test_eval_pbt_sub>() { + let mut rng = o1_utils::tests::make_test_rng(None); + let random_evaluation: [F; N] = std::array::from_fn(|_| F::rand(&mut rng)); + let p1 = unsafe { T::random(&mut rng, None) }; + let p2 = unsafe { T::random(&mut rng, None) }; + let p3 = p1.clone() - p2.clone(); + let eval_p1 = p1.eval(&random_evaluation); + let eval_p2 = p2.eval(&random_evaluation); + let eval_p3 = p3.eval(&random_evaluation); + assert_eq!(eval_p3, eval_p1 - eval_p2); +} + +pub fn test_eval_pbt_mul_by_scalar< + F: PrimeField, + const N: usize, + const D: usize, + T: MVPoly, +>() { + let mut rng = o1_utils::tests::make_test_rng(None); + let random_evaluation: [F; N] = std::array::from_fn(|_| F::rand(&mut rng)); + let p1 = unsafe { T::random(&mut rng, None) }; + let c = F::rand(&mut rng); + let p2 = p1.clone() * T::from(c); + let eval_p1 = p1.eval(&random_evaluation); + let eval_p2 = p2.eval(&random_evaluation); + assert_eq!(eval_p2, eval_p1 * c); +} + +pub fn test_eval_pbt_neg>() { + let mut rng = o1_utils::tests::make_test_rng(None); + let random_evaluation: [F; N] = std::array::from_fn(|_| F::rand(&mut rng)); + let p1 = unsafe { T::random(&mut rng, None) }; + let p2 = -p1.clone(); + let eval_p1 = p1.eval(&random_evaluation); + let eval_p2 = p2.eval(&random_evaluation); + assert_eq!(eval_p2, -eval_p1); +} + +pub fn test_neg_ref>() +where + for<'a> &'a T: Neg, +{ + let mut rng = o1_utils::tests::make_test_rng(None); + let p1 = unsafe { T::random(&mut rng, None) }; + let p2 = -&p1; + // Test that p1 + (-&p1) = 0 + let sum = p1.clone() + p2.clone(); + assert_eq!(sum, T::zero()); + // Test that -(-&p1) = p1 + let p3 = -&p2; + assert_eq!(p1, p3); +} + +pub fn test_mul_by_scalar>() { + let mut rng = o1_utils::tests::make_test_rng(None); + let p1 = unsafe { T::random(&mut rng, None) }; + let mut p2 = T::zero(); + let c = F::rand(&mut rng); + p2.modify_monomial_with_scalar(c); + assert_eq!(p2 * p1.clone(), p1.clone().mul_by_scalar(c)); +} + +pub fn test_mul_by_scalar_with_zero< + F: PrimeField, + const N: usize, + const D: usize, + T: MVPoly, +>() { + let mut rng = o1_utils::tests::make_test_rng(None); + let p1 = unsafe { T::random(&mut rng, None) }; + let c = F::zero(); + assert_eq!(p1.mul_by_scalar(c), T::zero()); +} + +pub fn test_mul_by_scalar_with_one< + F: PrimeField, + const N: usize, + const D: usize, + T: MVPoly, +>() { + let mut rng = o1_utils::tests::make_test_rng(None); + let p1 = unsafe { T::random(&mut rng, None) }; + let c = F::one(); + assert_eq!(p1.mul_by_scalar(c), p1); +} + +pub fn test_evaluation_zero_polynomial< + F: PrimeField, + const N: usize, + const D: usize, + T: MVPoly, +>() { + let mut rng = o1_utils::tests::make_test_rng(None); + let random_evaluation: [F; N] = std::array::from_fn(|_| F::rand(&mut rng)); + let zero = T::zero(); + let evaluation = zero.eval(&random_evaluation); + assert_eq!(evaluation, F::zero()); +} + +pub fn test_evaluation_constant_polynomial< + F: PrimeField, + const N: usize, + const D: usize, + T: MVPoly, +>() { + let mut rng = o1_utils::tests::make_test_rng(None); + let random_evaluation: [F; N] = std::array::from_fn(|_| F::rand(&mut rng)); + let cst = F::rand(&mut rng); + let poly = T::from(cst); + let evaluation = poly.eval(&random_evaluation); + assert_eq!(evaluation, cst); +} + +pub fn test_degree_constant>() { + let mut rng = o1_utils::tests::make_test_rng(None); + let c = F::rand(&mut rng); + let p = T::from(c); + let degree = unsafe { p.degree() }; + assert_eq!(degree, 0); + let p = T::zero(); + let degree = unsafe { p.degree() }; + assert_eq!(degree, 0); +} + +pub fn test_degree_random_degree< + F: PrimeField, + const N: usize, + const D: usize, + T: MVPoly, +>() { + let mut rng = o1_utils::tests::make_test_rng(None); + // Test with a random degree up to 5 + let max_degree: usize = rng.gen_range(1..5); + let p = unsafe { T::random(&mut rng, Some(max_degree)) }; + let degree = unsafe { p.degree() }; + assert!(degree <= max_degree); + // Test with a random degree up to 20 (for univariate polynomials) + let max_degree: usize = rng.gen_range(1..20); + let p = unsafe { T::random(&mut rng, Some(max_degree)) }; + let degree = unsafe { p.degree() }; + assert!(degree <= max_degree); +} + +pub fn test_mvpoly_add_degree_pbt< + F: PrimeField, + const N: usize, + const D: usize, + T: MVPoly, +>() { + let mut rng = o1_utils::tests::make_test_rng(None); + let degree = rng.gen_range(1..5); + let p1 = unsafe { T::random(&mut rng, Some(degree)) }; + let p2 = unsafe { T::random(&mut rng, Some(degree)) }; + let p3 = p1.clone() + p2.clone(); + let degree_p1 = unsafe { p1.degree() }; + let degree_p2 = unsafe { p2.degree() }; + let degree_p3 = unsafe { p3.degree() }; + assert!(degree_p3 <= std::cmp::max(degree_p1, degree_p2)); +} + +pub fn test_mvpoly_sub_degree_pbt< + F: PrimeField, + const N: usize, + const D: usize, + T: MVPoly, +>() { + let mut rng = o1_utils::tests::make_test_rng(None); + let degree = rng.gen_range(1..5); + let p1 = unsafe { T::random(&mut rng, Some(degree)) }; + let p2 = unsafe { T::random(&mut rng, Some(degree)) }; + let p3 = p1.clone() - p2.clone(); + let degree_p1 = unsafe { p1.degree() }; + let degree_p2 = unsafe { p2.degree() }; + let degree_p3 = unsafe { p3.degree() }; + assert!(degree_p3 <= std::cmp::max(degree_p1, degree_p2)); +} + +pub fn test_mvpoly_neg_degree_pbt< + F: PrimeField, + const N: usize, + const D: usize, + T: MVPoly, +>() { + let mut rng = o1_utils::tests::make_test_rng(None); + let degree = rng.gen_range(1..5); + let p1 = unsafe { T::random(&mut rng, Some(degree)) }; + let p2 = -p1.clone(); + let degree_p1 = unsafe { p1.degree() }; + let degree_p2 = unsafe { p2.degree() }; + assert_eq!(degree_p1, degree_p2); +} + +pub fn test_mvpoly_mul_by_scalar_degree_pbt< + F: PrimeField, + const N: usize, + const D: usize, + T: MVPoly, +>() { + let mut rng = o1_utils::tests::make_test_rng(None); + let degree = rng.gen_range(1..5); + let p1 = unsafe { T::random(&mut rng, Some(degree)) }; + let c = F::rand(&mut rng); + let p2 = p1.clone() * T::from(c); + let degree_p1 = unsafe { p1.degree() }; + let degree_p2 = unsafe { p2.degree() }; + assert!(degree_p2 <= degree_p1); +} + +pub fn test_mvpoly_mul_degree_pbt< + F: PrimeField, + const N: usize, + const D: usize, + T: MVPoly, +>() { + let mut rng = o1_utils::tests::make_test_rng(None); + let degree = rng.gen_range(1..3); + let p1 = unsafe { T::random(&mut rng, Some(degree)) }; + let p2 = unsafe { T::random(&mut rng, Some(degree)) }; + let p3 = p1.clone() * p2.clone(); + let degree_p1 = unsafe { p1.degree() }; + let degree_p2 = unsafe { p2.degree() }; + let degree_p3 = unsafe { p3.degree() }; + assert!(degree_p3 <= degree_p1 + degree_p2); +} + +pub fn test_mvpoly_mul_eval_pbt< + F: PrimeField, + const N: usize, + const D: usize, + T: MVPoly, +>() { + let mut rng = o1_utils::tests::make_test_rng(None); + let max_degree = rng.gen_range(1..3); + let p1 = unsafe { T::random(&mut rng, Some(max_degree)) }; + let p2 = unsafe { T::random(&mut rng, Some(max_degree)) }; + let p3 = p1.clone() * p2.clone(); + let random_evaluation: [F; N] = std::array::from_fn(|_| F::rand(&mut rng)); + let eval_p1 = p1.eval(&random_evaluation); + let eval_p2 = p2.eval(&random_evaluation); + let eval_p3 = p3.eval(&random_evaluation); + assert_eq!(eval_p3, eval_p1 * eval_p2); +} + +pub fn test_mvpoly_mul_pbt>() { + let mut rng = o1_utils::tests::make_test_rng(None); + let max_degree = rng.gen_range(1..3); + let p1 = unsafe { T::random(&mut rng, Some(max_degree)) }; + let p2 = unsafe { T::random(&mut rng, Some(max_degree)) }; + assert_eq!(p1.clone() * p2.clone(), p2.clone() * p1.clone()); +} + +pub fn test_can_be_printed_with_debug< + F: PrimeField, + const N: usize, + const D: usize, + T: MVPoly, +>() { + let mut rng = o1_utils::tests::make_test_rng(None); + let p1 = unsafe { T::random(&mut rng, None) }; + println!("{:?}", p1); +} + +pub fn test_is_zero>() { + let mut rng = o1_utils::tests::make_test_rng(None); + let p1 = T::zero(); + assert!(p1.is_zero()); + let p2 = unsafe { T::random(&mut rng, None) }; + assert!(!p2.is_zero()); +} diff --git a/mvpoly/src/prime.rs b/mvpoly/src/prime.rs index 28573c0301..036603feb3 100644 --- a/mvpoly/src/prime.rs +++ b/mvpoly/src/prime.rs @@ -448,6 +448,10 @@ impl MVPoly for Dense HashMap { unimplemented!() } + + fn modify_monomial_with_scalar(&mut self, scalar: F) { + self[0] = scalar; + } } impl Dense { diff --git a/mvpoly/tests/monomials.rs b/mvpoly/tests/monomials.rs index 0a630a2fce..58e232e270 100644 --- a/mvpoly/tests/monomials.rs +++ b/mvpoly/tests/monomials.rs @@ -1,140 +1,35 @@ use ark_ff::{Field, One, UniformRand, Zero}; use mina_curves::pasta::Fp; use mvpoly::{monomials::Sparse, MVPoly}; -use rand::Rng; #[test] fn test_mul_by_one() { - let mut rng = o1_utils::tests::make_test_rng(None); - let p1 = unsafe { Sparse::::random(&mut rng, None) }; - let one = Sparse::::one(); - let p2 = p1.clone() * one.clone(); - assert_eq!(p1.clone(), p2); - let p3 = one * p1.clone(); - assert_eq!(p1.clone(), p3); + mvpoly::pbt::test_mul_by_one::>(); } #[test] fn test_mul_by_zero() { - let mut rng = o1_utils::tests::make_test_rng(None); - let p1 = unsafe { Sparse::::random(&mut rng, None) }; - let zero = Sparse::::zero(); - let p2 = p1.clone() * zero.clone(); - assert_eq!(zero, p2); - let p3 = zero.clone() * p1.clone(); - assert_eq!(zero.clone(), p3); + mvpoly::pbt::test_mul_by_zero::>(); } #[test] fn test_add_zero() { - let mut rng = o1_utils::tests::make_test_rng(None); - let p1 = unsafe { Sparse::::random(&mut rng, None) }; - - let zero = Sparse::::zero(); - let p2 = p1.clone() + zero.clone(); - assert_eq!(p1.clone(), p2); - let p3 = zero.clone() + p1.clone(); - assert_eq!(p1.clone(), p3); + mvpoly::pbt::test_add_zero::>(); } #[test] fn test_double_is_add_twice() { - let mut rng = o1_utils::tests::make_test_rng(None); - let p1 = unsafe { Sparse::::random(&mut rng, None) }; - let p2 = p1.clone() + p1.clone(); - let p3 = p1.clone().double(); - assert_eq!(p2, p3); + mvpoly::pbt::test_double_is_add_twice::>(); } #[test] fn test_sub_zero() { - let mut rng = o1_utils::tests::make_test_rng(None); - let p1 = unsafe { Sparse::::random(&mut rng, None) }; - let zero = Sparse::::zero(); - let p2 = p1.clone() - zero.clone(); - assert_eq!(p1.clone(), p2); + mvpoly::pbt::test_sub_zero::>(); } #[test] fn test_neg() { - let mut rng = o1_utils::tests::make_test_rng(None); - let p1 = unsafe { Sparse::::random(&mut rng, None) }; - let p2 = -p1.clone(); - - // Test that p1 + (-p1) = 0 - let sum = p1.clone() + p2.clone(); - assert_eq!(sum, Sparse::::zero()); - - // Test that -(-p1) = p1 - let p3 = -p2; - assert_eq!(p1, p3); - - // Test negation of zero - let zero = Sparse::::zero(); - let neg_zero = -zero.clone(); - assert_eq!(zero, neg_zero); -} - -#[test] -fn test_neg_ref() { - let mut rng = o1_utils::tests::make_test_rng(None); - let p1 = unsafe { Sparse::::random(&mut rng, None) }; - let p2 = -&p1; - - // Test that p1 + (-&p1) = 0 - let sum = p1.clone() + p2.clone(); - assert_eq!(sum, Sparse::::zero()); - - // Test that -(-&p1) = p1 - let p3 = -&p2; - assert_eq!(p1, p3); -} - -#[test] -fn test_mul_by_scalar() { - let mut rng = o1_utils::tests::make_test_rng(None); - let p1 = unsafe { Sparse::::random(&mut rng, None) }; - let mut p2 = Sparse::::zero(); - let c = Fp::rand(&mut rng); - p2.modify_monomial([0; 4], c); - assert_eq!(p2 * p1.clone(), p1.clone().mul_by_scalar(c)) -} - -#[test] -fn test_mul_by_scalar_with_zero() { - let mut rng = o1_utils::tests::make_test_rng(None); - let p1 = unsafe { Sparse::::random(&mut rng, None) }; - let c = Fp::zero(); - assert_eq!(p1.mul_by_scalar(c), Sparse::::zero()) -} - -#[test] -fn test_mul_by_scalar_with_one() { - let mut rng = o1_utils::tests::make_test_rng(None); - let p1 = unsafe { Sparse::::random(&mut rng, None) }; - let c = Fp::one(); - assert_eq!(p1.mul_by_scalar(c), p1) -} - -#[test] -fn test_evaluation_zero_polynomial() { - let mut rng = o1_utils::tests::make_test_rng(None); - - let random_evaluation: [Fp; 4] = std::array::from_fn(|_| Fp::rand(&mut rng)); - let zero = Sparse::::zero(); - let evaluation = zero.eval(&random_evaluation); - assert_eq!(evaluation, Fp::zero()); -} - -#[test] -fn test_evaluation_constant_polynomial() { - let mut rng = o1_utils::tests::make_test_rng(None); - - let random_evaluation: [Fp; 4] = std::array::from_fn(|_| Fp::rand(&mut rng)); - let cst = Fp::rand(&mut rng); - let zero = Sparse::::from(cst); - let evaluation = zero.eval(&random_evaluation); - assert_eq!(evaluation, cst); + mvpoly::pbt::test_neg::>(); } #[test] @@ -202,55 +97,53 @@ fn test_eval_pbt_sub() { #[test] fn test_eval_pbt_mul_by_scalar() { - let mut rng = o1_utils::tests::make_test_rng(None); - - let random_evaluation: [Fp; 6] = std::array::from_fn(|_| Fp::rand(&mut rng)); - let p1 = unsafe { Sparse::::random(&mut rng, None) }; - let c = Fp::rand(&mut rng); - let p2 = p1.clone() * Sparse::::from(c); - let eval_p1 = p1.eval(&random_evaluation); - let eval_p2 = p2.eval(&random_evaluation); - assert_eq!(eval_p2, eval_p1 * c); + mvpoly::pbt::test_eval_pbt_mul_by_scalar::>(); } #[test] fn test_eval_pbt_neg() { - let mut rng = o1_utils::tests::make_test_rng(None); + mvpoly::pbt::test_eval_pbt_neg::>(); +} - let random_evaluation: [Fp; 6] = std::array::from_fn(|_| Fp::rand(&mut rng)); - let p1 = unsafe { Sparse::::random(&mut rng, None) }; - let p2 = -p1.clone(); - let eval_p1 = p1.eval(&random_evaluation); - let eval_p2 = p2.eval(&random_evaluation); - assert_eq!(eval_p2, -eval_p1); +#[test] +fn test_neg_ref() { + mvpoly::pbt::test_neg_ref::>(); } #[test] -fn test_degree_constant() { - let mut rng = o1_utils::tests::make_test_rng(None); - let c = Fp::rand(&mut rng); - let p = Sparse::::from(c); - let degree = unsafe { p.degree() }; - assert_eq!(degree, 0); +fn test_mul_by_scalar() { + mvpoly::pbt::test_mul_by_scalar::>(); +} - let p = Sparse::::zero(); - let degree = unsafe { p.degree() }; - assert_eq!(degree, 0); +#[test] +fn test_mul_by_scalar_with_zero() { + mvpoly::pbt::test_mul_by_scalar_with_zero::>(); } #[test] -fn test_degree_random_degree() { - let mut rng = o1_utils::tests::make_test_rng(None); - let max_degree: usize = rng.gen_range(1..5); - let p: Sparse = unsafe { Sparse::random(&mut rng, Some(max_degree)) }; - let degree = unsafe { p.degree() }; - assert!(degree <= max_degree); +fn test_mul_by_scalar_with_one() { + mvpoly::pbt::test_mul_by_scalar_with_one::>(); +} + +#[test] +fn test_evaluation_zero_polynomial() { + mvpoly::pbt::test_evaluation_zero_polynomial::>(); +} - let max_degree: usize = rng.gen_range(1..20); - // univariate - let p = unsafe { Sparse::::random(&mut rng, Some(max_degree)) }; - let degree = unsafe { p.degree() }; - assert!(degree <= max_degree); +#[test] +fn test_evaluation_constant_polynomial() { + mvpoly::pbt::test_evaluation_constant_polynomial::>(); +} + +#[test] +fn test_degree_constant() { + mvpoly::pbt::test_degree_constant::>(); +} + +#[test] +fn test_degree_random_degree() { + mvpoly::pbt::test_degree_random_degree::>(); + mvpoly::pbt::test_degree_random_degree::>(); } #[test] @@ -270,105 +163,47 @@ fn test_is_constant() { #[test] fn test_mvpoly_add_degree_pbt() { - let mut rng = o1_utils::tests::make_test_rng(None); - let degree = rng.gen_range(1..5); - let p1 = unsafe { Sparse::::random(&mut rng, Some(degree)) }; - let p2 = unsafe { Sparse::::random(&mut rng, Some(degree)) }; - let p3 = p1.clone() + p2.clone(); - let degree_p1 = unsafe { p1.degree() }; - let degree_p2 = unsafe { p2.degree() }; - let degree_p3 = unsafe { p3.degree() }; - assert!(degree_p3 <= std::cmp::max(degree_p1, degree_p2)); + mvpoly::pbt::test_mvpoly_add_degree_pbt::>(); } #[test] fn test_mvpoly_sub_degree_pbt() { - let mut rng = o1_utils::tests::make_test_rng(None); - let degree = rng.gen_range(1..5); - let p1 = unsafe { Sparse::::random(&mut rng, Some(degree)) }; - let p2 = unsafe { Sparse::::random(&mut rng, Some(degree)) }; - let p3 = p1.clone() - p2.clone(); - let degree_p1 = unsafe { p1.degree() }; - let degree_p2 = unsafe { p2.degree() }; - let degree_p3 = unsafe { p3.degree() }; - assert!(degree_p3 <= std::cmp::max(degree_p1, degree_p2)); + mvpoly::pbt::test_mvpoly_sub_degree_pbt::>(); } #[test] fn test_mvpoly_neg_degree_pbt() { - let mut rng = o1_utils::tests::make_test_rng(None); - let degree = rng.gen_range(1..5); - let p1 = unsafe { Sparse::::random(&mut rng, Some(degree)) }; - let p2 = -p1.clone(); - let degree_p1 = unsafe { p1.degree() }; - let degree_p2 = unsafe { p2.degree() }; - assert_eq!(degree_p1, degree_p2); + mvpoly::pbt::test_mvpoly_neg_degree_pbt::>(); } #[test] fn test_mvpoly_mul_by_scalar_degree_pbt() { - let mut rng = o1_utils::tests::make_test_rng(None); - let degree = rng.gen_range(1..5); - let p1 = unsafe { Sparse::::random(&mut rng, Some(degree)) }; - let c = Fp::rand(&mut rng); - let p2 = p1.clone() * Sparse::::from(c); - let degree_p1 = unsafe { p1.degree() }; - let degree_p2 = unsafe { p2.degree() }; - assert!(degree_p2 <= degree_p1); + mvpoly::pbt::test_mvpoly_mul_by_scalar_degree_pbt::>(); } #[test] fn test_mvpoly_mul_degree_pbt() { - let mut rng = o1_utils::tests::make_test_rng(None); - // half max degree - let degree = rng.gen_range(1..3); - let p1 = unsafe { Sparse::::random(&mut rng, Some(degree)) }; - let p2 = unsafe { Sparse::::random(&mut rng, Some(degree)) }; - let p3 = p1.clone() * p2.clone(); - let degree_p1 = unsafe { p1.degree() }; - let degree_p2 = unsafe { p2.degree() }; - let degree_p3 = unsafe { p3.degree() }; - assert!(degree_p3 <= degree_p1 + degree_p2); + mvpoly::pbt::test_mvpoly_mul_degree_pbt::>(); } #[test] fn test_mvpoly_mul_eval_pbt() { - let mut rng = o1_utils::tests::make_test_rng(None); - let max_degree = rng.gen_range(1..3); - let p1 = unsafe { Sparse::::random(&mut rng, Some(max_degree)) }; - let p2 = unsafe { Sparse::::random(&mut rng, Some(max_degree)) }; - let p3 = p1.clone() * p2.clone(); - let random_evaluation: [Fp; 4] = std::array::from_fn(|_| Fp::rand(&mut rng)); - let eval_p1 = p1.eval(&random_evaluation); - let eval_p2 = p2.eval(&random_evaluation); - let eval_p3 = p3.eval(&random_evaluation); - assert_eq!(eval_p3, eval_p1 * eval_p2); + mvpoly::pbt::test_mvpoly_mul_eval_pbt::>(); } #[test] fn test_mvpoly_mul_pbt() { - let mut rng = o1_utils::tests::make_test_rng(None); - let max_degree = rng.gen_range(1..3); - let p1 = unsafe { Sparse::::random(&mut rng, Some(max_degree)) }; - let p2 = unsafe { Sparse::::random(&mut rng, Some(max_degree)) }; - assert_eq!(p1.clone() * p2.clone(), p2.clone() * p1.clone()); + mvpoly::pbt::test_mvpoly_mul_pbt::>(); } #[test] fn test_can_be_printed_with_debug() { - let mut rng = o1_utils::tests::make_test_rng(None); - let p1 = unsafe { Sparse::::random(&mut rng, None) }; - println!("{:?}", p1); + mvpoly::pbt::test_can_be_printed_with_debug::>(); } #[test] fn test_is_zero() { - let mut rng = o1_utils::tests::make_test_rng(None); - let p1 = Sparse::::zero(); - assert!(p1.is_zero()); - - let p2 = unsafe { Sparse::::random(&mut rng, None) }; - assert!(!p2.is_zero()); + mvpoly::pbt::test_is_zero::>(); } #[test] diff --git a/mvpoly/tests/prime.rs b/mvpoly/tests/prime.rs index b7f5eec772..de7cfc43e8 100644 --- a/mvpoly/tests/prime.rs +++ b/mvpoly/tests/prime.rs @@ -5,7 +5,6 @@ use kimchi::circuits::{ }; use mina_curves::pasta::Fp; use mvpoly::{prime::Dense, utils::PrimeNumberGenerator, MVPoly}; -use rand::Rng; #[test] fn test_vector_space_dimension() { @@ -159,115 +158,72 @@ fn test_mul() { #[test] fn test_mul_by_one() { - let mut rng = o1_utils::tests::make_test_rng(None); - let p1 = unsafe { Dense::::random(&mut rng, None) }; - let one = Dense::::one(); - let p2 = p1.clone() * one.clone(); - assert_eq!(p1.clone(), p2); - let p3 = one * p1.clone(); - assert_eq!(p1.clone(), p3); + mvpoly::pbt::test_mul_by_one::>(); } #[test] fn test_mul_by_zero() { - let mut rng = o1_utils::tests::make_test_rng(None); - let p1 = unsafe { Dense::::random(&mut rng, None) }; - let zero = Dense::::zero(); - let p2 = p1.clone() * zero.clone(); - assert_eq!(zero, p2); - let p3 = zero.clone() * p1.clone(); - assert_eq!(zero.clone(), p3); + mvpoly::pbt::test_mul_by_zero::>(); } #[test] fn test_add_zero() { - let mut rng = o1_utils::tests::make_test_rng(None); - let p1 = unsafe { Dense::::random(&mut rng, None) }; - - let zero = Dense::::zero(); - let p2 = p1.clone() + zero.clone(); - assert_eq!(p1.clone(), p2); - let p3 = zero.clone() + p1.clone(); - assert_eq!(p1.clone(), p3); + mvpoly::pbt::test_add_zero::>(); } #[test] fn test_double_is_add_twice() { - let mut rng = o1_utils::tests::make_test_rng(None); - let p1 = unsafe { Dense::::random(&mut rng, None) }; - let p2 = p1.clone() + p1.clone(); - let p3 = p1.clone().double(); - assert_eq!(p2, p3); + mvpoly::pbt::test_double_is_add_twice::>(); } #[test] fn test_sub_zero() { - let mut rng = o1_utils::tests::make_test_rng(None); - let p1 = unsafe { Dense::::random(&mut rng, None) }; - let zero = Dense::::zero(); - let p2 = p1.clone() - zero.clone(); - assert_eq!(p1.clone(), p2); + mvpoly::pbt::test_sub_zero::>(); } #[test] fn test_neg() { - let mut rng = o1_utils::tests::make_test_rng(None); - let p1 = unsafe { Dense::::random(&mut rng, None) }; - let p2 = -p1.clone(); - - // Test that p1 + (-p1) = 0 - let sum = p1.clone() + p2.clone(); - assert_eq!(sum, Dense::::zero()); + mvpoly::pbt::test_neg::>(); +} - // Test that -(-p1) = p1 - let p3 = -p2; - assert_eq!(p1, p3); +#[test] +fn test_eval_pbt_add() { + mvpoly::pbt::test_eval_pbt_add::>(); +} - // Test negation of zero - let zero = Dense::::zero(); - let neg_zero = -zero.clone(); - assert_eq!(zero, neg_zero); +#[test] +fn test_eval_pbt_sub() { + mvpoly::pbt::test_eval_pbt_sub::>(); } #[test] -fn test_neg_ref() { - let mut rng = o1_utils::tests::make_test_rng(None); - let p1 = unsafe { Dense::::random(&mut rng, None) }; - let p2 = -&p1; +fn test_eval_pbt_mul_by_scalar() { + mvpoly::pbt::test_eval_pbt_mul_by_scalar::>(); +} - // Test that p1 + (-&p1) = 0 - let sum = p1.clone() + p2.clone(); - assert_eq!(sum, Dense::::zero()); +#[test] +fn test_eval_pbt_neg() { + mvpoly::pbt::test_eval_pbt_neg::>(); +} - // Test that -(-&p1) = p1 - let p3 = -&p2; - assert_eq!(p1, p3); +#[test] +fn test_neg_ref() { + mvpoly::pbt::test_neg_ref::>(); } #[test] fn test_mul_by_scalar() { - let mut rng = o1_utils::tests::make_test_rng(None); - let p1 = unsafe { Dense::::random(&mut rng, None) }; - let mut p2 = Dense::::zero(); - let c = Fp::rand(&mut rng); - p2[0] = c; - assert_eq!(p2 * p1.clone(), p1.clone().mul_by_scalar(c)) + mvpoly::pbt::test_mul_by_scalar::>(); } #[test] fn test_mul_by_scalar_with_zero() { - let mut rng = o1_utils::tests::make_test_rng(None); - let p1 = unsafe { Dense::::random(&mut rng, None) }; - let c = Fp::zero(); - assert_eq!(p1.mul_by_scalar(c), Dense::::zero()) + mvpoly::pbt::test_mul_by_scalar_with_zero::>(); } #[test] fn test_mul_by_scalar_with_one() { - let mut rng = o1_utils::tests::make_test_rng(None); - let p1 = unsafe { Dense::::random(&mut rng, None) }; - let c = Fp::one(); - assert_eq!(p1.mul_by_scalar(c), p1) + mvpoly::pbt::test_mul_by_scalar_with_one::>(); } #[test] @@ -362,23 +318,12 @@ fn test_from_variable_column() { #[test] fn test_evaluation_zero_polynomial() { - let mut rng = o1_utils::tests::make_test_rng(None); - - let random_evaluation: [Fp; 4] = std::array::from_fn(|_| Fp::rand(&mut rng)); - let zero = Dense::::zero(); - let evaluation = zero.eval(&random_evaluation); - assert_eq!(evaluation, Fp::zero()); + mvpoly::pbt::test_evaluation_zero_polynomial::>(); } #[test] fn test_evaluation_constant_polynomial() { - let mut rng = o1_utils::tests::make_test_rng(None); - - let random_evaluation: [Fp; 4] = std::array::from_fn(|_| Fp::rand(&mut rng)); - let cst = Fp::rand(&mut rng); - let zero = Dense::::from(cst); - let evaluation = zero.eval(&random_evaluation); - assert_eq!(evaluation, cst); + mvpoly::pbt::test_evaluation_constant_polynomial::>(); } #[test] @@ -406,59 +351,6 @@ fn test_evaluation_predefined_polynomial() { assert_eq!(evaluation, exp_eval); } -#[test] -fn test_eval_pbt_add() { - let mut rng = o1_utils::tests::make_test_rng(None); - - let random_evaluation: [Fp; 6] = std::array::from_fn(|_| Fp::rand(&mut rng)); - let p1 = unsafe { Dense::::random(&mut rng, None) }; - let p2 = unsafe { Dense::::random(&mut rng, None) }; - let p3 = p1.clone() + p2.clone(); - let eval_p1 = p1.eval(&random_evaluation); - let eval_p2 = p2.eval(&random_evaluation); - let eval_p3 = p3.eval(&random_evaluation); - assert_eq!(eval_p3, eval_p1 + eval_p2); -} - -#[test] -fn test_eval_pbt_sub() { - let mut rng = o1_utils::tests::make_test_rng(None); - - let random_evaluation: [Fp; 6] = std::array::from_fn(|_| Fp::rand(&mut rng)); - let p1 = unsafe { Dense::::random(&mut rng, None) }; - let p2 = unsafe { Dense::::random(&mut rng, None) }; - let p3 = p1.clone() - p2.clone(); - let eval_p1 = p1.eval(&random_evaluation); - let eval_p2 = p2.eval(&random_evaluation); - let eval_p3 = p3.eval(&random_evaluation); - assert_eq!(eval_p3, eval_p1 - eval_p2); -} - -#[test] -fn test_eval_pbt_mul_by_scalar() { - let mut rng = o1_utils::tests::make_test_rng(None); - - let random_evaluation: [Fp; 6] = std::array::from_fn(|_| Fp::rand(&mut rng)); - let p1 = unsafe { Dense::::random(&mut rng, None) }; - let c = Fp::rand(&mut rng); - let p2 = p1.clone() * Dense::::from(c); - let eval_p1 = p1.eval(&random_evaluation); - let eval_p2 = p2.eval(&random_evaluation); - assert_eq!(eval_p2, eval_p1 * c); -} - -#[test] -fn test_eval_pbt_neg() { - let mut rng = o1_utils::tests::make_test_rng(None); - - let random_evaluation: [Fp; 6] = std::array::from_fn(|_| Fp::rand(&mut rng)); - let p1 = unsafe { Dense::::random(&mut rng, None) }; - let p2 = -p1.clone(); - let eval_p1 = p1.eval(&random_evaluation); - let eval_p2 = p2.eval(&random_evaluation); - assert_eq!(eval_p2, -eval_p1); -} - /// As a reminder, here are the equations to compute the addition of two /// different points `P1 = (X1, Y1)` and `P2 = (X2, Y2)`. Let `P3 = (X3, /// Y3) = P1 + P2`. @@ -670,30 +562,13 @@ fn test_degree_with_coeffs() { #[test] fn test_degree_constant() { - let mut rng = o1_utils::tests::make_test_rng(None); - let c = Fp::rand(&mut rng); - let p = Dense::::from(c); - let degree = unsafe { p.degree() }; - assert_eq!(degree, 0); - - let p = Dense::::zero(); - let degree = unsafe { p.degree() }; - assert_eq!(degree, 0); + mvpoly::pbt::test_degree_constant::>(); } #[test] fn test_degree_random_degree() { - let mut rng = o1_utils::tests::make_test_rng(None); - let max_degree: usize = rng.gen_range(1..5); - let p: Dense = unsafe { Dense::random(&mut rng, Some(max_degree)) }; - let degree = unsafe { p.degree() }; - assert!(degree <= max_degree); - - let max_degree: usize = rng.gen_range(1..20); - // univariate - let p = unsafe { Dense::::random(&mut rng, Some(max_degree)) }; - let degree = unsafe { p.degree() }; - assert!(degree <= max_degree); + mvpoly::pbt::test_degree_random_degree::>(); + mvpoly::pbt::test_degree_random_degree::>(); } #[test] @@ -719,105 +594,47 @@ fn test_is_constant() { #[test] fn test_mvpoly_add_degree_pbt() { - let mut rng = o1_utils::tests::make_test_rng(None); - let degree = rng.gen_range(1..5); - let p1 = unsafe { Dense::::random(&mut rng, Some(degree)) }; - let p2 = unsafe { Dense::::random(&mut rng, Some(degree)) }; - let p3 = p1.clone() + p2.clone(); - let degree_p1 = unsafe { p1.degree() }; - let degree_p2 = unsafe { p2.degree() }; - let degree_p3 = unsafe { p3.degree() }; - assert!(degree_p3 <= std::cmp::max(degree_p1, degree_p2)); + mvpoly::pbt::test_mvpoly_add_degree_pbt::>(); } #[test] fn test_mvpoly_sub_degree_pbt() { - let mut rng = o1_utils::tests::make_test_rng(None); - let degree = rng.gen_range(1..5); - let p1 = unsafe { Dense::::random(&mut rng, Some(degree)) }; - let p2 = unsafe { Dense::::random(&mut rng, Some(degree)) }; - let p3 = p1.clone() - p2.clone(); - let degree_p1 = unsafe { p1.degree() }; - let degree_p2 = unsafe { p2.degree() }; - let degree_p3 = unsafe { p3.degree() }; - assert!(degree_p3 <= std::cmp::max(degree_p1, degree_p2)); + mvpoly::pbt::test_mvpoly_sub_degree_pbt::>(); } #[test] fn test_mvpoly_neg_degree_pbt() { - let mut rng = o1_utils::tests::make_test_rng(None); - let degree = rng.gen_range(1..5); - let p1 = unsafe { Dense::::random(&mut rng, Some(degree)) }; - let p2 = -p1.clone(); - let degree_p1 = unsafe { p1.degree() }; - let degree_p2 = unsafe { p2.degree() }; - assert_eq!(degree_p1, degree_p2); + mvpoly::pbt::test_mvpoly_neg_degree_pbt::>(); } #[test] fn test_mvpoly_mul_by_scalar_degree_pbt() { - let mut rng = o1_utils::tests::make_test_rng(None); - let degree = rng.gen_range(1..5); - let p1 = unsafe { Dense::::random(&mut rng, Some(degree)) }; - let c = Fp::rand(&mut rng); - let p2 = p1.clone() * Dense::::from(c); - let degree_p1 = unsafe { p1.degree() }; - let degree_p2 = unsafe { p2.degree() }; - assert!(degree_p2 <= degree_p1); + mvpoly::pbt::test_mvpoly_mul_by_scalar_degree_pbt::>(); } #[test] fn test_mvpoly_mul_degree_pbt() { - let mut rng = o1_utils::tests::make_test_rng(None); - // half max degree - let degree = rng.gen_range(1..3); - let p1 = unsafe { Dense::::random(&mut rng, Some(degree)) }; - let p2 = unsafe { Dense::::random(&mut rng, Some(degree)) }; - let p3 = p1.clone() * p2.clone(); - let degree_p1 = unsafe { p1.degree() }; - let degree_p2 = unsafe { p2.degree() }; - let degree_p3 = unsafe { p3.degree() }; - assert!(degree_p3 <= degree_p1 + degree_p2); + mvpoly::pbt::test_mvpoly_mul_degree_pbt::>(); } #[test] fn test_mvpoly_mul_eval_pbt() { - let mut rng = o1_utils::tests::make_test_rng(None); - let max_degree = rng.gen_range(1..3); - let p1 = unsafe { Dense::::random(&mut rng, Some(max_degree)) }; - let p2 = unsafe { Dense::::random(&mut rng, Some(max_degree)) }; - let p3 = p1.clone() * p2.clone(); - let random_evaluation: [Fp; 4] = std::array::from_fn(|_| Fp::rand(&mut rng)); - let eval_p1 = p1.eval(&random_evaluation); - let eval_p2 = p2.eval(&random_evaluation); - let eval_p3 = p3.eval(&random_evaluation); - assert_eq!(eval_p3, eval_p1 * eval_p2); + mvpoly::pbt::test_mvpoly_mul_eval_pbt::>(); } #[test] fn test_mvpoly_mul_pbt() { - let mut rng = o1_utils::tests::make_test_rng(None); - let max_degree = rng.gen_range(1..3); - let p1 = unsafe { Dense::::random(&mut rng, Some(max_degree)) }; - let p2 = unsafe { Dense::::random(&mut rng, Some(max_degree)) }; - assert_eq!(p1.clone() * p2.clone(), p2.clone() * p1.clone()); + mvpoly::pbt::test_mvpoly_mul_pbt::>(); } #[test] fn test_can_be_printed_with_debug() { - let mut rng = o1_utils::tests::make_test_rng(None); - let p1 = unsafe { Dense::::random(&mut rng, None) }; - println!("{:?}", p1); + mvpoly::pbt::test_can_be_printed_with_debug::>(); } #[test] fn test_is_zero() { - let mut rng = o1_utils::tests::make_test_rng(None); - let p1 = Dense::::zero(); - assert!(p1.is_zero()); - - let p2 = unsafe { Dense::::random(&mut rng, None) }; - assert!(!p2.is_zero()); + mvpoly::pbt::test_is_zero::>(); } #[test]