Remove useless Qua(d)r(a)ticFieldExtension traits

This commit is contained in:
wborgeaud 2021-05-24 14:12:08 +02:00
parent 84e9573c84
commit 66d6f3c338
4 changed files with 101 additions and 159 deletions

View File

@ -12,7 +12,7 @@ type F = CrandallField;
// from wire polynomials which "store" the outputs of S-boxes in our Poseidon gate.
const NUM_LDES: usize = 8 + 8 + 3 + 86 + 3 + 8;
const DEGREE: usize = 1 << 14;
const DEGREE: usize = 1 << 13;
const RATE_BITS: usize = 3;

View File

@ -1,10 +1,31 @@
use crate::field::extension_field::quadratic::QuadraticFieldExtension;
use crate::field::extension_field::quartic::QuarticFieldExtension;
use crate::field::field::Field;
pub mod quadratic;
pub mod quartic;
/// Optimal extension field trait.
/// A degree `d` field extension is optimal if there exists a base field element `W`,
/// such that the extension is `F[X]/(X^d-W)`.
pub trait OEF<const D: usize>: FieldExtension<D> {
// Element W of BaseField, such that `X^d - W` is irreducible over BaseField.
const W: Self::BaseField;
/// Frobenius automorphisms: x -> x^p, where p is the order of BaseField.
fn frobenius(&self) -> Self {
let arr = self.to_basefield_array();
let k = (Self::BaseField::ORDER - 1) / (D as u64);
let z0 = Self::W.exp(k);
let mut z = Self::BaseField::ONE;
let mut res = [Self::BaseField::ZERO; D];
for i in 0..D {
res[i] = arr[i] * z;
z *= z0;
}
Self::from_basefield_array(res)
}
}
pub trait Extendable<const D: usize>: Sized {
type Extension: Field + FieldExtension<D, BaseField = Self> + From<Self>;
}
@ -21,6 +42,10 @@ pub trait FieldExtension<const D: usize>: Field {
fn from_basefield_array(arr: [Self::BaseField; D]) -> Self;
fn from_basefield(x: Self::BaseField) -> Self;
fn is_in_basefield(&self) -> bool {
self.to_basefield_array()[1..].iter().all(|x| x.is_zero())
}
}
impl<F: Field> FieldExtension<1> for F {
@ -39,38 +64,6 @@ impl<F: Field> FieldExtension<1> for F {
}
}
impl<FE: QuadraticFieldExtension> FieldExtension<2> for FE {
type BaseField = FE::BaseField;
fn to_basefield_array(&self) -> [Self::BaseField; 2] {
self.to_canonical_representation()
}
fn from_basefield_array(arr: [Self::BaseField; 2]) -> Self {
Self::from_canonical_representation(arr)
}
fn from_basefield(x: Self::BaseField) -> Self {
x.into()
}
}
impl<FE: QuarticFieldExtension> FieldExtension<4> for FE {
type BaseField = FE::BaseField;
fn to_basefield_array(&self) -> [Self::BaseField; 4] {
self.to_canonical_representation()
}
fn from_basefield_array(arr: [Self::BaseField; 4]) -> Self {
Self::from_canonical_representation(arr)
}
fn from_basefield(x: Self::BaseField) -> Self {
x.into()
}
}
/// Flatten the slice by sending every extension field element to its D-sized canonical representation.
pub fn flatten<F: Field, const D: usize>(l: &[F::Extension]) -> Vec<F>
where

View File

@ -1,66 +1,49 @@
use crate::circuit_builder::CircuitBuilder;
use crate::field::crandall_field::CrandallField;
use crate::field::extension_field::{FieldExtension, OEF};
use crate::field::field::Field;
use crate::target::Target;
use rand::Rng;
use std::fmt::{Debug, Display, Formatter};
use std::hash::{Hash, Hasher};
use std::iter::{Product, Sum};
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
pub trait QuadraticFieldExtension:
Field + From<<Self as QuadraticFieldExtension>::BaseField>
{
type BaseField: Field;
// Element W of BaseField, such that `X^2 - W` is irreducible over BaseField.
const W: Self::BaseField;
fn to_canonical_representation(&self) -> [Self::BaseField; 2];
fn from_canonical_representation(v: [Self::BaseField; 2]) -> Self;
fn is_in_basefield(&self) -> bool {
self.to_canonical_representation()[1..]
.iter()
.all(|x| x.is_zero())
}
/// Frobenius automorphisms: x -> x^p, where p is the order of BaseField.
fn frobenius(&self) -> Self {
let [a0, a1] = self.to_canonical_representation();
let k = (Self::BaseField::ORDER - 1) / 2;
let z = Self::W.exp(k);
Self::from_canonical_representation([a0, a1 * z])
}
}
#[derive(Copy, Clone)]
pub struct QuadraticCrandallField([CrandallField; 2]);
impl QuadraticFieldExtension for QuadraticCrandallField {
type BaseField = CrandallField;
impl OEF<2> for QuadraticCrandallField {
// Verifiable in Sage with
// ``R.<x> = GF(p)[]; assert (x^2 -3).is_irreducible()`.
const W: Self::BaseField = CrandallField(3);
const W: CrandallField = CrandallField(3);
}
fn to_canonical_representation(&self) -> [Self::BaseField; 2] {
impl FieldExtension<2> for QuadraticCrandallField {
type BaseField = CrandallField;
fn to_basefield_array(&self) -> [Self::BaseField; 2] {
self.0
}
fn from_canonical_representation(v: [Self::BaseField; 2]) -> Self {
Self(v)
fn from_basefield_array(arr: [Self::BaseField; 2]) -> Self {
Self(arr)
}
fn from_basefield(x: Self::BaseField) -> Self {
x.into()
}
}
impl From<<Self as QuadraticFieldExtension>::BaseField> for QuadraticCrandallField {
fn from(x: <Self as QuadraticFieldExtension>::BaseField) -> Self {
Self([x, <Self as QuadraticFieldExtension>::BaseField::ZERO])
impl From<<Self as FieldExtension<2>>::BaseField> for QuadraticCrandallField {
fn from(x: <Self as FieldExtension<2>>::BaseField) -> Self {
Self([x, <Self as FieldExtension<2>>::BaseField::ZERO])
}
}
impl PartialEq for QuadraticCrandallField {
fn eq(&self, other: &Self) -> bool {
self.to_canonical_representation() == other.to_canonical_representation()
FieldExtension::<2>::to_basefield_array(self)
== FieldExtension::<2>::to_basefield_array(other)
}
}
@ -68,7 +51,7 @@ impl Eq for QuadraticCrandallField {}
impl Hash for QuadraticCrandallField {
fn hash<H: Hasher>(&self, state: &mut H) {
for l in &self.to_canonical_representation() {
for l in &FieldExtension::<2>::to_basefield_array(self) {
Hash::hash(l, state);
}
}
@ -101,7 +84,7 @@ impl Field for QuadraticCrandallField {
let a_pow_r_minus_1 = self.frobenius();
let a_pow_r = a_pow_r_minus_1 * *self;
debug_assert!(a_pow_r.is_in_basefield());
debug_assert!(FieldExtension::<2>::is_in_basefield(&a_pow_r));
Some(a_pow_r_minus_1 * a_pow_r.0[0].inverse().into())
}
@ -111,16 +94,13 @@ impl Field for QuadraticCrandallField {
}
fn from_canonical_u64(n: u64) -> Self {
Self([
<Self as QuadraticFieldExtension>::BaseField::from_canonical_u64(n),
<Self as QuadraticFieldExtension>::BaseField::ZERO,
])
<Self as FieldExtension<2>>::BaseField::from_canonical_u64(n).into()
}
fn rand_from_rng<R: Rng>(rng: &mut R) -> Self {
Self([
<Self as QuadraticFieldExtension>::BaseField::rand_from_rng(rng),
<Self as QuadraticFieldExtension>::BaseField::rand_from_rng(rng),
<Self as FieldExtension<2>>::BaseField::rand_from_rng(rng),
<Self as FieldExtension<2>>::BaseField::rand_from_rng(rng),
])
}
}
@ -226,11 +206,16 @@ impl DivAssign for QuadraticCrandallField {
}
}
pub struct ExtensionTarget(pub [Target; 2]);
// impl<F: Field> CircuitBuilder<F> {
// fn mul
// }
#[cfg(test)]
mod tests {
use crate::field::extension_field::quadratic::{
QuadraticCrandallField, QuadraticFieldExtension,
};
use crate::field::extension_field::quadratic::QuadraticCrandallField;
use crate::field::extension_field::{FieldExtension, OEF};
use crate::field::field::Field;
#[test]
@ -241,10 +226,7 @@ mod tests {
let z = F::rand();
assert_eq!(x + (-x), F::ZERO);
assert_eq!(-x, F::ZERO - x);
assert_eq!(
x + x,
x * <F as QuadraticFieldExtension>::BaseField::TWO.into()
);
assert_eq!(x + x, x * <F as FieldExtension<2>>::BaseField::TWO.into());
assert_eq!(x * (-x), -x.square());
assert_eq!(x + y, y + x);
assert_eq!(x * y, y * x);
@ -273,7 +255,7 @@ mod tests {
type F = QuadraticCrandallField;
let x = F::rand();
assert_eq!(
x.exp(<F as QuadraticFieldExtension>::BaseField::ORDER),
x.exp(<F as FieldExtension<2>>::BaseField::ORDER),
x.frobenius()
);
}
@ -300,10 +282,9 @@ mod tests {
F::POWER_OF_TWO_GENERATOR
);
assert_eq!(
F::POWER_OF_TWO_GENERATOR.exp(
1 << (F::TWO_ADICITY - <F as QuadraticFieldExtension>::BaseField::TWO_ADICITY)
),
<F as QuadraticFieldExtension>::BaseField::POWER_OF_TWO_GENERATOR.into()
F::POWER_OF_TWO_GENERATOR
.exp(1 << (F::TWO_ADICITY - <F as FieldExtension<2>>::BaseField::TWO_ADICITY)),
<F as FieldExtension<2>>::BaseField::POWER_OF_TWO_GENERATOR.into()
);
}
}

View File

@ -1,4 +1,5 @@
use crate::field::crandall_field::CrandallField;
use crate::field::extension_field::{FieldExtension, OEF};
use crate::field::field::Field;
use rand::Rng;
use std::fmt::{Debug, Display, Formatter};
@ -6,72 +7,46 @@ use std::hash::{Hash, Hasher};
use std::iter::{Product, Sum};
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
pub trait QuarticFieldExtension: Field + From<<Self as QuarticFieldExtension>::BaseField> {
type BaseField: Field;
// Element W of BaseField, such that `X^4 - W` is irreducible over BaseField.
const W: Self::BaseField;
fn to_canonical_representation(&self) -> [Self::BaseField; 4];
fn from_canonical_representation(v: [Self::BaseField; 4]) -> Self;
fn is_in_basefield(&self) -> bool {
self.to_canonical_representation()[1..]
.iter()
.all(|x| x.is_zero())
}
/// Frobenius automorphisms: x -> x^p, where p is the order of BaseField.
fn frobenius(&self) -> Self {
let [a0, a1, a2, a3] = self.to_canonical_representation();
let k = (Self::BaseField::ORDER - 1) / 4;
let z0 = Self::W.exp(k);
let mut z = Self::BaseField::ONE;
let b0 = a0 * z;
z *= z0;
let b1 = a1 * z;
z *= z0;
let b2 = a2 * z;
z *= z0;
let b3 = a3 * z;
Self::from_canonical_representation([b0, b1, b2, b3])
}
}
#[derive(Copy, Clone)]
pub struct QuarticCrandallField([CrandallField; 4]);
impl QuarticFieldExtension for QuarticCrandallField {
type BaseField = CrandallField;
impl OEF<4> for QuarticCrandallField {
// Verifiable in Sage with
// ``R.<x> = GF(p)[]; assert (x^4 -3).is_irreducible()`.
const W: Self::BaseField = CrandallField(3);
const W: CrandallField = CrandallField(3);
}
fn to_canonical_representation(&self) -> [Self::BaseField; 4] {
impl FieldExtension<4> for QuarticCrandallField {
type BaseField = CrandallField;
fn to_basefield_array(&self) -> [Self::BaseField; 4] {
self.0
}
fn from_canonical_representation(v: [Self::BaseField; 4]) -> Self {
Self(v)
fn from_basefield_array(arr: [Self::BaseField; 4]) -> Self {
Self(arr)
}
fn from_basefield(x: Self::BaseField) -> Self {
x.into()
}
}
impl From<<Self as QuarticFieldExtension>::BaseField> for QuarticCrandallField {
fn from(x: <Self as QuarticFieldExtension>::BaseField) -> Self {
impl From<<Self as FieldExtension<4>>::BaseField> for QuarticCrandallField {
fn from(x: <Self as FieldExtension<4>>::BaseField) -> Self {
Self([
x,
<Self as QuarticFieldExtension>::BaseField::ZERO,
<Self as QuarticFieldExtension>::BaseField::ZERO,
<Self as QuarticFieldExtension>::BaseField::ZERO,
<Self as FieldExtension<4>>::BaseField::ZERO,
<Self as FieldExtension<4>>::BaseField::ZERO,
<Self as FieldExtension<4>>::BaseField::ZERO,
])
}
}
impl PartialEq for QuarticCrandallField {
fn eq(&self, other: &Self) -> bool {
self.to_canonical_representation() == other.to_canonical_representation()
FieldExtension::<4>::to_basefield_array(self)
== FieldExtension::<4>::to_basefield_array(other)
}
}
@ -79,7 +54,7 @@ impl Eq for QuarticCrandallField {}
impl Hash for QuarticCrandallField {
fn hash<H: Hasher>(&self, state: &mut H) {
for l in &self.to_canonical_representation() {
for l in &FieldExtension::<4>::to_basefield_array(self) {
Hash::hash(l, state);
}
}
@ -136,7 +111,7 @@ impl Field for QuarticCrandallField {
let a_pow_p3_plus_p2 = a_pow_p_plus_1.frobenius().frobenius();
let a_pow_r_minus_1 = a_pow_p3_plus_p2 * a_pow_p;
let a_pow_r = a_pow_r_minus_1 * *self;
debug_assert!(a_pow_r.is_in_basefield());
debug_assert!(FieldExtension::<4>::is_in_basefield(&a_pow_r));
Some(a_pow_r_minus_1 * a_pow_r.0[0].inverse().into())
}
@ -146,20 +121,15 @@ impl Field for QuarticCrandallField {
}
fn from_canonical_u64(n: u64) -> Self {
Self([
<Self as QuarticFieldExtension>::BaseField::from_canonical_u64(n),
<Self as QuarticFieldExtension>::BaseField::ZERO,
<Self as QuarticFieldExtension>::BaseField::ZERO,
<Self as QuarticFieldExtension>::BaseField::ZERO,
])
<Self as FieldExtension<4>>::BaseField::from_canonical_u64(n).into()
}
fn rand_from_rng<R: Rng>(rng: &mut R) -> Self {
Self([
<Self as QuarticFieldExtension>::BaseField::rand_from_rng(rng),
<Self as QuarticFieldExtension>::BaseField::rand_from_rng(rng),
<Self as QuarticFieldExtension>::BaseField::rand_from_rng(rng),
<Self as QuarticFieldExtension>::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),
<Self as FieldExtension<4>>::BaseField::rand_from_rng(rng),
])
}
}
@ -283,7 +253,8 @@ impl DivAssign for QuarticCrandallField {
#[cfg(test)]
mod tests {
use crate::field::extension_field::quartic::{QuarticCrandallField, QuarticFieldExtension};
use crate::field::extension_field::quartic::QuarticCrandallField;
use crate::field::extension_field::{FieldExtension, OEF};
use crate::field::field::Field;
fn exp_naive<F: Field>(x: F, power: u128) -> F {
@ -307,10 +278,7 @@ mod tests {
let z = F::rand();
assert_eq!(x + (-x), F::ZERO);
assert_eq!(-x, F::ZERO - x);
assert_eq!(
x + x,
x * <F as QuarticFieldExtension>::BaseField::TWO.into()
);
assert_eq!(x + x, x * <F as FieldExtension<4>>::BaseField::TWO.into());
assert_eq!(x * (-x), -x.square());
assert_eq!(x + y, y + x);
assert_eq!(x * y, y * x);
@ -339,7 +307,7 @@ mod tests {
type F = QuarticCrandallField;
let x = F::rand();
assert_eq!(
exp_naive(x, <F as QuarticFieldExtension>::BaseField::ORDER as u128),
exp_naive(x, <F as FieldExtension<4>>::BaseField::ORDER as u128),
x.frobenius()
);
}
@ -374,8 +342,8 @@ mod tests {
);
assert_eq!(
F::POWER_OF_TWO_GENERATOR
.exp(1 << (F::TWO_ADICITY - <F as QuarticFieldExtension>::BaseField::TWO_ADICITY)),
<F as QuarticFieldExtension>::BaseField::POWER_OF_TWO_GENERATOR.into()
.exp(1 << (F::TWO_ADICITY - <F as FieldExtension<4>>::BaseField::TWO_ADICITY)),
<F as FieldExtension<4>>::BaseField::POWER_OF_TWO_GENERATOR.into()
);
}
}