#[cfg(not(feature = "std"))]
use alloc::{borrow::ToOwned, vec};
use crate::field::extension::Extendable;
use crate::gates::lookup::LookupGate;
use crate::gates::lookup_table::{LookupTable, LookupTableGate};
use crate::gates::noop::NoopGate;
use crate::hash::hash_types::RichField;
use crate::iop::target::Target;
use crate::plonk::circuit_builder::CircuitBuilder;
pub const TIP5_TABLE: [u16; 256] = [
0, 7, 26, 63, 124, 215, 85, 254, 214, 228, 45, 185, 140, 173, 33, 240, 29, 177, 176, 32, 8,
110, 87, 202, 204, 99, 150, 106, 230, 14, 235, 128, 213, 239, 212, 138, 23, 130, 208, 6, 44,
71, 93, 116, 146, 189, 251, 81, 199, 97, 38, 28, 73, 179, 95, 84, 152, 48, 35, 119, 49, 88,
242, 3, 148, 169, 72, 120, 62, 161, 166, 83, 175, 191, 137, 19, 100, 129, 112, 55, 221, 102,
218, 61, 151, 237, 68, 164, 17, 147, 46, 234, 203, 216, 22, 141, 65, 57, 123, 12, 244, 54, 219,
231, 96, 77, 180, 154, 5, 253, 133, 165, 98, 195, 205, 134, 245, 30, 9, 188, 59, 142, 186, 197,
181, 144, 92, 31, 224, 163, 111, 74, 58, 69, 113, 196, 67, 246, 225, 10, 121, 50, 60, 157, 90,
122, 2, 250, 101, 75, 178, 159, 24, 36, 201, 11, 243, 132, 198, 190, 114, 233, 39, 52, 21, 209,
108, 238, 91, 187, 18, 104, 194, 37, 153, 34, 200, 143, 126, 155, 236, 118, 64, 80, 172, 89,
94, 193, 135, 183, 86, 107, 252, 13, 167, 206, 136, 220, 207, 103, 171, 160, 76, 182, 227, 217,
158, 56, 174, 4, 66, 109, 139, 162, 184, 211, 249, 47, 125, 232, 117, 43, 16, 42, 127, 20, 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,
];
pub const OTHER_TABLE: [u16; 256] = [
2, 6, 25, 3, 9, 7, 0, 3, 25, 35, 10, 19, 36, 45, 216, 247, 35, 39, 57, 126, 2, 6, 25, 3, 9, 7,
0, 3, 25, 35, 10, 19, 36, 45, 216, 247, 35, 39, 57, 126, 2, 6, 25, 3, 9, 7, 0, 3, 25, 35, 10,
19, 36, 45, 216, 247, 35, 39, 57, 126, 2, 6, 25, 3, 9, 7, 0, 3, 25, 35, 10, 19, 36, 45, 216,
247, 35, 39, 57, 126, 2, 6, 25, 3, 9, 7, 0, 3, 25, 35, 10, 19, 36, 45, 216, 247, 35, 39, 57,
126, 2, 6, 25, 3, 9, 7, 0, 3, 25, 35, 10, 19, 36, 45, 216, 247, 35, 39, 57, 126, 2, 6, 25, 3,
9, 7, 0, 3, 25, 35, 10, 19, 36, 45, 216, 247, 35, 39, 57, 126, 2, 6, 25, 3, 9, 7, 0, 3, 25, 35,
10, 19, 36, 45, 216, 247, 35, 39, 57, 126, 2, 6, 25, 3, 9, 7, 0, 3, 25, 35, 10, 19, 36, 45,
216, 247, 35, 39, 57, 126, 2, 6, 25, 3, 9, 7, 0, 3, 25, 35, 10, 19, 36, 45, 216, 247, 35, 39,
57, 126, 2, 6, 25, 3, 9, 7, 0, 3, 25, 35, 10, 19, 36, 45, 216, 247, 35, 39, 57, 126, 2, 6, 25,
3, 9, 7, 0, 3, 25, 35, 10, 19, 36, 45, 216, 247, 35, 39, 57, 126, 2, 6, 25, 3, 9, 7, 0, 3, 25,
35, 10, 19, 36, 45, 216, 247,
];
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> {
pub fn add_lookup_table_from_pairs(&mut self, table: LookupTable) -> usize {
self.update_luts_from_pairs(table)
}
pub fn add_lookup_table_from_table(&mut self, inps: &[u16], outs: &[u16]) -> usize {
self.update_luts_from_table(inps, outs)
}
pub fn add_lookup_table_from_fn(&mut self, f: fn(u16) -> u16, inputs: &[u16]) -> usize {
self.update_luts_from_fn(f, inputs)
}
pub fn add_lookup_from_index(&mut self, looking_in: Target, lut_index: usize) -> Target {
assert!(
lut_index < self.get_luts_length(),
"lut number {} not in luts (length = {})",
lut_index,
self.get_luts_length()
);
let looking_out = self.add_virtual_target();
self.update_lookups(looking_in, looking_out, lut_index);
looking_out
}
pub fn add_all_lookups(&mut self) {
for lut_index in 0..self.num_luts() {
assert!(
!self.get_lut_lookups(lut_index).is_empty(),
"LUT number {:?} is unused",
lut_index
);
if !self.get_lut_lookups(lut_index).is_empty() {
let last_lu_gate = self.num_gates();
let lut = self.get_lut(lut_index);
let lookups = self.get_lut_lookups(lut_index).to_owned();
let gate = LookupGate::new_from_table(&self.config, lut.clone());
let num_slots = LookupGate::num_slots(&self.config);
let lookup_iter = lookups.chunks_exact(num_slots);
let last_chunk = lookup_iter.remainder();
lookup_iter.for_each(|chunk| {
let row = self.add_gate(gate.clone(), vec![]);
for (i, (looking_in, looking_out)) in chunk.iter().enumerate() {
let gate_in = Target::wire(row, LookupGate::wire_ith_looking_inp(i));
let gate_out = Target::wire(row, LookupGate::wire_ith_looking_out(i));
self.connect(gate_in, *looking_in);
self.connect(gate_out, *looking_out);
}
});
for (looking_in, looking_out) in last_chunk.iter() {
let (gate, i) =
self.find_slot(gate.clone(), &[F::from_canonical_usize(lut_index)], &[]);
let gate_in = Target::wire(gate, LookupGate::wire_ith_looking_inp(i));
let gate_out = Target::wire(gate, LookupGate::wire_ith_looking_out(i));
self.connect(gate_in, *looking_in);
self.connect(gate_out, *looking_out);
}
let last_lut_gate = self.num_gates();
let num_lut_entries = LookupTableGate::num_slots(&self.config);
let num_lut_rows = (self.get_luts_idx_length(lut_index) - 1) / num_lut_entries + 1;
let gate =
LookupTableGate::new_from_table(&self.config, lut.clone(), last_lut_gate);
for _ in 0..num_lut_rows {
self.add_gate(gate.clone(), vec![]);
}
let first_lut_gate = self.num_gates() - 1;
self.add_gate(NoopGate, vec![]);
self.add_lookup_rows(last_lu_gate, last_lut_gate, first_lut_gate);
}
}
}
}