Add wrapper types for Lookup and LookupTable

This commit is contained in:
Robin Salen 2023-05-05 08:37:08 +02:00
parent 4351237160
commit 91c55d15f9
No known key found for this signature in database
GPG Key ID: FB87BACFB3CB2007
9 changed files with 44 additions and 39 deletions

View File

@ -1,8 +1,6 @@
use alloc::sync::Arc;
use crate::field::extension::Extendable;
use crate::gates::lookup::LookupGate;
use crate::gates::lookup_table::LookupTableGate;
use crate::gates::lookup_table::{LookupTable, LookupTableGate};
use crate::gates::noop::NoopGate;
use crate::hash::hash_types::RichField;
use crate::iop::target::Target;
@ -47,7 +45,7 @@ pub const SMALLER_TABLE: [u16; 8] = [2, 24, 56, 100, 128, 16, 20, 49];
impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
/// Adds a lookup table to the list of stored lookup tables `self.luts` based on a table of (input, output) pairs. It returns the index of the LUT within `self.luts`.
pub fn add_lookup_table_from_pairs(&mut self, table: Arc<Vec<(u16, u16)>>) -> usize {
pub fn add_lookup_table_from_pairs(&mut self, table: LookupTable) -> usize {
self.update_luts_from_pairs(table)
}

View File

@ -4,6 +4,7 @@ use alloc::sync::Arc;
use alloc::vec::Vec;
use core::usize;
use super::lookup_table::LookupTable;
use crate::field::extension::Extendable;
use crate::field::packed::PackedField;
use crate::gates::gate::Gate;
@ -22,17 +23,19 @@ use crate::plonk::vars::{
};
use crate::util::serialization::{Buffer, IoResult, Read, Write};
pub type Lookup = Vec<(Target, Target)>;
/// A gate which stores (input, output) lookup pairs made elsewhere in the trace. It doesn't check any constraints itself.
#[derive(Debug, Clone)]
pub struct LookupGate {
/// Number of lookups per gate.
pub num_slots: usize,
/// LUT associated to the gate.
lut: Arc<Vec<(u16, u16)>>,
lut: LookupTable,
}
impl LookupGate {
pub fn new_from_table(config: &CircuitConfig, lut: Arc<Vec<(u16, u16)>>) -> Self {
pub fn new_from_table(config: &CircuitConfig, lut: LookupTable) -> Self {
Self {
num_slots: Self::num_slots(config),
lut,
@ -142,7 +145,7 @@ impl<F: RichField + Extendable<D>, const D: usize> PackedEvaluableBase<F, D> for
#[derive(Clone, Debug, Default)]
pub struct LookupGenerator {
row: usize,
lut: Arc<Vec<(u16, u16)>>,
lut: LookupTable,
slot_nb: usize,
}

View File

@ -24,23 +24,21 @@ use crate::plonk::vars::{
};
use crate::util::serialization::{Buffer, IoResult, Read, Write};
pub type LookupTable = Arc<Vec<(u16, u16)>>;
/// A gate which stores the set of (input, output) value pairs of a lookup table, and their multiplicities.
#[derive(Debug, Clone)]
pub struct LookupTableGate {
/// Number of lookup entries per gate.
pub num_slots: usize,
/// Lookup table associated to the gate.
pub lut: Arc<Vec<(u16, u16)>>,
pub lut: LookupTable,
/// First row of the lookup table.
last_lut_row: usize,
}
impl LookupTableGate {
pub fn new_from_table(
config: &CircuitConfig,
lut: Arc<Vec<(u16, u16)>>,
last_lut_row: usize,
) -> Self {
pub fn new_from_table(config: &CircuitConfig, lut: LookupTable, last_lut_row: usize) -> Self {
Self {
num_slots: Self::num_slots(config),
lut,
@ -164,7 +162,7 @@ impl<F: RichField + Extendable<D>, const D: usize> PackedEvaluableBase<F, D> for
#[derive(Clone, Debug, Default)]
pub struct LookupTableGenerator {
row: usize,
lut: Arc<Vec<(u16, u16)>>,
lut: LookupTable,
slot_nb: usize,
num_slots: usize,
last_lut_row: usize,

View File

@ -9,6 +9,7 @@ mod tests {
use log::{Level, LevelFilter};
use crate::gadgets::lookup::{OTHER_TABLE, SMALLER_TABLE, TIP5_TABLE};
use crate::gates::lookup_table::LookupTable;
use crate::gates::noop::NoopGate;
use crate::plonk::prover::prove;
use crate::util::timing::TimingTree;
@ -54,7 +55,7 @@ mod tests {
LOGGER_INITIALIZED.call_once(|| init_logger().unwrap());
let tip5_table = TIP5_TABLE.to_vec();
let table: Arc<Vec<(u16, u16)>> = Arc::new((0..256).zip_eq(tip5_table).collect());
let table: LookupTable = Arc::new((0..256).zip_eq(tip5_table).collect());
let config = CircuitConfig::standard_recursion_config();
let mut builder = CircuitBuilder::<F, D>::new(config);
@ -129,7 +130,7 @@ mod tests {
let first_out = tip5_table[look_val_a];
let second_out = tip5_table[look_val_b];
let table: Arc<Vec<(u16, u16)>> = Arc::new((0..256).zip_eq(tip5_table).collect());
let table: LookupTable = Arc::new((0..256).zip_eq(tip5_table).collect());
let other_table = OTHER_TABLE.to_vec();
@ -142,7 +143,7 @@ mod tests {
let s = first_out + second_out;
let final_out = other_table[s as usize];
let table2: Arc<Vec<(u16, u16)>> = Arc::new((0..256).zip_eq(other_table).collect());
let table2: LookupTable = Arc::new((0..256).zip_eq(other_table).collect());
let table2_index = builder.add_lookup_table_from_pairs(table2);
let output_final = builder.add_lookup_from_index(sum, table2_index);
@ -208,11 +209,11 @@ mod tests {
let init_b = 2;
let tab: Vec<u16> = SMALLER_TABLE.to_vec();
let table: Arc<Vec<(u16, u16)>> = Arc::new((2..10).zip_eq(tab).collect());
let table: LookupTable = Arc::new((2..10).zip_eq(tab).collect());
let other_table = OTHER_TABLE.to_vec();
let table2: Arc<Vec<(u16, u16)>> = Arc::new((0..256).zip_eq(other_table).collect());
let table2: LookupTable = Arc::new((0..256).zip_eq(other_table).collect());
let small_index = builder.add_lookup_table_from_pairs(table.clone());
let output_a = builder.add_lookup_from_index(initial_a, small_index);
@ -293,7 +294,7 @@ mod tests {
let look_val_b = 2;
let tip5_table = TIP5_TABLE.to_vec();
let table: Arc<Vec<(u16, u16)>> = Arc::new((0..256).zip_eq(tip5_table).collect());
let table: LookupTable = Arc::new((0..256).zip_eq(tip5_table).collect());
let out_a = table[look_val_a].1;
let out_b = table[look_val_b].1;
@ -310,7 +311,7 @@ mod tests {
let other_table = OTHER_TABLE.to_vec();
let table2: Arc<Vec<(u16, u16)>> = Arc::new((0..256).zip_eq(other_table).collect());
let table2: LookupTable = Arc::new((0..256).zip_eq(other_table).collect());
let s = out_a + out_b;
let out_final = table2[s as usize].1;
@ -384,7 +385,7 @@ mod tests {
let look_val_b = 2;
let tip5_table = TIP5_TABLE.to_vec();
let table: Arc<Vec<(u16, u16)>> = Arc::new((0..256).zip_eq(tip5_table).collect());
let table: LookupTable = Arc::new((0..256).zip_eq(tip5_table).collect());
let table_index = builder.add_lookup_table_from_pairs(table.clone());
let output_a = builder.add_lookup_from_index(initial_a, table_index);

View File

@ -25,7 +25,8 @@ use crate::gates::arithmetic_base::ArithmeticGate;
use crate::gates::arithmetic_extension::ArithmeticExtensionGate;
use crate::gates::constant::ConstantGate;
use crate::gates::gate::{CurrentSlot, Gate, GateInstance, GateRef};
use crate::gates::lookup::LookupGate;
use crate::gates::lookup::{Lookup, LookupGate};
use crate::gates::lookup_table::LookupTable;
use crate::gates::noop::NoopGate;
use crate::gates::public_input::PublicInputGate;
use crate::gates::selectors::{selector_ends_lookups, selector_polynomials, selectors_lookup};
@ -129,10 +130,10 @@ pub struct CircuitBuilder<F: RichField + Extendable<D>, const D: usize> {
lookup_rows: Vec<LookupWire>,
/// For each LUT index, vector of `(looking_in, looking_out)` pairs.
lut_to_lookups: Vec<Vec<(Target, Target)>>,
lut_to_lookups: Vec<Lookup>,
// Lookup tables in the form of `Vec<(input_value, output_value)>`.
luts: Vec<Arc<Vec<(u16, u16)>>>,
luts: Vec<LookupTable>,
/// Optional common data. When it is `Some(goal_data)`, the `build` function panics if the resulting
/// common data doesn't equal `goal_data`.
@ -581,12 +582,12 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
}
/// Checks whether a LUT is already stored in `self.luts`
pub fn is_stored(&self, lut: Arc<Vec<(u16, u16)>>) -> Option<usize> {
pub fn is_stored(&self, lut: LookupTable) -> Option<usize> {
self.luts.iter().position(|elt| *elt == lut)
}
/// Returns the LUT at index `idx`.
pub fn get_lut(&self, idx: usize) -> Arc<Vec<(u16, u16)>> {
pub fn get_lut(&self, idx: usize) -> LookupTable {
assert!(
idx < self.luts.len(),
"index idx: {} greater than the total number of created LUTS: {}",
@ -632,7 +633,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
.copied()
.zip_eq(table.iter().copied())
.collect();
let lut: Arc<Vec<(u16, u16)>> = Arc::new(pairs);
let lut: LookupTable = Arc::new(pairs);
// If the LUT `lut` is already stored in `self.luts`, return its index. Otherwise, append `table` to `self.luts` and return its index.
if let Some(idx) = self.is_stored(lut.clone()) {
@ -646,7 +647,7 @@ impl<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
}
/// Adds a table to the vector of LUTs in the circuit builder.
pub fn update_luts_from_pairs(&mut self, table: Arc<Vec<(u16, u16)>>) -> usize {
pub fn update_luts_from_pairs(&mut self, table: LookupTable) -> usize {
// If the LUT `table` is already stored in `self.luts`, return its index. Otherwise, append `table` to `self.luts` and return its index.
if let Some(idx) = self.is_stored(table.clone()) {
idx

View File

@ -1,5 +1,4 @@
use alloc::collections::BTreeMap;
use alloc::sync::Arc;
use alloc::vec;
use alloc::vec::Vec;
use core::ops::{Range, RangeFrom};
@ -19,6 +18,8 @@ use crate::fri::structure::{
};
use crate::fri::{FriConfig, FriParams};
use crate::gates::gate::GateRef;
use crate::gates::lookup::Lookup;
use crate::gates::lookup_table::LookupTable;
use crate::gates::selectors::SelectorsInfo;
use crate::hash::hash_types::{HashOutTarget, MerkleCapTarget, RichField};
use crate::hash::merkle_tree::MerkleCap;
@ -317,7 +318,7 @@ pub struct ProverOnlyCircuitData<
///The concrete placement of the lookup gates for each lookup table index.
pub lookup_rows: Vec<LookupWire>,
/// A vector of (looking_in, looking_out) pairs for for each lookup table index.
pub lut_to_lookups: Vec<Vec<(Target, Target)>>,
pub lut_to_lookups: Vec<Lookup>,
}
/// Circuit data required by the verifier, but not the prover.
@ -380,7 +381,7 @@ pub struct CommonCircuitData<F: RichField + Extendable<D>, const D: usize> {
pub num_lookup_selectors: usize,
/// The stored lookup tables.
pub luts: Vec<Arc<Vec<(u16, u16)>>>,
pub luts: Vec<LookupTable>,
}
impl<F: RichField + Extendable<D>, const D: usize> CommonCircuitData<F, D> {

View File

@ -456,6 +456,7 @@ mod tests {
use crate::field::types::Sample;
use crate::fri::reduction_strategies::FriReductionStrategy;
use crate::gates::lookup_table::LookupTable;
use crate::gates::noop::NoopGate;
use crate::iop::witness::PartialWitness;
use crate::plonk::circuit_builder::CircuitBuilder;
@ -529,7 +530,7 @@ mod tests {
241, 25, 149, 105, 156, 51, 53, 168, 145, 247, 223, 79, 78, 226, 15, 222, 82, 115, 70,
210, 27, 41, 1, 170, 40, 131, 192, 229, 248, 255,
];
let table: Arc<Vec<(u16, u16)>> = Arc::new((0..256).zip_eq(tip5_table).collect());
let table: LookupTable = Arc::new((0..256).zip_eq(tip5_table).collect());
let config = CircuitConfig::standard_recursion_config();
let mut builder = CircuitBuilder::<F, D>::new(config);
let lut_index = builder.add_lookup_table_from_pairs(table);

View File

@ -201,6 +201,7 @@ mod tests {
use crate::fri::reduction_strategies::FriReductionStrategy;
use crate::fri::FriConfig;
use crate::gadgets::lookup::{OTHER_TABLE, TIP5_TABLE};
use crate::gates::lookup_table::LookupTable;
use crate::gates::noop::NoopGate;
use crate::iop::witness::{PartialWitness, WitnessWrite};
use crate::plonk::circuit_data::{CircuitConfig, VerifierOnlyCircuitData};
@ -421,7 +422,7 @@ mod tests {
let look_val_b = 2;
let tip5_table = TIP5_TABLE.to_vec();
let table: Arc<Vec<(u16, u16)>> = Arc::new((0..256).zip_eq(tip5_table).collect());
let table: LookupTable = Arc::new((0..256).zip_eq(tip5_table).collect());
let out_a = table[look_val_a].1;
let out_b = table[look_val_b].1;
@ -482,7 +483,7 @@ mod tests {
let first_out = tip5_table[look_val_a];
let second_out = tip5_table[look_val_b];
let table: Arc<Vec<(u16, u16)>> = Arc::new((0..256).zip_eq(tip5_table).collect());
let table: LookupTable = Arc::new((0..256).zip_eq(tip5_table).collect());
let other_table = OTHER_TABLE.to_vec();
@ -495,7 +496,7 @@ mod tests {
let s = first_out + second_out;
let final_out = other_table[s as usize];
let table2: Arc<Vec<(u16, u16)>> = Arc::new((0..256).zip_eq(other_table).collect());
let table2: LookupTable = Arc::new((0..256).zip_eq(other_table).collect());
let other_index = builder.add_lookup_table_from_pairs(table2);
let output_final = builder.add_lookup_from_index(sum, other_index);
@ -556,7 +557,7 @@ mod tests {
let look_val_b = 2;
let tip5_table = TIP5_TABLE.to_vec();
let table: Arc<Vec<(u16, u16)>> = Arc::new((0..256).zip_eq(tip5_table).collect());
let table: LookupTable = Arc::new((0..256).zip_eq(tip5_table).collect());
let out_a = table[look_val_a].1;
let out_b = table[look_val_b].1;

View File

@ -31,6 +31,7 @@ use crate::fri::reduction_strategies::FriReductionStrategy;
use crate::fri::{FriConfig, FriParams};
use crate::gadgets::polynomial::PolynomialCoeffsExtTarget;
use crate::gates::gate::GateRef;
use crate::gates::lookup::Lookup;
use crate::gates::selectors::SelectorsInfo;
use crate::hash::hash_types::{HashOutTarget, MerkleCapTarget, RichField};
use crate::hash::merkle_proofs::{MerkleProof, MerkleProofTarget};
@ -1152,9 +1153,9 @@ pub trait Read {
Ok(lut)
}
/// Reads a target lookup table stored as `Vec<(Target, Target)>` from `self`.
/// Reads a target lookup table stored as `Lookup` from `self`.
#[inline]
fn read_target_lut(&mut self) -> IoResult<Vec<(Target, Target)>> {
fn read_target_lut(&mut self) -> IoResult<Lookup> {
let length = self.read_usize()?;
let mut lut = Vec::with_capacity(length);
for _ in 0..length {