1use crate::{challenge::ChallengeTerm, interpreter::Instruction};
2use kimchi::circuits::expr::{CacheId, ConstantExpr, Expr, FormattedOutput};
3use std::collections::HashMap;
4use strum_macros::{EnumCount as EnumCountMacro, EnumIter};
5
6use crate::NUMBER_OF_COLUMNS;
7
8#[derive(Debug, Clone, Copy, PartialEq, EnumCountMacro, EnumIter, Eq, Hash)]
16pub enum Gadget {
17 NoOp,
19
20 App,
28 EllipticCurveAddition,
30 EllipticCurveScaling,
31 PoseidonFullRound(usize),
42 PoseidonSpongeAbsorb,
52}
53
54impl From<Instruction> for Gadget {
56 fn from(val: Instruction) -> Gadget {
57 match val {
58 Instruction::NoOp => Gadget::NoOp,
59 Instruction::PoseidonFullRound(starting_round) => {
60 Gadget::PoseidonFullRound(starting_round)
61 }
62 Instruction::PoseidonSpongeAbsorb => Gadget::PoseidonSpongeAbsorb,
63 Instruction::EllipticCurveScaling(_i_comm, _s) => Gadget::EllipticCurveScaling,
64 Instruction::EllipticCurveAddition(_i) => Gadget::EllipticCurveAddition,
65 }
66 }
67}
68
69#[derive(Debug, Clone, Copy, PartialEq)]
70pub enum Column {
71 Selector(Gadget),
72 PublicInput(usize),
73 X(usize),
74}
75
76impl From<Column> for usize {
88 fn from(val: Column) -> usize {
89 match val {
90 Column::X(i) => i,
91 Column::PublicInput(i) => NUMBER_OF_COLUMNS + i,
92 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."),
93 }
94 }
95}
96
97pub type E<Fp> = Expr<ConstantExpr<Fp, ChallengeTerm>, Column>;
98
99impl From<Gadget> for usize {
100 fn from(val: Gadget) -> usize {
101 match val {
102 Gadget::NoOp => 0,
103 Gadget::App => 1,
104 Gadget::EllipticCurveAddition => 2,
105 Gadget::EllipticCurveScaling => 3,
106 Gadget::PoseidonSpongeAbsorb => 4,
107 Gadget::PoseidonFullRound(starting_round) => {
108 assert_eq!(starting_round % 5, 0);
109 5 + starting_round / 5
110 }
111 }
112 }
113}
114
115impl FormattedOutput for Column {
117 fn latex(&self, _cache: &mut HashMap<CacheId, Self>) -> String {
118 match self {
119 Column::Selector(sel) => match sel {
120 Gadget::NoOp => "q_noop".to_string(),
121 Gadget::App => "q_app".to_string(),
122 Gadget::EllipticCurveAddition => "q_ec_add".to_string(),
123 Gadget::EllipticCurveScaling => "q_ec_mul".to_string(),
124 Gadget::PoseidonSpongeAbsorb => "q_pos_sponge_absorb".to_string(),
125 Gadget::PoseidonFullRound(starting_round) => {
126 format!("q_pos_full_round_{}", starting_round)
127 }
128 },
129 Column::PublicInput(i) => format!("pi_{{{i}}}").to_string(),
130 Column::X(i) => format!("x_{{{i}}}").to_string(),
131 }
132 }
133
134 fn text(&self, _cache: &mut HashMap<CacheId, Self>) -> String {
135 match self {
136 Column::Selector(sel) => match sel {
137 Gadget::NoOp => "q_noop".to_string(),
138 Gadget::App => "q_app".to_string(),
139 Gadget::EllipticCurveAddition => "q_ec_add".to_string(),
140 Gadget::EllipticCurveScaling => "q_ec_mul".to_string(),
141 Gadget::PoseidonSpongeAbsorb => "q_pos_sponge_absorb".to_string(),
142 Gadget::PoseidonFullRound(starting_round) => {
143 format!("q_pos_full_round_{}", starting_round)
144 }
145 },
146 Column::PublicInput(i) => format!("pi[{i}]"),
147 Column::X(i) => format!("x[{i}]"),
148 }
149 }
150
151 fn ocaml(&self, _cache: &mut HashMap<CacheId, Self>) -> String {
152 unimplemented!("Not used at the moment")
154 }
155
156 fn is_alpha(&self) -> bool {
157 unimplemented!("Not used at the moment")
159 }
160}