From 66d6f3c338cc27b072b1f40e804f3d9cba9b9786 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Mon, 24 May 2021 14:12:08 +0200 Subject: [PATCH] Remove useless Qua(d)r(a)ticFieldExtension traits --- src/bin/bench_ldes.rs | 2 +- src/field/extension_field/mod.rs | 61 +++++++-------- src/field/extension_field/quadratic.rs | 97 ++++++++++-------------- src/field/extension_field/quartic.rs | 100 +++++++++---------------- 4 files changed, 101 insertions(+), 159 deletions(-) diff --git a/src/bin/bench_ldes.rs b/src/bin/bench_ldes.rs index 1fb02d65..0413b296 100644 --- a/src/bin/bench_ldes.rs +++ b/src/bin/bench_ldes.rs @@ -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; diff --git a/src/field/extension_field/mod.rs b/src/field/extension_field/mod.rs index 67329c3c..122c9416 100644 --- a/src/field/extension_field/mod.rs +++ b/src/field/extension_field/mod.rs @@ -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: FieldExtension { + // 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: Sized { type Extension: Field + FieldExtension + From; } @@ -21,6 +42,10 @@ pub trait FieldExtension: 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 FieldExtension<1> for F { @@ -39,38 +64,6 @@ impl FieldExtension<1> for F { } } -impl 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 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(l: &[F::Extension]) -> Vec where diff --git a/src/field/extension_field/quadratic.rs b/src/field/extension_field/quadratic.rs index 25b42e49..4fc60423 100644 --- a/src/field/extension_field/quadratic.rs +++ b/src/field/extension_field/quadratic.rs @@ -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<::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. = 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<::BaseField> for QuadraticCrandallField { - fn from(x: ::BaseField) -> Self { - Self([x, ::BaseField::ZERO]) +impl From<>::BaseField> for QuadraticCrandallField { + fn from(x: >::BaseField) -> Self { + Self([x, >::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(&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([ - ::BaseField::from_canonical_u64(n), - ::BaseField::ZERO, - ]) + >::BaseField::from_canonical_u64(n).into() } fn rand_from_rng(rng: &mut R) -> Self { Self([ - ::BaseField::rand_from_rng(rng), - ::BaseField::rand_from_rng(rng), + >::BaseField::rand_from_rng(rng), + >::BaseField::rand_from_rng(rng), ]) } } @@ -226,11 +206,16 @@ impl DivAssign for QuadraticCrandallField { } } +pub struct ExtensionTarget(pub [Target; 2]); + +// impl CircuitBuilder { +// 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 * ::BaseField::TWO.into() - ); + assert_eq!(x + x, x * >::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(::BaseField::ORDER), + x.exp(>::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 - ::BaseField::TWO_ADICITY) - ), - ::BaseField::POWER_OF_TWO_GENERATOR.into() + F::POWER_OF_TWO_GENERATOR + .exp(1 << (F::TWO_ADICITY - >::BaseField::TWO_ADICITY)), + >::BaseField::POWER_OF_TWO_GENERATOR.into() ); } } diff --git a/src/field/extension_field/quartic.rs b/src/field/extension_field/quartic.rs index 121e4c67..c69e365d 100644 --- a/src/field/extension_field/quartic.rs +++ b/src/field/extension_field/quartic.rs @@ -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<::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. = 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<::BaseField> for QuarticCrandallField { - fn from(x: ::BaseField) -> Self { +impl From<>::BaseField> for QuarticCrandallField { + fn from(x: >::BaseField) -> Self { Self([ x, - ::BaseField::ZERO, - ::BaseField::ZERO, - ::BaseField::ZERO, + >::BaseField::ZERO, + >::BaseField::ZERO, + >::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(&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([ - ::BaseField::from_canonical_u64(n), - ::BaseField::ZERO, - ::BaseField::ZERO, - ::BaseField::ZERO, - ]) + >::BaseField::from_canonical_u64(n).into() } fn rand_from_rng(rng: &mut R) -> Self { Self([ - ::BaseField::rand_from_rng(rng), - ::BaseField::rand_from_rng(rng), - ::BaseField::rand_from_rng(rng), - ::BaseField::rand_from_rng(rng), + >::BaseField::rand_from_rng(rng), + >::BaseField::rand_from_rng(rng), + >::BaseField::rand_from_rng(rng), + >::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(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 * ::BaseField::TWO.into() - ); + assert_eq!(x + x, x * >::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, ::BaseField::ORDER as u128), + exp_naive(x, >::BaseField::ORDER as u128), x.frobenius() ); } @@ -374,8 +342,8 @@ mod tests { ); assert_eq!( F::POWER_OF_TWO_GENERATOR - .exp(1 << (F::TWO_ADICITY - ::BaseField::TWO_ADICITY)), - ::BaseField::POWER_OF_TWO_GENERATOR.into() + .exp(1 << (F::TWO_ADICITY - >::BaseField::TWO_ADICITY)), + >::BaseField::POWER_OF_TWO_GENERATOR.into() ); } }