kimchi/circuits/polynomials/foreign_field_mul/
gadget.rs1use ark_ff::PrimeField;
4use num_bigint::BigUint;
5use o1_utils::foreign_field::ForeignFieldHelpers;
6
7use crate::{
8 alphas::Alphas,
9 circuits::{
10 argument::Argument,
11 berkeley_columns::E,
12 expr::Cache,
13 gate::{CircuitGate, GateType},
14 lookup::{
15 self,
16 tables::{GateLookupTable, LookupTable},
17 },
18 polynomials::{
19 foreign_field_common::{BigUintForeignFieldHelpers, KimchiForeignElement},
20 generic::GenericGateSpec,
21 },
22 wires::Wire,
23 },
24};
25
26use super::circuitgates::ForeignFieldMul;
27
28pub const GATE_COUNT: usize = 1;
30
31impl<F: PrimeField> CircuitGate<F> {
32 pub fn create_foreign_field_mul(
38 start_row: usize,
39 foreign_field_modulus: &BigUint,
40 ) -> (usize, Vec<Self>) {
41 let neg_foreign_field_modulus = foreign_field_modulus.negate().to_field_limbs::<F>();
42 let foreign_field_modulus = foreign_field_modulus.to_field_limbs::<F>();
43 let circuit_gates = vec![
44 CircuitGate {
45 typ: GateType::ForeignFieldMul,
46 wires: Wire::for_row(start_row),
47 coeffs: vec![
48 foreign_field_modulus[2],
49 neg_foreign_field_modulus[0],
50 neg_foreign_field_modulus[1],
51 neg_foreign_field_modulus[2],
52 ],
53 },
54 CircuitGate {
55 typ: GateType::Zero,
56 wires: Wire::for_row(start_row + 1),
57 coeffs: vec![],
58 },
59 ];
60
61 (start_row + circuit_gates.len(), circuit_gates)
62 }
63
64 pub fn extend_foreign_field_mul(
66 gates: &mut Vec<Self>,
67 curr_row: &mut usize,
68 foreign_field_modulus: &BigUint,
69 ) {
70 let (next_row, circuit_gates) =
71 Self::create_foreign_field_mul(*curr_row, foreign_field_modulus);
72 *curr_row = next_row;
73 gates.extend_from_slice(&circuit_gates);
74 }
75
76 pub fn extend_high_bounds(
77 gates: &mut Vec<Self>,
78 curr_row: &mut usize,
79 foreign_field_modulus: &BigUint,
80 ) {
81 let r = gates.len();
82 let hi_fmod = foreign_field_modulus.to_field_limbs::<F>()[2];
83 let hi_limb: F = KimchiForeignElement::<F>::two_to_limb() - hi_fmod - F::one();
84 let g = GenericGateSpec::Plus(hi_limb);
85 CircuitGate::extend_generic(gates, curr_row, Wire::for_row(r), g.clone(), Some(g));
86 }
87}
88
89pub fn circuit_gate_selector_index(typ: GateType) -> usize {
91 match typ {
92 GateType::ForeignFieldMul => 0,
93 _ => panic!("invalid gate type"),
94 }
95}
96
97pub fn circuit_gates() -> [GateType; GATE_COUNT] {
99 [GateType::ForeignFieldMul]
100}
101
102pub fn circuit_gate_constraints<F: PrimeField>(
104 typ: GateType,
105 alphas: &Alphas<F>,
106 cache: &mut Cache,
107) -> E<F> {
108 match typ {
109 GateType::ForeignFieldMul => ForeignFieldMul::combined_constraints(alphas, cache),
110 _ => panic!("invalid gate type"),
111 }
112}
113
114pub fn circuit_gate_constraint_count<F: PrimeField>(typ: GateType) -> u32 {
116 match typ {
117 GateType::ForeignFieldMul => ForeignFieldMul::<F>::CONSTRAINTS,
118 _ => panic!("invalid gate type"),
119 }
120}
121
122pub fn combined_constraints<F: PrimeField>(alphas: &Alphas<F>, cache: &mut Cache) -> E<F> {
124 ForeignFieldMul::combined_constraints(alphas, cache)
125}
126
127pub fn lookup_table<F: PrimeField>() -> LookupTable<F> {
129 lookup::tables::get_table::<F>(GateLookupTable::RangeCheck)
130}