Remove Frobeniable trait

This commit is contained in:
wborgeaud 2021-06-14 10:28:15 +02:00
parent 133c75d68e
commit 445ea3771d
7 changed files with 35 additions and 64 deletions

View File

@ -6,7 +6,7 @@ use num::Integer;
use crate::field::extension_field::quadratic::QuadraticCrandallField; use crate::field::extension_field::quadratic::QuadraticCrandallField;
use crate::field::extension_field::quartic::QuarticCrandallField; use crate::field::extension_field::quartic::QuarticCrandallField;
use crate::field::extension_field::{Extendable, Frobeniable}; use crate::field::extension_field::{Extendable, Frobenius};
use crate::field::field::Field; use crate::field::field::Field;
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use std::iter::{Product, Sum}; use std::iter::{Product, Sum};
@ -444,16 +444,7 @@ fn split(x: u128) -> (u64, u64) {
(x as u64, (x >> 64) as u64) (x as u64, (x >> 64) as u64)
} }
impl Frobeniable for CrandallField { impl Frobenius<1> for CrandallField {}
const FROBENIUS_CONSTANTS_2: [u64; 1] = [9223372035646816256];
/// Placeholder since there's no OEF of degree 3 for `CrandallField`.
const FROBENIUS_CONSTANTS_3: [u64; 2] = [0, 0];
const FROBENIUS_CONSTANTS_4: [u64; 3] = [
4611686017823408128,
9223372035646816256,
13835058053470224384,
];
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {

View File

@ -19,59 +19,36 @@ impl<F: Field> OEF<1> for F {
const W: Self::BaseField = F::ZERO; const W: Self::BaseField = F::ZERO;
} }
pub trait Frobenius<BF: Frobeniable, const D: usize>: OEF<D, BaseField = BF> { pub trait Frobenius<const D: usize>: OEF<D> {
/// FrobeniusField automorphisms: x -> x^p, where p is the order of BaseField. /// FrobeniusField automorphisms: x -> x^p, where p is the order of BaseField.
fn frobenius(&self) -> Self { fn frobenius(&self) -> Self {
self.repeated_frobenius(1) self.repeated_frobenius(1)
} }
/// Repeated Frobenius automorphisms: x -> x^(p^k). /// Repeated Frobenius automorphisms: x -> x^(p^k).
fn repeated_frobenius(&self, k: usize) -> Self { fn repeated_frobenius(&self, count: usize) -> Self {
if k == 0 { if count == 0 {
return *self; return *self;
} else if k >= D { } else if count >= D {
return self.repeated_frobenius(k % D); return self.repeated_frobenius(count % D);
} }
let arr = self.to_basefield_array(); let arr = self.to_basefield_array();
let z0 = match D { let k = (Self::BaseField::ORDER - 1) / (D as u64);
2 => Self::W.exp(BF::FROBENIUS_CONSTANTS_2[k - 1]), let z0 = Self::W.exp(k * count as u64);
3 => Self::W.exp(BF::FROBENIUS_CONSTANTS_3[k - 1]),
4 => Self::W.exp(BF::FROBENIUS_CONSTANTS_4[k - 1]),
_ => unimplemented!("Only extensions of degree 2, 3, or 4 are allowed for now."),
};
let mut z = Self::BaseField::ONE;
let mut res = [Self::BaseField::ZERO; D]; let mut res = [Self::BaseField::ZERO; D];
for i in 0..D { for (i, z) in z0.powers().take(D).enumerate() {
res[i] = arr[i] * z; res[i] = arr[i] * z;
z *= z0;
} }
Self::from_basefield_array(res) Self::from_basefield_array(res)
} }
} }
impl<F: Frobeniable> Frobenius<F, 1> for F { pub trait Extendable<const D: usize>: Field + Sized {
fn frobenius(&self) -> Self { type Extension: Field + OEF<D, BaseField = Self> + Frobenius<D> + From<Self>;
*self
}
fn repeated_frobenius(&self, _k: usize) -> Self {
*self
}
} }
/// Trait to hardcode constants used in the Frobenius automorphism. impl<F: Frobenius<1> + FieldExtension<1, BaseField = F>> Extendable<1> for F {
pub trait Frobeniable: Field {
//! `FROBENIUS_CONSTANTS_D[i-1] = floor( p^i / D) mod p-1`
const FROBENIUS_CONSTANTS_2: [u64; 1];
const FROBENIUS_CONSTANTS_3: [u64; 2];
const FROBENIUS_CONSTANTS_4: [u64; 3];
}
pub trait Extendable<const D: usize>: Frobeniable + Sized {
type Extension: Field + OEF<D, BaseField = Self> + Frobenius<Self, D> + From<Self>;
}
impl<F: Frobeniable + Frobenius<F, 1>> Extendable<1> for F {
type Extension = F; type Extension = F;
} }

View File

@ -16,7 +16,7 @@ impl OEF<2> for QuadraticCrandallField {
const W: CrandallField = CrandallField(3); const W: CrandallField = CrandallField(3);
} }
impl Frobenius<CrandallField, 2> for QuadraticCrandallField {} impl Frobenius<2> for QuadraticCrandallField {}
impl FieldExtension<2> for QuadraticCrandallField { impl FieldExtension<2> for QuadraticCrandallField {
type BaseField = CrandallField; type BaseField = CrandallField;

View File

@ -20,7 +20,7 @@ impl OEF<4> for QuarticCrandallField {
const W: CrandallField = CrandallField(3); const W: CrandallField = CrandallField(3);
} }
impl Frobenius<CrandallField, 4> for QuarticCrandallField {} impl Frobenius<4> for QuarticCrandallField {}
impl FieldExtension<4> for QuarticCrandallField { impl FieldExtension<4> for QuarticCrandallField {
type BaseField = CrandallField; type BaseField = CrandallField;
@ -294,16 +294,18 @@ mod tests {
#[test] #[test]
fn test_frobenius() { fn test_frobenius() {
type F = QuarticCrandallField; type F = QuarticCrandallField;
const D: usize = 4;
let x = F::rand(); let x = F::rand();
assert_eq!( assert_eq!(
exp_naive(x, <F as FieldExtension<4>>::BaseField::ORDER as u128), exp_naive(x, <F as FieldExtension<D>>::BaseField::ORDER as u128),
x.frobenius() x.frobenius()
); );
assert_eq!(x.repeated_frobenius(2), x.frobenius().frobenius()); for count in 2..D {
assert_eq!( assert_eq!(
x.repeated_frobenius(3), x.repeated_frobenius(count),
x.frobenius().frobenius().frobenius() (0..count).fold(x, |acc, _| acc.frobenius())
); );
}
} }
#[test] #[test]

View File

@ -34,16 +34,17 @@ impl<const D: usize> ExtensionTarget<D> {
pub fn repeated_frobenius<F: Extendable<D>>( pub fn repeated_frobenius<F: Extendable<D>>(
&self, &self,
k: usize, count: usize,
builder: &mut CircuitBuilder<F, D>, builder: &mut CircuitBuilder<F, D>,
) -> Self { ) -> Self {
if count == 0 {
return *self;
} else if count >= D {
return self.repeated_frobenius(count % D, builder);
}
let arr = self.to_target_array(); let arr = self.to_target_array();
let z0 = match D { let k = (F::ORDER - 1) / (D as u64);
2 => F::Extension::W.exp(F::FROBENIUS_CONSTANTS_2[k - 1]), let z0 = F::W.exp(k * count as u64);
3 => F::Extension::W.exp(F::FROBENIUS_CONSTANTS_3[k - 1]),
4 => F::Extension::W.exp(F::FROBENIUS_CONSTANTS_4[k - 1]),
_ => unimplemented!("Only extensions of degree 2, 3, or 4 are allowed for now."),
};
let zs = z0 let zs = z0
.powers() .powers()
.take(D) .take(D)

View File

@ -7,7 +7,7 @@ use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssi
use num::Integer; use num::Integer;
use rand::Rng; use rand::Rng;
use crate::field::extension_field::{Extendable, FieldExtension, Frobeniable, Frobenius, OEF}; use crate::field::extension_field::{Extendable, FieldExtension, Frobenius, OEF};
use crate::util::bits_u64; use crate::util::bits_u64;
/// A finite field with prime order less than 2^64. /// A finite field with prime order less than 2^64.
@ -287,9 +287,9 @@ impl<F: Field> Iterator for Powers<F> {
impl<F: Field> Powers<F> { impl<F: Field> Powers<F> {
/// Apply the Frobenius automorphism `k` times. /// Apply the Frobenius automorphism `k` times.
pub fn repeated_frobenius<BF: Frobeniable, const D: usize>(self, k: usize) -> Self pub fn repeated_frobenius<const D: usize>(self, k: usize) -> Self
where where
F: Frobenius<BF, D>, F: Frobenius<D>,
{ {
let Self { base, current } = self; let Self { base, current } = self;
Self { Self {

View File

@ -119,7 +119,7 @@ mod tests {
#[test] #[test]
fn test_rotate() { fn test_rotate() {
for len_log in 1..4 { for len_log in 1..3 {
test_rotate_given_len(len_log); test_rotate_given_len(len_log);
} }
} }