@@ -517,22 +517,18 @@ impl Air for ComplianceAir {
517517 // Amount recomposition (limb 0), gated by rescue_init
518518 let limb0 = current[ cols:: AMOUNT_START ] ;
519519 let mut recomp0 = E :: ZERO ;
520- let two = E :: from ( felt_from_u64 ( 2 ) ) ;
521- let mut power = E :: ONE ;
520+ let powers = & * POWERS_OF_TWO ;
522521 for i in 0 ..32 {
523- recomp0 += current[ cols:: AMOUNT_BITS_LIMB0_START + i] * power;
524- power *= two;
522+ recomp0 += current[ cols:: AMOUNT_BITS_LIMB0_START + i] * E :: from ( powers[ i] ) ;
525523 }
526524 result[ idx] = rescue_init * ( limb0 - recomp0) ;
527525 idx += 1 ;
528526
529527 // Amount recomposition (limb 1), gated by rescue_init
530528 let limb1 = current[ cols:: AMOUNT_START + 1 ] ;
531529 let mut recomp1 = E :: ZERO ;
532- let mut power = E :: ONE ;
533530 for i in 0 ..32 {
534- recomp1 += current[ cols:: AMOUNT_BITS_LIMB1_START + i] * power;
535- power *= two;
531+ recomp1 += current[ cols:: AMOUNT_BITS_LIMB1_START + i] * E :: from ( powers[ i] ) ;
536532 }
537533 result[ idx] = rescue_init * ( limb1 - recomp1) ;
538534 idx += 1 ;
@@ -554,21 +550,17 @@ impl Air for ComplianceAir {
554550 // Diff recomposition (limb 0), gated by rescue_init
555551 let diff0 = current[ cols:: diff ( 0 ) ] ;
556552 let mut diff_recomp0 = E :: ZERO ;
557- let mut power = E :: ONE ;
558553 for i in 0 ..32 {
559- diff_recomp0 += current[ cols:: DIFF_BITS_LIMB0_START + i] * power;
560- power *= two;
554+ diff_recomp0 += current[ cols:: DIFF_BITS_LIMB0_START + i] * E :: from ( powers[ i] ) ;
561555 }
562556 result[ idx] = rescue_init * ( diff0 - diff_recomp0) ;
563557 idx += 1 ;
564558
565559 // Diff recomposition (limb 1), gated by rescue_init
566560 let diff1 = current[ cols:: diff ( 1 ) ] ;
567561 let mut diff_recomp1 = E :: ZERO ;
568- let mut power = E :: ONE ;
569562 for i in 0 ..32 {
570- diff_recomp1 += current[ cols:: DIFF_BITS_LIMB1_START + i] * power;
571- power *= two;
563+ diff_recomp1 += current[ cols:: DIFF_BITS_LIMB1_START + i] * E :: from ( powers[ i] ) ;
572564 }
573565 result[ idx] = rescue_init * ( diff1 - diff_recomp1) ;
574566 idx += 1 ;
@@ -581,7 +573,7 @@ impl Air for ComplianceAir {
581573 }
582574
583575 // Subtraction constraints for limbs 0-1, gated by rescue_init
584- let two_pow_32 = E :: from ( felt_from_u64 ( 1u64 << 32 ) ) ;
576+ let two_pow_32 = E :: from ( * TWO_POW_32_FELT ) ;
585577 let threshold_low = current[ cols:: THRESHOLD_START ] ;
586578 let threshold_high = current[ cols:: THRESHOLD_START + 1 ] ;
587579 let borrow0 = current[ cols:: borrow ( 0 ) ] ;
@@ -675,6 +667,21 @@ fn pow7<E: FieldElement<BaseField = Felt>>(x: E) -> E {
675667 x6 * x
676668}
677669
670+ /// Precomputed powers of 2 as Felt values for bit recomposition (avoids repeated multiplication)
671+ static POWERS_OF_TWO : std:: sync:: LazyLock < [ Felt ; 32 ] > = std:: sync:: LazyLock :: new ( || {
672+ let mut powers = [ FELT_ZERO ; 32 ] ;
673+ let mut p = 1u64 ;
674+ for power in & mut powers {
675+ * power = felt_from_u64 ( p) ;
676+ p <<= 1 ;
677+ }
678+ powers
679+ } ) ;
680+
681+ /// Precomputed 2^32 as Felt
682+ static TWO_POW_32_FELT : std:: sync:: LazyLock < Felt > =
683+ std:: sync:: LazyLock :: new ( || felt_from_u64 ( 1u64 << 32 ) ) ;
684+
678685/// Precomputed MDS matrix as Felt values (avoids u64→Felt conversion on hot path)
679686static MDS_FELT : std:: sync:: LazyLock < [ [ Felt ; RESCUE_STATE_WIDTH ] ; RESCUE_STATE_WIDTH ] > =
680687 std:: sync:: LazyLock :: new ( || {
0 commit comments