@@ -55,8 +55,10 @@ pub struct ProverBuilder<'a, F: IsSubFieldOf<E> + IsFFTField, E: IsField> {
5555 step_size : usize ,
5656 num_rows : usize ,
5757 accumulator : FieldElement < E > ,
58- alpha : FieldElement < E > ,
59- alpha_power : FieldElement < E > ,
58+ /// Pre-computed composition alpha powers [1, α, α², ...].
59+ /// Indexed by constraint_idx to avoid E×E multiply per constraint.
60+ alpha_powers : & ' a [ FieldElement < E > ] ,
61+ constraint_idx : usize ,
6062 rap_challenges : & ' a [ FieldElement < E > ] ,
6163 logup_alpha_powers : & ' a [ FieldElement < E > ] ,
6264 logup_table_offset_val : & ' a FieldElement < E > ,
7375 pub fn new (
7476 lde_trace : & ' a LDETraceTable < F , E > ,
7577 row : usize ,
76- alpha : & FieldElement < E > ,
78+ alpha_powers : & ' a [ FieldElement < E > ] ,
7779 rap_challenges : & ' a [ FieldElement < E > ] ,
7880 logup_alpha_powers : & ' a [ FieldElement < E > ] ,
7981 logup_table_offset : & ' a FieldElement < E > ,
8486 step_size : lde_trace. lde_step_size ,
8587 num_rows : lde_trace. num_rows ( ) ,
8688 accumulator : FieldElement :: zero ( ) ,
87- alpha : alpha . clone ( ) ,
88- alpha_power : FieldElement :: one ( ) ,
89+ alpha_powers ,
90+ constraint_idx : 0 ,
8991 rap_challenges,
9092 logup_alpha_powers,
9193 logup_table_offset_val : logup_table_offset,
@@ -101,7 +103,7 @@ where
101103 pub fn new_with_cache (
102104 lde_trace : & ' a LDETraceTable < F , E > ,
103105 row : usize ,
104- alpha : & FieldElement < E > ,
106+ alpha_powers : & ' a [ FieldElement < E > ] ,
105107 rap_challenges : & ' a [ FieldElement < E > ] ,
106108 logup_alpha_powers : & ' a [ FieldElement < E > ] ,
107109 logup_table_offset : & ' a FieldElement < E > ,
@@ -120,8 +122,8 @@ where
120122 step_size : lde_trace. lde_step_size ,
121123 num_rows : lde_trace. num_rows ( ) ,
122124 accumulator : FieldElement :: zero ( ) ,
123- alpha : alpha . clone ( ) ,
124- alpha_power : FieldElement :: one ( ) ,
125+ alpha_powers ,
126+ constraint_idx : 0 ,
125127 rap_challenges,
126128 logup_alpha_powers,
127129 logup_table_offset_val : logup_table_offset,
@@ -142,7 +144,6 @@ where
142144 #[ inline]
143145 fn main ( & self , offset : usize , col : usize ) -> FieldElement < E > {
144146 if offset == 0 && !self . main_row_cache . is_empty ( ) {
145- // Use contiguous pre-fetched cache (avoids random column-major access)
146147 self . main_row_cache [ col] . clone ( ) . to_extension ( )
147148 } else {
148149 let lde_row = ( self . row + offset * self . step_size ) % self . num_rows ;
@@ -158,8 +159,9 @@ where
158159
159160 #[ inline]
160161 fn assert_zero ( & mut self , expr : FieldElement < E > ) {
161- self . accumulator = & self . accumulator + & self . alpha_power * & expr;
162- self . alpha_power = & self . alpha_power * & self . alpha ;
162+ // Use pre-computed alpha power — no E×E multiply per constraint
163+ self . accumulator = & self . accumulator + & self . alpha_powers [ self . constraint_idx ] * & expr;
164+ self . constraint_idx += 1 ;
163165 }
164166
165167 fn challenge ( & self , idx : usize ) -> & FieldElement < E > {
@@ -187,17 +189,17 @@ where
187189
188190 #[ inline]
189191 fn assert_zero_base ( & mut self , expr : FieldElement < F > ) {
190- // F* E multiplication: 3 base muls (vs 6 for E* E)
191- self . accumulator = & self . accumulator + & expr * & self . alpha_power ;
192- self . alpha_power = & self . alpha_power * & self . alpha ;
192+ // F× E multiplication ( 3 base muls) with pre-computed alpha power (no E× E)
193+ self . accumulator = & self . accumulator + & expr * & self . alpha_powers [ self . constraint_idx ] ;
194+ self . constraint_idx += 1 ;
193195 }
194196}
195197
196198pub struct VerifierBuilder < ' a , E : IsField > {
197199 frame : & ' a Frame < E , E > ,
198200 accumulator : FieldElement < E > ,
199- alpha : FieldElement < E > ,
200- alpha_power : FieldElement < E > ,
201+ alpha_powers : & ' a [ FieldElement < E > ] ,
202+ constraint_idx : usize ,
201203 rap_challenges : & ' a [ FieldElement < E > ] ,
202204 logup_alpha_powers : & ' a [ FieldElement < E > ] ,
203205 logup_table_offset_val : & ' a FieldElement < E > ,
@@ -206,16 +208,16 @@ pub struct VerifierBuilder<'a, E: IsField> {
206208impl < ' a , E : IsField > VerifierBuilder < ' a , E > {
207209 pub fn new (
208210 frame : & ' a Frame < E , E > ,
209- alpha : & FieldElement < E > ,
211+ alpha_powers : & ' a [ FieldElement < E > ] ,
210212 rap_challenges : & ' a [ FieldElement < E > ] ,
211213 logup_alpha_powers : & ' a [ FieldElement < E > ] ,
212214 logup_table_offset : & ' a FieldElement < E > ,
213215 ) -> Self {
214216 Self {
215217 frame,
216218 accumulator : FieldElement :: zero ( ) ,
217- alpha : alpha . clone ( ) ,
218- alpha_power : FieldElement :: one ( ) ,
219+ alpha_powers ,
220+ constraint_idx : 0 ,
219221 rap_challenges,
220222 logup_alpha_powers,
221223 logup_table_offset_val : logup_table_offset,
@@ -246,8 +248,8 @@ impl<'a, E: IsField> AirBuilder<E> for VerifierBuilder<'a, E> {
246248
247249 #[ inline]
248250 fn assert_zero ( & mut self , expr : FieldElement < E > ) {
249- self . accumulator = & self . accumulator + & self . alpha_power * & expr;
250- self . alpha_power = & self . alpha_power * & self . alpha ;
251+ self . accumulator = & self . accumulator + & self . alpha_powers [ self . constraint_idx ] * & expr;
252+ self . constraint_idx += 1 ;
251253 }
252254
253255 fn challenge ( & self , idx : usize ) -> & FieldElement < E > {
@@ -275,9 +277,9 @@ impl<'a, E: IsField> MainAirBuilder<E, E> for VerifierBuilder<'a, E> {
275277
276278 #[ inline]
277279 fn assert_zero_base ( & mut self , expr : FieldElement < E > ) {
278- // E*E (same as assert_zero for verifier )
279- self . accumulator = & self . accumulator + & self . alpha_power * & expr;
280- self . alpha_power = & self . alpha_power * & self . alpha ;
280+ // Use pre-computed alpha power (same indexing as assert_zero)
281+ self . accumulator = & self . accumulator + & self . alpha_powers [ self . constraint_idx ] * & expr;
282+ self . constraint_idx += 1 ;
281283 }
282284}
283285
0 commit comments