mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-05-24 02:39:25 +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::quadratic::QuadraticCrandallField;
|
||||||
use crate::field::extension_field::quartic::QuarticCrandallField;
|
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 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,6 +444,17 @@ fn split(x: u128) -> (u64, u64) {
|
|||||||
(x as u64, (x >> 64) as 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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::test_arithmetic;
|
use crate::test_arithmetic;
|
||||||
|
|||||||
@ -13,12 +13,32 @@ pub mod target;
|
|||||||
pub trait OEF<const D: usize>: FieldExtension<D> {
|
pub trait OEF<const D: usize>: FieldExtension<D> {
|
||||||
// Element W of BaseField, such that `X^d - W` is irreducible over BaseField.
|
// Element W of BaseField, such that `X^d - W` is irreducible over BaseField.
|
||||||
const W: Self::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 {
|
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 arr = self.to_basefield_array();
|
||||||
let k = (Self::BaseField::ORDER - 1) / (D as u64);
|
let z0 = match D {
|
||||||
let z0 = Self::W.exp(k);
|
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 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 in 0..D {
|
||||||
@ -28,25 +48,30 @@ pub trait OEF<const D: usize>: FieldExtension<D> {
|
|||||||
|
|
||||||
Self::from_basefield_array(res)
|
Self::from_basefield_array(res)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Repeated Frobenius automorphisms: x -> x^(p^k).
|
impl<F: Frobeniable> Frobenius<F, 1> for F {
|
||||||
// TODO: Implement this. Is basically the same as `frobenius` above, but using
|
fn frobenius(&self) -> Self {
|
||||||
// `z = W^floor(j*p^k/D)`. I'm not sure there is a closed form for these so
|
*self
|
||||||
// might require to hardcode them.
|
}
|
||||||
fn repeated_frobenius(&self, k: usize) -> Self {
|
fn repeated_frobenius(&self, _k: usize) -> Self {
|
||||||
todo!()
|
*self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F: Field> OEF<1> for F {
|
/// Trait to hardcode constants used in the Frobenius automorphism.
|
||||||
const W: Self::BaseField = F::ZERO;
|
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 {
|
pub trait Extendable<const D: usize>: Frobeniable + Sized {
|
||||||
type Extension: Field + OEF<D, BaseField = Self> + From<Self>;
|
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;
|
type Extension = F;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
use crate::field::crandall_field::CrandallField;
|
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 crate::field::field::Field;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use std::fmt::{Debug, Display, Formatter};
|
use std::fmt::{Debug, Display, Formatter};
|
||||||
@ -16,6 +16,8 @@ impl OEF<2> for QuadraticCrandallField {
|
|||||||
const W: CrandallField = CrandallField(3);
|
const W: CrandallField = CrandallField(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Frobenius<CrandallField, 2> for QuadraticCrandallField {}
|
||||||
|
|
||||||
impl FieldExtension<2> for QuadraticCrandallField {
|
impl FieldExtension<2> for QuadraticCrandallField {
|
||||||
type BaseField = CrandallField;
|
type BaseField = CrandallField;
|
||||||
|
|
||||||
@ -63,7 +65,7 @@ impl Field for QuadraticCrandallField {
|
|||||||
return None;
|
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;
|
let a_pow_r = a_pow_r_minus_1 * *self;
|
||||||
debug_assert!(FieldExtension::<2>::is_in_basefield(&a_pow_r));
|
debug_assert!(FieldExtension::<2>::is_in_basefield(&a_pow_r));
|
||||||
|
|
||||||
@ -190,7 +192,7 @@ impl DivAssign for QuadraticCrandallField {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::field::extension_field::quadratic::QuadraticCrandallField;
|
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;
|
use crate::field::field::Field;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -231,7 +233,7 @@ mod tests {
|
|||||||
let x = F::rand();
|
let x = F::rand();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
x.exp(<F as FieldExtension<2>>::BaseField::ORDER),
|
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 rand::Rng;
|
||||||
|
|
||||||
use crate::field::crandall_field::CrandallField;
|
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 crate::field::field::Field;
|
||||||
|
|
||||||
/// A quartic extension of `CrandallField`.
|
/// A quartic extension of `CrandallField`.
|
||||||
@ -20,6 +20,8 @@ impl OEF<4> for QuarticCrandallField {
|
|||||||
const W: CrandallField = CrandallField(3);
|
const W: CrandallField = CrandallField(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Frobenius<CrandallField, 4> for QuarticCrandallField {}
|
||||||
|
|
||||||
impl FieldExtension<4> for QuarticCrandallField {
|
impl FieldExtension<4> for QuarticCrandallField {
|
||||||
type BaseField = CrandallField;
|
type BaseField = CrandallField;
|
||||||
|
|
||||||
@ -93,9 +95,9 @@ impl Field for QuarticCrandallField {
|
|||||||
return None;
|
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_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_minus_1 = a_pow_p3_plus_p2 * a_pow_p;
|
||||||
let a_pow_r = a_pow_r_minus_1 * *self;
|
let a_pow_r = a_pow_r_minus_1 * *self;
|
||||||
debug_assert!(FieldExtension::<4>::is_in_basefield(&a_pow_r));
|
debug_assert!(FieldExtension::<4>::is_in_basefield(&a_pow_r));
|
||||||
@ -241,7 +243,7 @@ impl DivAssign for QuarticCrandallField {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::field::extension_field::quartic::QuarticCrandallField;
|
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;
|
use crate::field::field::Field;
|
||||||
|
|
||||||
fn exp_naive<F: Field>(x: F, power: u128) -> F {
|
fn exp_naive<F: Field>(x: F, power: u128) -> F {
|
||||||
@ -295,7 +297,12 @@ mod tests {
|
|||||||
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<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 num::Integer;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
|
||||||
use crate::field::extension_field::OEF;
|
use crate::field::extension_field::{Extendable, FieldExtension, Frobeniable, 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,15 +287,14 @@ 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.
|
||||||
// TODO: Use `OEF::repeated_frobenius` when it is implemented.
|
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: OEF<D>,
|
F: Frobenius<BF, D>,
|
||||||
{
|
{
|
||||||
let Self { base, current } = self;
|
let Self { base, current } = self;
|
||||||
Self {
|
Self {
|
||||||
base: (0..k).fold(base, |acc, _| acc.frobenius()),
|
base: base.repeated_frobenius(k),
|
||||||
current: (0..k).fold(current, |acc, _| acc.frobenius()),
|
current: base.repeated_frobenius(k),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
use anyhow::{ensure, Result};
|
use anyhow::{ensure, Result};
|
||||||
use itertools::izip;
|
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::field::Field;
|
||||||
use crate::field::lagrange::{barycentric_weights, interpolant, interpolate};
|
use crate::field::lagrange::{barycentric_weights, interpolant, interpolate};
|
||||||
use crate::fri::FriConfig;
|
use crate::fri::FriConfig;
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
|
|
||||||
use crate::field::extension_field::FieldExtension;
|
|
||||||
use crate::field::extension_field::{Extendable, OEF};
|
use crate::field::extension_field::{Extendable, OEF};
|
||||||
|
use crate::field::extension_field::{FieldExtension, Frobenius};
|
||||||
use crate::field::field::Field;
|
use crate::field::field::Field;
|
||||||
use crate::field::lagrange::interpolant;
|
use crate::field::lagrange::interpolant;
|
||||||
use crate::fri::{prover::fri_proof, verifier::verify_fri_proof, FriConfig};
|
use crate::fri::{prover::fri_proof, verifier::verify_fri_proof, FriConfig};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user