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