use ark_ff::{FftField, PrimeField};
use crate::{
alphas::Alphas,
circuits::{
argument::Argument,
berkeley_columns::E,
expr::Cache,
gate::{CircuitGate, Connect, GateType},
lookup::{
self,
tables::{GateLookupTable, LookupTable},
},
wires::Wire,
},
};
use super::circuitgates::{RangeCheck0, RangeCheck1};
pub const GATE_COUNT: usize = 2;
impl<F: PrimeField> CircuitGate<F> {
pub fn create_multi_range_check(start_row: usize) -> (usize, Vec<Self>) {
Self::create_multi_range_check_gadget(start_row, false)
}
pub fn create_compact_multi_range_check(start_row: usize) -> (usize, Vec<Self>) {
Self::create_multi_range_check_gadget(start_row, true)
}
pub fn extend_multi_range_check(gates: &mut Vec<Self>, curr_row: &mut usize) {
let (next_row, circuit_gates) = Self::create_multi_range_check(*curr_row);
*curr_row = next_row;
gates.extend_from_slice(&circuit_gates);
}
pub fn extend_compact_multi_range_check(gates: &mut Vec<Self>, curr_row: &mut usize) {
let (next_row, circuit_gates) = Self::create_compact_multi_range_check(*curr_row);
*curr_row = next_row;
gates.extend_from_slice(&circuit_gates);
}
pub fn create_range_check(start_row: usize) -> (usize, Vec<Self>) {
let gate = CircuitGate::new(
GateType::RangeCheck0,
Wire::for_row(start_row),
vec![F::zero()],
);
(start_row + 1, vec![gate])
}
pub fn extend_range_check(gates: &mut Vec<Self>, curr_row: &mut usize) {
let (next_row, circuit_gates) = Self::create_range_check(*curr_row);
*curr_row = next_row;
gates.extend_from_slice(&circuit_gates);
}
fn create_multi_range_check_gadget(start_row: usize, compact: bool) -> (usize, Vec<Self>) {
let coeff = if compact { F::one() } else { F::zero() };
let mut circuit_gates = vec![
CircuitGate::new(
GateType::RangeCheck0,
Wire::for_row(start_row),
vec![F::zero()],
),
CircuitGate::new(
GateType::RangeCheck0,
Wire::for_row(start_row + 1),
vec![coeff],
),
CircuitGate::new(GateType::RangeCheck1, Wire::for_row(start_row + 2), vec![]),
CircuitGate::new(GateType::Zero, Wire::for_row(start_row + 3), vec![]),
];
circuit_gates.connect_cell_pair((0, 1), (3, 3));
circuit_gates.connect_cell_pair((0, 2), (3, 4));
circuit_gates.connect_cell_pair((1, 1), (3, 5));
circuit_gates.connect_cell_pair((1, 2), (3, 6));
(start_row + circuit_gates.len(), circuit_gates)
}
}
pub fn circuit_gates() -> [GateType; GATE_COUNT] {
[GateType::RangeCheck0, GateType::RangeCheck1]
}
pub fn circuit_gate_constraint_count<F: PrimeField>(typ: GateType) -> u32 {
match typ {
GateType::RangeCheck0 => RangeCheck0::<F>::CONSTRAINTS,
GateType::RangeCheck1 => RangeCheck1::<F>::CONSTRAINTS,
_ => panic!("invalid gate type"),
}
}
pub fn circuit_gate_constraints<F: PrimeField>(
typ: GateType,
alphas: &Alphas<F>,
cache: &mut Cache,
) -> E<F> {
match typ {
GateType::RangeCheck0 => RangeCheck0::combined_constraints(alphas, cache),
GateType::RangeCheck1 => RangeCheck1::combined_constraints(alphas, cache),
_ => panic!("invalid gate type"),
}
}
pub fn combined_constraints<F: PrimeField>(alphas: &Alphas<F>, cache: &mut Cache) -> E<F> {
RangeCheck0::combined_constraints(alphas, cache)
+ RangeCheck1::combined_constraints(alphas, cache)
}
pub fn lookup_table<F: FftField>() -> LookupTable<F> {
lookup::tables::get_table::<F>(GateLookupTable::RangeCheck)
}