mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-05 23:33:07 +00:00
Merge pull request #57 from mir-protocol/quartic_quartic_algebra
Field extension algebras
This commit is contained in:
commit
2b5b5f87e1
251
src/field/extension_field/algebra.rs
Normal file
251
src/field/extension_field/algebra.rs
Normal file
@ -0,0 +1,251 @@
|
|||||||
|
use crate::field::extension_field::OEF;
|
||||||
|
use std::fmt::{Debug, Display, Formatter};
|
||||||
|
use std::iter::{Product, Sum};
|
||||||
|
use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
|
||||||
|
|
||||||
|
/// Let `F_D` be the optimal extension field `F[X]/(X^D-W)`. Then `ExtensionAlgebra<F_D>` is the quotient `F_D[X]/(X^D-W)`.
|
||||||
|
/// It's a `D`-dimensional algebra over `F_D` useful to lift the multiplication over `F_D` to a multiplication over `(F_D)^D`.
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct ExtensionAlgebra<F: OEF<D>, const D: usize>([F; D]);
|
||||||
|
|
||||||
|
impl<F: OEF<D>, const D: usize> ExtensionAlgebra<F, D> {
|
||||||
|
pub const ZERO: Self = Self([F::ZERO; D]);
|
||||||
|
|
||||||
|
pub fn one() -> Self {
|
||||||
|
F::ONE.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_basefield_array(arr: [F; D]) -> Self {
|
||||||
|
Self(arr)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_basefield_array(self) -> [F; D] {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F: OEF<D>, const D: usize> From<F> for ExtensionAlgebra<F, D> {
|
||||||
|
fn from(x: F) -> Self {
|
||||||
|
let mut arr = [F::ZERO; D];
|
||||||
|
arr[0] = x;
|
||||||
|
Self(arr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F: OEF<D>, const D: usize> Display for ExtensionAlgebra<F, D> {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "({})", self.0[0])?;
|
||||||
|
for i in 1..D {
|
||||||
|
write!(f, " + ({})*b^{}", self.0[i], i)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F: OEF<D>, const D: usize> Debug for ExtensionAlgebra<F, D> {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
Display::fmt(self, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F: OEF<D>, const D: usize> Neg for ExtensionAlgebra<F, D> {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn neg(self) -> Self {
|
||||||
|
let mut arr = self.0;
|
||||||
|
arr.iter_mut().for_each(|x| *x = -*x);
|
||||||
|
Self(arr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F: OEF<D>, const D: usize> Add for ExtensionAlgebra<F, D> {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn add(self, rhs: Self) -> Self {
|
||||||
|
let mut arr = self.0;
|
||||||
|
arr.iter_mut().zip(&rhs.0).for_each(|(x, &y)| *x += y);
|
||||||
|
Self(arr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F: OEF<D>, const D: usize> AddAssign for ExtensionAlgebra<F, D> {
|
||||||
|
fn add_assign(&mut self, rhs: Self) {
|
||||||
|
*self = *self + rhs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F: OEF<D>, const D: usize> Sum for ExtensionAlgebra<F, D> {
|
||||||
|
fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
|
||||||
|
iter.fold(Self::ZERO, |acc, x| acc + x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F: OEF<D>, const D: usize> Sub for ExtensionAlgebra<F, D> {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn sub(self, rhs: Self) -> Self {
|
||||||
|
let mut arr = self.0;
|
||||||
|
arr.iter_mut().zip(&rhs.0).for_each(|(x, &y)| *x -= y);
|
||||||
|
Self(arr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F: OEF<D>, const D: usize> SubAssign for ExtensionAlgebra<F, D> {
|
||||||
|
#[inline]
|
||||||
|
fn sub_assign(&mut self, rhs: Self) {
|
||||||
|
*self = *self - rhs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F: OEF<D>, const D: usize> Mul for ExtensionAlgebra<F, D> {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn mul(self, rhs: Self) -> Self {
|
||||||
|
let mut res = [F::ZERO; D];
|
||||||
|
let w = F::from_basefield(F::W);
|
||||||
|
for i in 0..D {
|
||||||
|
for j in 0..D {
|
||||||
|
res[(i + j) % D] += if i + j < D {
|
||||||
|
self.0[i] * rhs.0[j]
|
||||||
|
} else {
|
||||||
|
w * self.0[i] * rhs.0[j]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Self(res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F: OEF<D>, const D: usize> MulAssign for ExtensionAlgebra<F, D> {
|
||||||
|
#[inline]
|
||||||
|
fn mul_assign(&mut self, rhs: Self) {
|
||||||
|
*self = *self * rhs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F: OEF<D>, const D: usize> Product for ExtensionAlgebra<F, D> {
|
||||||
|
fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
|
||||||
|
iter.fold(Self::one(), |acc, x| acc * x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A polynomial in coefficient form.
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct PolynomialCoeffsAlgebra<F: OEF<D>, const D: usize> {
|
||||||
|
pub(crate) coeffs: Vec<ExtensionAlgebra<F, D>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F: OEF<D>, const D: usize> PolynomialCoeffsAlgebra<F, D> {
|
||||||
|
pub fn new(coeffs: Vec<ExtensionAlgebra<F, D>>) -> Self {
|
||||||
|
PolynomialCoeffsAlgebra { coeffs }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn eval(&self, x: ExtensionAlgebra<F, D>) -> ExtensionAlgebra<F, D> {
|
||||||
|
self.coeffs
|
||||||
|
.iter()
|
||||||
|
.rev()
|
||||||
|
.fold(ExtensionAlgebra::ZERO, |acc, &c| acc * x + c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::field::crandall_field::CrandallField;
|
||||||
|
use crate::field::extension_field::algebra::ExtensionAlgebra;
|
||||||
|
use crate::field::extension_field::{Extendable, FieldExtension};
|
||||||
|
use crate::field::field::Field;
|
||||||
|
use itertools::Itertools;
|
||||||
|
|
||||||
|
/// Tests that the multiplication on the extension algebra lifts that of the field extension.
|
||||||
|
fn test_extension_algebra<F: Extendable<D>, const D: usize>() {
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
enum ZeroOne {
|
||||||
|
Zero,
|
||||||
|
One,
|
||||||
|
}
|
||||||
|
|
||||||
|
let to_field = |zo: &ZeroOne| match zo {
|
||||||
|
ZeroOne::Zero => F::ZERO,
|
||||||
|
ZeroOne::One => F::ONE,
|
||||||
|
};
|
||||||
|
let to_fields = |x: &[ZeroOne], y: &[ZeroOne]| -> (F::Extension, F::Extension) {
|
||||||
|
let mut arr0 = [F::ZERO; D];
|
||||||
|
let mut arr1 = [F::ZERO; D];
|
||||||
|
arr0.copy_from_slice(&x.iter().map(to_field).collect::<Vec<_>>());
|
||||||
|
arr1.copy_from_slice(&y.iter().map(to_field).collect::<Vec<_>>());
|
||||||
|
(
|
||||||
|
<F as Extendable<D>>::Extension::from_basefield_array(arr0),
|
||||||
|
<F as Extendable<D>>::Extension::from_basefield_array(arr1),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Standard MLE formula.
|
||||||
|
let selector = |xs: Vec<ZeroOne>, ts: &[F::Extension]| -> F::Extension {
|
||||||
|
(0..2 * D)
|
||||||
|
.map(|i| match xs[i] {
|
||||||
|
ZeroOne::Zero => F::Extension::ONE - ts[i],
|
||||||
|
ZeroOne::One => ts[i],
|
||||||
|
})
|
||||||
|
.product()
|
||||||
|
};
|
||||||
|
|
||||||
|
let mul_mle = |ts: Vec<F::Extension>| -> [F::Extension; D] {
|
||||||
|
let mut ans = [F::Extension::ZERO; D];
|
||||||
|
for xs in (0..2 * D)
|
||||||
|
.map(|_| vec![ZeroOne::Zero, ZeroOne::One])
|
||||||
|
.multi_cartesian_product()
|
||||||
|
{
|
||||||
|
let (a, b) = to_fields(&xs[..D], &xs[D..]);
|
||||||
|
let c = a * b;
|
||||||
|
let res = selector(xs, &ts);
|
||||||
|
for i in 0..D {
|
||||||
|
ans[i] += res * c.to_basefield_array()[i].into();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ans
|
||||||
|
};
|
||||||
|
|
||||||
|
let ts = F::Extension::rand_vec(2 * D);
|
||||||
|
let mut arr0 = [F::Extension::ZERO; D];
|
||||||
|
let mut arr1 = [F::Extension::ZERO; D];
|
||||||
|
arr0.copy_from_slice(&ts[..D]);
|
||||||
|
arr1.copy_from_slice(&ts[D..]);
|
||||||
|
let x = ExtensionAlgebra::from_basefield_array(arr0);
|
||||||
|
let y = ExtensionAlgebra::from_basefield_array(arr1);
|
||||||
|
let z = x * y;
|
||||||
|
|
||||||
|
dbg!(z.0, mul_mle(ts.clone()));
|
||||||
|
assert_eq!(z.0, mul_mle(ts));
|
||||||
|
}
|
||||||
|
|
||||||
|
mod base {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_algebra() {
|
||||||
|
test_extension_algebra::<CrandallField, 1>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod quadratic {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_algebra() {
|
||||||
|
test_extension_algebra::<CrandallField, 2>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod quartic {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_algebra() {
|
||||||
|
test_extension_algebra::<CrandallField, 4>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,8 +1,8 @@
|
|||||||
use crate::field::field::Field;
|
use crate::field::field::Field;
|
||||||
|
|
||||||
|
pub mod algebra;
|
||||||
pub mod quadratic;
|
pub mod quadratic;
|
||||||
pub mod quartic;
|
pub mod quartic;
|
||||||
mod quartic_quartic;
|
|
||||||
pub mod target;
|
pub mod target;
|
||||||
|
|
||||||
/// Optimal extension field trait.
|
/// Optimal extension field trait.
|
||||||
|
|||||||
@ -6,8 +6,7 @@ use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssi
|
|||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
|
||||||
use crate::field::crandall_field::CrandallField;
|
use crate::field::crandall_field::CrandallField;
|
||||||
use crate::field::extension_field::quartic_quartic::QuarticQuarticCrandallField;
|
use crate::field::extension_field::{FieldExtension, OEF};
|
||||||
use crate::field::extension_field::{Extendable, FieldExtension, OEF};
|
|
||||||
use crate::field::field::Field;
|
use crate::field::field::Field;
|
||||||
|
|
||||||
/// A quartic extension of `CrandallField`.
|
/// A quartic extension of `CrandallField`.
|
||||||
@ -239,10 +238,6 @@ impl DivAssign for QuarticCrandallField {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Extendable<4> for QuarticCrandallField {
|
|
||||||
type Extension = QuarticQuarticCrandallField;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::field::extension_field::quartic::QuarticCrandallField;
|
use crate::field::extension_field::quartic::QuarticCrandallField;
|
||||||
|
|||||||
@ -1,259 +0,0 @@
|
|||||||
use crate::field::crandall_field::CrandallField;
|
|
||||||
use crate::field::extension_field::quartic::QuarticCrandallField;
|
|
||||||
use crate::field::extension_field::{FieldExtension, OEF};
|
|
||||||
use crate::field::field::Field;
|
|
||||||
use rand::Rng;
|
|
||||||
use std::fmt::{Debug, Display, Formatter};
|
|
||||||
use std::hash::Hash;
|
|
||||||
use std::iter::{Product, Sum};
|
|
||||||
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
|
|
||||||
|
|
||||||
/// A quartic extension of `QuarticCrandallField`.
|
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
|
||||||
pub struct QuarticQuarticCrandallField(pub(crate) [QuarticCrandallField; 4]);
|
|
||||||
|
|
||||||
impl OEF<4> for QuarticQuarticCrandallField {
|
|
||||||
// Verifiable in Sage with
|
|
||||||
// p = 2^64 - 9 * 2^28 + 1
|
|
||||||
// F = GF(p)
|
|
||||||
// PR_F.<x> = PolynomialRing(F)
|
|
||||||
// assert (x^4 - 3).is_irreducible()
|
|
||||||
// F4.<y> = F.extension(x^4 - 3)
|
|
||||||
// PR_F4.<z> = PolynomialRing(F4)
|
|
||||||
// assert (x^4 - y).is_irreducible()
|
|
||||||
// F44.<w> = F4.extension(x^4 - y)
|
|
||||||
const W: QuarticCrandallField = QuarticCrandallField([
|
|
||||||
CrandallField(0),
|
|
||||||
CrandallField(1),
|
|
||||||
CrandallField(0),
|
|
||||||
CrandallField(0),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FieldExtension<4> for QuarticQuarticCrandallField {
|
|
||||||
type BaseField = QuarticCrandallField;
|
|
||||||
|
|
||||||
fn to_basefield_array(&self) -> [Self::BaseField; 4] {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
|
|
||||||
fn from_basefield_array(arr: [Self::BaseField; 4]) -> Self {
|
|
||||||
Self(arr)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn from_basefield(x: Self::BaseField) -> Self {
|
|
||||||
x.into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<<Self as FieldExtension<4>>::BaseField> for QuarticQuarticCrandallField {
|
|
||||||
fn from(x: <Self as FieldExtension<4>>::BaseField) -> Self {
|
|
||||||
Self([
|
|
||||||
x,
|
|
||||||
<Self as FieldExtension<4>>::BaseField::ZERO,
|
|
||||||
<Self as FieldExtension<4>>::BaseField::ZERO,
|
|
||||||
<Self as FieldExtension<4>>::BaseField::ZERO,
|
|
||||||
])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Field for QuarticQuarticCrandallField {
|
|
||||||
const ZERO: Self = Self([QuarticCrandallField::ZERO; 4]);
|
|
||||||
const ONE: Self = Self([
|
|
||||||
QuarticCrandallField::ONE,
|
|
||||||
QuarticCrandallField::ZERO,
|
|
||||||
QuarticCrandallField::ZERO,
|
|
||||||
QuarticCrandallField::ZERO,
|
|
||||||
]);
|
|
||||||
const TWO: Self = Self([
|
|
||||||
QuarticCrandallField::TWO,
|
|
||||||
QuarticCrandallField::ZERO,
|
|
||||||
QuarticCrandallField::ZERO,
|
|
||||||
QuarticCrandallField::ZERO,
|
|
||||||
]);
|
|
||||||
const NEG_ONE: Self = Self([
|
|
||||||
QuarticCrandallField::NEG_ONE,
|
|
||||||
QuarticCrandallField::ZERO,
|
|
||||||
QuarticCrandallField::ZERO,
|
|
||||||
QuarticCrandallField::ZERO,
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Does not fit in 64-bits.
|
|
||||||
const ORDER: u64 = 0;
|
|
||||||
const TWO_ADICITY: usize = 32;
|
|
||||||
const MULTIPLICATIVE_GROUP_GENERATOR: Self = Self([
|
|
||||||
QuarticCrandallField([
|
|
||||||
CrandallField(7562951059982399618),
|
|
||||||
CrandallField(16734862117167184487),
|
|
||||||
CrandallField(8532193866847630013),
|
|
||||||
CrandallField(15462716295551021898),
|
|
||||||
]),
|
|
||||||
QuarticCrandallField([
|
|
||||||
CrandallField(16143979237658148445),
|
|
||||||
CrandallField(12004617499933809221),
|
|
||||||
CrandallField(11826153143854535879),
|
|
||||||
CrandallField(14780824604953232397),
|
|
||||||
]),
|
|
||||||
QuarticCrandallField([
|
|
||||||
CrandallField(12779077039546101185),
|
|
||||||
CrandallField(15745975127331074164),
|
|
||||||
CrandallField(4297791107105154033),
|
|
||||||
CrandallField(5966855376644799108),
|
|
||||||
]),
|
|
||||||
QuarticCrandallField([
|
|
||||||
CrandallField(1942992936904935291),
|
|
||||||
CrandallField(6041097781717465159),
|
|
||||||
CrandallField(16875726992388585780),
|
|
||||||
CrandallField(17742746479895474446),
|
|
||||||
]),
|
|
||||||
]);
|
|
||||||
const POWER_OF_TWO_GENERATOR: Self = Self([
|
|
||||||
QuarticCrandallField::ZERO,
|
|
||||||
QuarticCrandallField([
|
|
||||||
CrandallField::ZERO,
|
|
||||||
CrandallField::ZERO,
|
|
||||||
CrandallField::ZERO,
|
|
||||||
CrandallField(6809469153480715254),
|
|
||||||
]),
|
|
||||||
QuarticCrandallField::ZERO,
|
|
||||||
QuarticCrandallField::ZERO,
|
|
||||||
]);
|
|
||||||
|
|
||||||
fn try_inverse(&self) -> Option<Self> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_canonical_u64(&self) -> u64 {
|
|
||||||
panic!("Doesn't fit!")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn from_canonical_u64(n: u64) -> Self {
|
|
||||||
<Self as FieldExtension<4>>::BaseField::from_canonical_u64(n).into()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn rand_from_rng<R: Rng>(rng: &mut R) -> Self {
|
|
||||||
Self([
|
|
||||||
<Self as FieldExtension<4>>::BaseField::rand_from_rng(rng),
|
|
||||||
<Self as FieldExtension<4>>::BaseField::rand_from_rng(rng),
|
|
||||||
<Self as FieldExtension<4>>::BaseField::rand_from_rng(rng),
|
|
||||||
<Self as FieldExtension<4>>::BaseField::rand_from_rng(rng),
|
|
||||||
])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for QuarticQuarticCrandallField {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
"({}) + ({})*b + ({})*b^2 + ({})*b^3",
|
|
||||||
self.0[0], self.0[1], self.0[2], self.0[3]
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Debug for QuarticQuarticCrandallField {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
||||||
Display::fmt(self, f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Neg for QuarticQuarticCrandallField {
|
|
||||||
type Output = Self;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn neg(self) -> Self {
|
|
||||||
Self([-self.0[0], -self.0[1], -self.0[2], -self.0[3]])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Add for QuarticQuarticCrandallField {
|
|
||||||
type Output = Self;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn add(self, rhs: Self) -> Self {
|
|
||||||
Self([
|
|
||||||
self.0[0] + rhs.0[0],
|
|
||||||
self.0[1] + rhs.0[1],
|
|
||||||
self.0[2] + rhs.0[2],
|
|
||||||
self.0[3] + rhs.0[3],
|
|
||||||
])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AddAssign for QuarticQuarticCrandallField {
|
|
||||||
fn add_assign(&mut self, rhs: Self) {
|
|
||||||
*self = *self + rhs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Sum for QuarticQuarticCrandallField {
|
|
||||||
fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
|
|
||||||
iter.fold(Self::ZERO, |acc, x| acc + x)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Sub for QuarticQuarticCrandallField {
|
|
||||||
type Output = Self;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn sub(self, rhs: Self) -> Self {
|
|
||||||
Self([
|
|
||||||
self.0[0] - rhs.0[0],
|
|
||||||
self.0[1] - rhs.0[1],
|
|
||||||
self.0[2] - rhs.0[2],
|
|
||||||
self.0[3] - rhs.0[3],
|
|
||||||
])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SubAssign for QuarticQuarticCrandallField {
|
|
||||||
#[inline]
|
|
||||||
fn sub_assign(&mut self, rhs: Self) {
|
|
||||||
*self = *self - rhs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Mul for QuarticQuarticCrandallField {
|
|
||||||
type Output = Self;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn mul(self, rhs: Self) -> Self {
|
|
||||||
let Self([a0, a1, a2, a3]) = self;
|
|
||||||
let Self([b0, b1, b2, b3]) = rhs;
|
|
||||||
|
|
||||||
let c0 = a0 * b0 + <Self as OEF<4>>::W * (a1 * b3 + a2 * b2 + a3 * b1);
|
|
||||||
let c1 = a0 * b1 + a1 * b0 + <Self as OEF<4>>::W * (a2 * b3 + a3 * b2);
|
|
||||||
let c2 = a0 * b2 + a1 * b1 + a2 * b0 + <Self as OEF<4>>::W * a3 * b3;
|
|
||||||
let c3 = a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0;
|
|
||||||
|
|
||||||
Self([c0, c1, c2, c3])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MulAssign for QuarticQuarticCrandallField {
|
|
||||||
#[inline]
|
|
||||||
fn mul_assign(&mut self, rhs: Self) {
|
|
||||||
*self = *self * rhs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Product for QuarticQuarticCrandallField {
|
|
||||||
fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
|
|
||||||
iter.fold(Self::ONE, |acc, x| acc * x)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Div for QuarticQuarticCrandallField {
|
|
||||||
type Output = Self;
|
|
||||||
|
|
||||||
#[allow(clippy::suspicious_arithmetic_impl)]
|
|
||||||
fn div(self, rhs: Self) -> Self::Output {
|
|
||||||
self * rhs.inverse()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DivAssign for QuarticQuarticCrandallField {
|
|
||||||
fn div_assign(&mut self, rhs: Self) {
|
|
||||||
*self = *self / rhs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,4 +1,5 @@
|
|||||||
use crate::circuit_builder::CircuitBuilder;
|
use crate::circuit_builder::CircuitBuilder;
|
||||||
|
use crate::field::extension_field::algebra::ExtensionAlgebra;
|
||||||
use crate::field::extension_field::{Extendable, FieldExtension, OEF};
|
use crate::field::extension_field::{Extendable, FieldExtension, OEF};
|
||||||
use crate::field::field::Field;
|
use crate::field::field::Field;
|
||||||
use crate::target::Target;
|
use crate::target::Target;
|
||||||
@ -15,9 +16,9 @@ impl<const D: usize> ExtensionTarget<D> {
|
|||||||
|
|
||||||
/// `Target`s representing an element of an extension of an extension field.
|
/// `Target`s representing an element of an extension of an extension field.
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub struct ExtensionExtensionTarget<const D: usize>(pub [ExtensionTarget<D>; D]);
|
pub struct ExtensionAlgebraTarget<const D: usize>(pub [ExtensionTarget<D>; D]);
|
||||||
|
|
||||||
impl<const D: usize> ExtensionExtensionTarget<D> {
|
impl<const D: usize> ExtensionAlgebraTarget<D> {
|
||||||
pub fn to_ext_target_array(&self) -> [ExtensionTarget<D>; D] {
|
pub fn to_ext_target_array(&self) -> [ExtensionTarget<D>; D] {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
@ -33,19 +34,16 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
|||||||
ExtensionTarget(parts)
|
ExtensionTarget(parts)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn constant_ext_ext(
|
pub fn constant_ext_algebra(
|
||||||
&mut self,
|
&mut self,
|
||||||
c: <<F as Extendable<D>>::Extension as Extendable<D>>::Extension,
|
c: ExtensionAlgebra<F::Extension, D>,
|
||||||
) -> ExtensionExtensionTarget<D>
|
) -> ExtensionAlgebraTarget<D> {
|
||||||
where
|
|
||||||
F::Extension: Extendable<D>,
|
|
||||||
{
|
|
||||||
let c_parts = c.to_basefield_array();
|
let c_parts = c.to_basefield_array();
|
||||||
let mut parts = [self.zero_extension(); D];
|
let mut parts = [self.zero_extension(); D];
|
||||||
for i in 0..D {
|
for i in 0..D {
|
||||||
parts[i] = self.constant_extension(c_parts[i]);
|
parts[i] = self.constant_extension(c_parts[i]);
|
||||||
}
|
}
|
||||||
ExtensionExtensionTarget(parts)
|
ExtensionAlgebraTarget(parts)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn zero_extension(&mut self) -> ExtensionTarget<D> {
|
pub fn zero_extension(&mut self) -> ExtensionTarget<D> {
|
||||||
@ -60,11 +58,8 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
|||||||
self.constant_extension(F::Extension::TWO)
|
self.constant_extension(F::Extension::TWO)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn zero_ext_ext(&mut self) -> ExtensionExtensionTarget<D>
|
pub fn zero_ext_algebra(&mut self) -> ExtensionAlgebraTarget<D> {
|
||||||
where
|
self.constant_ext_algebra(ExtensionAlgebra::ZERO)
|
||||||
F::Extension: Extendable<D>,
|
|
||||||
{
|
|
||||||
self.constant_ext_ext(<<F as Extendable<D>>::Extension as Extendable<D>>::Extension::ZERO)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_extension(
|
pub fn add_extension(
|
||||||
@ -78,11 +73,11 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
|||||||
a
|
a
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_ext_ext(
|
pub fn add_ext_algebra(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut a: ExtensionExtensionTarget<D>,
|
mut a: ExtensionAlgebraTarget<D>,
|
||||||
b: ExtensionExtensionTarget<D>,
|
b: ExtensionAlgebraTarget<D>,
|
||||||
) -> ExtensionExtensionTarget<D> {
|
) -> ExtensionAlgebraTarget<D> {
|
||||||
for i in 0..D {
|
for i in 0..D {
|
||||||
a.0[i] = self.add_extension(a.0[i], b.0[i]);
|
a.0[i] = self.add_extension(a.0[i], b.0[i]);
|
||||||
}
|
}
|
||||||
@ -108,11 +103,11 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
|||||||
a
|
a
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sub_ext_ext(
|
pub fn sub_ext_algebra(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut a: ExtensionExtensionTarget<D>,
|
mut a: ExtensionAlgebraTarget<D>,
|
||||||
b: ExtensionExtensionTarget<D>,
|
b: ExtensionAlgebraTarget<D>,
|
||||||
) -> ExtensionExtensionTarget<D> {
|
) -> ExtensionAlgebraTarget<D> {
|
||||||
for i in 0..D {
|
for i in 0..D {
|
||||||
a.0[i] = self.sub_extension(a.0[i], b.0[i]);
|
a.0[i] = self.sub_extension(a.0[i], b.0[i]);
|
||||||
}
|
}
|
||||||
@ -138,29 +133,25 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
|||||||
ExtensionTarget(res)
|
ExtensionTarget(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mul_ext_ext(
|
pub fn mul_ext_algebra(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut a: ExtensionExtensionTarget<D>,
|
a: ExtensionAlgebraTarget<D>,
|
||||||
b: ExtensionExtensionTarget<D>,
|
b: ExtensionAlgebraTarget<D>,
|
||||||
) -> ExtensionExtensionTarget<D>
|
) -> ExtensionAlgebraTarget<D> {
|
||||||
where
|
|
||||||
F::Extension: Extendable<D>,
|
|
||||||
{
|
|
||||||
let mut res = [self.zero_extension(); D];
|
let mut res = [self.zero_extension(); D];
|
||||||
let w = self
|
let w = self.constant(F::Extension::W);
|
||||||
.constant_extension(<<F as Extendable<D>>::Extension as Extendable<D>>::Extension::W);
|
|
||||||
for i in 0..D {
|
for i in 0..D {
|
||||||
for j in 0..D {
|
for j in 0..D {
|
||||||
let ai_bi = self.mul_extension(a.0[i], b.0[j]);
|
let ai_bi = self.mul_extension(a.0[i], b.0[j]);
|
||||||
res[(i + j) % D] = if i + j < D {
|
res[(i + j) % D] = if i + j < D {
|
||||||
self.add_extension(ai_bi, res[(i + j) % D])
|
self.add_extension(ai_bi, res[(i + j) % D])
|
||||||
} else {
|
} else {
|
||||||
let w_ai_bi = self.mul_extension(w, ai_bi);
|
let w_ai_bi = self.scalar_mul_ext(w, ai_bi);
|
||||||
self.add_extension(w_ai_bi, res[(i + j) % D])
|
self.add_extension(w_ai_bi, res[(i + j) % D])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExtensionExtensionTarget(res)
|
ExtensionAlgebraTarget(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mul_many_extension(&mut self, terms: &[ExtensionTarget<D>]) -> ExtensionTarget<D> {
|
pub fn mul_many_extension(&mut self, terms: &[ExtensionTarget<D>]) -> ExtensionTarget<D> {
|
||||||
@ -193,14 +184,11 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
|||||||
|
|
||||||
/// Returns `a * b`, where `b` is in the extension of the extension field, and `a` is in the
|
/// Returns `a * b`, where `b` is in the extension of the extension field, and `a` is in the
|
||||||
/// extension field.
|
/// extension field.
|
||||||
pub fn scalar_mul_ext_ext(
|
pub fn scalar_mul_ext_algebra(
|
||||||
&mut self,
|
&mut self,
|
||||||
a: ExtensionTarget<D>,
|
a: ExtensionTarget<D>,
|
||||||
mut b: ExtensionExtensionTarget<D>,
|
mut b: ExtensionAlgebraTarget<D>,
|
||||||
) -> ExtensionExtensionTarget<D>
|
) -> ExtensionAlgebraTarget<D> {
|
||||||
where
|
|
||||||
F::Extension: Extendable<D>,
|
|
||||||
{
|
|
||||||
for i in 0..D {
|
for i in 0..D {
|
||||||
b.0[i] = self.mul_extension(a, b.0[i]);
|
b.0[i] = self.mul_extension(a, b.0[i]);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
use crate::circuit_builder::CircuitBuilder;
|
use crate::circuit_builder::CircuitBuilder;
|
||||||
use crate::field::extension_field::target::{ExtensionExtensionTarget, ExtensionTarget};
|
use crate::field::extension_field::target::{ExtensionAlgebraTarget, ExtensionTarget};
|
||||||
use crate::field::extension_field::Extendable;
|
use crate::field::extension_field::Extendable;
|
||||||
use crate::target::Target;
|
use crate::target::Target;
|
||||||
|
|
||||||
@ -33,22 +33,21 @@ impl<const D: usize> PolynomialCoeffsExtTarget<D> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PolynomialCoeffsExtExtTarget<const D: usize>(pub Vec<ExtensionExtensionTarget<D>>);
|
pub struct PolynomialCoeffsExtAlgebraTarget<const D: usize>(pub Vec<ExtensionAlgebraTarget<D>>);
|
||||||
|
|
||||||
impl<const D: usize> PolynomialCoeffsExtExtTarget<D> {
|
impl<const D: usize> PolynomialCoeffsExtAlgebraTarget<D> {
|
||||||
pub fn eval_scalar<F>(
|
pub fn eval_scalar<F>(
|
||||||
&self,
|
&self,
|
||||||
builder: &mut CircuitBuilder<F, D>,
|
builder: &mut CircuitBuilder<F, D>,
|
||||||
point: ExtensionTarget<D>,
|
point: ExtensionTarget<D>,
|
||||||
) -> ExtensionExtensionTarget<D>
|
) -> ExtensionAlgebraTarget<D>
|
||||||
where
|
where
|
||||||
F: Extendable<D>,
|
F: Extendable<D>,
|
||||||
F::Extension: Extendable<D>,
|
|
||||||
{
|
{
|
||||||
let mut acc = builder.zero_ext_ext();
|
let mut acc = builder.zero_ext_algebra();
|
||||||
for &c in self.0.iter().rev() {
|
for &c in self.0.iter().rev() {
|
||||||
let tmp = builder.scalar_mul_ext_ext(point, acc);
|
let tmp = builder.scalar_mul_ext_algebra(point, acc);
|
||||||
acc = builder.add_ext_ext(tmp, c);
|
acc = builder.add_ext_algebra(tmp, c);
|
||||||
}
|
}
|
||||||
acc
|
acc
|
||||||
}
|
}
|
||||||
@ -56,16 +55,15 @@ impl<const D: usize> PolynomialCoeffsExtExtTarget<D> {
|
|||||||
pub fn eval<F>(
|
pub fn eval<F>(
|
||||||
&self,
|
&self,
|
||||||
builder: &mut CircuitBuilder<F, D>,
|
builder: &mut CircuitBuilder<F, D>,
|
||||||
point: ExtensionExtensionTarget<D>,
|
point: ExtensionAlgebraTarget<D>,
|
||||||
) -> ExtensionExtensionTarget<D>
|
) -> ExtensionAlgebraTarget<D>
|
||||||
where
|
where
|
||||||
F: Extendable<D>,
|
F: Extendable<D>,
|
||||||
F::Extension: Extendable<D>,
|
|
||||||
{
|
{
|
||||||
let mut acc = builder.zero_ext_ext();
|
let mut acc = builder.zero_ext_algebra();
|
||||||
for &c in self.0.iter().rev() {
|
for &c in self.0.iter().rev() {
|
||||||
let tmp = builder.mul_ext_ext(point, acc);
|
let tmp = builder.mul_ext_algebra(point, acc);
|
||||||
acc = builder.add_ext_ext(tmp, c);
|
acc = builder.add_ext_algebra(tmp, c);
|
||||||
}
|
}
|
||||||
acc
|
acc
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,13 +3,13 @@ use std::marker::PhantomData;
|
|||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
|
|
||||||
use crate::circuit_builder::CircuitBuilder;
|
use crate::circuit_builder::CircuitBuilder;
|
||||||
|
use crate::field::extension_field::algebra::PolynomialCoeffsAlgebra;
|
||||||
use crate::field::extension_field::target::ExtensionTarget;
|
use crate::field::extension_field::target::ExtensionTarget;
|
||||||
use crate::field::extension_field::{Extendable, FieldExtension};
|
use crate::field::extension_field::{Extendable, FieldExtension};
|
||||||
use crate::field::lagrange::interpolant;
|
use crate::field::lagrange::interpolant;
|
||||||
use crate::gadgets::polynomial::PolynomialCoeffsExtExtTarget;
|
use crate::gadgets::polynomial::PolynomialCoeffsExtAlgebraTarget;
|
||||||
use crate::gates::gate::{Gate, GateRef};
|
use crate::gates::gate::{Gate, GateRef};
|
||||||
use crate::generator::{SimpleGenerator, WitnessGenerator};
|
use crate::generator::{SimpleGenerator, WitnessGenerator};
|
||||||
use crate::polynomial::polynomial::PolynomialCoeffs;
|
|
||||||
use crate::target::Target;
|
use crate::target::Target;
|
||||||
use crate::vars::{EvaluationTargets, EvaluationVars};
|
use crate::vars::{EvaluationTargets, EvaluationVars};
|
||||||
use crate::wire::Wire;
|
use crate::wire::Wire;
|
||||||
@ -22,16 +22,12 @@ use crate::witness::PartialWitness;
|
|||||||
/// given point.
|
/// given point.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub(crate) struct InterpolationGate<F: Extendable<D>, const D: usize>
|
pub(crate) struct InterpolationGate<F: Extendable<D>, const D: usize>
|
||||||
where
|
|
||||||
F::Extension: Extendable<D>,
|
|
||||||
{
|
{
|
||||||
num_points: usize,
|
num_points: usize,
|
||||||
_phantom: PhantomData<F>,
|
_phantom: PhantomData<F>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F: Extendable<D>, const D: usize> InterpolationGate<F, D>
|
impl<F: Extendable<D>, const D: usize> InterpolationGate<F, D>
|
||||||
where
|
|
||||||
F::Extension: Extendable<D>,
|
|
||||||
{
|
{
|
||||||
pub fn new(num_points: usize) -> GateRef<F, D> {
|
pub fn new(num_points: usize) -> GateRef<F, D> {
|
||||||
let gate = Self {
|
let gate = Self {
|
||||||
@ -100,8 +96,6 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<F: Extendable<D>, const D: usize> Gate<F, D> for InterpolationGate<F, D>
|
impl<F: Extendable<D>, const D: usize> Gate<F, D> for InterpolationGate<F, D>
|
||||||
where
|
|
||||||
F::Extension: Extendable<D>,
|
|
||||||
{
|
{
|
||||||
fn id(&self) -> String {
|
fn id(&self) -> String {
|
||||||
format!("{:?}<D={}>", self, D)
|
format!("{:?}<D={}>", self, D)
|
||||||
@ -111,19 +105,19 @@ where
|
|||||||
let mut constraints = Vec::with_capacity(self.num_constraints());
|
let mut constraints = Vec::with_capacity(self.num_constraints());
|
||||||
|
|
||||||
let coeffs = (0..self.num_points)
|
let coeffs = (0..self.num_points)
|
||||||
.map(|i| vars.get_local_ext_ext(self.wires_coeff(i)))
|
.map(|i| vars.get_local_ext_algebra(self.wires_coeff(i)))
|
||||||
.collect();
|
.collect();
|
||||||
let interpolant = PolynomialCoeffs::new(coeffs);
|
let interpolant = PolynomialCoeffsAlgebra::new(coeffs);
|
||||||
|
|
||||||
for i in 0..self.num_points {
|
for i in 0..self.num_points {
|
||||||
let point = vars.local_wires[self.wire_point(i)];
|
let point = vars.local_wires[self.wire_point(i)];
|
||||||
let value = vars.get_local_ext_ext(self.wires_value(i));
|
let value = vars.get_local_ext_algebra(self.wires_value(i));
|
||||||
let computed_value = interpolant.eval(point.into());
|
let computed_value = interpolant.eval(point.into());
|
||||||
constraints.extend(&(value - computed_value).to_basefield_array());
|
constraints.extend(&(value - computed_value).to_basefield_array());
|
||||||
}
|
}
|
||||||
|
|
||||||
let evaluation_point = vars.get_local_ext_ext(self.wires_evaluation_point());
|
let evaluation_point = vars.get_local_ext_algebra(self.wires_evaluation_point());
|
||||||
let evaluation_value = vars.get_local_ext_ext(self.wires_evaluation_value());
|
let evaluation_value = vars.get_local_ext_algebra(self.wires_evaluation_value());
|
||||||
let computed_evaluation_value = interpolant.eval(evaluation_point);
|
let computed_evaluation_value = interpolant.eval(evaluation_point);
|
||||||
constraints.extend(&(evaluation_value - computed_evaluation_value).to_basefield_array());
|
constraints.extend(&(evaluation_value - computed_evaluation_value).to_basefield_array());
|
||||||
|
|
||||||
@ -138,27 +132,27 @@ where
|
|||||||
let mut constraints = Vec::with_capacity(self.num_constraints());
|
let mut constraints = Vec::with_capacity(self.num_constraints());
|
||||||
|
|
||||||
let coeffs = (0..self.num_points)
|
let coeffs = (0..self.num_points)
|
||||||
.map(|i| vars.get_local_ext_ext(self.wires_coeff(i)))
|
.map(|i| vars.get_local_ext_algebra(self.wires_coeff(i)))
|
||||||
.collect();
|
.collect();
|
||||||
let interpolant = PolynomialCoeffsExtExtTarget(coeffs);
|
let interpolant = PolynomialCoeffsExtAlgebraTarget(coeffs);
|
||||||
|
|
||||||
for i in 0..self.num_points {
|
for i in 0..self.num_points {
|
||||||
let point = vars.local_wires[self.wire_point(i)];
|
let point = vars.local_wires[self.wire_point(i)];
|
||||||
let value = vars.get_local_ext_ext(self.wires_value(i));
|
let value = vars.get_local_ext_algebra(self.wires_value(i));
|
||||||
let computed_value = interpolant.eval_scalar(builder, point);
|
let computed_value = interpolant.eval_scalar(builder, point);
|
||||||
constraints.extend(
|
constraints.extend(
|
||||||
&builder
|
&builder
|
||||||
.sub_ext_ext(value, computed_value)
|
.sub_ext_algebra(value, computed_value)
|
||||||
.to_ext_target_array(),
|
.to_ext_target_array(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let evaluation_point = vars.get_local_ext_ext(self.wires_evaluation_point());
|
let evaluation_point = vars.get_local_ext_algebra(self.wires_evaluation_point());
|
||||||
let evaluation_value = vars.get_local_ext_ext(self.wires_evaluation_value());
|
let evaluation_value = vars.get_local_ext_algebra(self.wires_evaluation_value());
|
||||||
let computed_evaluation_value = interpolant.eval(builder, evaluation_point);
|
let computed_evaluation_value = interpolant.eval(builder, evaluation_point);
|
||||||
constraints.extend(
|
constraints.extend(
|
||||||
&builder
|
&builder
|
||||||
.sub_ext_ext(evaluation_value, computed_evaluation_value)
|
.sub_ext_algebra(evaluation_value, computed_evaluation_value)
|
||||||
.to_ext_target_array(),
|
.to_ext_target_array(),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -200,8 +194,6 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct InterpolationGenerator<F: Extendable<D>, const D: usize>
|
struct InterpolationGenerator<F: Extendable<D>, const D: usize>
|
||||||
where
|
|
||||||
F::Extension: Extendable<D>,
|
|
||||||
{
|
{
|
||||||
gate_index: usize,
|
gate_index: usize,
|
||||||
gate: InterpolationGate<F, D>,
|
gate: InterpolationGate<F, D>,
|
||||||
@ -209,8 +201,6 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<F: Extendable<D>, const D: usize> SimpleGenerator<F> for InterpolationGenerator<F, D>
|
impl<F: Extendable<D>, const D: usize> SimpleGenerator<F> for InterpolationGenerator<F, D>
|
||||||
where
|
|
||||||
F::Extension: Extendable<D>,
|
|
||||||
{
|
{
|
||||||
fn dependencies(&self) -> Vec<Target> {
|
fn dependencies(&self) -> Vec<Target> {
|
||||||
let local_target = |input| {
|
let local_target = |input| {
|
||||||
@ -281,9 +271,14 @@ mod tests {
|
|||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use crate::field::crandall_field::CrandallField;
|
use crate::field::crandall_field::CrandallField;
|
||||||
|
use crate::field::extension_field::quartic::QuarticCrandallField;
|
||||||
|
use crate::field::extension_field::FieldExtension;
|
||||||
|
use crate::field::field::Field;
|
||||||
use crate::gates::gate::Gate;
|
use crate::gates::gate::Gate;
|
||||||
use crate::gates::gate_testing::test_low_degree;
|
use crate::gates::gate_testing::test_low_degree;
|
||||||
use crate::gates::interpolation::InterpolationGate;
|
use crate::gates::interpolation::InterpolationGate;
|
||||||
|
use crate::polynomial::polynomial::PolynomialCoeffs;
|
||||||
|
use crate::vars::EvaluationVars;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn wire_indices() {
|
fn wire_indices() {
|
||||||
@ -310,4 +305,67 @@ mod tests {
|
|||||||
type F = CrandallField;
|
type F = CrandallField;
|
||||||
test_low_degree(InterpolationGate::<F, 4>::new(4));
|
test_low_degree(InterpolationGate::<F, 4>::new(4));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_gate_constraint() {
|
||||||
|
type F = CrandallField;
|
||||||
|
type FF = QuarticCrandallField;
|
||||||
|
const D: usize = 4;
|
||||||
|
|
||||||
|
/// Returns the local wires for an interpolation gate for given coeffs, points and eval point.
|
||||||
|
fn get_wires(
|
||||||
|
num_points: usize,
|
||||||
|
coeffs: PolynomialCoeffs<FF>,
|
||||||
|
points: Vec<F>,
|
||||||
|
eval_point: FF,
|
||||||
|
) -> Vec<FF> {
|
||||||
|
let mut v = vec![F::ZERO; num_points * 5 + (coeffs.len() + 3) * D];
|
||||||
|
for j in 0..num_points {
|
||||||
|
v[j] = points[j];
|
||||||
|
}
|
||||||
|
for j in 0..num_points {
|
||||||
|
for i in 0..D {
|
||||||
|
v[num_points + D * j + i] = <FF as FieldExtension<D>>::to_basefield_array(
|
||||||
|
&coeffs.eval(points[j].into()),
|
||||||
|
)[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i in 0..D {
|
||||||
|
v[num_points * 5 + i] =
|
||||||
|
<FF as FieldExtension<D>>::to_basefield_array(&eval_point)[i];
|
||||||
|
}
|
||||||
|
for i in 0..D {
|
||||||
|
v[num_points * 5 + D + i] =
|
||||||
|
<FF as FieldExtension<D>>::to_basefield_array(&coeffs.eval(eval_point))[i];
|
||||||
|
}
|
||||||
|
for i in 0..coeffs.len() {
|
||||||
|
for (j, input) in
|
||||||
|
(0..D).zip(num_points * 5 + (2 + i) * D..num_points * 5 + (3 + i) * D)
|
||||||
|
{
|
||||||
|
v[input] = <FF as FieldExtension<D>>::to_basefield_array(&coeffs.coeffs[i])[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v.iter().map(|&x| x.into()).collect::<Vec<_>>()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get a working row for InterpolationGate.
|
||||||
|
let coeffs = PolynomialCoeffs::new(vec![FF::rand(), FF::rand()]);
|
||||||
|
let points = vec![F::rand(), F::rand()];
|
||||||
|
let eval_point = FF::rand();
|
||||||
|
let gate = InterpolationGate::<F, D> {
|
||||||
|
num_points: 2,
|
||||||
|
_phantom: PhantomData,
|
||||||
|
};
|
||||||
|
let vars = EvaluationVars {
|
||||||
|
local_constants: &[],
|
||||||
|
local_wires: &get_wires(2, coeffs, points, eval_point),
|
||||||
|
};
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
gate.eval_unfiltered(vars.clone())
|
||||||
|
.iter()
|
||||||
|
.all(|x| x.is_zero()),
|
||||||
|
"Gate constraints are not satisfied."
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
18
src/vars.rs
18
src/vars.rs
@ -1,8 +1,9 @@
|
|||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
|
|
||||||
use crate::field::extension_field::target::{ExtensionExtensionTarget, ExtensionTarget};
|
use crate::field::extension_field::algebra::ExtensionAlgebra;
|
||||||
use crate::field::extension_field::{Extendable, FieldExtension};
|
use crate::field::extension_field::target::{ExtensionAlgebraTarget, ExtensionTarget};
|
||||||
|
use crate::field::extension_field::Extendable;
|
||||||
use crate::field::field::Field;
|
use crate::field::field::Field;
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
@ -18,16 +19,13 @@ pub struct EvaluationVarsBase<'a, F: Field> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, F: Extendable<D>, const D: usize> EvaluationVars<'a, F, D> {
|
impl<'a, F: Extendable<D>, const D: usize> EvaluationVars<'a, F, D> {
|
||||||
pub fn get_local_ext_ext(
|
pub fn get_local_ext_algebra(
|
||||||
&self,
|
&self,
|
||||||
wire_range: Range<usize>,
|
wire_range: Range<usize>,
|
||||||
) -> <<F as Extendable<D>>::Extension as Extendable<D>>::Extension
|
) -> ExtensionAlgebra<F::Extension, D> {
|
||||||
where
|
|
||||||
F::Extension: Extendable<D>,
|
|
||||||
{
|
|
||||||
debug_assert_eq!(wire_range.len(), D);
|
debug_assert_eq!(wire_range.len(), D);
|
||||||
let arr = self.local_wires[wire_range].try_into().unwrap();
|
let arr = self.local_wires[wire_range].try_into().unwrap();
|
||||||
<<F as Extendable<D>>::Extension as Extendable<D>>::Extension::from_basefield_array(arr)
|
ExtensionAlgebra::from_basefield_array(arr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,9 +36,9 @@ pub struct EvaluationTargets<'a, const D: usize> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, const D: usize> EvaluationTargets<'a, D> {
|
impl<'a, const D: usize> EvaluationTargets<'a, D> {
|
||||||
pub fn get_local_ext_ext(&self, wire_range: Range<usize>) -> ExtensionExtensionTarget<D> {
|
pub fn get_local_ext_algebra(&self, wire_range: Range<usize>) -> ExtensionAlgebraTarget<D> {
|
||||||
debug_assert_eq!(wire_range.len(), D);
|
debug_assert_eq!(wire_range.len(), D);
|
||||||
let arr = self.local_wires[wire_range].try_into().unwrap();
|
let arr = self.local_wires[wire_range].try_into().unwrap();
|
||||||
ExtensionExtensionTarget(arr)
|
ExtensionAlgebraTarget(arr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user