Skip to content

Commit

Permalink
Merge pull request #26 from eryxcoop/15-07-add-poly
Browse files Browse the repository at this point in the history
Add LinePoly
  • Loading branch information
andrewmilson authored Sep 19, 2024
2 parents c390067 + 70809e5 commit a02de6f
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 0 deletions.
1 change: 1 addition & 0 deletions stwo_cairo_verifier/src/lib.cairo
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
mod channel;
mod circle;
mod fields;
mod poly;
mod utils;
mod vcs;

Expand Down
2 changes: 2 additions & 0 deletions stwo_cairo_verifier/src/poly.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
mod line;
mod utils;
88 changes: 88 additions & 0 deletions stwo_cairo_verifier/src/poly/line.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
use stwo_cairo_verifier::fields::SecureField;
use stwo_cairo_verifier::fields::m31::m31;
use stwo_cairo_verifier::poly::utils::fold;

/// A univariate polynomial represented by its coefficients in the line part of the FFT-basis
/// in bit reversed order.
#[derive(Drop, Clone)]
pub struct LinePoly {
pub coeffs: Array<SecureField>,
pub log_size: u32,
}

#[generate_trait]
pub impl LinePolyImpl of LinePolyTrait {
fn len(self: @LinePoly) -> usize {
self.coeffs.len()
}

fn eval_at_point(self: @LinePoly, mut x: SecureField) -> SecureField {
let mut doublings = array![];
let mut i = 0;
while i < *self.log_size {
doublings.append(x);
let x_square = x * x;
x = x_square + x_square - m31(1).into();
i += 1;
};

fold(self.coeffs, @doublings, 0, 0, self.coeffs.len())
}
}


#[cfg(test)]
mod tests {
use super::{LinePoly, LinePolyTrait};
use stwo_cairo_verifier::fields::qm31::qm31;
use stwo_cairo_verifier::fields::m31::m31;

#[test]
fn test_eval_at_point_1() {
let line_poly = LinePoly {
coeffs: array![
qm31(1080276375, 1725024947, 477465525, 102017026),
qm31(1080276375, 1725024947, 477465525, 102017026)
],
log_size: 1
};
let x = m31(590768354);
let result = line_poly.eval_at_point(x.into());
let expected_result = qm31(515899232, 1030391528, 1006544539, 11142505);
assert_eq!(expected_result, result);
}

#[test]
fn test_eval_at_point_2() {
let line_poly = LinePoly {
coeffs: array![qm31(1, 2, 3, 4), qm31(5, 6, 7, 8)], log_size: 1
};
let x = m31(10);
let result = line_poly.eval_at_point(x.into());
let expected_result = qm31(51, 62, 73, 84);
assert_eq!(expected_result, result);
}

#[test]
fn test_eval_at_point_3() {
let poly = LinePoly {
coeffs: array![
qm31(1, 2, 3, 4),
qm31(5, 6, 7, 8),
qm31(9, 10, 11, 12),
qm31(13, 14, 15, 16),
qm31(17, 18, 19, 20),
qm31(21, 22, 23, 24),
qm31(25, 26, 27, 28),
qm31(29, 30, 31, 32),
],
log_size: 3
};
let x = qm31(2, 5, 7, 11);

let result = poly.eval_at_point(x);

let expected_result = qm31(1857853974, 839310133, 939318020, 651207981);
assert_eq!(expected_result, result);
}
}
35 changes: 35 additions & 0 deletions stwo_cairo_verifier/src/poly/utils.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use stwo_cairo_verifier::fields::SecureField;

/// Folds values recursively in `O(n)` by a hierarchical application of folding factors.
///
/// i.e. folding `n = 8` values with `folding_factors = [x, y, z]`:
///
/// ```text
/// n2=n1+x*n2
/// / \
/// n1=n3+y*n4 n2=n5+y*n6
/// / \ / \
/// n3=a+z*b n4=c+z*d n5=e+z*f n6=g+z*h
/// / \ / \ / \ / \
/// a b c d e f g h
/// ```
///
/// # Panics
///
/// Panics if the number of values is not a power of two or if an incorrect number of of folding
/// factors is provided.
pub fn fold(
values: @Array<SecureField>,
folding_factors: @Array<SecureField>,
index: usize,
level: usize,
n: usize
) -> SecureField {
if n == 1 {
return *values[index];
}

let lhs_val = fold(values, folding_factors, index, level + 1, n / 2);
let rhs_val = fold(values, folding_factors, index + n / 2, level + 1, n / 2);
return lhs_val + rhs_val * *folding_factors[level];
}

0 comments on commit a02de6f

Please sign in to comment.