• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

TritonVM / triton-vm / 10825170249

12 Sep 2024 06:08AM UTC coverage: 98.369%. Remained the same
10825170249

push

github

jan-ferdinand
chore: Use “main” & “aux over “base” & “ext”

This completes the transition started in 07fdf159.

changelog: ignore

546 of 558 new or added lines in 17 files covered. (97.85%)

30 existing lines in 4 files now uncovered.

23038 of 23420 relevant lines covered (98.37%)

7954849.83 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.32
/triton-constraint-builder/src/substitutions.rs
1
use constraint_circuit::BinOp;
2
use constraint_circuit::CircuitExpression;
3
use constraint_circuit::ConstraintCircuit;
4
use constraint_circuit::ConstraintCircuitMonad;
5
use constraint_circuit::DegreeLoweringInfo;
6
use constraint_circuit::DualRowIndicator;
7
use constraint_circuit::InputIndicator;
8
use constraint_circuit::SingleRowIndicator;
9
use itertools::Itertools;
10
use proc_macro2::TokenStream;
11
use quote::format_ident;
12
use quote::quote;
13

14
use crate::codegen::RustBackend;
15

16
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
17
pub struct AllSubstitutions {
18
    pub main: Substitutions,
19
    pub aux: Substitutions,
20
}
21

22
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
23
pub struct Substitutions {
24
    pub lowering_info: DegreeLoweringInfo,
25
    pub init: Vec<ConstraintCircuitMonad<SingleRowIndicator>>,
26
    pub cons: Vec<ConstraintCircuitMonad<SingleRowIndicator>>,
27
    pub tran: Vec<ConstraintCircuitMonad<DualRowIndicator>>,
28
    pub term: Vec<ConstraintCircuitMonad<SingleRowIndicator>>,
29
}
30

31
impl AllSubstitutions {
32
    /// Generate code that evaluates all substitution rules in order.
33
    /// This includes generating the columns that are to be filled using the substitution rules.
34
    pub fn generate_degree_lowering_table_code(&self) -> TokenStream {
2✔
35
        let num_new_main_cols = self.main.len();
2✔
36
        let num_new_aux_cols = self.aux.len();
2✔
37

38
        // A zero-variant enum cannot be annotated with `repr(usize)`.
39
        let main_repr_usize = match num_new_main_cols {
2✔
40
            0 => quote!(),
×
41
            _ => quote!(#[repr(usize)]),
2✔
42
        };
43
        let aux_repr_usize = match num_new_aux_cols {
2✔
44
            0 => quote!(),
1✔
45
            _ => quote!(#[repr(usize)]),
1✔
46
        };
47

48
        let main_columns = (0..num_new_main_cols)
2✔
49
            .map(|i| format_ident!("DegreeLoweringMainCol{i}"))
227✔
50
            .map(|ident| quote!(#ident))
227✔
51
            .collect_vec();
2✔
52
        let aux_columns = (0..num_new_aux_cols)
2✔
53
            .map(|i| format_ident!("DegreeLoweringAuxCol{i}"))
38✔
54
            .map(|ident| quote!(#ident))
38✔
55
            .collect_vec();
2✔
56

2✔
57
        let fill_main_columns_code = self.main.generate_fill_main_columns_code();
2✔
58
        let fill_aux_columns_code = self.aux.generate_fill_aux_columns_code();
2✔
59

2✔
60
        quote!(
2✔
61
            use ndarray::Array1;
2✔
62
            use ndarray::s;
2✔
63
            use ndarray::ArrayView2;
2✔
64
            use ndarray::ArrayViewMut2;
2✔
65
            use ndarray::Axis;
2✔
66
            use ndarray::Zip;
2✔
67
            use strum::Display;
2✔
68
            use strum::EnumCount;
2✔
69
            use strum::EnumIter;
2✔
70
            use twenty_first::prelude::BFieldElement;
2✔
71
            use twenty_first::prelude::XFieldElement;
2✔
72
            use air::table_column::MasterMainColumn;
2✔
73
            use air::table_column::MasterAuxColumn;
2✔
74

2✔
75
            use crate::challenges::Challenges;
2✔
76
            use crate::table::master_table::MasterTable;
2✔
77

2✔
78
            #main_repr_usize
2✔
79
            #[derive(Debug, Display, Copy, Clone, Eq, PartialEq, Hash, EnumCount, EnumIter)]
2✔
80
            pub enum DegreeLoweringMainColumn {
2✔
81
                #(#main_columns),*
2✔
82
            }
2✔
83

2✔
84
            impl MasterMainColumn for DegreeLoweringMainColumn {
2✔
85
                fn main_index(&self) -> usize {
2✔
86
                    (*self) as usize
2✔
87
                }
2✔
88

2✔
89
                fn master_main_index(&self) -> usize {
2✔
90
                    // hardcore domain-specific knowledge, and bad style
2✔
91
                    air::table::U32_TABLE_END + self.main_index()
2✔
92
                }
2✔
93
            }
2✔
94

2✔
95
            #aux_repr_usize
2✔
96
            #[derive(Debug, Display, Copy, Clone, Eq, PartialEq, Hash, EnumCount, EnumIter)]
2✔
97
            pub enum DegreeLoweringAuxColumn {
2✔
98
                #(#aux_columns),*
2✔
99
            }
2✔
100

2✔
101
            impl MasterAuxColumn for DegreeLoweringAuxColumn {
2✔
102
                fn aux_index(&self) -> usize {
2✔
103
                    (*self) as usize
2✔
104
                }
2✔
105

2✔
106
                fn master_aux_index(&self) -> usize {
2✔
107
                    // hardcore domain-specific knowledge, and bad style
2✔
108
                    air::table::AUX_U32_TABLE_END + self.aux_index()
2✔
109
                }
2✔
110
            }
2✔
111

2✔
112
            #[derive(Debug, Copy, Clone, Eq, PartialEq)]
2✔
113
            pub struct DegreeLoweringTable;
2✔
114

2✔
115
            impl DegreeLoweringTable {
2✔
116
                #fill_main_columns_code
2✔
117
                #fill_aux_columns_code
2✔
118
            }
2✔
119
        )
2✔
120
    }
2✔
121
}
122

123
impl Substitutions {
124
    fn len(&self) -> usize {
4✔
125
        self.init.len() + self.cons.len() + self.tran.len() + self.term.len()
4✔
126
    }
4✔
127

128
    fn generate_fill_main_columns_code(&self) -> TokenStream {
2✔
129
        let derived_section_init_start = self.lowering_info.num_main_cols;
2✔
130
        let derived_section_cons_start = derived_section_init_start + self.init.len();
2✔
131
        let derived_section_tran_start = derived_section_cons_start + self.cons.len();
2✔
132
        let derived_section_term_start = derived_section_tran_start + self.tran.len();
2✔
133

2✔
134
        let init_substitutions = Self::several_substitution_rules_to_code(&self.init);
2✔
135
        let cons_substitutions = Self::several_substitution_rules_to_code(&self.cons);
2✔
136
        let tran_substitutions = Self::several_substitution_rules_to_code(&self.tran);
2✔
137
        let term_substitutions = Self::several_substitution_rules_to_code(&self.term);
2✔
138

2✔
139
        let init_substitutions =
2✔
140
            Self::main_single_row_substitutions(derived_section_init_start, &init_substitutions);
2✔
141
        let cons_substitutions =
2✔
142
            Self::main_single_row_substitutions(derived_section_cons_start, &cons_substitutions);
2✔
143
        let tran_substitutions =
2✔
144
            Self::main_dual_row_substitutions(derived_section_tran_start, &tran_substitutions);
2✔
145
        let term_substitutions =
2✔
146
            Self::main_single_row_substitutions(derived_section_term_start, &term_substitutions);
2✔
147

2✔
148
        quote!(
2✔
149
            #[allow(unused_variables)]
2✔
150
            pub fn fill_derived_main_columns(
2✔
151
                mut master_main_table: ArrayViewMut2<BFieldElement>
2✔
152
            ) {
2✔
153
                let num_expected_columns =
2✔
154
                    crate::table::master_table::MasterMainTable::NUM_COLUMNS;
2✔
155
                assert_eq!(num_expected_columns, master_main_table.ncols());
2✔
156
                #init_substitutions
2✔
157
                #cons_substitutions
2✔
158
                #tran_substitutions
2✔
159
                #term_substitutions
2✔
160
            }
2✔
161
        )
2✔
162
    }
2✔
163

164
    fn generate_fill_aux_columns_code(&self) -> TokenStream {
2✔
165
        let derived_section_init_start = self.lowering_info.num_aux_cols;
2✔
166
        let derived_section_cons_start = derived_section_init_start + self.init.len();
2✔
167
        let derived_section_tran_start = derived_section_cons_start + self.cons.len();
2✔
168
        let derived_section_term_start = derived_section_tran_start + self.tran.len();
2✔
169

2✔
170
        let init_substitutions = Self::several_substitution_rules_to_code(&self.init);
2✔
171
        let cons_substitutions = Self::several_substitution_rules_to_code(&self.cons);
2✔
172
        let tran_substitutions = Self::several_substitution_rules_to_code(&self.tran);
2✔
173
        let term_substitutions = Self::several_substitution_rules_to_code(&self.term);
2✔
174

2✔
175
        let init_substitutions =
2✔
176
            Self::aux_single_row_substitutions(derived_section_init_start, &init_substitutions);
2✔
177
        let cons_substitutions =
2✔
178
            Self::aux_single_row_substitutions(derived_section_cons_start, &cons_substitutions);
2✔
179
        let tran_substitutions =
2✔
180
            Self::aux_dual_row_substitutions(derived_section_tran_start, &tran_substitutions);
2✔
181
        let term_substitutions =
2✔
182
            Self::aux_single_row_substitutions(derived_section_term_start, &term_substitutions);
2✔
183

2✔
184
        quote!(
2✔
185
            #[allow(unused_variables)]
2✔
186
            #[allow(unused_mut)]
2✔
187
            pub fn fill_derived_aux_columns(
2✔
188
                master_main_table: ArrayView2<BFieldElement>,
2✔
189
                mut master_aux_table: ArrayViewMut2<XFieldElement>,
2✔
190
                challenges: &Challenges,
2✔
191
            ) {
2✔
192
                let num_expected_main_columns =
2✔
193
                    crate::table::master_table::MasterMainTable::NUM_COLUMNS;
2✔
194
                let num_expected_aux_columns =
2✔
195
                    crate::table::master_table::MasterAuxTable::NUM_COLUMNS;
2✔
196
                assert_eq!(num_expected_main_columns, master_main_table.ncols());
2✔
197
                assert_eq!(num_expected_aux_columns, master_aux_table.ncols());
2✔
198
                assert_eq!(master_main_table.nrows(), master_aux_table.nrows());
2✔
199
                #init_substitutions
2✔
200
                #cons_substitutions
2✔
201
                #tran_substitutions
2✔
202
                #term_substitutions
2✔
203
            }
2✔
204
        )
2✔
205
    }
2✔
206

207
    fn several_substitution_rules_to_code<II: InputIndicator>(
16✔
208
        substitution_rules: &[ConstraintCircuitMonad<II>],
16✔
209
    ) -> Vec<TokenStream> {
16✔
210
        substitution_rules
16✔
211
            .iter()
16✔
212
            .map(|c| Self::substitution_rule_to_code(c.circuit.borrow().to_owned()))
265✔
213
            .collect()
16✔
214
    }
16✔
215

216
    /// Given a substitution rule, i.e., a `ConstraintCircuit` of the form `x - expr`, generate code
217
    /// that evaluates `expr`.
218
    fn substitution_rule_to_code<II: InputIndicator>(
265✔
219
        circuit: ConstraintCircuit<II>,
265✔
220
    ) -> TokenStream {
265✔
221
        let CircuitExpression::BinOp(BinOp::Add, new_var, expr) = circuit.expression else {
265✔
UNCOV
222
            panic!("Substitution rule must be a subtraction, i.e., addition of `x` and `-expr`.");
×
223
        };
224
        let CircuitExpression::Input(_) = new_var.borrow().expression else {
265✔
UNCOV
225
            panic!("Substitution rule must be a simple substitution.");
×
226
        };
227
        let expr = expr.borrow();
265✔
228
        let CircuitExpression::BinOp(BinOp::Mul, neg_one, expr) = &expr.expression else {
265✔
UNCOV
229
            panic!("Substitution rule must be a subtraction.");
×
230
        };
231
        assert!(neg_one.borrow().is_neg_one());
265✔
232

233
        let expr = expr.borrow();
265✔
234
        RustBackend::default().evaluate_single_node(&expr)
265✔
235
    }
265✔
236

237
    fn main_single_row_substitutions(
6✔
238
        section_start_index: usize,
6✔
239
        substitutions: &[TokenStream],
6✔
240
    ) -> TokenStream {
6✔
241
        let num_substitutions = substitutions.len();
6✔
242
        let indices = (0..num_substitutions).collect_vec();
6✔
243
        if indices.is_empty() {
6✔
244
            return quote!();
3✔
245
        }
3✔
246
        quote!(
3✔
247
            let (original_part, mut current_section) =
3✔
248
                master_main_table.multi_slice_mut(
3✔
249
                    (
3✔
250
                        s![.., 0..#section_start_index],
3✔
251
                        s![.., #section_start_index..#section_start_index+#num_substitutions],
3✔
252
                    )
3✔
253
                );
3✔
254
            Zip::from(original_part.rows())
3✔
255
                .and(current_section.rows_mut())
3✔
256
                .par_for_each(|original_row, mut section_row| {
3✔
257
                    let mut main_row = original_row.to_owned();
3✔
258
                    #(
3✔
259
                        section_row[#indices] = #substitutions;
3✔
260
                        main_row.push(Axis(0), section_row.slice(s![#indices])).unwrap();
3✔
261
                    )*
3✔
262
                });
3✔
263
        )
3✔
264
    }
6✔
265

266
    fn main_dual_row_substitutions(
2✔
267
        section_start_index: usize,
2✔
268
        substitutions: &[TokenStream],
2✔
269
    ) -> TokenStream {
2✔
270
        let num_substitutions = substitutions.len();
2✔
271
        let indices = (0..substitutions.len()).collect_vec();
2✔
272
        if indices.is_empty() {
2✔
273
            return quote!();
1✔
274
        }
1✔
275
        quote!(
1✔
276
            let num_rows = master_main_table.nrows();
1✔
277
            let (original_part, mut current_section) =
1✔
278
                master_main_table.multi_slice_mut(
1✔
279
                    (
1✔
280
                        s![.., 0..#section_start_index],
1✔
281
                        s![.., #section_start_index..#section_start_index+#num_substitutions],
1✔
282
                    )
1✔
283
                );
1✔
284
            let row_indices = Array1::from_vec((0..num_rows - 1).collect::<Vec<_>>());
1✔
285
            Zip::from(current_section.slice_mut(s![0..num_rows-1, ..]).rows_mut())
1✔
286
                .and(row_indices.view())
1✔
287
                .par_for_each( |mut section_row, &current_row_index| {
1✔
288
                    let next_row_index = current_row_index + 1;
1✔
289
                    let current_main_row_slice = original_part.slice(s![current_row_index..=current_row_index, ..]);
1✔
290
                    let next_main_row_slice = original_part.slice(s![next_row_index..=next_row_index, ..]);
1✔
291
                    let mut current_main_row = current_main_row_slice.row(0).to_owned();
1✔
292
                    let next_main_row = next_main_row_slice.row(0);
1✔
293
                    #(
1✔
294
                        section_row[#indices] = #substitutions;
1✔
295
                        current_main_row.push(Axis(0), section_row.slice(s![#indices])).unwrap();
1✔
296
                    )*
1✔
297
                });
1✔
298
        )
1✔
299
    }
2✔
300

301
    fn aux_single_row_substitutions(
6✔
302
        section_start_index: usize,
6✔
303
        substitutions: &[TokenStream],
6✔
304
    ) -> TokenStream {
6✔
305
        let num_substitutions = substitutions.len();
6✔
306
        let indices = (0..substitutions.len()).collect_vec();
6✔
307
        if indices.is_empty() {
6✔
308
            return quote!();
6✔
UNCOV
309
        }
×
310
        quote!(
×
311
            let (original_part, mut current_section) = master_aux_table.multi_slice_mut(
×
312
                (
×
313
                    s![.., 0..#section_start_index],
×
314
                    s![.., #section_start_index..#section_start_index+#num_substitutions],
×
315
                )
×
316
            );
×
317
            Zip::from(master_main_table.rows())
×
318
                .and(original_part.rows())
×
319
                .and(current_section.rows_mut())
×
320
                .par_for_each(
×
321
                    |main_table_row, original_row, mut section_row| {
×
322
                        let mut auxiliary_row = original_row.to_owned();
×
323
                        #(
×
324
                            let (original_row_auxiliary_row, mut det_col) =
×
325
                                section_row.multi_slice_mut((s![..#indices],s![#indices..=#indices]));
×
326
                            det_col[0] = #substitutions;
×
327
                            auxiliary_row.push(Axis(0), det_col.slice(s![0])).unwrap();
×
328
                        )*
×
329
                    }
×
330
                );
×
331
        )
×
332
    }
6✔
333

334
    fn aux_dual_row_substitutions(
2✔
335
        section_start_index: usize,
2✔
336
        substitutions: &[TokenStream],
2✔
337
    ) -> TokenStream {
2✔
338
        let num_substitutions = substitutions.len();
2✔
339
        let indices = (0..substitutions.len()).collect_vec();
2✔
340
        if indices.is_empty() {
2✔
341
            return quote!();
1✔
342
        }
1✔
343
        quote!(
1✔
344
            let num_rows = master_main_table.nrows();
1✔
345
            let (original_part, mut current_section) = master_aux_table.multi_slice_mut(
1✔
346
                (
1✔
347
                    s![.., 0..#section_start_index],
1✔
348
                    s![.., #section_start_index..#section_start_index+#num_substitutions],
1✔
349
                )
1✔
350
            );
1✔
351
            let row_indices = Array1::from_vec((0..num_rows - 1).collect::<Vec<_>>());
1✔
352
            Zip::from(current_section.slice_mut(s![0..num_rows-1, ..]).rows_mut())
1✔
353
                .and(row_indices.view())
1✔
354
                .par_for_each(|mut section_row, &current_row_index| {
1✔
355
                    let next_row_index = current_row_index + 1;
1✔
356
                    let current_main_row = master_main_table.row(current_row_index);
1✔
357
                    let next_main_row = master_main_table.row(next_row_index);
1✔
358
                    let mut current_aux_row = original_part.row(current_row_index).to_owned();
1✔
359
                    let next_aux_row = original_part.row(next_row_index);
1✔
360
                    #(
1✔
361
                        section_row[#indices]= #substitutions;
1✔
362
                        current_aux_row.push(Axis(0), section_row.slice(s![#indices])).unwrap();
1✔
363
                    )*
1✔
364
                });
1✔
365
        )
1✔
366
    }
2✔
367
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc