2021-03-30 20:16:20 -07:00
|
|
|
use crate::field::fft::{fft, ifft};
|
2021-03-30 13:30:31 -07:00
|
|
|
use crate::field::field::Field;
|
|
|
|
|
use crate::util::log2_strict;
|
|
|
|
|
|
2021-04-23 10:26:57 -07:00
|
|
|
/// A polynomial in point-value form.
|
2021-03-30 13:30:31 -07:00
|
|
|
///
|
|
|
|
|
/// The points are implicitly `g^i`, where `g` generates the subgroup whose size equals the number
|
|
|
|
|
/// of points.
|
2021-04-02 17:49:51 -07:00
|
|
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
2021-04-06 13:14:59 -07:00
|
|
|
pub struct PolynomialValues<F: Field> {
|
|
|
|
|
pub values: Vec<F>,
|
2021-03-30 13:30:31 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<F: Field> PolynomialValues<F> {
|
2021-04-06 13:14:59 -07:00
|
|
|
pub fn new(values: Vec<F>) -> Self {
|
2021-03-30 13:30:31 -07:00
|
|
|
PolynomialValues { values }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub(crate) fn zero(len: usize) -> Self {
|
|
|
|
|
Self::new(vec![F::ZERO; len])
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// The number of values stored.
|
|
|
|
|
pub(crate) fn len(&self) -> usize {
|
|
|
|
|
self.values.len()
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-21 22:31:45 +02:00
|
|
|
pub fn lde_multiple(polys: Vec<Self>, rate_bits: usize) -> Vec<Self> {
|
|
|
|
|
polys.into_iter().map(|p| p.lde(rate_bits)).collect()
|
2021-03-30 13:30:31 -07:00
|
|
|
}
|
|
|
|
|
|
2021-04-06 13:14:59 -07:00
|
|
|
pub fn lde(self, rate_bits: usize) -> Self {
|
2021-04-23 12:35:19 -07:00
|
|
|
let coeffs = ifft(self).lde(rate_bits);
|
2021-03-30 13:30:31 -07:00
|
|
|
fft(coeffs)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-23 10:26:57 -07:00
|
|
|
/// A polynomial in coefficient form.
|
2021-04-02 17:49:51 -07:00
|
|
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
2021-04-06 13:14:59 -07:00
|
|
|
pub struct PolynomialCoeffs<F: Field> {
|
2021-03-30 13:30:31 -07:00
|
|
|
pub(crate) coeffs: Vec<F>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<F: Field> PolynomialCoeffs<F> {
|
2021-04-06 13:14:59 -07:00
|
|
|
pub fn new(coeffs: Vec<F>) -> Self {
|
2021-03-30 13:30:31 -07:00
|
|
|
PolynomialCoeffs { coeffs }
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-23 10:26:57 -07:00
|
|
|
/// Create a new polynomial with its coefficient list padded to the next power of two.
|
|
|
|
|
pub(crate) fn new_padded(mut coeffs: Vec<F>) -> Self {
|
2021-04-02 17:49:51 -07:00
|
|
|
while !coeffs.len().is_power_of_two() {
|
|
|
|
|
coeffs.push(F::ZERO);
|
|
|
|
|
}
|
|
|
|
|
PolynomialCoeffs { coeffs }
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-30 13:30:31 -07:00
|
|
|
pub(crate) fn zero(len: usize) -> Self {
|
|
|
|
|
Self::new(vec![F::ZERO; len])
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// The number of coefficients. This does not filter out any zero coefficients, so it is not
|
|
|
|
|
/// necessarily related to the degree.
|
|
|
|
|
pub(crate) fn len(&self) -> usize {
|
|
|
|
|
self.coeffs.len()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub(crate) fn log_len(&self) -> usize {
|
|
|
|
|
log2_strict(self.len())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub(crate) fn chunks(&self, chunk_size: usize) -> Vec<Self> {
|
|
|
|
|
self.coeffs
|
|
|
|
|
.chunks(chunk_size)
|
|
|
|
|
.map(|chunk| PolynomialCoeffs::new(chunk.to_vec()))
|
|
|
|
|
.collect()
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-21 22:31:45 +02:00
|
|
|
pub fn eval(&self, x: F) -> F {
|
|
|
|
|
self.coeffs
|
|
|
|
|
.iter()
|
|
|
|
|
.rev()
|
|
|
|
|
.fold(F::ZERO, |acc, &c| acc * x + c)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn lde_multiple(polys: Vec<Self>, rate_bits: usize) -> Vec<Self> {
|
|
|
|
|
polys.into_iter().map(|p| p.lde(rate_bits)).collect()
|
2021-03-30 13:30:31 -07:00
|
|
|
}
|
|
|
|
|
|
2021-04-23 12:35:19 -07:00
|
|
|
pub(crate) fn lde(self, rate_bits: usize) -> Self {
|
2021-03-30 13:30:31 -07:00
|
|
|
let original_size = self.len();
|
|
|
|
|
let lde_size = original_size << rate_bits;
|
|
|
|
|
let Self { mut coeffs } = self;
|
|
|
|
|
for _ in 0..(lde_size - original_size) {
|
|
|
|
|
coeffs.push(F::ZERO);
|
|
|
|
|
}
|
|
|
|
|
Self { coeffs }
|
|
|
|
|
}
|
2021-04-23 10:26:57 -07:00
|
|
|
|
|
|
|
|
/// Removes leading zero coefficients.
|
|
|
|
|
pub fn trim(&mut self) {
|
|
|
|
|
self.coeffs.drain(self.degree_plus_one()..);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Degree of the polynomial + 1.
|
|
|
|
|
fn degree_plus_one(&self) -> usize {
|
|
|
|
|
(0usize..self.len())
|
|
|
|
|
.rev()
|
|
|
|
|
.find(|&i| self.coeffs[i].is_nonzero())
|
|
|
|
|
.map_or(0, |i| i + 1)
|
|
|
|
|
}
|
2021-03-30 13:30:31 -07:00
|
|
|
}
|