mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-07 00:03:10 +00:00
some more BigUint arithmetic
This commit is contained in:
parent
9077c7fa3c
commit
b567cf9baf
@ -5,7 +5,7 @@ use crate::gates::subtraction_u32::U32SubtractionGate;
|
||||
use crate::iop::target::Target;
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct U32Target(pub Target);
|
||||
|
||||
impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
@ -28,6 +28,14 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
U32Target(self.one())
|
||||
}
|
||||
|
||||
pub fn connect_u32(&mut self, x: U32Target, y: U32Target) {
|
||||
self.connect(x.0, y.0)
|
||||
}
|
||||
|
||||
pub fn assert_zero_u32(&self, x: U32Target) {
|
||||
self.assert_zero(x.0)
|
||||
}
|
||||
|
||||
// Returns x * y + z.
|
||||
pub fn mul_add_u32(
|
||||
&mut self,
|
||||
|
||||
@ -1,17 +1,81 @@
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::Neg;
|
||||
|
||||
use num::BigUint;
|
||||
|
||||
use crate::field::field_types::RichField;
|
||||
use crate::field::{extension_field::Extendable, field_types::Field};
|
||||
use crate::gadgets::arithmetic_u32::U32Target;
|
||||
use crate::iop::generator::{GeneratedValues, SimpleGenerator};
|
||||
use crate::iop::target::{BoolTarget, Target};
|
||||
use crate::iop::witness::PartitionWitness;
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct BigUintTarget {
|
||||
limbs: Vec<U32Target>,
|
||||
pub limbs: Vec<U32Target>,
|
||||
}
|
||||
|
||||
impl BigUintTarget {
|
||||
pub fn num_limbs(&self) -> usize {
|
||||
self.limbs.len()
|
||||
}
|
||||
|
||||
pub fn get_limb(&self, i: usize) -> U32Target {
|
||||
self.limbs[i]
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
fn connect_biguint(&self, lhs: BigUintTarget, rhs: BigUintTarget) {
|
||||
let min_limbs = lhs.num_limbs().min(rhs.num_limbs());
|
||||
for i in 0..min_limbs {
|
||||
self.connect_u32(lhs.get_limb(i), rhs.get_limb(i));
|
||||
}
|
||||
|
||||
for i in min_limbs..lhs.num_limbs() {
|
||||
self.assert_zero_u32(lhs.get_limb(i));
|
||||
}
|
||||
for i in min_limbs..rhs.num_limbs() {
|
||||
self.assert_zero_u32(rhs.get_limb(i));
|
||||
}
|
||||
}
|
||||
|
||||
fn pad_biguints(&mut self, a: BigUintTarget, b: BigUintTarget) -> (BigUintTarget, BigUintTarget) {
|
||||
if a.num_limbs() > b.num_limbs() {
|
||||
let mut padded_b_limbs = b.limbs.clone();
|
||||
padded_b_limbs.extend(self.add_virtual_u32_targets(a.num_limbs() - b.num_limbs()));
|
||||
let padded_b = BigUintTarget {
|
||||
limbs: padded_b_limbs,
|
||||
};
|
||||
(a, padded_b)
|
||||
} else {
|
||||
let mut padded_a_limbs = a.limbs.clone();
|
||||
padded_a_limbs.extend(self.add_virtual_u32_targets(b.num_limbs() - a.num_limbs()));
|
||||
let padded_a = BigUintTarget {
|
||||
limbs: padded_a_limbs,
|
||||
};
|
||||
(padded_a, b)
|
||||
}
|
||||
}
|
||||
|
||||
fn cmp_biguint(&mut self, a: BigUintTarget, b: BigUintTarget) -> BoolTarget {
|
||||
let (padded_a, padded_b) = self.pad_biguints(a, b);
|
||||
|
||||
let a_vec = a.limbs.iter().map(|&x| x.0).collect();
|
||||
let b_vec = b.limbs.iter().map(|&x| x.0).collect();
|
||||
|
||||
self.list_le(a_vec, b_vec, 32)
|
||||
}
|
||||
|
||||
fn add_virtual_biguint_target(&mut self, num_limbs: usize) -> BigUintTarget {
|
||||
let limbs = (0..num_limbs).map(|_| self.add_virtual_u32_target()).collect();
|
||||
|
||||
BigUintTarget {
|
||||
limbs,
|
||||
}
|
||||
}
|
||||
|
||||
// Add two `BigUintTarget`s.
|
||||
pub fn add_biguint(&mut self, a: BigUintTarget, b: BigUintTarget) -> BigUintTarget {
|
||||
let num_limbs = a.limbs.len();
|
||||
@ -79,4 +143,49 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
limbs: combined_limbs,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn div_rem_biguint(&mut self, a: BigUintTarget, b: BigUintTarget) -> (BigUintTarget, BigUintTarget) {
|
||||
let num_limbs = a.limbs.len();
|
||||
let div = self.add_virtual_biguint_target(num_limbs);
|
||||
let rem = self.add_virtual_biguint_target(num_limbs);
|
||||
|
||||
self.add_simple_generator(BigUintDivRemGenerator::<F, D> {
|
||||
a: a.clone(),
|
||||
b: b.clone(),
|
||||
div: div.clone(),
|
||||
rem: rem.clone(),
|
||||
_phantom: PhantomData,
|
||||
});
|
||||
|
||||
let div_b = self.mul_biguint(div, b);
|
||||
let div_b_plus_rem = self.add_biguint(div_b, rem);
|
||||
self.connect_biguint(x, div_b_plus_rem);
|
||||
|
||||
let
|
||||
|
||||
self.assert_one()
|
||||
|
||||
(div, rem)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct BigUintDivRemGenerator<F: RichField + Extendable<D>, const D: usize> {
|
||||
a: BigUintTarget,
|
||||
b: BigUintTarget,
|
||||
div: BigUintTarget,
|
||||
rem: BigUintTarget,
|
||||
_phantom: PhantomData<F>,
|
||||
}
|
||||
|
||||
impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
|
||||
for BigUintDivRemGenerator<F, D>
|
||||
{
|
||||
fn dependencies(&self) -> Vec<Target> {
|
||||
self.a.limbs.iter().map(|&l| l.0).chain(self.b.limbs.iter().map(|&l| l.0)).collect()
|
||||
}
|
||||
|
||||
fn run_once(&self, witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>) {
|
||||
|
||||
}
|
||||
}
|
||||
@ -11,7 +11,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
assert_eq!(
|
||||
a.len(),
|
||||
b.len(),
|
||||
"Permutation must have same number of inputs and outputs"
|
||||
"Comparison must be between same number of inputs and outputs"
|
||||
);
|
||||
let n = a.len();
|
||||
|
||||
|
||||
@ -1,21 +1,12 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use num::bigint::BigUint;
|
||||
|
||||
use crate::field::field_types::RichField;
|
||||
use crate::field::{extension_field::Extendable, field_types::Field};
|
||||
use crate::gadgets::arithmetic_u32::U32Target;
|
||||
use crate::gates::arithmetic_u32::U32ArithmeticGate;
|
||||
use crate::gates::switch::SwitchGate;
|
||||
use crate::iop::generator::{GeneratedValues, SimpleGenerator};
|
||||
use crate::iop::target::Target;
|
||||
use crate::iop::witness::{PartitionWitness, Witness};
|
||||
use crate::plonk::circuit_builder::CircuitBuilder;
|
||||
use crate::util::bimap::bimap_from_lists;
|
||||
|
||||
pub struct ForeignFieldTarget<FF: Field> {
|
||||
/// These F elements are assumed to contain 32-bit values.
|
||||
limbs: Vec<U32Target>,
|
||||
_phantom: PhantomData<FF>,
|
||||
}
|
||||
@ -30,6 +21,16 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn power_of_2_mod_order<FF: Field>(&mut self, i: usize) -> Vec<U32Target> {
|
||||
|
||||
}
|
||||
|
||||
pub fn powers_of_2_mod_order<FF: Field>(&mut self, max: usize) -> Vec<Vec<U32Target>> {
|
||||
for i in 0..max {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Add two `ForeignFieldTarget`s.
|
||||
pub fn add_nonnative<FF: Field>(
|
||||
&mut self,
|
||||
@ -63,7 +64,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
let mut modulus_limbs = self.order_u32_limbs::<FF>();
|
||||
modulus_limbs.append(self.zero_u32());
|
||||
|
||||
let needs_reduce = self.list_le(modulus, limbs);
|
||||
let needs_reduce = self.list_le(modulus_limbs, limbs);
|
||||
|
||||
let mut to_subtract = vec![];
|
||||
for i in 0..num_limbs {
|
||||
@ -98,7 +99,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
let mut borrow = self.zero_u32();
|
||||
for i in 0..num_limbs {
|
||||
let (result, new_borrow) = self.sub_u32(a.limbs[i], b.limbs[i], borrow);
|
||||
reduced_limbs[i] = result;
|
||||
result_limbs[i] = result;
|
||||
borrow = new_borrow;
|
||||
}
|
||||
// Borrow should be zero here.
|
||||
@ -147,6 +148,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
}
|
||||
|
||||
pub fn reduce_mul_result<FF: Field>(&mut self, limbs: Vec<U32Target>) -> Vec<U32Target> {
|
||||
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,9 +1,13 @@
|
||||
use std::collections::HashMap;
|
||||
use std::convert::TryInto;
|
||||
|
||||
use num::BigUint;
|
||||
|
||||
use crate::field::extension_field::target::ExtensionTarget;
|
||||
use crate::field::extension_field::{Extendable, FieldExtension};
|
||||
use crate::field::field_types::Field;
|
||||
use crate::field::field_types::{Field, PrimeField};
|
||||
use crate::gadgets::arithmetic_u32::U32Target;
|
||||
use crate::gadgets::biguint::BigUintTarget;
|
||||
use crate::hash::hash_types::HashOutTarget;
|
||||
use crate::hash::hash_types::{HashOut, MerkleCapTarget};
|
||||
use crate::hash::merkle_tree::MerkleCap;
|
||||
@ -53,12 +57,24 @@ pub trait Witness<F: Field> {
|
||||
panic!("not a bool")
|
||||
}
|
||||
|
||||
fn get_u32_target(&self, target: U32Target) -> F {
|
||||
let result = self.get_target(target.0);
|
||||
debug_assert!(result.to_canonical_u64() < 1 << 32u64);
|
||||
result
|
||||
}
|
||||
|
||||
fn get_hash_target(&self, ht: HashOutTarget) -> HashOut<F> {
|
||||
HashOut {
|
||||
elements: self.get_targets(&ht.elements).try_into().unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_biguint_target(&self, target: BigUintTarget) -> BigUint {
|
||||
let mut result = BigUint::zero();
|
||||
for (i, &limb) in target
|
||||
result
|
||||
}
|
||||
|
||||
fn get_wire(&self, wire: Wire) -> F {
|
||||
self.get_target(Target::Wire(wire))
|
||||
}
|
||||
|
||||
@ -246,6 +246,11 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
self.connect(x, zero);
|
||||
}
|
||||
|
||||
pub fn assert_one(&mut self, x: Target) {
|
||||
let one = self.one();
|
||||
self.connect(x, one);
|
||||
}
|
||||
|
||||
pub fn add_generators(&mut self, generators: Vec<Box<dyn WitnessGenerator<F>>>) {
|
||||
self.generators.extend(generators);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user