From bdfe124b0cceda186fcd62f5d44bc6398e14442d Mon Sep 17 00:00:00 2001 From: Nicholas Ward Date: Tue, 12 Oct 2021 14:20:39 -0700 Subject: [PATCH] multiple comparison --- src/gadgets/multiple_comparison.rs | 61 ++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 src/gadgets/multiple_comparison.rs diff --git a/src/gadgets/multiple_comparison.rs b/src/gadgets/multiple_comparison.rs new file mode 100644 index 00000000..5291323d --- /dev/null +++ b/src/gadgets/multiple_comparison.rs @@ -0,0 +1,61 @@ +use std::marker::PhantomData; + +use itertools::izip; + +use crate::field::extension_field::Extendable; +use crate::field::field_types::{Field, RichField}; +use crate::gates::comparison::ComparisonGate; +use crate::iop::generator::{GeneratedValues, SimpleGenerator}; +use crate::iop::target::{BoolTarget, Target}; +use crate::iop::witness::{PartitionWitness, Witness}; +use crate::plonk::circuit_builder::CircuitBuilder; +use crate::util::ceil_div_usize; + +impl, const D: usize> CircuitBuilder { + /// Returns true if a is less than or equal to b, considered as limbs of a large value. + pub fn compare_lists(&mut self, a: Vec, b: Vec, num_bits: usize) -> BoolTarget { + assert_eq!( + a.len(), + b.len(), + "Permutation must have same number of inputs and outputs" + ); + let n = a.len(); + + let chunk_size = 4; + let num_chunks = ceil_div_usize(num_bits, 4); + + let one = self.one(); + let mut result = self.one(); + for i in 0..n { + let a_le_b_gate = ComparisonGate::new(num_bits, num_chunks); + let a_le_b_gate_index = self.add_gate(a_le_b_gate.clone(), vec![]); + self.connect( + Target::wire(a_le_b_gate_index, a_le_b_gate.wire_first_input()), + a[i], + ); + self.connect( + Target::wire(a_le_b_gate_index, a_le_b_gate.wire_second_input()), + b[i], + ); + let a_le_b_result = Target::wire(a_le_b_gate_index, a_le_b_gate.wire_result_bool()); + + let b_le_a_gate = ComparisonGate::new(num_bits, num_chunks); + let b_le_a_gate_index = self.add_gate(b_le_a_gate.clone(), vec![]); + self.connect( + Target::wire(b_le_a_gate_index, b_le_a_gate.wire_first_input()), + b[i], + ); + self.connect( + Target::wire(b_le_a_gate_index, b_le_a_gate.wire_second_input()), + a[i], + ); + let b_le_a_result = Target::wire(b_le_a_gate_index, b_le_a_gate.wire_result_bool()); + + let these_limbs_equal = self.mul(a_le_b_result, b_le_a_result); + let these_limbs_less_than = self.sub(one, b_le_a_result); + result = self.mul_add(these_limbs_equal, result, these_limbs_less_than); + } + + BoolTarget::new_unsafe(result) + } +}