-
Notifications
You must be signed in to change notification settings - Fork 93
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
<!-- Reviewable:start --> This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/starkware-libs/stwo/481) <!-- Reviewable:end -->
- Loading branch information
1 parent
584c52d
commit 20412e4
Showing
4 changed files
with
128 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
mod circle; | ||
mod fri; | ||
pub mod quotients; | ||
|
||
use std::fmt::Debug; | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
use num_traits::Zero; | ||
|
||
use super::CPUBackend; | ||
use crate::core::circle::CirclePoint; | ||
use crate::core::commitment_scheme::quotients::{ColumnSampleBatch, QuotientOps}; | ||
use crate::core::constraints::{complex_conjugate_line, pair_vanishing}; | ||
use crate::core::fields::m31::BaseField; | ||
use crate::core::fields::qm31::SecureField; | ||
use crate::core::fields::secure_column::SecureColumn; | ||
use crate::core::fields::{ComplexConjugate, FieldExpOps}; | ||
use crate::core::poly::circle::{CircleDomain, CircleEvaluation}; | ||
use crate::core::poly::BitReversedOrder; | ||
use crate::core::utils::bit_reverse_index; | ||
|
||
impl QuotientOps for CPUBackend { | ||
fn accumulate_quotients( | ||
domain: CircleDomain, | ||
columns: &[&CircleEvaluation<Self, BaseField, BitReversedOrder>], | ||
random_coeff: SecureField, | ||
samples: &[ColumnSampleBatch], | ||
) -> SecureColumn<Self> { | ||
let mut res = SecureColumn::zeros(domain.size()); | ||
for row in 0..domain.size() { | ||
// TODO(alonh): Make an efficient bit reverse domain iterator, possibly for AVX backend. | ||
let domain_point = domain.at(bit_reverse_index(row, domain.log_size())); | ||
let row_value = | ||
accumulate_row_quotients(samples, columns, row, random_coeff, domain_point); | ||
res.set(row, row_value); | ||
} | ||
res | ||
} | ||
} | ||
|
||
pub fn accumulate_row_quotients( | ||
samples: &[ColumnSampleBatch], | ||
columns: &[&CircleEvaluation<CPUBackend, BaseField, BitReversedOrder>], | ||
row: usize, | ||
random_coeff: SecureField, | ||
domain_point: CirclePoint<BaseField>, | ||
) -> SecureField { | ||
let mut row_accumlator = SecureField::zero(); | ||
for sample in samples { | ||
let mut numerator = SecureField::zero(); | ||
for (column_index, sampled_value) in &sample.column_indices_and_values { | ||
let column = &columns[*column_index]; | ||
let value = column[row]; | ||
let linear_term = complex_conjugate_line(sample.point, *sampled_value, domain_point); | ||
numerator = numerator * random_coeff + value - linear_term; | ||
} | ||
|
||
let denominator = pair_vanishing( | ||
sample.point, | ||
sample.point.complex_conjugate(), | ||
domain_point.into_ef(), | ||
); | ||
|
||
row_accumlator = row_accumlator | ||
* random_coeff.pow(sample.column_indices_and_values.len() as u128) | ||
+ numerator / denominator; | ||
} | ||
row_accumlator | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use crate::core::backend::cpu::{CPUCircleEvaluation, CPUCirclePoly}; | ||
use crate::core::backend::CPUBackend; | ||
use crate::core::circle::SECURE_FIELD_CIRCLE_GEN; | ||
use crate::core::commitment_scheme::quotients::{ColumnSampleBatch, QuotientOps}; | ||
use crate::core::poly::circle::CanonicCoset; | ||
use crate::{m31, qm31}; | ||
|
||
#[test] | ||
fn test_quotients_are_low_degree() { | ||
const LOG_SIZE: u32 = 7; | ||
let polynomial = CPUCirclePoly::new((0..1 << LOG_SIZE).map(|i| m31!(i)).collect()); | ||
let eval_domain = CanonicCoset::new(LOG_SIZE + 1).circle_domain(); | ||
let eval = polynomial.evaluate(eval_domain); | ||
let point = SECURE_FIELD_CIRCLE_GEN; | ||
let value = polynomial.eval_at_point(point); | ||
let coeff = qm31!(1, 2, 3, 4); | ||
let quot_eval = CPUBackend::accumulate_quotients( | ||
eval_domain, | ||
&[&eval], | ||
coeff, | ||
&[ColumnSampleBatch { | ||
point, | ||
column_indices_and_values: vec![(0, value)], | ||
}], | ||
); | ||
let quot_poly_base_field = | ||
CPUCircleEvaluation::new(eval_domain, quot_eval.columns[0].clone()).interpolate(); | ||
assert!(quot_poly_base_field.is_in_fft_space(LOG_SIZE)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
use crate::core::backend::Backend; | ||
use crate::core::circle::CirclePoint; | ||
use crate::core::fields::m31::BaseField; | ||
use crate::core::fields::qm31::SecureField; | ||
use crate::core::fields::secure_column::SecureColumn; | ||
use crate::core::poly::circle::{CircleDomain, CircleEvaluation}; | ||
use crate::core::poly::BitReversedOrder; | ||
|
||
pub trait QuotientOps: Backend { | ||
/// Accumulates the quotients of the columns at the given domain. | ||
/// For a column f(x), and a point sample (p,v), the quotient is | ||
/// (f(x) - V0(x))/V1(x) | ||
/// where V0(p)=v, V0(conj(p))=conj(v), and V1 is a vanishing polynomial for p,conj(p). | ||
/// This ensures that if f(p)=v, then the quotient is a polynomial. | ||
/// The result is a linear combination of the quotients using powers of random_coeff. | ||
fn accumulate_quotients( | ||
domain: CircleDomain, | ||
columns: &[&CircleEvaluation<Self, BaseField, BitReversedOrder>], | ||
random_coeff: SecureField, | ||
samples: &[ColumnSampleBatch], | ||
) -> SecureColumn<Self>; | ||
} | ||
|
||
/// A batch of column samplings at a point. | ||
pub struct ColumnSampleBatch { | ||
/// The point at which the columns are sampled. | ||
pub point: CirclePoint<SecureField>, | ||
/// The sampled column indices and their values at the point. | ||
pub column_indices_and_values: Vec<(usize, SecureField)>, | ||
} |