1
- use std:: { cell:: RefCell , ops:: Deref , rc:: Rc } ;
1
+ use std:: { cell:: RefCell , iter , ops:: Deref , rc:: Rc } ;
2
2
3
+ use itertools:: { zip_eq, Itertools } ;
3
4
use num_bigint:: { BigInt , BigUint , Sign } ;
4
5
use num_traits:: Zero ;
5
6
use openvm_circuit_primitives:: {
@@ -209,6 +210,9 @@ pub struct FieldExpr {
209
210
pub check_carry_mod_to_zero : CheckCarryModToZeroSubAir ,
210
211
211
212
pub range_bus : VariableRangeCheckerBus ,
213
+
214
+ // any values other than the prime modulus that need to be checked at setup
215
+ pub setup_values : Vec < BigUint > ,
212
216
}
213
217
214
218
impl FieldExpr {
@@ -229,8 +233,20 @@ impl FieldExpr {
229
233
builder,
230
234
check_carry_mod_to_zero : subair,
231
235
range_bus,
236
+ setup_values : vec ! [ ] ,
232
237
}
233
238
}
239
+
240
+ pub fn new_with_setup_values (
241
+ builder : ExprBuilder ,
242
+ range_bus : VariableRangeCheckerBus ,
243
+ needs_setup : bool ,
244
+ setup_values : Vec < BigUint > ,
245
+ ) -> Self {
246
+ let mut ret = Self :: new ( builder, range_bus, needs_setup) ;
247
+ ret. setup_values = setup_values;
248
+ ret
249
+ }
234
250
}
235
251
236
252
impl Deref for FieldExpr {
@@ -295,18 +311,27 @@ impl<AB: InteractionBuilder> SubAir<AB> for FieldExpr {
295
311
// however this has the challenge that when the same chip is used
296
312
// across continuation segments,
297
313
// only the first segment will have setup called
298
- for i in 0 ..inputs[ 0 ] . len ( ) . max ( self . builder . prime_limbs . len ( ) ) {
299
- let lhs = if i < inputs[ 0 ] . len ( ) {
300
- inputs[ 0 ] [ i] . into ( )
301
- } else {
302
- AB :: Expr :: ZERO
303
- } ;
304
- let rhs = if i < self . builder . prime_limbs . len ( ) {
305
- AB :: Expr :: from_canonical_usize ( self . builder . prime_limbs [ i] )
306
- } else {
307
- AB :: Expr :: ZERO
308
- } ;
309
- builder. when ( is_setup. clone ( ) ) . assert_eq ( lhs, rhs) ;
314
+
315
+ let expected = iter:: empty ( )
316
+ . chain ( self . builder . prime_limbs . clone ( ) )
317
+ . chain ( self . setup_values . iter ( ) . flat_map ( |x| {
318
+ big_uint_to_num_limbs ( x, self . builder . limb_bits , self . builder . num_limbs )
319
+ . into_iter ( )
320
+ } ) )
321
+ . collect_vec ( ) ;
322
+
323
+ let reads: Vec < AB :: Expr > = inputs
324
+ . clone ( )
325
+ . into_iter ( )
326
+ . flatten ( )
327
+ . map ( Into :: into)
328
+ . take ( expected. len ( ) )
329
+ . collect ( ) ;
330
+
331
+ for ( lhs, rhs) in zip_eq ( & reads, expected) {
332
+ builder
333
+ . when ( is_setup. clone ( ) )
334
+ . assert_eq ( lhs. clone ( ) , AB :: F :: from_canonical_usize ( rhs) ) ;
310
335
}
311
336
}
312
337
0 commit comments