From 4ed11e94569063f511d93d3865483031934d186d Mon Sep 17 00:00:00 2001
From: Shahar Papini <43779613+spapinistarkware@users.noreply.github.com>
Date: Thu, 21 Mar 2024 13:24:07 +0200
Subject: [PATCH] Use only canonic domains
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This change is [](https://reviewable.io/reviews/starkware-libs/stwo/463)
---
src/core/air/evaluation.rs | 13 +++----
src/core/air/mod.rs | 3 +-
src/core/backend/avx512/circle.rs | 13 ++++---
src/core/circle.rs | 21 +----------
src/core/poly/circle/canonic.rs | 11 ------
src/core/poly/circle/domain.rs | 8 +----
src/core/poly/circle/evaluation.rs | 4 +--
src/core/poly/circle/mod.rs | 44 ++---------------------
src/fibonacci/component.rs | 57 ++++++++++++------------------
9 files changed, 41 insertions(+), 133 deletions(-)
diff --git a/src/core/air/evaluation.rs b/src/core/air/evaluation.rs
index 9e7f8d36c..cca111d2e 100644
--- a/src/core/air/evaluation.rs
+++ b/src/core/air/evaluation.rs
@@ -7,7 +7,7 @@ use crate::core::backend::{Backend, CPUBackend, Col, Column};
use crate::core::fields::m31::BaseField;
use crate::core::fields::qm31::SecureField;
use crate::core::fields::{ExtensionOf, FieldExpOps};
-use crate::core::poly::circle::{CircleDomain, CirclePoly, SecureCirclePoly};
+use crate::core::poly::circle::{CanonicCoset, CirclePoly, SecureCirclePoly};
use crate::core::poly::BitReversedOrder;
use crate::core::utils::IteratorMutExt;
@@ -169,7 +169,7 @@ impl DomainEvaluationAccumulator {
let coeffs = SecureColumn {
cols: values.cols.map(|c| {
CPUCircleEvaluation::<_, BitReversedOrder>::new(
- CircleDomain::constraint_evaluation_domain(log_size as u32),
+ CanonicCoset::new(log_size as u32).circle_domain(),
c,
)
.interpolate()
@@ -304,12 +304,9 @@ mod tests {
let mut res = SecureField::default();
for (log_size, values) in pairs.into_iter() {
res = res * alpha
- + CPUCircleEvaluation::new(
- CircleDomain::constraint_evaluation_domain(log_size),
- values,
- )
- .interpolate()
- .eval_at_point(point);
+ + CPUCircleEvaluation::new(CanonicCoset::new(log_size).circle_domain(), values)
+ .interpolate()
+ .eval_at_point(point);
}
assert_eq!(accumulator_res, res);
diff --git a/src/core/air/mod.rs b/src/core/air/mod.rs
index 0f9024585..f90d34d49 100644
--- a/src/core/air/mod.rs
+++ b/src/core/air/mod.rs
@@ -63,8 +63,7 @@ pub trait Component {
/// Returns the degree bounds of each trace column.
fn trace_log_degree_bounds(&self) -> Vec;
- /// Evaluates the constraint quotients of the component on constraint evaluation domains.
- /// See [`super::poly::circle::CircleDomain::constraint_evaluation_domain`].
+ /// Evaluates the constraint quotients of the component on the evaluation domain.
/// Accumulates quotients in `evaluation_accumulator`.
// Note: This will be computed using a MaterializedGraph.
fn evaluate_constraint_quotients_on_domain(
diff --git a/src/core/backend/avx512/circle.rs b/src/core/backend/avx512/circle.rs
index dbe443186..8769ee128 100644
--- a/src/core/backend/avx512/circle.rs
+++ b/src/core/backend/avx512/circle.rs
@@ -333,9 +333,7 @@ mod tests {
use crate::core::backend::Column;
use crate::core::circle::CirclePoint;
use crate::core::fields::m31::BaseField;
- use crate::core::poly::circle::{
- CanonicCoset, CircleDomain, CircleEvaluation, CirclePoly, PolyOps,
- };
+ use crate::core::poly::circle::{CanonicCoset, CircleEvaluation, CirclePoly, PolyOps};
use crate::core::poly::{BitReversedOrder, NaturalOrder};
use crate::qm31;
@@ -359,8 +357,8 @@ mod tests {
fn test_eval_extension() {
for log_size in MIN_FFT_LOG_SIZE..(CACHED_FFT_LOG_SIZE + 4) {
let log_size = log_size as u32;
- let domain = CircleDomain::constraint_evaluation_domain(log_size);
- let domain_ext = CircleDomain::constraint_evaluation_domain(log_size + 3);
+ let domain = CanonicCoset::new(log_size).circle_domain();
+ let domain_ext = CanonicCoset::new(log_size + 3).circle_domain();
let evaluation = CircleEvaluation::::new(
domain,
(0..(1 << log_size))
@@ -369,9 +367,10 @@ mod tests {
);
let poly = evaluation.clone().interpolate();
let evaluation2 = poly.evaluate(domain_ext);
+ let poly2 = evaluation2.interpolate();
assert_eq!(
- evaluation2.values.to_vec()[..(1 << log_size)],
- evaluation.values.to_vec()
+ poly.extend(log_size + 3).coeffs.to_vec(),
+ poly2.coeffs.to_vec()
);
}
}
diff --git a/src/core/circle.rs b/src/core/circle.rs
index 8c4b1cea6..c0a7b9cf5 100644
--- a/src/core/circle.rs
+++ b/src/core/circle.rs
@@ -461,26 +461,7 @@ mod tests {
use crate::core::circle::{CirclePoint, SECURE_FIELD_CIRCLE_GEN};
use crate::core::fields::qm31::{SecureField, P4};
use crate::core::fields::FieldExpOps;
- use crate::core::poly::circle::{CanonicCoset, CircleDomain};
-
- #[test]
- fn test_domains() {
- let log_size = 4;
- let canonic_cosets_extensions = [
- CanonicCoset::new(2).evaluation_domain(log_size + 1),
- CanonicCoset::new(2).evaluation_domain(log_size + 2),
- CanonicCoset::new(log_size - 1).evaluation_domain(log_size),
- ];
-
- let subgroup_gen = CirclePointIndex::subgroup_gen(log_size);
- let constraint_evaluation_domain = CircleDomain::constraint_evaluation_domain(log_size - 1);
-
- for point_index in constraint_evaluation_domain.iter_indices() {
- for eval in &canonic_cosets_extensions {
- assert!(eval.find(point_index - subgroup_gen).is_some());
- }
- }
- }
+ use crate::core::poly::circle::CanonicCoset;
#[test]
fn test_iterator() {
diff --git a/src/core/poly/circle/canonic.rs b/src/core/poly/circle/canonic.rs
index 2e6f37ddc..0e571d51a 100644
--- a/src/core/poly/circle/canonic.rs
+++ b/src/core/poly/circle/canonic.rs
@@ -45,17 +45,6 @@ impl CanonicCoset {
CircleDomain::new(Coset::half_odds(self.coset.log_size - 1))
}
- /// Gets a good [CircleDomain] for extension of a poly defined on this coset.
- /// The reason the domain looks like this is a bit more intricate, and not covered here.
- pub fn evaluation_domain(&self, log_size: u32) -> CircleDomain {
- assert!(log_size > self.coset.log_size);
- // TODO(spapini): Document why this is like this.
- CircleDomain::new(Coset::new(
- CirclePointIndex::generator() + CirclePointIndex::subgroup_gen(self.coset.log_size + 1),
- log_size - 1,
- ))
- }
-
/// Returns the log size of the coset.
pub fn log_size(&self) -> u32 {
self.coset.log_size
diff --git a/src/core/poly/circle/domain.rs b/src/core/poly/circle/domain.rs
index 4cf598697..d47141221 100644
--- a/src/core/poly/circle/domain.rs
+++ b/src/core/poly/circle/domain.rs
@@ -22,12 +22,6 @@ impl CircleDomain {
Self { half_coset }
}
- /// Constructs a domain for constraint evaluation.
- pub fn constraint_evaluation_domain(log_size: u32) -> Self {
- assert!(log_size > 0);
- CircleDomain::new(Coset::new(CirclePointIndex::generator(), log_size - 1))
- }
-
pub fn iter(&self) -> CircleDomainIterator {
self.half_coset
.iter()
@@ -112,7 +106,7 @@ mod tests {
#[test]
fn test_circle_domain_iterator() {
- let domain = CircleDomain::constraint_evaluation_domain(3);
+ let domain = CircleDomain::new(Coset::new(CirclePointIndex::generator(), 2));
for (i, point) in domain.iter().enumerate() {
if i < 4 {
assert_eq!(
diff --git a/src/core/poly/circle/evaluation.rs b/src/core/poly/circle/evaluation.rs
index 5c52f953d..1d50559ed 100644
--- a/src/core/poly/circle/evaluation.rs
+++ b/src/core/poly/circle/evaluation.rs
@@ -154,13 +154,13 @@ mod tests {
use crate::core::backend::cpu::CPUCircleEvaluation;
use crate::core::circle::Coset;
use crate::core::fields::m31::BaseField;
- use crate::core::poly::circle::{CanonicCoset, CircleDomain};
+ use crate::core::poly::circle::CanonicCoset;
use crate::core::poly::NaturalOrder;
use crate::m31;
#[test]
fn test_interpolate_non_canonic() {
- let domain = CircleDomain::constraint_evaluation_domain(3);
+ let domain = CanonicCoset::new(3).circle_domain();
assert_eq!(domain.log_size(), 3);
let evaluation = CPUCircleEvaluation::<_, NaturalOrder>::new(
domain,
diff --git a/src/core/poly/circle/mod.rs b/src/core/poly/circle/mod.rs
index ab90285a0..f2cdb308d 100644
--- a/src/core/poly/circle/mod.rs
+++ b/src/core/poly/circle/mod.rs
@@ -14,16 +14,14 @@ pub use secure_poly::{combine_secure_value, SecureCirclePoly};
#[cfg(test)]
mod tests {
- use super::{CanonicCoset, CircleDomain};
+ use super::CanonicCoset;
use crate::core::backend::cpu::CPUCircleEvaluation;
use crate::core::fields::m31::BaseField;
- use crate::core::fields::FieldExpOps;
- use crate::core::poly::NaturalOrder;
use crate::core::utils::bit_reverse_index;
#[test]
fn test_interpolate_and_eval() {
- let domain = CircleDomain::constraint_evaluation_domain(3);
+ let domain = CanonicCoset::new(3).circle_domain();
assert_eq!(domain.log_size(), 3);
let evaluation =
CPUCircleEvaluation::new(domain, (0..8).map(BaseField::from_u32_unchecked).collect());
@@ -32,44 +30,6 @@ mod tests {
assert_eq!(evaluation.values, evaluation2.values);
}
- #[test]
- fn test_mixed_degree_example() {
- let log_size = 4;
-
- // Compute domains.
- let domain0 = CanonicCoset::new(log_size);
- let eval_domain0 = domain0.evaluation_domain(log_size + 4);
- let domain1 = CanonicCoset::new(log_size + 2);
- let eval_domain1 = domain1.evaluation_domain(log_size + 3);
- let constraint_domain = CircleDomain::constraint_evaluation_domain(log_size + 1);
-
- // Compute values.
- let values1: Vec<_> = (0..(domain1.size() as u32))
- .map(BaseField::from_u32_unchecked)
- .collect();
- let values0: Vec<_> = values1[1..].iter().step_by(4).map(|x| *x * *x).collect();
-
- // Extend.
- let trace_eval0 = CPUCircleEvaluation::new_canonical_ordered(domain0, values0);
- let eval0 = trace_eval0.interpolate().evaluate(eval_domain0);
- let trace_eval1 = CPUCircleEvaluation::new_canonical_ordered(domain1, values1);
- let eval1 = trace_eval1.interpolate().evaluate(eval_domain1);
-
- // Compute constraint.
- let constraint_eval = CPUCircleEvaluation::::new(
- constraint_domain,
- constraint_domain
- .iter_indices()
- .map(|ind| {
- // The constraint is poly0(x+off0)^2 = poly1(x+off1).
- eval0.get_at(ind).square() - eval1.get_at(domain1.index_at(1) + ind).square()
- })
- .collect(),
- );
- // TODO(spapini): Check low degree.
- println!("{:?}", constraint_eval);
- }
-
#[test]
fn is_canonic_valid_domain() {
let canonic_domain = CanonicCoset::new(4).circle_domain();
diff --git a/src/fibonacci/component.rs b/src/fibonacci/component.rs
index a1ec44770..09b6be864 100644
--- a/src/fibonacci/component.rs
+++ b/src/fibonacci/component.rs
@@ -10,7 +10,7 @@ use crate::core::constraints::{coset_vanishing, pair_vanishing};
use crate::core::fields::m31::BaseField;
use crate::core::fields::qm31::SecureField;
use crate::core::fields::{ExtensionOf, FieldExpOps};
-use crate::core::poly::circle::{CanonicCoset, CircleDomain};
+use crate::core::poly::circle::CanonicCoset;
use crate::core::utils::bit_reverse_index;
use crate::core::ColumnVec;
@@ -85,14 +85,13 @@ impl Component for FibonacciComponent {
) {
let poly = &trace.columns[0];
let trace_domain = CanonicCoset::new(self.log_size);
- let trace_eval_domain = trace_domain.evaluation_domain(self.log_size + 1);
+ let trace_eval_domain = CanonicCoset::new(self.log_size + 1).circle_domain();
let trace_eval = poly.evaluate(trace_eval_domain).bit_reverse();
// Step constraint.
let constraint_log_degree_bound = trace_domain.log_size() + 1;
let [mut accum] = evaluation_accumulator.columns([(constraint_log_degree_bound, 1)]);
- let constraint_eval_domain =
- CircleDomain::constraint_evaluation_domain(constraint_log_degree_bound);
+ let constraint_eval_domain = trace_eval_domain;
for (off, point_coset) in [
(0, constraint_eval_domain.half_coset),
(
@@ -104,28 +103,14 @@ impl Component for FibonacciComponent {
let mul = trace_domain.step_size().div(point_coset.step_size);
for (i, point) in point_coset.iter().enumerate() {
let mask = [eval[i], eval[i as isize + mul], eval[i as isize + 2 * mul]];
- let res = self.step_constraint_eval_quotient_by_mask(point, &mask);
- accum.accumulate(bit_reverse_index(i + off, constraint_log_degree_bound), res);
- }
- }
-
- // Boundary constraint.
- let constraint_log_degree_bound = trace_domain.log_size();
- let [mut accum] = evaluation_accumulator.columns([(constraint_log_degree_bound, 1)]);
- let constraint_eval_domain =
- CircleDomain::constraint_evaluation_domain(constraint_log_degree_bound);
- for (off, point_coset) in [
- (0, constraint_eval_domain.half_coset),
- (
- constraint_eval_domain.half_coset.size(),
- constraint_eval_domain.half_coset.conjugate(),
- ),
- ] {
- let eval = trace_eval.fetch_eval_on_coset(point_coset.shift(trace_domain.index_at(0)));
- for (i, point) in point_coset.iter().enumerate() {
- let mask = [eval[i]];
- let res = self.boundary_constraint_eval_quotient_by_mask(point, &mask);
- accum.accumulate(bit_reverse_index(i + off, constraint_log_degree_bound), res);
+ accum.accumulate(
+ bit_reverse_index(i + off, constraint_log_degree_bound),
+ self.step_constraint_eval_quotient_by_mask(point, &mask),
+ );
+ accum.accumulate(
+ bit_reverse_index(i + off, constraint_log_degree_bound),
+ self.boundary_constraint_eval_quotient_by_mask(point, &[mask[0]]),
+ );
}
}
}
@@ -140,13 +125,17 @@ impl Component for FibonacciComponent {
mask: &ColumnVec>,
evaluation_accumulator: &mut PointEvaluationAccumulator,
) {
- let res =
- self.step_constraint_eval_quotient_by_mask(point, &mask[0][..].try_into().unwrap());
- let constraint_log_degree_bound = self.log_size + 1;
- evaluation_accumulator.accumulate(constraint_log_degree_bound, res);
- let res = self
- .boundary_constraint_eval_quotient_by_mask(point, &mask[0][..1].try_into().unwrap());
- let constraint_log_degree_bound = self.log_size;
- evaluation_accumulator.accumulate(constraint_log_degree_bound, res);
+ let constraints_log_degree_bound = self.log_size + 1;
+ evaluation_accumulator.accumulate(
+ constraints_log_degree_bound,
+ self.step_constraint_eval_quotient_by_mask(point, &mask[0][..].try_into().unwrap()),
+ );
+ evaluation_accumulator.accumulate(
+ constraints_log_degree_bound,
+ self.boundary_constraint_eval_quotient_by_mask(
+ point,
+ &mask[0][..1].try_into().unwrap(),
+ ),
+ );
}
}