This commit is contained in:
Nicholas Ward 2021-10-12 11:41:52 -07:00
parent 7e8c021b46
commit 0ff6e6e0a0
5 changed files with 44 additions and 35 deletions

View File

@ -1,7 +1,7 @@
use std::marker::PhantomData;
use crate::field::field_types::RichField;
use crate::field::extension_field::Extendable;
use crate::field::field_types::RichField;
use crate::gates::arithmetic_u32::{U32ArithmeticGate, NUM_U32_ARITHMETIC_OPS};
use crate::iop::target::Target;
use crate::plonk::circuit_builder::CircuitBuilder;

View File

@ -13,7 +13,7 @@ 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>,
@ -24,18 +24,26 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
pub fn order_u32_limbs<FF: Field>(&mut self) -> Vec<U32Target> {
let modulus = FF::order();
let limbs = modulus.to_u32_digits();
limbs.iter().map(|&limb| self.constant_u32(F::from_canonical_u32(limb))).collect()
limbs
.iter()
.map(|&limb| self.constant_u32(F::from_canonical_u32(limb)))
.collect()
}
// Add two `ForeignFieldTarget`s, which we assume are both normalized.
pub fn add_nonnative<FF: Field>(&mut self, a: ForeignFieldTarget<FF>, b: ForeignFieldTarget<FF>) -> ForeignFieldTarget<FF> {
pub fn add_nonnative<FF: Field>(
&mut self,
a: ForeignFieldTarget<FF>,
b: ForeignFieldTarget<FF>,
) -> ForeignFieldTarget<FF> {
let num_limbs = a.limbs.len();
debug_assert!(b.limbs.len() == num_limbs);
let mut combined_limbs = self.add_virtual_u32_targets(num_limbs + 1);
let mut carry = self.zero_u32();
for i in 0..num_limbs {
let (new_limb, carry) = self.add_three_u32(carry.clone(), a.limbs[i].clone(), b.limbs[i].clone());
let (new_limb, carry) =
self.add_three_u32(carry.clone(), a.limbs[i].clone(), b.limbs[i].clone());
combined_limbs[i] = new_limb;
}
combined_limbs[num_limbs] = carry;
@ -51,7 +59,11 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
todo!()
}
pub fn mul_nonnative<FF: Field>(&mut self, a: ForeignFieldTarget<FF>, b: ForeignFieldTarget<FF>) -> ForeignFieldTarget<FF> {
pub fn mul_nonnative<FF: Field>(
&mut self,
a: ForeignFieldTarget<FF>,
b: ForeignFieldTarget<FF>,
) -> ForeignFieldTarget<FF> {
let num_limbs = a.limbs.len();
debug_assert!(b.limbs.len() == num_limbs);

View File

@ -471,7 +471,9 @@ mod tests {
let num_bits = 40;
let num_chunks = 5;
test_low_degree::<CrandallField, _, 4>(AssertLessThanGate::<_, 4>::new(num_bits, num_chunks))
test_low_degree::<CrandallField, _, 4>(AssertLessThanGate::<_, 4>::new(
num_bits, num_chunks,
))
}
#[test]

View File

@ -149,11 +149,9 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for ComparisonGate
let most_significant_diff_bits: Vec<F::Extension> = (0..self.chunk_bits() + 1)
.map(|i| vars.local_wires[self.wire_most_significant_diff_bit(i)])
.collect();
let bits_combined = reduce_with_powers(
&most_significant_diff_bits,
F::Extension::TWO,
);
let two_n_minus_1 = F::Extension::from_canonical_u64(1 << self.chunk_bits()) - F::Extension::ONE;
let bits_combined = reduce_with_powers(&most_significant_diff_bits, F::Extension::TWO);
let two_n_minus_1 =
F::Extension::from_canonical_u64(1 << self.chunk_bits()) - F::Extension::ONE;
constraints.push((two_n_minus_1 + most_significant_diff) - bits_combined);
// Iff first < second, the top (n + 1st) bit of (2^n - 1 + most_significant_diff) will be 1.
@ -225,10 +223,7 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for ComparisonGate
let most_significant_diff_bits: Vec<F> = (0..self.chunk_bits() + 1)
.map(|i| vars.local_wires[self.wire_most_significant_diff_bit(i)])
.collect();
let bits_combined = reduce_with_powers(
&most_significant_diff_bits,
F::TWO,
);
let bits_combined = reduce_with_powers(&most_significant_diff_bits, F::TWO);
let two_n_minus_1 = F::from_canonical_u64(1 << self.chunk_bits()) - F::ONE;
constraints.push((two_n_minus_1 + most_significant_diff) - bits_combined);
@ -257,11 +252,11 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for ComparisonGate
.map(|i| vars.local_wires[self.wire_second_chunk_val(i)])
.collect();
let chunk_base = builder.constant(F::from_canonical_usize(1 << self.chunk_bits()));
let first_chunks_combined =
reduce_with_powers_ext_recursive(builder, &first_chunks, chunk_base);
let second_chunks_combined =
reduce_with_powers_ext_recursive(builder, &second_chunks, chunk_base);
let chunk_base = builder.constant(F::from_canonical_usize(1 << self.chunk_bits()));
let first_chunks_combined =
reduce_with_powers_ext_recursive(builder, &first_chunks, chunk_base);
let second_chunks_combined =
reduce_with_powers_ext_recursive(builder, &second_chunks, chunk_base);
constraints.push(builder.sub_extension(first_chunks_combined, first_input));
constraints.push(builder.sub_extension(second_chunks_combined, second_input));
@ -314,18 +309,19 @@ impl<F: RichField + Extendable<D>, const D: usize> Gate<F, D> for ComparisonGate
.map(|i| vars.local_wires[self.wire_most_significant_diff_bit(i)])
.collect();
let two = builder.two();
let bits_combined = reduce_with_powers_ext_recursive(
builder,
&most_significant_diff_bits,
two,
let bits_combined =
reduce_with_powers_ext_recursive(builder, &most_significant_diff_bits, two);
let two_n_minus_1 = builder.constant_extension(
F::Extension::from_canonical_u64(1 << self.chunk_bits()) - F::Extension::ONE,
);
let two_n_minus_1 = builder.constant_extension(F::Extension::from_canonical_u64(1 << self.chunk_bits()) - F::Extension::ONE);
let sum = builder.add_extension(two_n_minus_1, most_significant_diff);
constraints.push(builder.sub_extension(sum, bits_combined));
// Iff first < second, the top (n + 1st) bit of (2^n - 1 + most_significant_diff) will be 1.
let result_bool = vars.local_wires[self.wire_result_bool()];
constraints.push(builder.sub_extension(result_bool, most_significant_diff_bits[self.chunk_bits()]));
constraints.push(
builder.sub_extension(result_bool, most_significant_diff_bits[self.chunk_bits()]),
);
constraints
}
@ -430,7 +426,8 @@ impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
}
let most_significant_diff = most_significant_diff_so_far;
let two_n_plus_msd = ((1 << self.gate.chunk_bits()) - 1) as u64 + most_significant_diff.to_canonical_u64();
let two_n_plus_msd =
((1 << self.gate.chunk_bits()) - 1) as u64 + most_significant_diff.to_canonical_u64();
let msd_bits: Vec<F> = (0..self.gate.chunk_bits() + 1)
.scan(two_n_plus_msd, |acc, _| {
let tmp = *acc % 2;
@ -439,10 +436,7 @@ impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
})
.collect();
out_buffer.set_wire(
local_wire(self.gate.wire_result_bool()),
result,
);
out_buffer.set_wire(local_wire(self.gate.wire_result_bool()), result);
out_buffer.set_wire(
local_wire(self.gate.wire_most_significant_diff()),
most_significant_diff,
@ -468,7 +462,7 @@ impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
}
for i in 0..self.gate.chunk_bits() + 1 {
out_buffer.set_wire(
local_wire(self.gate.wire_most_significant_diff_bit(i)),
local_wire(self.gate.wire_most_significant_diff_bit(i)),
msd_bits[i],
);
}
@ -593,7 +587,8 @@ mod tests {
}
let most_significant_diff = most_significant_diff_so_far;
let two_n_min_1_plus_msd = ((1 << chunk_bits) - 1) as u64 + most_significant_diff.to_canonical_u64();
let two_n_min_1_plus_msd =
((1 << chunk_bits) - 1) as u64 + most_significant_diff.to_canonical_u64();
let mut msd_bits: Vec<F> = (0..chunk_bits + 1)
.scan(two_n_min_1_plus_msd, |acc, _| {
let tmp = *acc % 2;

View File

@ -3,8 +3,8 @@
pub mod arithmetic;
pub mod arithmetic_u32;
pub mod base_sum;
pub mod assert_le;
pub mod base_sum;
pub mod comparison;
pub mod constant;
pub mod exponentiation;