use super::{CircleEvaluation, PolyOps};
use crate::core::circle::CirclePoint;
use crate::core::fields::m31::BaseField;
use crate::core::fields::qm31::SecureField;
use crate::core::poly::circle::CircleDomain;
use crate::prover::backend::{Col, Column, ColumnOps};
use crate::prover::poly::twiddles::TwiddleTree;
use crate::prover::poly::BitReversedOrder;
#[derive(Clone, Debug)]
pub struct CircleCoefficients<B: ColumnOps<BaseField>> {
pub coeffs: Col<B, BaseField>,
log_size: u32,
}
impl<B: PolyOps> CircleCoefficients<B> {
pub fn new(coeffs: Col<B, BaseField>) -> Self {
assert!(coeffs.len().is_power_of_two());
let log_size = coeffs.len().ilog2();
Self { log_size, coeffs }
}
pub const fn log_size(&self) -> u32 {
self.log_size
}
pub fn eval_at_point(&self, point: CirclePoint<SecureField>) -> SecureField {
B::eval_at_point(self, point)
}
pub fn extend(&self, log_size: u32) -> Self {
B::extend(self, log_size)
}
pub fn evaluate(
&self,
domain: CircleDomain,
) -> CircleEvaluation<B, BaseField, BitReversedOrder> {
B::evaluate(self, domain, &B::precompute_twiddles(domain.half_coset))
}
pub fn evaluate_with_twiddles(
&self,
domain: CircleDomain,
twiddles: &TwiddleTree<B>,
) -> CircleEvaluation<B, BaseField, BitReversedOrder> {
B::evaluate(self, domain, twiddles)
}
pub fn split_at_mid(self) -> (Self, Self) {
B::split_at_mid(self)
}
}
#[cfg(test)]
impl crate::prover::backend::cpu::CpuCirclePoly {
pub fn is_in_fft_space(&self, log_fft_size: u32) -> bool {
use num_traits::Zero;
let mut coeffs = self.coeffs.clone();
while coeffs.last() == Some(&BaseField::zero()) {
coeffs.pop();
}
let highest_degree_allowed_monomial_offset = 1 << log_fft_size;
coeffs.len() <= highest_degree_allowed_monomial_offset
}
pub fn is_in_fri_space(&self, log_fft_size: u32) -> bool {
use num_traits::Zero;
let mut coeffs = self.coeffs.clone();
while coeffs.last() == Some(&BaseField::zero()) {
coeffs.pop();
}
let highest_degree_monomial_offset = (1 << log_fft_size) + 1;
coeffs.len() <= highest_degree_monomial_offset
}
}
#[cfg(test)]
mod tests {
use crate::core::circle::CirclePoint;
use crate::core::fields::m31::BaseField;
use crate::prover::backend::cpu::CpuCirclePoly;
#[test]
fn test_circle_poly_extend() {
let poly = CpuCirclePoly::new((0..16).map(BaseField::from_u32_unchecked).collect());
let extended = poly.clone().extend(8);
let random_point = CirclePoint::get_point(21903);
assert_eq!(
poly.eval_at_point(random_point),
extended.eval_at_point(random_point)
);
}
}