mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-04 23:03:08 +00:00
Implement out-of-circuit repeated_frobenius using hardcoded constants
This commit is contained in:
parent
1ebeab2c3a
commit
20741cfb4a
@ -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;
|
||||
use crate::field::extension_field::{Extendable, Frobeniable};
|
||||
use crate::field::field::Field;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::iter::{Product, Sum};
|
||||
@ -444,6 +444,17 @@ 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,
|
||||
];
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::test_arithmetic;
|
||||
|
||||
@ -13,12 +13,32 @@ pub mod target;
|
||||
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.
|
||||
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> {
|
||||
/// 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 {
|
||||
return *self;
|
||||
} else if k >= D {
|
||||
return self.repeated_frobenius(k % D);
|
||||
}
|
||||
let arr = self.to_basefield_array();
|
||||
let k = (Self::BaseField::ORDER - 1) / (D as u64);
|
||||
let z0 = Self::W.exp(k);
|
||||
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 mut res = [Self::BaseField::ZERO; D];
|
||||
for i in 0..D {
|
||||
@ -28,25 +48,30 @@ pub trait OEF<const D: usize>: FieldExtension<D> {
|
||||
|
||||
Self::from_basefield_array(res)
|
||||
}
|
||||
}
|
||||
|
||||
/// Repeated Frobenius automorphisms: x -> x^(p^k).
|
||||
// TODO: Implement this. Is basically the same as `frobenius` above, but using
|
||||
// `z = W^floor(j*p^k/D)`. I'm not sure there is a closed form for these so
|
||||
// might require to hardcode them.
|
||||
fn repeated_frobenius(&self, k: usize) -> Self {
|
||||
todo!()
|
||||
impl<F: Frobeniable> Frobenius<F, 1> for F {
|
||||
fn frobenius(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
fn repeated_frobenius(&self, _k: usize) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Field> OEF<1> for F {
|
||||
const W: Self::BaseField = F::ZERO;
|
||||
/// 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>: Field + Sized {
|
||||
type Extension: Field + OEF<D, BaseField = Self> + From<Self>;
|
||||
pub trait Extendable<const D: usize>: Frobeniable + Sized {
|
||||
type Extension: Field + OEF<D, BaseField = Self> + Frobenius<Self, D> + From<Self>;
|
||||
}
|
||||
|
||||
impl<F: Field> Extendable<1> for F {
|
||||
impl<F: Frobeniable + Frobenius<F, 1>> Extendable<1> for F {
|
||||
type Extension = F;
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
use crate::field::crandall_field::CrandallField;
|
||||
use crate::field::extension_field::{FieldExtension, OEF};
|
||||
use crate::field::extension_field::{FieldExtension, Frobenius, OEF};
|
||||
use crate::field::field::Field;
|
||||
use rand::Rng;
|
||||
use std::fmt::{Debug, Display, Formatter};
|
||||
@ -16,6 +16,8 @@ impl OEF<2> for QuadraticCrandallField {
|
||||
const W: CrandallField = CrandallField(3);
|
||||
}
|
||||
|
||||
impl Frobenius<CrandallField, 2> for QuadraticCrandallField {}
|
||||
|
||||
impl FieldExtension<2> for QuadraticCrandallField {
|
||||
type BaseField = CrandallField;
|
||||
|
||||
@ -63,7 +65,7 @@ impl Field for QuadraticCrandallField {
|
||||
return None;
|
||||
}
|
||||
|
||||
let a_pow_r_minus_1 = OEF::<2>::frobenius(self);
|
||||
let a_pow_r_minus_1 = self.frobenius();
|
||||
let a_pow_r = a_pow_r_minus_1 * *self;
|
||||
debug_assert!(FieldExtension::<2>::is_in_basefield(&a_pow_r));
|
||||
|
||||
@ -190,7 +192,7 @@ impl DivAssign for QuadraticCrandallField {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::field::extension_field::quadratic::QuadraticCrandallField;
|
||||
use crate::field::extension_field::{FieldExtension, OEF};
|
||||
use crate::field::extension_field::{FieldExtension, Frobenius, OEF};
|
||||
use crate::field::field::Field;
|
||||
|
||||
#[test]
|
||||
@ -231,7 +233,7 @@ mod tests {
|
||||
let x = F::rand();
|
||||
assert_eq!(
|
||||
x.exp(<F as FieldExtension<2>>::BaseField::ORDER),
|
||||
OEF::<2>::frobenius(&x)
|
||||
x.frobenius()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@ use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssi
|
||||
use rand::Rng;
|
||||
|
||||
use crate::field::crandall_field::CrandallField;
|
||||
use crate::field::extension_field::{FieldExtension, OEF};
|
||||
use crate::field::extension_field::{FieldExtension, Frobenius, OEF};
|
||||
use crate::field::field::Field;
|
||||
|
||||
/// A quartic extension of `CrandallField`.
|
||||
@ -20,6 +20,8 @@ impl OEF<4> for QuarticCrandallField {
|
||||
const W: CrandallField = CrandallField(3);
|
||||
}
|
||||
|
||||
impl Frobenius<CrandallField, 4> for QuarticCrandallField {}
|
||||
|
||||
impl FieldExtension<4> for QuarticCrandallField {
|
||||
type BaseField = CrandallField;
|
||||
|
||||
@ -93,9 +95,9 @@ impl Field for QuarticCrandallField {
|
||||
return None;
|
||||
}
|
||||
|
||||
let a_pow_p = OEF::<4>::frobenius(self);
|
||||
let a_pow_p = self.frobenius();
|
||||
let a_pow_p_plus_1 = a_pow_p * *self;
|
||||
let a_pow_p3_plus_p2 = OEF::<4>::frobenius(&OEF::<4>::frobenius(&a_pow_p_plus_1));
|
||||
let a_pow_p3_plus_p2 = a_pow_p_plus_1.repeated_frobenius(2);
|
||||
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!(FieldExtension::<4>::is_in_basefield(&a_pow_r));
|
||||
@ -241,7 +243,7 @@ impl DivAssign for QuarticCrandallField {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::field::extension_field::quartic::QuarticCrandallField;
|
||||
use crate::field::extension_field::{FieldExtension, OEF};
|
||||
use crate::field::extension_field::{FieldExtension, Frobenius, OEF};
|
||||
use crate::field::field::Field;
|
||||
|
||||
fn exp_naive<F: Field>(x: F, power: u128) -> F {
|
||||
@ -295,7 +297,12 @@ mod tests {
|
||||
let x = F::rand();
|
||||
assert_eq!(
|
||||
exp_naive(x, <F as FieldExtension<4>>::BaseField::ORDER as u128),
|
||||
OEF::<4>::frobenius(&x)
|
||||
x.frobenius()
|
||||
);
|
||||
assert_eq!(x.repeated_frobenius(2), x.frobenius().frobenius());
|
||||
assert_eq!(
|
||||
x.repeated_frobenius(3),
|
||||
x.frobenius().frobenius().frobenius()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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::OEF;
|
||||
use crate::field::extension_field::{Extendable, FieldExtension, Frobeniable, Frobenius, OEF};
|
||||
use crate::util::bits_u64;
|
||||
|
||||
/// A finite field with prime order less than 2^64.
|
||||
@ -287,15 +287,14 @@ impl<F: Field> Iterator for Powers<F> {
|
||||
|
||||
impl<F: Field> Powers<F> {
|
||||
/// Apply the Frobenius automorphism `k` times.
|
||||
// TODO: Use `OEF::repeated_frobenius` when it is implemented.
|
||||
pub fn repeated_frobenius<const D: usize>(self, k: usize) -> Self
|
||||
pub fn repeated_frobenius<BF: Frobeniable, const D: usize>(self, k: usize) -> Self
|
||||
where
|
||||
F: OEF<D>,
|
||||
F: Frobenius<BF, D>,
|
||||
{
|
||||
let Self { base, current } = self;
|
||||
Self {
|
||||
base: (0..k).fold(base, |acc, _| acc.frobenius()),
|
||||
current: (0..k).fold(current, |acc, _| acc.frobenius()),
|
||||
base: base.repeated_frobenius(k),
|
||||
current: base.repeated_frobenius(k),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
use anyhow::{ensure, Result};
|
||||
use itertools::izip;
|
||||
|
||||
use crate::field::extension_field::{flatten, Extendable, FieldExtension, OEF};
|
||||
use crate::field::extension_field::{flatten, Extendable, FieldExtension, Frobenius, OEF};
|
||||
use crate::field::field::Field;
|
||||
use crate::field::lagrange::{barycentric_weights, interpolant, interpolate};
|
||||
use crate::fri::FriConfig;
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
use anyhow::Result;
|
||||
use rayon::prelude::*;
|
||||
|
||||
use crate::field::extension_field::FieldExtension;
|
||||
use crate::field::extension_field::{Extendable, OEF};
|
||||
use crate::field::extension_field::{FieldExtension, Frobenius};
|
||||
use crate::field::field::Field;
|
||||
use crate::field::lagrange::interpolant;
|
||||
use crate::fri::{prover::fri_proof, verifier::verify_fri_proof, FriConfig};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user