@@ -62,7 +62,12 @@ impl QM31 {
6262 let [ c1, c2] = a. value ( ) ;
6363 let [ c3, c4] = b. value ( ) ;
6464
65- ( c1. to_raw ( ) , c2. to_raw ( ) , c3. to_raw ( ) , c4. to_raw ( ) )
65+ (
66+ c1. representative ( ) ,
67+ c2. representative ( ) ,
68+ c3. representative ( ) ,
69+ c4. representative ( ) ,
70+ )
6671 }
6772
6873 /// Packs the [QM31] into a [Felt].
@@ -208,7 +213,7 @@ mod test {
208213
209214 #[ test]
210215 fn qm31_packing ( ) {
211- const MAX : u32 = MERSENNE_31_PRIME_FIELD_ORDER - 2 ;
216+ const MAX : u32 = MERSENNE_31_PRIME_FIELD_ORDER - 1 ;
212217
213218 let cases = [
214219 [ 1 , 2 , 3 , 4 ] ,
@@ -262,4 +267,33 @@ mod test {
262267
263268 QM31 :: unpack_from_felt ( & invalid_packing) . unwrap_err ( ) ;
264269 }
270+
271+ /// Tests the QM31 packing when some coefficients have a value of PRIME.
272+ ///
273+ /// If we try to create an M31 with a value of PRIME, it won't be reduced
274+ /// to 0 internally. This tests verifies that a PRIME coefficient is being
275+ /// packed as its representative value, instead of the raw value.
276+ #[ test]
277+ fn qm31_packing_with_prime_coefficients ( ) {
278+ const PRIME : u32 = MERSENNE_31_PRIME_FIELD_ORDER ;
279+
280+ let cases = [
281+ [ PRIME , 0 , 0 , 0 ] ,
282+ [ 0 , PRIME , 0 , 0 ] ,
283+ [ 0 , 0 , PRIME , 0 ] ,
284+ [ 0 , 0 , 0 , PRIME ] ,
285+ ] ;
286+
287+ for [ c1, c2, c3, c4] in cases {
288+ let qm31 = QM31 :: from_coefficients ( c1, c2, c3, c4) ;
289+ let packed_qm31 = qm31. pack_into_felt ( ) ;
290+
291+ let expected_packing = BigInt :: from ( c1 % PRIME )
292+ + ( BigInt :: from ( c2 % PRIME ) << 36 )
293+ + ( BigInt :: from ( c3 % PRIME ) << 72 )
294+ + ( BigInt :: from ( c4 % PRIME ) << 108 ) ;
295+
296+ assert_eq ! ( packed_qm31, Felt :: from( expected_packing) )
297+ }
298+ }
265299}
0 commit comments