use crate::field::Goldilocks;
#[derive(Clone, Debug, PartialEq)]
pub struct SpectralSignal {
pub num_vars: usize,
pub values: Vec<i64>,
}
impl SpectralSignal {
pub fn new(values: Vec<i64>) -> Self {
let len = values.len();
assert!(len.is_power_of_two(), "Signal size must be a power of two.");
let num_vars = len.trailing_zeros() as usize;
Self { num_vars, values }
}
pub fn from_bools(bools: &[bool]) -> Self {
let values = bools.iter().map(|&b| if b { 1 } else { 0 }).collect();
Self::new(values)
}
pub fn verify_integrity(&self) -> bool {
self.values.iter().all(|&v| v == 0 || v == 1)
}
pub fn verify_integrity_strict(&self) -> Result<(), (usize, i64)> {
for (i, &v) in self.values.iter().enumerate() {
if v != 0 && v != 1 {
return Err((i, v));
}
}
Ok(())
}
pub fn mul(&self, other: &Self) -> Self {
assert_eq!(self.values.len(), other.values.len());
let new_vals = self
.values
.iter()
.zip(other.values.iter())
.map(|(a, b)| a * b)
.collect();
Self::new(new_vals)
}
pub fn add(&self, other: &Self) -> Self {
assert_eq!(self.values.len(), other.values.len());
let new_vals = self
.values
.iter()
.zip(other.values.iter())
.map(|(a, b)| a + b)
.collect();
Self::new(new_vals)
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct SpectralManifold {
pub values: Vec<Goldilocks>,
}
impl SpectralManifold {
pub fn new(values: Vec<Goldilocks>) -> Self {
assert!(values.len().is_power_of_two());
Self { values }
}
pub fn mul(&self, other: &Self) -> Self {
assert_eq!(self.values.len(), other.values.len());
let new_vals = self
.values
.iter()
.zip(other.values.iter())
.map(|(&a, &b)| a.mul(b))
.collect();
Self { values: new_vals }
}
pub fn add(&self, other: &Self) -> Self {
assert_eq!(self.values.len(), other.values.len());
let new_vals = self
.values
.iter()
.zip(other.values.iter())
.map(|(&a, &b)| a.add(b))
.collect();
Self { values: new_vals }
}
}
#[deprecated(note = "Use SpectralSignal instead")]
pub type BooleanTensor = SpectralSignal;
#[deprecated(note = "Use SpectralManifold instead")]
pub type SpectralTensor = SpectralManifold;