Replace CrandallQuarticField with a more generic QuarticExtension (#232)

* Replace `CrandallQuarticField` with a more generic `QuarticExtension`

And likewise for `CrandallQuadraticField`.

There are a few parameters which we can't automatically derive (in const Rust), so I specified them in a `AutoExtendable` trait.

This would make it fairly easy to add extension fields for `GoldilocksField` and any future fields.

* Attempt to derive 2-adicity, see Hamish's feedback

* Simplify TWO_ADICITY based on chat with Hamish

* PR feedback

* Merge AutoExtendable into Extendable (#235)
This commit is contained in:
Daniel Lubarov 2021-09-13 11:45:17 -07:00 committed by GitHub
parent c76eb9ddeb
commit 91f7b4e300
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 206 additions and 209 deletions

View File

@ -2,7 +2,6 @@
use criterion::{criterion_group, criterion_main, BatchSize, Criterion};
use plonky2::field::crandall_field::CrandallField;
use plonky2::field::extension_field::quartic::QuarticCrandallField;
use plonky2::field::field_types::Field;
use plonky2::field::goldilocks_field::GoldilocksField;
use tynm::type_name;
@ -92,7 +91,7 @@ pub(crate) fn bench_field<F: Field>(c: &mut Criterion) {
fn criterion_benchmark(c: &mut Criterion) {
bench_field::<CrandallField>(c);
bench_field::<GoldilocksField>(c);
bench_field::<QuarticCrandallField>(c);
bench_field::<QuarticExtension<CrandallField>>(c);
}
criterion_group!(benches, criterion_benchmark);

View File

@ -8,8 +8,8 @@ use num::bigint::BigUint;
use rand::Rng;
use serde::{Deserialize, Serialize};
use crate::field::extension_field::quadratic::QuadraticCrandallField;
use crate::field::extension_field::quartic::QuarticCrandallField;
use crate::field::extension_field::quadratic::QuadraticExtension;
use crate::field::extension_field::quartic::QuarticExtension;
use crate::field::extension_field::{Extendable, Frobenius};
use crate::field::field_types::{Field, PrimeField, RichField};
use crate::field::inversion::try_inverse_u64;
@ -287,11 +287,32 @@ impl DivAssign for CrandallField {
}
impl Extendable<2> for CrandallField {
type Extension = QuadraticCrandallField;
type Extension = QuadraticExtension<Self>;
// Verifiable in Sage with
// `R.<x> = GF(p)[]; assert (x^2 - 3).is_irreducible()`.
const W: Self = Self(3);
const EXT_MULTIPLICATIVE_GROUP_GENERATOR: [Self; 2] =
[Self(6483724566312148654), Self(12194665049945415126)];
const EXT_POWER_OF_TWO_GENERATOR: [Self; 2] = [Self(0), Self(14420468973723774561)];
}
impl Extendable<4> for CrandallField {
type Extension = QuarticCrandallField;
type Extension = QuarticExtension<Self>;
const W: Self = Self(3);
const EXT_MULTIPLICATIVE_GROUP_GENERATOR: [Self; 4] = [
Self(12476589904174392631),
Self(896937834427772243),
Self(7795248119019507390),
Self(9005769437373554825),
];
const EXT_POWER_OF_TWO_GENERATOR: [Self; 4] =
[Self(0), Self(0), Self(0), Self(15170983443234254033)];
}
impl RichField for CrandallField {}

View File

@ -1,6 +1,6 @@
use std::convert::TryInto;
use crate::field::field_types::Field;
use crate::field::field_types::{Field, PrimeField};
pub mod algebra;
pub mod quadratic;
@ -45,12 +45,24 @@ pub trait Frobenius<const D: usize>: OEF<D> {
}
}
pub trait Extendable<const D: usize>: Field + Sized {
pub trait Extendable<const D: usize>: PrimeField + Sized {
type Extension: Field + OEF<D, BaseField = Self> + Frobenius<D> + From<Self>;
const W: Self;
const EXT_MULTIPLICATIVE_GROUP_GENERATOR: [Self; D];
/// Chosen so that when raised to the power `1<<(Self::TWO_ADICITY-Self::BaseField::TWO_ADICITY)`,
/// we get `Self::BaseField::POWER_OF_TWO_GENERATOR`. This makes `primitive_root_of_unity` coherent
/// with the base field which implies that the FFT commutes with field inclusion.
const EXT_POWER_OF_TWO_GENERATOR: [Self; D];
}
impl<F: Frobenius<1> + FieldExtension<1, BaseField = F>> Extendable<1> for F {
impl<F: PrimeField + Frobenius<1> + FieldExtension<1, BaseField = F>> Extendable<1> for F {
type Extension = F;
const W: Self = F::ZERO;
const EXT_MULTIPLICATIVE_GROUP_GENERATOR: [Self; 1] = [F::MULTIPLICATIVE_GROUP_GENERATOR];
const EXT_POWER_OF_TWO_GENERATOR: [Self; 1] = [F::POWER_OF_TWO_GENERATOR];
}
pub trait FieldExtension<const D: usize>: Field {

View File

@ -6,71 +6,67 @@ use num::bigint::BigUint;
use rand::Rng;
use serde::{Deserialize, Serialize};
use crate::field::crandall_field::CrandallField;
use crate::field::extension_field::{FieldExtension, Frobenius, OEF};
use crate::field::extension_field::{Extendable, FieldExtension, Frobenius, OEF};
use crate::field::field_types::Field;
#[derive(Copy, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
pub struct QuadraticCrandallField([CrandallField; 2]);
#[serde(bound = "")]
pub struct QuadraticExtension<F: Extendable<2>>(pub(crate) [F; 2]);
impl Default for QuadraticCrandallField {
impl<F: Extendable<2>> Default for QuadraticExtension<F> {
fn default() -> Self {
Self::ZERO
}
}
impl OEF<2> for QuadraticCrandallField {
// Verifiable in Sage with
// ``R.<x> = GF(p)[]; assert (x^2 -3).is_irreducible()`.
const W: CrandallField = CrandallField(3);
impl<F: Extendable<2>> OEF<2> for QuadraticExtension<F> {
const W: F = F::W;
}
impl Frobenius<2> for QuadraticCrandallField {}
impl<F: Extendable<2>> Frobenius<2> for QuadraticExtension<F> {}
impl FieldExtension<2> for QuadraticCrandallField {
type BaseField = CrandallField;
impl<F: Extendable<2>> FieldExtension<2> for QuadraticExtension<F> {
type BaseField = F;
fn to_basefield_array(&self) -> [Self::BaseField; 2] {
fn to_basefield_array(&self) -> [F; 2] {
self.0
}
fn from_basefield_array(arr: [Self::BaseField; 2]) -> Self {
fn from_basefield_array(arr: [F; 2]) -> Self {
Self(arr)
}
fn from_basefield(x: Self::BaseField) -> Self {
fn from_basefield(x: F) -> Self {
x.into()
}
}
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<F: Extendable<2>> From<F> for QuadraticExtension<F> {
fn from(x: F) -> Self {
Self([x, F::ZERO])
}
}
impl Field for QuadraticCrandallField {
type PrimeField = CrandallField;
impl<F: Extendable<2>> Field for QuadraticExtension<F> {
type PrimeField = F;
const ZERO: Self = Self([CrandallField::ZERO; 2]);
const ONE: Self = Self([CrandallField::ONE, CrandallField::ZERO]);
const TWO: Self = Self([CrandallField::TWO, CrandallField::ZERO]);
const NEG_ONE: Self = Self([CrandallField::NEG_ONE, CrandallField::ZERO]);
const ZERO: Self = Self([F::ZERO; 2]);
const ONE: Self = Self([F::ONE, F::ZERO]);
const TWO: Self = Self([F::TWO, F::ZERO]);
const NEG_ONE: Self = Self([F::NEG_ONE, F::ZERO]);
const CHARACTERISTIC: u64 = CrandallField::CHARACTERISTIC;
const TWO_ADICITY: usize = 29;
const MULTIPLICATIVE_GROUP_GENERATOR: Self = Self([
CrandallField(6483724566312148654),
CrandallField(12194665049945415126),
]);
// Chosen so that when raised to the power `1<<(Self::TWO_ADICITY-Self::BaseField::TWO_ADICITY)`,
// we get `Self::BaseField::POWER_OF_TWO_GENERATOR`. This makes `primitive_root_of_unity` coherent
// with the base field which implies that the FFT commutes with field inclusion.
const POWER_OF_TWO_GENERATOR: Self =
Self([CrandallField::ZERO, CrandallField(14420468973723774561)]);
const CHARACTERISTIC: u64 = F::CHARACTERISTIC;
// `p^2 - 1 = (p - 1)(p + 1)`. The `p - 1` term has a two-adicity of `F::TWO_ADICITY`. As
// long as `F::TWO_ADICITY >= 2`, `p` can be written as `4n + 1`, so `p + 1` can be written as
// `2(2n + 1)`, which has a 2-adicity of 1.
const TWO_ADICITY: usize = F::TWO_ADICITY + 1;
const MULTIPLICATIVE_GROUP_GENERATOR: Self = Self(F::EXT_MULTIPLICATIVE_GROUP_GENERATOR);
const POWER_OF_TWO_GENERATOR: Self = Self(F::EXT_POWER_OF_TWO_GENERATOR);
fn order() -> BigUint {
CrandallField::order() * CrandallField::order()
F::order() * F::order()
}
// Algorithm 11.3.4 in Handbook of Elliptic and Hyperelliptic Curve Cryptography.
@ -90,34 +86,31 @@ impl Field for QuadraticCrandallField {
}
fn from_canonical_u64(n: u64) -> Self {
<Self as FieldExtension<2>>::BaseField::from_canonical_u64(n).into()
F::from_canonical_u64(n).into()
}
fn from_noncanonical_u128(n: u128) -> Self {
<Self as FieldExtension<2>>::BaseField::from_noncanonical_u128(n).into()
F::from_noncanonical_u128(n).into()
}
fn rand_from_rng<R: Rng>(rng: &mut R) -> Self {
Self([
<Self as FieldExtension<2>>::BaseField::rand_from_rng(rng),
<Self as FieldExtension<2>>::BaseField::rand_from_rng(rng),
])
Self([F::rand_from_rng(rng), F::rand_from_rng(rng)])
}
}
impl Display for QuadraticCrandallField {
impl<F: Extendable<2>> Display for QuadraticExtension<F> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{} + {}*a", self.0[0], self.0[1])
}
}
impl Debug for QuadraticCrandallField {
impl<F: Extendable<2>> Debug for QuadraticExtension<F> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
Display::fmt(self, f)
}
}
impl Neg for QuadraticCrandallField {
impl<F: Extendable<2>> Neg for QuadraticExtension<F> {
type Output = Self;
#[inline]
@ -126,7 +119,7 @@ impl Neg for QuadraticCrandallField {
}
}
impl Add for QuadraticCrandallField {
impl<F: Extendable<2>> Add for QuadraticExtension<F> {
type Output = Self;
#[inline]
@ -135,19 +128,19 @@ impl Add for QuadraticCrandallField {
}
}
impl AddAssign for QuadraticCrandallField {
impl<F: Extendable<2>> AddAssign for QuadraticExtension<F> {
fn add_assign(&mut self, rhs: Self) {
*self = *self + rhs;
}
}
impl Sum for QuadraticCrandallField {
impl<F: Extendable<2>> Sum for QuadraticExtension<F> {
fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
iter.fold(Self::ZERO, |acc, x| acc + x)
}
}
impl Sub for QuadraticCrandallField {
impl<F: Extendable<2>> Sub for QuadraticExtension<F> {
type Output = Self;
#[inline]
@ -156,14 +149,14 @@ impl Sub for QuadraticCrandallField {
}
}
impl SubAssign for QuadraticCrandallField {
impl<F: Extendable<2>> SubAssign for QuadraticExtension<F> {
#[inline]
fn sub_assign(&mut self, rhs: Self) {
*self = *self - rhs;
}
}
impl Mul for QuadraticCrandallField {
impl<F: Extendable<2>> Mul for QuadraticExtension<F> {
type Output = Self;
#[inline]
@ -178,20 +171,20 @@ impl Mul for QuadraticCrandallField {
}
}
impl MulAssign for QuadraticCrandallField {
impl<F: Extendable<2>> MulAssign for QuadraticExtension<F> {
#[inline]
fn mul_assign(&mut self, rhs: Self) {
*self = *self * rhs;
}
}
impl Product for QuadraticCrandallField {
impl<F: Extendable<2>> Product for QuadraticExtension<F> {
fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
iter.fold(Self::ONE, |acc, x| acc * x)
}
}
impl Div for QuadraticCrandallField {
impl<F: Extendable<2>> Div for QuadraticExtension<F> {
type Output = Self;
#[allow(clippy::suspicious_arithmetic_impl)]
@ -200,7 +193,7 @@ impl Div for QuadraticCrandallField {
}
}
impl DivAssign for QuadraticCrandallField {
impl<F: Extendable<2>> DivAssign for QuadraticExtension<F> {
fn div_assign(&mut self, rhs: Self) {
*self = *self / rhs;
}
@ -208,20 +201,21 @@ impl DivAssign for QuadraticCrandallField {
#[cfg(test)]
mod tests {
use crate::field::extension_field::quadratic::QuadraticCrandallField;
use crate::field::extension_field::{FieldExtension, Frobenius};
use crate::field::crandall_field::CrandallField;
use crate::field::extension_field::quadratic::QuadraticExtension;
use crate::field::extension_field::Frobenius;
use crate::field::field_types::Field;
use crate::test_field_arithmetic;
#[test]
fn test_add_neg_sub_mul() {
type F = QuadraticCrandallField;
type F = QuadraticExtension<CrandallField>;
let x = F::rand();
let y = F::rand();
let z = F::rand();
assert_eq!(x + (-x), F::ZERO);
assert_eq!(-x, F::ZERO - x);
assert_eq!(x + x, x * <F as FieldExtension<2>>::BaseField::TWO.into());
assert_eq!(x + x, x * F::TWO);
assert_eq!(x * (-x), -x.square());
assert_eq!(x + y, y + x);
assert_eq!(x * y, y * x);
@ -233,7 +227,7 @@ mod tests {
#[test]
fn test_inv_div() {
type F = QuadraticCrandallField;
type F = QuadraticExtension<CrandallField>;
let x = F::rand();
let y = F::rand();
let z = F::rand();
@ -247,18 +241,15 @@ mod tests {
#[test]
fn test_frobenius() {
type F = QuadraticCrandallField;
type F = QuadraticExtension<CrandallField>;
let x = F::rand();
assert_eq!(
x.exp_biguint(&<F as FieldExtension<2>>::BaseField::order()),
x.frobenius()
);
assert_eq!(x.exp_biguint(&CrandallField::order()), x.frobenius());
}
#[test]
fn test_field_order() {
// F::order() = 340282366831806780677557380898690695169 = 18446744071293632512 *18446744071293632514 + 1
type F = QuadraticCrandallField;
type F = QuadraticExtension<CrandallField>;
let x = F::rand();
assert_eq!(
x.exp_u64(18446744071293632512)
@ -269,7 +260,7 @@ mod tests {
#[test]
fn test_power_of_two_gen() {
type F = QuadraticCrandallField;
type F = QuadraticExtension<CrandallField>;
// F::order() = 2^29 * 2762315674048163 * 229454332791453 + 1
assert_eq!(
F::MULTIPLICATIVE_GROUP_GENERATOR
@ -278,11 +269,14 @@ mod tests {
F::POWER_OF_TWO_GENERATOR
);
assert_eq!(
F::POWER_OF_TWO_GENERATOR
.exp_u64(1 << (F::TWO_ADICITY - <F as FieldExtension<2>>::BaseField::TWO_ADICITY)),
<F as FieldExtension<2>>::BaseField::POWER_OF_TWO_GENERATOR.into()
F::POWER_OF_TWO_GENERATOR.exp_u64(1 << (F::TWO_ADICITY - CrandallField::TWO_ADICITY)),
CrandallField::POWER_OF_TWO_GENERATOR.into()
);
}
test_field_arithmetic!(crate::field::extension_field::quadratic::QuadraticCrandallField);
test_field_arithmetic!(
crate::field::extension_field::quadratic::QuadraticExtension<
crate::field::crandall_field::CrandallField,
>
);
}

View File

@ -7,100 +7,68 @@ use num::traits::Pow;
use rand::Rng;
use serde::{Deserialize, Serialize};
use crate::field::crandall_field::CrandallField;
use crate::field::extension_field::{FieldExtension, Frobenius, OEF};
use crate::field::extension_field::{Extendable, FieldExtension, Frobenius, OEF};
use crate::field::field_types::Field;
/// A quartic extension of `CrandallField`.
#[derive(Copy, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
pub struct QuarticCrandallField(pub(crate) [CrandallField; 4]);
#[serde(bound = "")]
pub struct QuarticExtension<F: Extendable<4>>(pub(crate) [F; 4]);
impl Default for QuarticCrandallField {
impl<F: Extendable<4>> Default for QuarticExtension<F> {
fn default() -> Self {
Self::ZERO
}
}
impl OEF<4> for QuarticCrandallField {
// Verifiable in Sage with
// R.<x> = GF(p)[]
// assert (x^4 - 3).is_irreducible()
const W: CrandallField = CrandallField(3);
impl<F: Extendable<4>> OEF<4> for QuarticExtension<F> {
const W: F = F::W;
}
impl Frobenius<4> for QuarticCrandallField {}
impl<F: Extendable<4>> Frobenius<4> for QuarticExtension<F> {}
impl FieldExtension<4> for QuarticCrandallField {
type BaseField = CrandallField;
impl<F: Extendable<4>> FieldExtension<4> for QuarticExtension<F> {
type BaseField = F;
fn to_basefield_array(&self) -> [Self::BaseField; 4] {
fn to_basefield_array(&self) -> [F; 4] {
self.0
}
fn from_basefield_array(arr: [Self::BaseField; 4]) -> Self {
fn from_basefield_array(arr: [F; 4]) -> Self {
Self(arr)
}
fn from_basefield(x: Self::BaseField) -> Self {
fn from_basefield(x: F) -> Self {
x.into()
}
}
impl From<<Self as FieldExtension<4>>::BaseField> for QuarticCrandallField {
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<F: Extendable<4>> From<F> for QuarticExtension<F> {
fn from(x: F) -> Self {
Self([x, F::ZERO, F::ZERO, F::ZERO])
}
}
impl Field for QuarticCrandallField {
type PrimeField = CrandallField;
impl<F: Extendable<4>> Field for QuarticExtension<F> {
type PrimeField = F;
const ZERO: Self = Self([CrandallField::ZERO; 4]);
const ONE: Self = Self([
CrandallField::ONE,
CrandallField::ZERO,
CrandallField::ZERO,
CrandallField::ZERO,
]);
const TWO: Self = Self([
CrandallField::TWO,
CrandallField::ZERO,
CrandallField::ZERO,
CrandallField::ZERO,
]);
const NEG_ONE: Self = Self([
CrandallField::NEG_ONE,
CrandallField::ZERO,
CrandallField::ZERO,
CrandallField::ZERO,
]);
const ZERO: Self = Self([F::ZERO; 4]);
const ONE: Self = Self([F::ONE, F::ZERO, F::ZERO, F::ZERO]);
const TWO: Self = Self([F::TWO, F::ZERO, F::ZERO, F::ZERO]);
const NEG_ONE: Self = Self([F::NEG_ONE, F::ZERO, F::ZERO, F::ZERO]);
const CHARACTERISTIC: u64 = CrandallField::CHARACTERISTIC;
// Does not fit in 64-bits.
const TWO_ADICITY: usize = 30;
const MULTIPLICATIVE_GROUP_GENERATOR: Self = Self([
CrandallField(12476589904174392631),
CrandallField(896937834427772243),
CrandallField(7795248119019507390),
CrandallField(9005769437373554825),
]);
// Chosen so that when raised to the power `1<<(Self::TWO_ADICITY-Self::BaseField::TWO_ADICITY)`,
// we get `Self::BaseField::POWER_OF_TWO_GENERATOR`. This makes `primitive_root_of_unity` coherent
// with the base field which implies that the FFT commutes with field inclusion.
const POWER_OF_TWO_GENERATOR: Self = Self([
CrandallField::ZERO,
CrandallField::ZERO,
CrandallField::ZERO,
CrandallField(15170983443234254033),
]);
const CHARACTERISTIC: u64 = F::ORDER;
// `p^4 - 1 = (p - 1)(p + 1)(p^2 + 1)`. The `p - 1` term has a two-adicity of `F::TWO_ADICITY`.
// As long as `F::TWO_ADICITY >= 2`, `p` can be written as `4n + 1`, so `p + 1` can be written as
// `2(2n + 1)`, which has a 2-adicity of 1. A similar argument can show that `p^2 + 1` also has
// a 2-adicity of 1.
const TWO_ADICITY: usize = F::TWO_ADICITY + 2;
const MULTIPLICATIVE_GROUP_GENERATOR: Self = Self(F::EXT_MULTIPLICATIVE_GROUP_GENERATOR);
const POWER_OF_TWO_GENERATOR: Self = Self(F::EXT_POWER_OF_TWO_GENERATOR);
fn order() -> BigUint {
CrandallField::order().pow(4u32)
F::order().pow(4u32)
}
// Algorithm 11.3.4 in Handbook of Elliptic and Hyperelliptic Curve Cryptography.
@ -123,24 +91,24 @@ impl Field for QuarticCrandallField {
}
fn from_canonical_u64(n: u64) -> Self {
<Self as FieldExtension<4>>::BaseField::from_canonical_u64(n).into()
F::from_canonical_u64(n).into()
}
fn from_noncanonical_u128(n: u128) -> Self {
<Self as FieldExtension<4>>::BaseField::from_noncanonical_u128(n).into()
F::from_noncanonical_u128(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),
Self::from_basefield_array([
F::rand_from_rng(rng),
F::rand_from_rng(rng),
F::rand_from_rng(rng),
F::rand_from_rng(rng),
])
}
}
impl Display for QuarticCrandallField {
impl<F: Extendable<4>> Display for QuarticExtension<F> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
@ -150,13 +118,13 @@ impl Display for QuarticCrandallField {
}
}
impl Debug for QuarticCrandallField {
impl<F: Extendable<4>> Debug for QuarticExtension<F> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
Display::fmt(self, f)
}
}
impl Neg for QuarticCrandallField {
impl<F: Extendable<4>> Neg for QuarticExtension<F> {
type Output = Self;
#[inline]
@ -165,7 +133,7 @@ impl Neg for QuarticCrandallField {
}
}
impl Add for QuarticCrandallField {
impl<F: Extendable<4>> Add for QuarticExtension<F> {
type Output = Self;
#[inline]
@ -179,19 +147,19 @@ impl Add for QuarticCrandallField {
}
}
impl AddAssign for QuarticCrandallField {
impl<F: Extendable<4>> AddAssign for QuarticExtension<F> {
fn add_assign(&mut self, rhs: Self) {
*self = *self + rhs;
}
}
impl Sum for QuarticCrandallField {
impl<F: Extendable<4>> Sum for QuarticExtension<F> {
fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
iter.fold(Self::ZERO, |acc, x| acc + x)
}
}
impl Sub for QuarticCrandallField {
impl<F: Extendable<4>> Sub for QuarticExtension<F> {
type Output = Self;
#[inline]
@ -205,14 +173,14 @@ impl Sub for QuarticCrandallField {
}
}
impl SubAssign for QuarticCrandallField {
impl<F: Extendable<4>> SubAssign for QuarticExtension<F> {
#[inline]
fn sub_assign(&mut self, rhs: Self) {
*self = *self - rhs;
}
}
impl Mul for QuarticCrandallField {
impl<F: Extendable<4>> Mul for QuarticExtension<F> {
type Output = Self;
#[inline]
@ -229,20 +197,20 @@ impl Mul for QuarticCrandallField {
}
}
impl MulAssign for QuarticCrandallField {
impl<F: Extendable<4>> MulAssign for QuarticExtension<F> {
#[inline]
fn mul_assign(&mut self, rhs: Self) {
*self = *self * rhs;
}
}
impl Product for QuarticCrandallField {
impl<F: Extendable<4>> Product for QuarticExtension<F> {
fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
iter.fold(Self::ONE, |acc, x| acc * x)
}
}
impl Div for QuarticCrandallField {
impl<F: Extendable<4>> Div for QuarticExtension<F> {
type Output = Self;
#[allow(clippy::suspicious_arithmetic_impl)]
@ -251,7 +219,7 @@ impl Div for QuarticCrandallField {
}
}
impl DivAssign for QuarticCrandallField {
impl<F: Extendable<4>> DivAssign for QuarticExtension<F> {
fn div_assign(&mut self, rhs: Self) {
*self = *self / rhs;
}
@ -259,8 +227,9 @@ impl DivAssign for QuarticCrandallField {
#[cfg(test)]
mod tests {
use crate::field::extension_field::quartic::QuarticCrandallField;
use crate::field::extension_field::{FieldExtension, Frobenius};
use crate::field::crandall_field::CrandallField;
use crate::field::extension_field::quartic::QuarticExtension;
use crate::field::extension_field::Frobenius;
use crate::field::field_types::Field;
use crate::test_field_arithmetic;
@ -279,13 +248,13 @@ mod tests {
#[test]
fn test_add_neg_sub_mul() {
type F = QuarticCrandallField;
type F = QuarticExtension<CrandallField>;
let x = F::rand();
let y = F::rand();
let z = F::rand();
assert_eq!(x + (-x), F::ZERO);
assert_eq!(-x, F::ZERO - x);
assert_eq!(x + x, x * <F as FieldExtension<4>>::BaseField::TWO.into());
assert_eq!(x + x, x * F::TWO.into());
assert_eq!(x * (-x), -x.square());
assert_eq!(x + y, y + x);
assert_eq!(x * y, y * x);
@ -297,7 +266,7 @@ mod tests {
#[test]
fn test_inv_div() {
type F = QuarticCrandallField;
type F = QuarticExtension<CrandallField>;
let x = F::rand();
let y = F::rand();
let z = F::rand();
@ -311,13 +280,10 @@ mod tests {
#[test]
fn test_frobenius() {
type F = QuarticCrandallField;
type F = QuarticExtension<CrandallField>;
const D: usize = 4;
let x = F::rand();
assert_eq!(
x.exp_biguint(&<F as FieldExtension<D>>::BaseField::order()),
x.frobenius()
);
assert_eq!(x.exp_biguint(&CrandallField::order()), x.frobenius());
for count in 2..D {
assert_eq!(
x.repeated_frobenius(count),
@ -329,7 +295,7 @@ mod tests {
#[test]
fn test_field_order() {
// F::order() = 340282366831806780677557380898690695168 * 340282366831806780677557380898690695170 + 1
type F = QuarticCrandallField;
type F = QuarticExtension<CrandallField>;
let x = F::rand();
assert_eq!(
exp_naive(
@ -342,7 +308,7 @@ mod tests {
#[test]
fn test_power_of_two_gen() {
type F = QuarticCrandallField;
type F = QuarticExtension<CrandallField>;
// F::order() = 2^30 * 1090552343587053358839971118999869 * 98885475095492590491252558464653635 + 1
assert_eq!(
exp_naive(
@ -355,11 +321,14 @@ mod tests {
F::POWER_OF_TWO_GENERATOR
);
assert_eq!(
F::POWER_OF_TWO_GENERATOR
.exp_u64(1 << (F::TWO_ADICITY - <F as FieldExtension<4>>::BaseField::TWO_ADICITY)),
<F as FieldExtension<4>>::BaseField::POWER_OF_TWO_GENERATOR.into()
F::POWER_OF_TWO_GENERATOR.exp_u64(1 << (F::TWO_ADICITY - CrandallField::TWO_ADICITY)),
CrandallField::POWER_OF_TWO_GENERATOR.into()
);
}
test_field_arithmetic!(crate::field::extension_field::quartic::QuarticCrandallField);
test_field_arithmetic!(
crate::field::extension_field::quartic::QuarticExtension<
crate::field::crandall_field::CrandallField,
>
);
}

View File

@ -51,6 +51,8 @@ pub trait Field:
const NEG_ONE: Self;
const CHARACTERISTIC: u64;
/// The 2-adicity of this field's multiplicative group.
const TWO_ADICITY: usize;
/// Generator of the entire multiplicative group, i.e. all non-zero elements.

View File

@ -78,7 +78,7 @@ pub fn interpolate2<F: Field>(points: [(F, F); 2], x: F) -> F {
mod tests {
use super::*;
use crate::field::crandall_field::CrandallField;
use crate::field::extension_field::quartic::QuarticCrandallField;
use crate::field::extension_field::quartic::QuarticExtension;
use crate::field::field_types::Field;
use crate::polynomial::polynomial::PolynomialCoeffs;
@ -132,7 +132,7 @@ mod tests {
#[test]
fn test_interpolate2() {
type F = QuarticCrandallField;
type F = QuarticExtension<CrandallField>;
let points = [(F::rand(), F::rand()), (F::rand(), F::rand())];
let x = F::rand();

View File

@ -504,7 +504,7 @@ mod tests {
use crate::field::crandall_field::CrandallField;
use crate::field::extension_field::algebra::ExtensionAlgebra;
use crate::field::extension_field::quartic::QuarticCrandallField;
use crate::field::extension_field::quartic::QuarticExtension;
use crate::field::field_types::Field;
use crate::iop::witness::{PartialWitness, Witness};
use crate::plonk::circuit_builder::CircuitBuilder;
@ -514,7 +514,7 @@ mod tests {
#[test]
fn test_mul_many() -> Result<()> {
type F = CrandallField;
type FF = QuarticCrandallField;
type FF = QuarticExtension<CrandallField>;
const D: usize = 4;
let config = CircuitConfig::large_config();
@ -549,7 +549,7 @@ mod tests {
#[test]
fn test_div_extension() -> Result<()> {
type F = CrandallField;
type FF = QuarticCrandallField;
type FF = QuarticExtension<CrandallField>;
const D: usize = 4;
let config = CircuitConfig::large_zk_config();
@ -577,7 +577,7 @@ mod tests {
#[test]
fn test_mul_algebra() -> Result<()> {
type F = CrandallField;
type FF = QuarticCrandallField;
type FF = QuarticExtension<CrandallField>;
const D: usize = 4;
let config = CircuitConfig::large_config();

View File

@ -44,7 +44,7 @@ mod tests {
use super::*;
use crate::field::crandall_field::CrandallField;
use crate::field::extension_field::quartic::QuarticCrandallField;
use crate::field::extension_field::quartic::QuarticExtension;
use crate::field::field_types::Field;
use crate::iop::witness::PartialWitness;
use crate::plonk::circuit_data::CircuitConfig;
@ -62,7 +62,7 @@ mod tests {
fn test_insert_given_len(len_log: usize) -> Result<()> {
type F = CrandallField;
type FF = QuarticCrandallField;
type FF = QuarticExtension<CrandallField>;
let len = 1 << len_log;
let config = CircuitConfig::large_config();
let pw = PartialWitness::new();

View File

@ -36,7 +36,7 @@ mod tests {
use anyhow::Result;
use crate::field::crandall_field::CrandallField;
use crate::field::extension_field::quartic::QuarticCrandallField;
use crate::field::extension_field::quartic::QuarticExtension;
use crate::field::extension_field::FieldExtension;
use crate::field::field_types::Field;
use crate::field::interpolation::interpolant;
@ -48,7 +48,7 @@ mod tests {
#[test]
fn test_interpolate() -> Result<()> {
type F = CrandallField;
type FF = QuarticCrandallField;
type FF = QuarticExtension<CrandallField>;
let config = CircuitConfig::large_config();
let pw = PartialWitness::new();
let mut builder = CircuitBuilder::<F, 4>::new(config);

View File

@ -56,7 +56,7 @@ mod tests {
use super::*;
use crate::field::crandall_field::CrandallField;
use crate::field::extension_field::quartic::QuarticCrandallField;
use crate::field::extension_field::quartic::QuarticExtension;
use crate::field::field_types::Field;
use crate::iop::witness::PartialWitness;
use crate::plonk::circuit_data::CircuitConfig;
@ -64,7 +64,7 @@ mod tests {
fn test_random_access_given_len(len_log: usize) -> Result<()> {
type F = CrandallField;
type FF = QuarticCrandallField;
type FF = QuarticExtension<CrandallField>;
let len = 1 << len_log;
let config = CircuitConfig::large_config();
let pw = PartialWitness::new();

View File

@ -42,7 +42,7 @@ mod tests {
use anyhow::Result;
use crate::field::crandall_field::CrandallField;
use crate::field::extension_field::quartic::QuarticCrandallField;
use crate::field::extension_field::quartic::QuarticExtension;
use crate::field::field_types::Field;
use crate::iop::witness::{PartialWitness, Witness};
use crate::plonk::circuit_builder::CircuitBuilder;
@ -52,7 +52,7 @@ mod tests {
#[test]
fn test_select() -> Result<()> {
type F = CrandallField;
type FF = QuarticCrandallField;
type FF = QuarticExtension<CrandallField>;
let config = CircuitConfig::large_config();
let mut pw = PartialWitness::new();
let mut builder = CircuitBuilder::<F, 4>::new(config);

View File

@ -267,7 +267,7 @@ mod tests {
use rand::Rng;
use crate::field::crandall_field::CrandallField;
use crate::field::extension_field::quartic::QuarticCrandallField;
use crate::field::extension_field::quartic::QuarticExtension;
use crate::field::field_types::Field;
use crate::gates::exponentiation::ExponentiationGate;
use crate::gates::gate::Gate;
@ -315,7 +315,7 @@ mod tests {
#[test]
fn test_gate_constraint() {
type F = CrandallField;
type FF = QuarticCrandallField;
type FF = QuarticExtension<CrandallField>;
const D: usize = 4;
/// Returns the local wires for an exponentiation gate given the base, power, and power bit

View File

@ -325,7 +325,7 @@ mod tests {
use anyhow::Result;
use crate::field::crandall_field::CrandallField;
use crate::field::extension_field::quartic::QuarticCrandallField;
use crate::field::extension_field::quartic::QuarticExtension;
use crate::field::field_types::Field;
use crate::gates::gate::Gate;
use crate::gates::gate_testing::{test_eval_fns, test_low_degree};
@ -365,7 +365,7 @@ mod tests {
#[test]
fn test_gate_constraint() {
type F = CrandallField;
type FF = QuarticCrandallField;
type FF = QuarticExtension<CrandallField>;
const D: usize = 4;
/// Returns the local wires for an insertion gate given the original vector, element to

View File

@ -290,7 +290,7 @@ mod tests {
use anyhow::Result;
use crate::field::crandall_field::CrandallField;
use crate::field::extension_field::quartic::QuarticCrandallField;
use crate::field::extension_field::quartic::QuarticExtension;
use crate::field::field_types::Field;
use crate::gates::gate::Gate;
use crate::gates::gate_testing::{test_eval_fns, test_low_degree};
@ -332,7 +332,7 @@ mod tests {
#[test]
fn test_gate_constraint() {
type F = CrandallField;
type FF = QuarticCrandallField;
type FF = QuarticExtension<CrandallField>;
const D: usize = 4;
/// Returns the local wires for an interpolation gate for given coeffs, points and eval point.

View File

@ -255,7 +255,7 @@ mod tests {
use anyhow::Result;
use crate::field::crandall_field::CrandallField;
use crate::field::extension_field::quartic::QuarticCrandallField;
use crate::field::extension_field::quartic::QuarticExtension;
use crate::field::field_types::Field;
use crate::gates::gate::Gate;
use crate::gates::gate_testing::{test_eval_fns, test_low_degree};
@ -293,7 +293,7 @@ mod tests {
#[test]
fn test_gate_constraint() {
type F = CrandallField;
type FF = QuarticCrandallField;
type FF = QuarticExtension<CrandallField>;
const D: usize = 4;
/// Returns the local wires for a random access gate given the vector, element to compare,

View File

@ -308,7 +308,7 @@ mod tests {
use anyhow::Result;
use crate::field::crandall_field::CrandallField;
use crate::field::extension_field::quartic::QuarticCrandallField;
use crate::field::extension_field::quartic::QuarticExtension;
use crate::field::field_types::Field;
use crate::gates::gate::Gate;
use crate::gates::gate_testing::{test_eval_fns, test_low_degree};
@ -363,7 +363,7 @@ mod tests {
#[test]
fn test_gate_constraint() {
type F = CrandallField;
type FF = QuarticCrandallField;
type FF = QuarticExtension<CrandallField>;
const D: usize = 4;
const CHUNK_SIZE: usize = 4;
let num_copies = 3;

View File

@ -185,7 +185,7 @@ mod tests {
use std::time::Instant;
use crate::field::crandall_field::CrandallField;
use crate::field::extension_field::quartic::QuarticCrandallField;
use crate::field::extension_field::quartic::QuarticExtension;
use crate::field::field_types::Field;
use crate::polynomial::polynomial::PolynomialCoeffs;
@ -220,7 +220,7 @@ mod tests {
#[test]
#[ignore]
fn test_division_by_linear() {
type F = QuarticCrandallField;
type F = QuarticExtension<CrandallField>;
let n = 1_000_000;
let poly = PolynomialCoeffs::new(F::rand_vec(n));
let z = F::rand();
@ -245,7 +245,7 @@ mod tests {
#[test]
#[ignore]
fn test_division_by_quadratic() {
type F = QuarticCrandallField;
type F = QuarticExtension<CrandallField>;
let n = 1_000_000;
let poly = PolynomialCoeffs::new(F::rand_vec(n));
let quad = PolynomialCoeffs::new(F::rand_vec(2));

View File

@ -188,14 +188,14 @@ mod tests {
use super::*;
use crate::field::crandall_field::CrandallField;
use crate::field::extension_field::quartic::QuarticCrandallField;
use crate::field::extension_field::quartic::QuarticExtension;
use crate::iop::witness::PartialWitness;
use crate::plonk::circuit_data::CircuitConfig;
use crate::plonk::verifier::verify;
fn test_reduce_gadget_base(n: usize) -> Result<()> {
type F = CrandallField;
type FF = QuarticCrandallField;
type FF = QuarticExtension<CrandallField>;
const D: usize = 4;
let config = CircuitConfig::large_config();
@ -223,7 +223,7 @@ mod tests {
fn test_reduce_gadget(n: usize) -> Result<()> {
type F = CrandallField;
type FF = QuarticCrandallField;
type FF = QuarticExtension<CrandallField>;
const D: usize = 4;
let config = CircuitConfig::large_config();