use alloc::vec::Vec;
use p3_binary_field::TowerLevel;
use crate::domain::{domain_point, domain_point_steps};
pub(super) struct Twiddles<F> {
bases: Vec<F>,
steps: Vec<F>,
}
impl<F: TowerLevel> Twiddles<F> {
pub(super) fn new(log_n: usize, shift: F) -> Self {
let mut base = shift;
let bases = (0..log_n)
.map(|_| {
let current = base;
base = base.square() + base;
current
})
.collect();
let steps = domain_point_steps::<F>(log_n.saturating_sub(1));
Self { bases, steps }
}
#[inline]
pub(super) fn at(&self, stage: usize, block: usize) -> F {
self.bases[stage] + domain_point::<F>(block << 1)
}
#[inline]
pub(super) fn step(&self, index: usize) -> F {
self.steps[index.trailing_zeros() as usize]
}
}