mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-07 16:23:12 +00:00
sqrt
This commit is contained in:
parent
bda96e84ee
commit
880bc87bb1
@ -280,6 +280,61 @@ 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.exp_biguint(&t);
|
||||||
|
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 = b * z;
|
||||||
|
x = x * w;
|
||||||
|
v = k;
|
||||||
|
}
|
||||||
|
Some(x)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/// Fast addition modulo ORDER for x86-64.
|
/// Fast addition modulo ORDER for x86-64.
|
||||||
/// This function is marked unsafe for the following reasons:
|
/// This function is marked unsafe for the following reasons:
|
||||||
/// - It is only correct if x + y < 2**64 + ORDER = 0x1ffffffff00000001.
|
/// - It is only correct if x + y < 2**64 + ORDER = 0x1ffffffff00000001.
|
||||||
|
|||||||
@ -10,6 +10,7 @@ use plonky2::plonk::circuit_builder::CircuitBuilder;
|
|||||||
use plonky2::plonk::circuit_data::CircuitConfig;
|
use plonky2::plonk::circuit_data::CircuitConfig;
|
||||||
use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
|
use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
|
||||||
use plonky2_field::extension::Extendable;
|
use plonky2_field::extension::Extendable;
|
||||||
|
use plonky2_field::goldilocks_field::GoldilocksField;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct SquareRootGenerator<F: RichField + Extendable<D>, const D: usize> {
|
struct SquareRootGenerator<F: RichField + Extendable<D>, const D: usize> {
|
||||||
@ -18,15 +19,14 @@ struct SquareRootGenerator<F: RichField + Extendable<D>, const D: usize> {
|
|||||||
_phantom: PhantomData<F>,
|
_phantom: PhantomData<F>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F> for SquareRootGenerator<F, D> {
|
impl SimpleGenerator<GoldilocksField> for SquareRootGenerator<GoldilocksField, 2> {
|
||||||
fn dependencies(&self) -> Vec<Target> {
|
fn dependencies(&self) -> Vec<Target> {
|
||||||
vec![self.x_squared]
|
vec![self.x_squared]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_once(&self, witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>) {
|
fn run_once(&self, witness: &PartitionWitness<GoldilocksField>, out_buffer: &mut GeneratedValues<GoldilocksField>) {
|
||||||
let x_squared = witness.get_target(self.x);
|
let x_squared = witness.get_target(self.x_squared);
|
||||||
let s = F::from_canonical_u32(4294967295);
|
let x = x_squared.sqrt().unwrap();
|
||||||
let x =
|
|
||||||
|
|
||||||
out_buffer.set_target(self.x, x);
|
out_buffer.set_target(self.x, x);
|
||||||
}
|
}
|
||||||
@ -48,16 +48,22 @@ fn main() -> Result<()> {
|
|||||||
builder.register_public_input(x);
|
builder.register_public_input(x);
|
||||||
builder.register_public_input(x_squared);
|
builder.register_public_input(x_squared);
|
||||||
|
|
||||||
// builder.add_simple_generator(SquareGenerator::<F, D> {
|
builder.add_simple_generator(SquareRootGenerator::<F, D> {
|
||||||
// x,
|
x,
|
||||||
// x_squared,
|
x_squared,
|
||||||
// _phantom: PhantomData,
|
_phantom: PhantomData,
|
||||||
// });
|
});
|
||||||
|
|
||||||
let x_value = F::rand();
|
let x_squared_value = {
|
||||||
|
let mut val = F::rand();
|
||||||
|
while !val.is_quadratic_residue() {
|
||||||
|
val = F::rand();
|
||||||
|
}
|
||||||
|
val
|
||||||
|
};
|
||||||
|
|
||||||
let mut pw = PartialWitness::new();
|
let mut pw = PartialWitness::new();
|
||||||
pw.set_target(x, x_value);
|
pw.set_target(x_squared, x_squared_value);
|
||||||
|
|
||||||
let data = builder.build::<C>();
|
let data = builder.build::<C>();
|
||||||
let proof = data.prove(pw)?;
|
let proof = data.prove(pw)?;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user