From 0c4a4445e97b15f7f3ddc4f8786cdb9532a15a74 Mon Sep 17 00:00:00 2001 From: Danny Willems Date: Tue, 15 Oct 2024 21:16:17 +0200 Subject: [PATCH] WIP --- mvpoly/src/lib.rs | 30 +++++++++++++++++------------- mvpoly/src/monomials.rs | 24 +++++++++++++++++------- mvpoly/src/prime.rs | 28 +++++++++++++++++++--------- mvpoly/tests/monomials.rs | 17 ++++++++++------- mvpoly/tests/prime.rs | 39 ++++++++++++++++++++++++--------------- 5 files changed, 87 insertions(+), 51 deletions(-) diff --git a/mvpoly/src/lib.rs b/mvpoly/src/lib.rs index 65a5025ce6..ec927a43d6 100644 --- a/mvpoly/src/lib.rs +++ b/mvpoly/src/lib.rs @@ -84,7 +84,6 @@ pub trait MVPoly: /// speed up the computation. fn eval(&self, x: &[F; N]) -> F; - /// Build the univariate polynomial `x_i` from the variable `i`. /// The conversion into the type `usize` is unspecified by this trait. It /// is left to the trait implementation. @@ -93,7 +92,12 @@ pub trait MVPoly: /// used. /// For [crate::monomials], the output must be the index of the variable, /// starting from `0`. - fn from_variable>(var: Variable) -> Self; + /// + /// The parameter `offset_next_row` is an optional argument that is used to + /// support the case where the "next row" is used. In this case, the type + /// parameter `N` must include this offset (i.e. if 4 variables are in ued, + /// N should be at least `8 = 2 * 4`). + fn from_variable>(var: Variable, offset_next_row: Option) -> Self; fn from_constant(op: Operations>) -> Self { use kimchi::circuits::expr::Operations::*; @@ -145,7 +149,7 @@ pub trait MVPoly: /// "the expression framework". /// In the near future, the "expression framework" should be moved also into /// this library. - fn from_expr, ChallengeTerm: Clone>(expr: Expr, Column>) -> Self { + fn from_expr, ChallengeTerm: Clone>(expr: Expr, Column>, offset_next_row: Option) -> Self { use kimchi::circuits::expr::Operations::*; match expr { @@ -159,36 +163,36 @@ pub trait MVPoly: } ExprInner::Constant(c) => Self::from_constant(c), ExprInner::Cell(var) => { - Self::from_variable(var) + Self::from_variable::(var, offset_next_row) } } } Add(e1, e2) => { - let p1 = Self::from_expr(*e1); - let p2 = Self::from_expr(*e2); + let p1 = Self::from_expr::(*e1, offset_next_row); + let p2 = Self::from_expr::(*e2, offset_next_row); p1 + p2 } Sub(e1, e2) => { - let p1 = Self::from_expr(*e1); - let p2 = Self::from_expr(*e2); + let p1 = Self::from_expr::(*e1, offset_next_row); + let p2 = Self::from_expr::(*e2, offset_next_row); p1 - p2 } Mul(e1, e2) => { - let p1 = Self::from_expr(*e1); - let p2 = Self::from_expr(*e2); + let p1 = Self::from_expr::(*e1, offset_next_row); + let p2 = Self::from_expr::(*e2, offset_next_row); p1 * p2 } Double(p) => { - let p = Self::from_expr(*p); + let p = Self::from_expr::(*p, offset_next_row); p.double() } Square(p) => { - let p = Self::from_expr(*p); + let p = Self::from_expr::(*p, offset_next_row); p.clone() * p.clone() } Pow(c, e) => { // FIXME: dummy implementation - let p = Self::from_expr(*c); + let p = Self::from_expr::(*c, offset_next_row); let mut result = p.clone(); for _ in 0..e { result = result.clone() * p.clone(); diff --git a/mvpoly/src/monomials.rs b/mvpoly/src/monomials.rs index 4f33e8dd81..1b40b5f210 100644 --- a/mvpoly/src/monomials.rs +++ b/mvpoly/src/monomials.rs @@ -356,16 +356,26 @@ impl MVPoly for Sparse>(var: Variable) -> Self { + fn from_variable>( + var: Variable, + offset_next_row: Option, + ) -> Self { let Variable { col, row } = var; - assert_eq!( - row, - CurrOrNext::Curr, - "Only current row is supported for now. You cannot reference the next row" - ); + if row == CurrOrNext::Next { + assert!( + offset_next_row.is_some(), + "The offset must be provided for the next row" + ); + } let var_usize: usize = col.into(); let mut monomials = HashMap::new(); - let exponents: [usize; N] = std::array::from_fn(|i| if i == var_usize { 1 } else { 0 }); + let offset = if row == CurrOrNext::Curr { + 0 + } else { + offset_next_row.unwrap() + }; + let exponents: [usize; N] = + std::array::from_fn(|i| if i == offset + var_usize { 1 } else { 0 }); monomials.insert(exponents, F::one()); Self { monomials } } diff --git a/mvpoly/src/prime.rs b/mvpoly/src/prime.rs index d8518f2192..f611031e2a 100644 --- a/mvpoly/src/prime.rs +++ b/mvpoly/src/prime.rs @@ -338,22 +338,32 @@ impl MVPoly for Dense>(var: Variable) -> Self { + fn from_variable>( + var: Variable, + offset_next_row: Option, + ) -> Self { let Variable { col, row } = var; - assert_eq!( - row, - CurrOrNext::Curr, - "Only current row is supported for now. You cannot reference the next row" - ); + if row == CurrOrNext::Next { + assert!( + offset_next_row.is_some(), + "The offset for the next row must be provided" + ); + } + let offset = if row == CurrOrNext::Curr { + 0 + } else { + offset_next_row.unwrap() + }; + let var_usize: usize = col.into(); + let idx = var_usize + offset; let mut res = Self::zero(); let mut prime_gen = PrimeNumberGenerator::new(); let primes = prime_gen.get_first_nth_primes(N); - let var_usize: usize = col.into(); - assert!(primes.contains(&var_usize), "The usize representation of the variable must be a prime number, and unique for each variable"); + assert!(primes.contains(&idx), "The usize representation of the variable must be a prime number, and unique for each variable"); let inv_var = res .normalized_indices .iter() - .position(|&x| x == var_usize) + .position(|&x| x == idx) .unwrap(); res[inv_var] = F::one(); res diff --git a/mvpoly/tests/monomials.rs b/mvpoly/tests/monomials.rs index 782a4211d3..cbf940d625 100644 --- a/mvpoly/tests/monomials.rs +++ b/mvpoly/tests/monomials.rs @@ -466,10 +466,13 @@ fn test_build_from_variable() { let mut rng = o1_utils::tests::make_test_rng(None); let idx: usize = rng.gen_range(0..4); - let p = Sparse::::from_variable(Variable { - col: Column::X(idx), - row: CurrOrNext::Curr, - }); + let p = Sparse::::from_variable::( + Variable { + col: Column::X(idx), + row: CurrOrNext::Curr, + }, + None, + ); let eval: [Fp; 4] = std::array::from_fn(|_i| Fp::rand(&mut rng)); @@ -599,7 +602,7 @@ fn test_from_expr_ec_addition() { // - Constraint 1: λ (X1 - X2) - Y1 + Y2 = 0 let expression = lambda.clone() * (x1.clone() - x2.clone()) - (y1.clone() - y2.clone()); - let p = Sparse::::from_expr(expression); + let p = Sparse::::from_expr::(expression, None); let random_evaluation: [Fp; 7] = std::array::from_fn(|_| Fp::rand(&mut rng)); let eval = p.eval(&random_evaluation); let exp_eval = { @@ -612,7 +615,7 @@ fn test_from_expr_ec_addition() { { // - Constraint 2: X3 + X1 + X2 - λ^2 = 0 let expr = x3.clone() + x1.clone() + x2.clone() - lambda.clone() * lambda.clone(); - let p = Sparse::::from_expr(expr); + let p = Sparse::::from_expr::(expr, None); let random_evaluation: [Fp; 7] = std::array::from_fn(|_| Fp::rand(&mut rng)); let eval = p.eval(&random_evaluation); let exp_eval = { @@ -624,7 +627,7 @@ fn test_from_expr_ec_addition() { { // - Constraint 3: Y3 - λ (X1 - X3) + Y1 = 0 let expr = y3.clone() - lambda.clone() * (x1.clone() - x3.clone()) + y1.clone(); - let p = Sparse::::from_expr(expr); + let p = Sparse::::from_expr::(expr, None); let random_evaluation: [Fp; 7] = std::array::from_fn(|_| Fp::rand(&mut rng)); let eval = p.eval(&random_evaluation); let exp_eval = { diff --git a/mvpoly/tests/prime.rs b/mvpoly/tests/prime.rs index 4249e37bfe..92220975bb 100644 --- a/mvpoly/tests/prime.rs +++ b/mvpoly/tests/prime.rs @@ -264,10 +264,13 @@ fn test_from_variable_column() { } } - let p = Dense::::from_variable(Variable { - col: Column::X(0), - row: CurrOrNext::Curr, - }); + let p = Dense::::from_variable::( + Variable { + col: Column::X(0), + row: CurrOrNext::Curr, + }, + None, + ); assert_eq!(p[0], Fp::zero()); assert_eq!(p[1], Fp::one()); assert_eq!(p[2], Fp::zero()); @@ -276,10 +279,13 @@ fn test_from_variable_column() { assert_eq!(p[5], Fp::zero()); // Test for z variable (index 3) - let p = Dense::::from_variable(Variable { - col: Column::X(1), - row: CurrOrNext::Curr, - }); + let p = Dense::::from_variable::( + Variable { + col: Column::X(1), + row: CurrOrNext::Curr, + }, + None, + ); assert_eq!(p[0], Fp::zero()); assert_eq!(p[1], Fp::zero()); assert_eq!(p[2], Fp::one()); @@ -287,10 +293,13 @@ fn test_from_variable_column() { assert_eq!(p[4], Fp::zero()); // Test for w variable (index 5) - let p = Dense::::from_variable(Variable { - col: Column::X(2), - row: CurrOrNext::Curr, - }); + let p = Dense::::from_variable::( + Variable { + col: Column::X(2), + row: CurrOrNext::Curr, + }, + None, + ); assert_eq!(p[0], Fp::zero()); assert_eq!(p[1], Fp::zero()); assert_eq!(p[2], Fp::zero()); @@ -459,7 +468,7 @@ fn test_from_expr_ec_addition() { // - Constraint 1: λ (X1 - X2) - Y1 + Y2 = 0 let expression = lambda.clone() * (x1.clone() - x2.clone()) - (y1.clone() - y2.clone()); - let p = Dense::::from_expr(expression); + let p = Dense::::from_expr::(expression, None); let random_evaluation: [Fp; 7] = std::array::from_fn(|_| Fp::rand(&mut rng)); let eval = p.eval(&random_evaluation); let exp_eval = { @@ -472,7 +481,7 @@ fn test_from_expr_ec_addition() { { // - Constraint 2: X3 + X1 + X2 - λ^2 = 0 let expr = x3.clone() + x1.clone() + x2.clone() - lambda.clone() * lambda.clone(); - let p = Dense::::from_expr(expr); + let p = Dense::::from_expr::(expr, None); let random_evaluation: [Fp; 7] = std::array::from_fn(|_| Fp::rand(&mut rng)); let eval = p.eval(&random_evaluation); let exp_eval = { @@ -484,7 +493,7 @@ fn test_from_expr_ec_addition() { { // - Constraint 3: Y3 - λ (X1 - X3) + Y1 = 0 let expr = y3.clone() - lambda.clone() * (x1.clone() - x3.clone()) + y1.clone(); - let p = Dense::::from_expr(expr); + let p = Dense::::from_expr::(expr, None); let random_evaluation: [Fp; 7] = std::array::from_fn(|_| Fp::rand(&mut rng)); let eval = p.eval(&random_evaluation); let exp_eval = {