1use crate::{challenge::ChallengeTerm, interpreter::Instruction};
2use kimchi::{
3 circuits::expr::{CacheId, ConstantExpr, Expr, FormattedOutput},
4 collections::HashMap,
5};
6use strum_macros::{EnumCount as EnumCountMacro, EnumIter};
7
8use crate::NUMBER_OF_COLUMNS;
9
10#[derive(Debug, Clone, Copy, PartialEq, EnumCountMacro, EnumIter, Eq, Hash)]
18pub enum Gadget {
19 NoOp,
21
22 App,
30 EllipticCurveAddition,
32 EllipticCurveScaling,
33 PoseidonFullRound(usize),
44 PoseidonSpongeAbsorb,
54}
55
56impl From<Instruction> for Gadget {
58 fn from(val: Instruction) -> Gadget {
59 match val {
60 Instruction::NoOp => Gadget::NoOp,
61 Instruction::PoseidonFullRound(starting_round) => {
62 Gadget::PoseidonFullRound(starting_round)
63 }
64 Instruction::PoseidonSpongeAbsorb => Gadget::PoseidonSpongeAbsorb,
65 Instruction::EllipticCurveScaling(_i_comm, _s) => Gadget::EllipticCurveScaling,
66 Instruction::EllipticCurveAddition(_i) => Gadget::EllipticCurveAddition,
67 }
68 }
69}
70
71#[derive(Debug, Clone, Copy, PartialEq)]
72pub enum Column {
73 Selector(Gadget),
74 PublicInput(usize),
75 X(usize),
76}
77
78impl From<Column> for usize {
90 fn from(val: Column) -> usize {
91 match val {
92 Column::X(i) => i,
93 Column::PublicInput(i) => NUMBER_OF_COLUMNS + i,
94 Column::Selector(_) => unimplemented!("Selectors are not supported. This method is supposed to be called only to compute the cross-term and an optimisation is in progress to avoid the inclusion of the selectors in the multi-variate polynomial."),
95 }
96 }
97}
98
99pub type E<Fp> = Expr<ConstantExpr<Fp, ChallengeTerm>, Column>;
100
101impl From<Gadget> for usize {
102 fn from(val: Gadget) -> usize {
103 match val {
104 Gadget::NoOp => 0,
105 Gadget::App => 1,
106 Gadget::EllipticCurveAddition => 2,
107 Gadget::EllipticCurveScaling => 3,
108 Gadget::PoseidonSpongeAbsorb => 4,
109 Gadget::PoseidonFullRound(starting_round) => {
110 assert_eq!(starting_round % 5, 0);
111 5 + starting_round / 5
112 }
113 }
114 }
115}
116
117impl FormattedOutput for Column {
119 fn latex(&self, _cache: &mut HashMap<CacheId, Self>) -> String {
120 match self {
121 Column::Selector(sel) => match sel {
122 Gadget::NoOp => "q_noop".to_string(),
123 Gadget::App => "q_app".to_string(),
124 Gadget::EllipticCurveAddition => "q_ec_add".to_string(),
125 Gadget::EllipticCurveScaling => "q_ec_mul".to_string(),
126 Gadget::PoseidonSpongeAbsorb => "q_pos_sponge_absorb".to_string(),
127 Gadget::PoseidonFullRound(starting_round) => {
128 format!("q_pos_full_round_{}", starting_round)
129 }
130 },
131 Column::PublicInput(i) => format!("pi_{{{i}}}").to_string(),
132 Column::X(i) => format!("x_{{{i}}}").to_string(),
133 }
134 }
135
136 fn text(&self, _cache: &mut HashMap<CacheId, Self>) -> String {
137 match self {
138 Column::Selector(sel) => match sel {
139 Gadget::NoOp => "q_noop".to_string(),
140 Gadget::App => "q_app".to_string(),
141 Gadget::EllipticCurveAddition => "q_ec_add".to_string(),
142 Gadget::EllipticCurveScaling => "q_ec_mul".to_string(),
143 Gadget::PoseidonSpongeAbsorb => "q_pos_sponge_absorb".to_string(),
144 Gadget::PoseidonFullRound(starting_round) => {
145 format!("q_pos_full_round_{}", starting_round)
146 }
147 },
148 Column::PublicInput(i) => format!("pi[{i}]"),
149 Column::X(i) => format!("x[{i}]"),
150 }
151 }
152
153 fn ocaml(&self, _cache: &mut HashMap<CacheId, Self>) -> String {
154 unimplemented!("Not used at the moment")
156 }
157
158 fn is_alpha(&self) -> bool {
159 unimplemented!("Not used at the moment")
161 }
162}