mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-02 13:53:07 +00:00
moved sqrt to PrimeField
This commit is contained in:
parent
a053372176
commit
33d97eff1c
@ -280,61 +280,6 @@ impl DivAssign for GoldilocksField {
|
||||
}
|
||||
}
|
||||
|
||||
impl GoldilocksField {
|
||||
pub fn is_quadratic_residue(&self) -> bool {
|
||||
if self.is_zero() {
|
||||
return true;
|
||||
}
|
||||
// This is based on Euler's criterion.
|
||||
let power = Self::NEG_ONE.to_canonical_biguint() / 2u8;
|
||||
let exp = self.exp_biguint(&power);
|
||||
if exp == Self::ONE {
|
||||
return true;
|
||||
}
|
||||
if exp == Self::NEG_ONE {
|
||||
return false;
|
||||
}
|
||||
panic!("Unreachable")
|
||||
}
|
||||
|
||||
pub fn sqrt(&self) -> Option<Self> {
|
||||
if self.is_zero() {
|
||||
Some(*self)
|
||||
} else if self.is_quadratic_residue() {
|
||||
let t = (Self::order() - BigUint::from(1u32))
|
||||
/ (BigUint::from(2u32).pow(Self::TWO_ADICITY as u32));
|
||||
let mut z = Self::POWER_OF_TWO_GENERATOR;
|
||||
let mut w = self.exp_biguint(&((t - BigUint::from(1u32)) / BigUint::from(2u32)));
|
||||
let mut x = w * *self;
|
||||
let mut b = x * w;
|
||||
|
||||
let mut v = Self::TWO_ADICITY as usize;
|
||||
|
||||
while !b.is_one() {
|
||||
let mut k = 0usize;
|
||||
let mut b2k = b;
|
||||
while !b2k.is_one() {
|
||||
b2k = b2k * b2k;
|
||||
k += 1;
|
||||
}
|
||||
let j = v - k - 1;
|
||||
w = z;
|
||||
for _ in 0..j {
|
||||
w = w * w;
|
||||
}
|
||||
|
||||
z = w * w;
|
||||
b *= z;
|
||||
x *= w;
|
||||
v = k;
|
||||
}
|
||||
Some(x)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Fast addition modulo ORDER for x86-64.
|
||||
/// This function is marked unsafe for the following reasons:
|
||||
/// - It is only correct if x + y < 2**64 + ORDER = 0x1ffffffff00000001.
|
||||
|
||||
@ -427,6 +427,59 @@ pub trait Field:
|
||||
|
||||
pub trait PrimeField: Field {
|
||||
fn to_canonical_biguint(&self) -> BigUint;
|
||||
|
||||
fn is_quadratic_residue(&self) -> bool {
|
||||
if self.is_zero() {
|
||||
return true;
|
||||
}
|
||||
// This is based on Euler's criterion.
|
||||
let power = Self::NEG_ONE.to_canonical_biguint() / 2u8;
|
||||
let exp = self.exp_biguint(&power);
|
||||
if exp == Self::ONE {
|
||||
return true;
|
||||
}
|
||||
if exp == Self::NEG_ONE {
|
||||
return false;
|
||||
}
|
||||
panic!("Unreachable")
|
||||
}
|
||||
|
||||
fn sqrt(&self) -> Option<Self> {
|
||||
if self.is_zero() {
|
||||
Some(*self)
|
||||
} else if self.is_quadratic_residue() {
|
||||
let t = (Self::order() - BigUint::from(1u32))
|
||||
/ (BigUint::from(2u32).pow(Self::TWO_ADICITY as u32));
|
||||
let mut z = Self::POWER_OF_TWO_GENERATOR;
|
||||
let mut w = self.exp_biguint(&((t - BigUint::from(1u32)) / BigUint::from(2u32)));
|
||||
let mut x = w * *self;
|
||||
let mut b = x * w;
|
||||
|
||||
let mut v = Self::TWO_ADICITY as usize;
|
||||
|
||||
while !b.is_one() {
|
||||
let mut k = 0usize;
|
||||
let mut b2k = b;
|
||||
while !b2k.is_one() {
|
||||
b2k = b2k * b2k;
|
||||
k += 1;
|
||||
}
|
||||
let j = v - k - 1;
|
||||
w = z;
|
||||
for _ in 0..j {
|
||||
w = w * w;
|
||||
}
|
||||
|
||||
z = w * w;
|
||||
b *= z;
|
||||
x *= w;
|
||||
v = k;
|
||||
}
|
||||
Some(x)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A finite field of order less than 2^64.
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use anyhow::Result;
|
||||
use plonky2::field::types::Field;
|
||||
use plonky2::field::types::{Field, PrimeField};
|
||||
use plonky2::hash::hash_types::RichField;
|
||||
use plonky2::iop::generator::{GeneratedValues, SimpleGenerator};
|
||||
use plonky2::iop::target::Target;
|
||||
@ -10,7 +10,6 @@ use plonky2::plonk::circuit_builder::CircuitBuilder;
|
||||
use plonky2::plonk::circuit_data::CircuitConfig;
|
||||
use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
|
||||
use plonky2_field::extension::Extendable;
|
||||
use plonky2_field::goldilocks_field::GoldilocksField;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct SquareRootGenerator<F: RichField + Extendable<D>, const D: usize> {
|
||||
@ -19,18 +18,14 @@ struct SquareRootGenerator<F: RichField + Extendable<D>, const D: usize> {
|
||||
_phantom: PhantomData<F>,
|
||||
}
|
||||
|
||||
// We implement specifically for the Goldilocks field because it's currently the only field with
|
||||
// the sqrt() function written.
|
||||
impl SimpleGenerator<GoldilocksField> for SquareRootGenerator<GoldilocksField, 2> {
|
||||
impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
|
||||
for SquareRootGenerator<F, D>
|
||||
{
|
||||
fn dependencies(&self) -> Vec<Target> {
|
||||
vec![self.x_squared]
|
||||
}
|
||||
|
||||
fn run_once(
|
||||
&self,
|
||||
witness: &PartitionWitness<GoldilocksField>,
|
||||
out_buffer: &mut GeneratedValues<GoldilocksField>,
|
||||
) {
|
||||
fn run_once(&self, witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>) {
|
||||
let x_squared = witness.get_target(self.x_squared);
|
||||
let x = x_squared.sqrt().unwrap();
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user