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::quartic::QuarticCrandallField;
use crate::field::extension_field::{Extendable, Frobeniable};
use crate::field::extension_field::{Extendable, Frobenius};
use crate::field::field::Field;
use std::hash::{Hash, Hasher};
use std::iter::{Product, Sum};
@ -444,16 +444,7 @@ fn split(x: u128) -> (u64, u64) {
(x as u64, (x >> 64) as u64)
}
impl Frobeniable 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,
];
}
impl Frobenius<1> for CrandallField {}
#[cfg(test)]
mod tests {

View File

@ -19,59 +19,36 @@ impl<F: Field> OEF<1> for F {
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.
fn frobenius(&self) -> Self {
self.repeated_frobenius(1)
}
/// Repeated Frobenius automorphisms: x -> x^(p^k).
fn repeated_frobenius(&self, k: usize) -> Self {
if k == 0 {
fn repeated_frobenius(&self, count: usize) -> Self {
if count == 0 {
return *self;
} else if k >= D {
return self.repeated_frobenius(k % D);
} else if count >= D {
return self.repeated_frobenius(count % D);
}
let arr = self.to_basefield_array();
let z0 = match D {
2 => Self::W.exp(BF::FROBENIUS_CONSTANTS_2[k - 1]),
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 k = (Self::BaseField::ORDER - 1) / (D as u64);
let z0 = Self::W.exp(k * count as u64);
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;
z *= z0;
}
Self::from_basefield_array(res)
}
}
impl<F: Frobeniable> Frobenius<F, 1> for F {
fn frobenius(&self) -> Self {
*self
}
fn repeated_frobenius(&self, _k: usize) -> Self {
*self
}
pub trait Extendable<const D: usize>: Field + Sized {
type Extension: Field + OEF<D, BaseField = Self> + Frobenius<D> + From<Self>;
}
/// Trait to hardcode constants used in the Frobenius automorphism.
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 {
impl<F: Frobenius<1> + FieldExtension<1, BaseField = F>> Extendable<1> for F {
type Extension = F;
}

View File

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

View File

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

View File

@ -34,16 +34,17 @@ impl<const D: usize> ExtensionTarget<D> {
pub fn repeated_frobenius<F: Extendable<D>>(
&self,
k: usize,
count: usize,
builder: &mut CircuitBuilder<F, D>,
) -> Self {
if count == 0 {
return *self;
} else if count >= D {
return self.repeated_frobenius(count % D, builder);
}
let arr = self.to_target_array();
let z0 = match D {
2 => F::Extension::W.exp(F::FROBENIUS_CONSTANTS_2[k - 1]),
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 k = (F::ORDER - 1) / (D as u64);
let z0 = F::W.exp(k * count as u64);
let zs = z0
.powers()
.take(D)

View File

@ -7,7 +7,7 @@ use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssi
use num::Integer;
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;
/// 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> {
/// 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
F: Frobenius<BF, D>,
F: Frobenius<D>,
{
let Self { base, current } = self;
Self {

View File

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