kimchi/circuits/polynomials/range_check/
gadget.rs1use ark_ff::{FftField, PrimeField};
4
5use crate::{
6 alphas::Alphas,
7 circuits::{
8 argument::Argument,
9 berkeley_columns::E,
10 expr::Cache,
11 gate::{CircuitGate, Connect, GateType},
12 lookup::{
13 self,
14 tables::{GateLookupTable, LookupTable},
15 },
16 wires::Wire,
17 },
18};
19
20use super::circuitgates::{RangeCheck0, RangeCheck1};
21
22pub const GATE_COUNT: usize = 2;
23
24impl<F: PrimeField> CircuitGate<F> {
25 pub fn create_multi_range_check(start_row: usize) -> (usize, Vec<Self>) {
31 Self::create_multi_range_check_gadget(start_row, false)
32 }
33
34 pub fn create_compact_multi_range_check(start_row: usize) -> (usize, Vec<Self>) {
40 Self::create_multi_range_check_gadget(start_row, true)
41 }
42
43 pub fn extend_multi_range_check(gates: &mut Vec<Self>, curr_row: &mut usize) {
45 let (next_row, circuit_gates) = Self::create_multi_range_check(*curr_row);
46 *curr_row = next_row;
47 gates.extend_from_slice(&circuit_gates);
48 }
49
50 pub fn extend_compact_multi_range_check(gates: &mut Vec<Self>, curr_row: &mut usize) {
52 let (next_row, circuit_gates) = Self::create_compact_multi_range_check(*curr_row);
53 *curr_row = next_row;
54 gates.extend_from_slice(&circuit_gates);
55 }
56
57 pub fn create_range_check(start_row: usize) -> (usize, Vec<Self>) {
63 let gate = CircuitGate::new(
64 GateType::RangeCheck0,
65 Wire::for_row(start_row),
66 vec![F::zero()],
67 );
68 (start_row + 1, vec![gate])
69 }
70
71 pub fn extend_range_check(gates: &mut Vec<Self>, curr_row: &mut usize) {
73 let (next_row, circuit_gates) = Self::create_range_check(*curr_row);
74 *curr_row = next_row;
75 gates.extend_from_slice(&circuit_gates);
76 }
77
78 fn create_multi_range_check_gadget(start_row: usize, compact: bool) -> (usize, Vec<Self>) {
84 let coeff = if compact { F::one() } else { F::zero() };
85
86 let mut circuit_gates = vec![
87 CircuitGate::new(
88 GateType::RangeCheck0,
89 Wire::for_row(start_row),
90 vec![F::zero()],
91 ),
92 CircuitGate::new(
93 GateType::RangeCheck0,
94 Wire::for_row(start_row + 1),
95 vec![coeff],
96 ),
97 CircuitGate::new(GateType::RangeCheck1, Wire::for_row(start_row + 2), vec![]),
98 CircuitGate::new(GateType::Zero, Wire::for_row(start_row + 3), vec![]),
99 ];
100
101 circuit_gates.connect_cell_pair((0, 1), (3, 3));
103
104 circuit_gates.connect_cell_pair((0, 2), (3, 4));
106
107 circuit_gates.connect_cell_pair((1, 1), (3, 5));
109
110 circuit_gates.connect_cell_pair((1, 2), (3, 6));
112
113 (start_row + circuit_gates.len(), circuit_gates)
114 }
115}
116
117pub fn circuit_gates() -> [GateType; GATE_COUNT] {
119 [GateType::RangeCheck0, GateType::RangeCheck1]
120}
121
122pub fn circuit_gate_constraint_count<F: PrimeField>(typ: GateType) -> u32 {
128 match typ {
129 GateType::RangeCheck0 => RangeCheck0::<F>::CONSTRAINTS,
130 GateType::RangeCheck1 => RangeCheck1::<F>::CONSTRAINTS,
131 _ => panic!("invalid gate type"),
132 }
133}
134
135pub fn circuit_gate_constraints<F: PrimeField>(
141 typ: GateType,
142 alphas: &Alphas<F>,
143 cache: &mut Cache,
144) -> E<F> {
145 match typ {
146 GateType::RangeCheck0 => RangeCheck0::combined_constraints(alphas, cache),
147 GateType::RangeCheck1 => RangeCheck1::combined_constraints(alphas, cache),
148 _ => panic!("invalid gate type"),
149 }
150}
151
152pub fn combined_constraints<F: PrimeField>(alphas: &Alphas<F>, cache: &mut Cache) -> E<F> {
154 RangeCheck0::combined_constraints(alphas, cache)
155 + RangeCheck1::combined_constraints(alphas, cache)
156}
157
158pub fn lookup_table<F: FftField>() -> LookupTable<F> {
160 lookup::tables::get_table::<F>(GateLookupTable::RangeCheck)
161}