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