@@ -61,6 +61,7 @@ pub struct MemcpyIterCols<T> {
61
61
pub shift : [ T ; 2 ] ,
62
62
pub is_valid : T ,
63
63
pub is_valid_not_start : T ,
64
+ pub is_shift_non_zero : T ,
64
65
// -1 for the first iteration, 1 for the last iteration, 0 for the middle iterations
65
66
pub is_boundary : T ,
66
67
pub data_1 : [ T ; MEMCPY_LOOP_NUM_LIMBS ] ,
@@ -105,8 +106,7 @@ impl<AB: InteractionBuilder> Air<AB> for MemcpyIterAir {
105
106
} ;
106
107
107
108
let shift = local. shift [ 0 ] * AB :: Expr :: TWO + local. shift [ 1 ] ;
108
- let is_shift_non_zero = or :: < AB :: Expr > ( local. shift [ 0 ] , local. shift [ 1 ] ) ;
109
- let is_shift_zero = not :: < AB :: Expr > ( is_shift_non_zero. clone ( ) ) ;
109
+ let is_shift_zero = not :: < AB :: Expr > ( local. is_shift_non_zero . clone ( ) ) ;
110
110
let is_shift_one = and :: < AB :: Expr > ( local. shift [ 0 ] , not :: < AB :: Expr > ( local. shift [ 1 ] ) ) ;
111
111
let is_shift_two = and :: < AB :: Expr > ( not :: < AB :: Expr > ( local. shift [ 0 ] ) , local. shift [ 1 ] ) ;
112
112
let is_shift_three = and :: < AB :: Expr > ( local. shift [ 0 ] , local. shift [ 1 ] ) ;
@@ -122,6 +122,8 @@ impl<AB: InteractionBuilder> Air<AB> for MemcpyIterAir {
122
122
123
123
let len = local. len [ 0 ]
124
124
+ local. len [ 1 ] * AB :: Expr :: from_canonical_u32 ( 1 << ( 2 * MEMCPY_LOOP_LIMB_BITS ) ) ;
125
+ let prev_len = prev. len [ 0 ]
126
+ + prev. len [ 1 ] * AB :: Expr :: from_canonical_u32 ( 1 << ( 2 * MEMCPY_LOOP_LIMB_BITS ) ) ;
125
127
126
128
// write_data =
127
129
// (local.data_1[shift..4], prev.data_4[0..shift]),
@@ -165,6 +167,7 @@ impl<AB: InteractionBuilder> Air<AB> for MemcpyIterAir {
165
167
builder. assert_bool ( local. is_valid ) ;
166
168
local. shift . iter ( ) . for_each ( |x| builder. assert_bool ( * x) ) ;
167
169
builder. assert_bool ( local. is_valid_not_start ) ;
170
+ builder. assert_bool ( local. is_shift_non_zero ) ;
168
171
// is_boundary is either -1, 0 or 1
169
172
builder. assert_tern ( local. is_boundary + AB :: Expr :: ONE ) ;
170
173
@@ -174,6 +177,9 @@ impl<AB: InteractionBuilder> Air<AB> for MemcpyIterAir {
174
177
and :: < AB :: Expr > ( local. is_valid , is_not_start) ,
175
178
) ;
176
179
180
+ // is_shift_non_zero is correct
181
+ builder. assert_eq ( local. is_shift_non_zero , or :: < AB :: Expr > ( local. shift [ 0 ] , local. shift [ 1 ] ) ) ;
182
+
177
183
// if !is_valid, then is_boundary = 0, shift = 0 (we will use this assumption later)
178
184
let mut is_not_valid_when = builder. when ( not :: < AB :: Expr > ( local. is_valid ) ) ;
179
185
is_not_valid_when. assert_zero ( local. is_boundary ) ;
@@ -183,7 +189,7 @@ impl<AB: InteractionBuilder> Air<AB> for MemcpyIterAir {
183
189
// and dest = prev_dest + 16, shift = prev_shift
184
190
let mut is_valid_not_start_when = builder. when ( local. is_valid_not_start ) ;
185
191
is_valid_not_start_when
186
- . assert_eq ( local . len [ 0 ] , prev . len [ 0 ] - AB :: Expr :: from_canonical_u32 ( 16 ) ) ;
192
+ . assert_eq ( len. clone ( ) , prev_len - AB :: Expr :: from_canonical_u32 ( 16 ) ) ;
187
193
is_valid_not_start_when
188
194
. assert_eq ( local. source , prev. source + AB :: Expr :: from_canonical_u32 ( 16 ) ) ;
189
195
is_valid_not_start_when. assert_eq ( local. dest , prev. dest + AB :: Expr :: from_canonical_u32 ( 16 ) ) ;
@@ -199,7 +205,7 @@ impl<AB: InteractionBuilder> Air<AB> for MemcpyIterAir {
199
205
// since is_shift_non_zero degree is 2, we need to keep the degree of the condition to 1
200
206
builder
201
207
. when ( not :: < AB :: Expr > ( prev. is_valid_not_start ) - not :: < AB :: Expr > ( prev. is_valid ) )
202
- . assert_eq ( local. timestamp , prev. timestamp + is_shift_non_zero. clone ( ) ) ;
208
+ . assert_eq ( local. timestamp , prev. timestamp + local . is_shift_non_zero . clone ( ) ) ;
203
209
204
210
// if prev.is_valid_not_start and local.is_valid_not_start, then timestamp=prev_timestamp+8
205
211
// prev.is_valid_not_start is the opposite of previous condition
@@ -222,7 +228,7 @@ impl<AB: InteractionBuilder> Air<AB> for MemcpyIterAir {
222
228
+ ( local. is_boundary + AB :: Expr :: ONE ) * AB :: Expr :: from_canonical_usize ( 4 ) ,
223
229
local. dest ,
224
230
local. source ,
225
- len,
231
+ len. clone ( ) ,
226
232
( AB :: Expr :: ONE - local. is_boundary ) * shift. clone ( ) * ( AB :: F :: TWO ) . inverse ( )
227
233
+ ( local. is_boundary + AB :: Expr :: ONE ) * AB :: Expr :: TWO ,
228
234
)
@@ -241,7 +247,7 @@ impl<AB: InteractionBuilder> Air<AB> for MemcpyIterAir {
241
247
. enumerate ( )
242
248
. for_each ( |( idx, ( data, read_aux) ) | {
243
249
let is_valid_read = if idx == 3 {
244
- or :: < AB :: Expr > ( is_shift_non_zero. clone ( ) , local. is_valid_not_start )
250
+ or :: < AB :: Expr > ( local . is_shift_non_zero . clone ( ) , local. is_valid_not_start )
245
251
} else {
246
252
local. is_valid_not_start . into ( )
247
253
} ;
@@ -288,10 +294,10 @@ impl<AB: InteractionBuilder> Air<AB> for MemcpyIterAir {
288
294
) ,
289
295
] ;
290
296
self . range_bus
291
- . push ( local. len [ 0 ] , len_bits_limit[ 0 ] . clone ( ) , true )
297
+ . push ( local. len [ 0 ] . clone ( ) , len_bits_limit[ 0 ] . clone ( ) , true )
292
298
. eval ( builder, local. is_valid ) ;
293
299
self . range_bus
294
- . push ( local. len [ 1 ] , len_bits_limit[ 1 ] . clone ( ) , true )
300
+ . push ( local. len [ 1 ] . clone ( ) , len_bits_limit[ 1 ] . clone ( ) , true )
295
301
. eval ( builder, local. is_valid ) ;
296
302
}
297
303
}
@@ -688,6 +694,7 @@ impl<F: PrimeField32> TraceFiller<F> for MemcpyIterFiller {
688
694
} else {
689
695
F :: ZERO
690
696
} ;
697
+ cols. is_shift_non_zero = F :: from_canonical_u8 ( ( record. inner . shift != 0 ) as u8 ) ;
691
698
cols. is_valid_not_start = F :: from_canonical_u8 ( 1 - is_start as u8 ) ;
692
699
cols. is_valid = F :: ONE ;
693
700
cols. shift = [ record. inner . shift & 1 , record. inner . shift >> 1 ]
0 commit comments