1pub use crate::arch::{
4 packed_1::*, packed_2::*, packed_4::*, packed_8::*, packed_16::*, packed_32::*, packed_64::*,
5 packed_128::*, packed_256::*, packed_512::*, packed_aes_8::*, packed_aes_16::*,
6 packed_aes_32::*, packed_aes_64::*, packed_aes_128::*, packed_aes_256::*, packed_aes_512::*,
7};
8
9#[cfg(test)]
11pub mod test_utils {
12 use crate::{
13 BinaryField, PackedField,
14 linear_transformation::PackedTransformationFactory,
15 underlier::{U1, U2, U4, WithUnderlier},
16 };
17
18 pub struct Unit;
19
20 impl From<U1> for Unit {
21 fn from(_: U1) -> Self {
22 Self
23 }
24 }
25
26 impl From<U2> for Unit {
27 fn from(_: U2) -> Self {
28 Self
29 }
30 }
31
32 impl From<U4> for Unit {
33 fn from(_: U4) -> Self {
34 Self
35 }
36 }
37
38 impl From<u8> for Unit {
39 fn from(_: u8) -> Self {
40 Self
41 }
42 }
43
44 impl From<u16> for Unit {
45 fn from(_: u16) -> Self {
46 Self
47 }
48 }
49
50 impl From<u32> for Unit {
51 fn from(_: u32) -> Self {
52 Self
53 }
54 }
55
56 impl From<u64> for Unit {
57 fn from(_: u64) -> Self {
58 Self
59 }
60 }
61
62 impl From<u128> for Unit {
63 fn from(_: u128) -> Self {
64 Self
65 }
66 }
67
68 impl From<[u128; 2]> for Unit {
69 fn from(_: [u128; 2]) -> Self {
70 Self
71 }
72 }
73
74 impl From<[u128; 4]> for Unit {
75 fn from(_: [u128; 4]) -> Self {
76 Self
77 }
78 }
79
80 macro_rules! define_check_packed_mul {
84 ($mult_func:path, $constraint:path) => {
85 #[allow(unused)]
86 trait TestMulTrait<T> {
87 fn test_mul(_a: T, _b: T) {}
88 }
89
90 impl<T> TestMulTrait<$crate::packed_binary_field::test_utils::Unit> for T {}
91
92 struct TestMult<T>(std::marker::PhantomData<T>);
93
94 impl<T: $constraint + PackedField + $crate::underlier::WithUnderlier> TestMult<T> {
95 #[allow(unused)]
96 fn test_mul(
97 a: <T as $crate::underlier::WithUnderlier>::Underlier,
98 b: <T as $crate::underlier::WithUnderlier>::Underlier,
99 ) {
100 let a = T::from_underlier(a);
101 let b = T::from_underlier(b);
102
103 let c = $mult_func(a, b);
104 for i in 0..T::WIDTH {
105 assert_eq!(c.get(i), a.get(i) * b.get(i));
106 }
107 }
108 }
109 };
110 }
111
112 pub(crate) use define_check_packed_mul;
113
114 macro_rules! define_check_packed_square {
115 ($square_func:path, $constraint:path) => {
116 #[allow(unused)]
117 trait TestSquareTrait<T> {
118 fn test_square(_a: T) {}
119 }
120
121 impl<T> TestSquareTrait<$crate::packed_binary_field::test_utils::Unit> for T {}
122
123 struct TestSquare<T>(std::marker::PhantomData<T>);
124
125 impl<T: $constraint + PackedField + $crate::underlier::WithUnderlier> TestSquare<T> {
126 #[allow(unused)]
127 fn test_square(a: <T as $crate::underlier::WithUnderlier>::Underlier) {
128 let a = T::from_underlier(a);
129
130 let c = $square_func(a);
131 for i in 0..T::WIDTH {
132 assert_eq!(c.get(i), a.get(i) * a.get(i));
133 }
134 }
135 }
136 };
137 }
138
139 pub(crate) use define_check_packed_square;
140
141 macro_rules! define_check_packed_inverse {
142 ($invert_func:path, $constraint:path) => {
143 #[allow(unused)]
144 trait TestInvertTrait<T> {
145 fn test_invert(_a: T) {}
146 }
147
148 impl<T> TestInvertTrait<$crate::packed_binary_field::test_utils::Unit> for T {}
149
150 struct TestInvert<T>(std::marker::PhantomData<T>);
151
152 #[allow(unused)]
153 impl<T: $constraint + PackedField + $crate::underlier::WithUnderlier> TestInvert<T> {
154 fn test_invert(a: <T as $crate::underlier::WithUnderlier>::Underlier) {
155 use crate::Field;
156
157 let a = T::from_underlier(a);
158
159 let c = $invert_func(a);
160 for i in 0..T::WIDTH {
161 assert!(
162 (c.get(i).is_zero().into()
163 && a.get(i).is_zero().into()
164 && c.get(i).is_zero().into())
165 || T::Scalar::ONE == a.get(i) * c.get(i)
166 );
167 }
168 }
169 }
170 };
171 }
172
173 pub(crate) use define_check_packed_inverse;
174
175 macro_rules! define_check_packed_transformation {
176 ($constraint:path) => {
177 #[allow(unused)]
178 trait TestTransformationTrait<T> {
179 fn test_transformation(_a: T) {}
180 }
181
182 impl<T> TestTransformationTrait<$crate::packed_binary_field::test_utils::Unit> for T {}
183
184 struct TestTransformation<T>(std::marker::PhantomData<T>);
185
186 impl<T: $constraint + PackedField + $crate::underlier::WithUnderlier>
187 TestTransformation<T>
188 {
189 fn test_transformation(a: <T as $crate::underlier::WithUnderlier>::Underlier) {
190 use ::rand::prelude::*;
191 use $crate::linear_transformation::{
192 FieldLinearTransformation, Transformation,
193 };
194
195 let a = T::from_underlier(a);
196
197 let rng = StdRng::seed_from_u64(0);
199 let field_transformation =
200 FieldLinearTransformation::<T::Scalar, _>::random(rng);
201 let packed_transformation =
202 T::make_packed_transformation(field_transformation.clone());
203
204 let c = packed_transformation.transform(&a);
205 for i in 0..T::WIDTH {
206 assert_eq!(c.get(i), field_transformation.transform(&a.get(i)));
207 }
208 }
209 }
210 };
211 }
212
213 pub(crate) use define_check_packed_transformation;
214
215 macro_rules! define_multiply_tests {
218 ($mult_func:path, $constraint:path) => {
219 $crate::packed_binary_field::test_utils::define_check_packed_mul!(
220 $mult_func,
221 $constraint
222 );
223
224 proptest::proptest! {
225 #[test]
226 fn test_mul_packed_8(a_val in proptest::prelude::any::<u8>(), b_val in proptest::prelude::any::<u8>()) {
227 use $crate::arch::packed_8::*;
228 use $crate::arch::packed_aes_8::*;
229
230 TestMult::<PackedBinaryField8x1b>::test_mul(a_val.into(), b_val.into());
231 TestMult::<PackedAESBinaryField1x8b>::test_mul(a_val.into(), b_val.into());
232 }
233
234 #[test]
235 fn test_mul_packed_16(a_val in proptest::prelude::any::<u16>(), b_val in proptest::prelude::any::<u16>()) {
236 use $crate::arch::packed_16::*;
237 use $crate::arch::packed_aes_16::*;
238
239 TestMult::<PackedBinaryField16x1b>::test_mul(a_val.into(), b_val.into());
240 TestMult::<PackedAESBinaryField2x8b>::test_mul(a_val.into(), b_val.into());
241 }
242
243 #[test]
244 fn test_mul_packed_32(a_val in proptest::prelude::any::<u32>(), b_val in proptest::prelude::any::<u32>()) {
245 use $crate::arch::packed_32::*;
246 use $crate::arch::packed_aes_32::*;
247
248 TestMult::<PackedBinaryField32x1b>::test_mul(a_val.into(), b_val.into());
249 TestMult::<PackedAESBinaryField4x8b>::test_mul(a_val.into(), b_val.into());
250 }
251
252 #[test]
253 fn test_mul_packed_64(a_val in proptest::prelude::any::<u64>(), b_val in proptest::prelude::any::<u64>()) {
254 use $crate::arch::packed_64::*;
255 use $crate::arch::packed_aes_64::*;
256
257 TestMult::<PackedBinaryField64x1b>::test_mul(a_val.into(), b_val.into());
258 TestMult::<PackedAESBinaryField8x8b>::test_mul(a_val.into(), b_val.into());
259 }
260
261 #[test]
262 fn test_mul_packed_128(a_val in proptest::prelude::any::<u128>(), b_val in proptest::prelude::any::<u128>()) {
263 use $crate::arch::packed_128::*;
264 use $crate::arch::packed_aes_128::*;
265 use $crate::arch::packed_ghash_128::*;
266
267 TestMult::<PackedBinaryField128x1b>::test_mul(a_val.into(), b_val.into());
268 TestMult::<PackedAESBinaryField16x8b>::test_mul(a_val.into(), b_val.into());
269 TestMult::<PackedBinaryGhash1x128b>::test_mul(a_val.into(), b_val.into());
270 }
271
272 #[test]
273 fn test_mul_packed_256(a_val in proptest::prelude::any::<[u128; 2]>(), b_val in proptest::prelude::any::<[u128; 2]>()) {
274 use $crate::arch::packed_256::*;
275 use $crate::arch::packed_aes_256::*;
276 use $crate::arch::packed_ghash_256::*;
277
278 TestMult::<PackedBinaryField256x1b>::test_mul(a_val.into(), b_val.into());
279 TestMult::<PackedAESBinaryField32x8b>::test_mul(a_val.into(), b_val.into());
280 TestMult::<PackedBinaryGhash2x128b>::test_mul(a_val.into(), b_val.into());
281 }
282
283 #[test]
284 fn test_mul_packed_512(a_val in proptest::prelude::any::<[u128; 4]>(), b_val in proptest::prelude::any::<[u128; 4]>()) {
285 use $crate::arch::packed_512::*;
286 use $crate::arch::packed_aes_512::*;
287 use $crate::arch::packed_ghash_512::*;
288
289 TestMult::<PackedBinaryField512x1b>::test_mul(a_val.into(), b_val.into());
290 TestMult::<PackedAESBinaryField64x8b>::test_mul(a_val.into(), b_val.into());
291 TestMult::<PackedBinaryGhash4x128b>::test_mul(a_val.into(), b_val.into());
292 }
293 }
294 };
295 }
296
297 macro_rules! define_square_tests {
300 ($square_func:path, $constraint:path) => {
301 $crate::packed_binary_field::test_utils::define_check_packed_square!(
302 $square_func,
303 $constraint
304 );
305
306 proptest::proptest! {
307 #[test]
308 fn test_square_packed_8(a_val in proptest::prelude::any::<u8>()) {
309 use $crate::arch::packed_8::*;
310 use $crate::arch::packed_aes_8::*;
311
312 TestSquare::<PackedBinaryField8x1b>::test_square(a_val.into());
313 TestSquare::<PackedAESBinaryField1x8b>::test_square(a_val.into());
314 }
315
316 #[test]
317 fn test_square_packed_16(a_val in proptest::prelude::any::<u16>()) {
318 use $crate::arch::packed_16::*;
319 use $crate::arch::packed_aes_16::*;
320
321 TestSquare::<PackedBinaryField16x1b>::test_square(a_val.into());
322 TestSquare::<PackedAESBinaryField2x8b>::test_square(a_val.into());
323 }
324
325 #[test]
326 fn test_square_packed_32(a_val in proptest::prelude::any::<u32>()) {
327 use $crate::arch::packed_32::*;
328 use $crate::arch::packed_aes_32::*;
329
330 TestSquare::<PackedBinaryField32x1b>::test_square(a_val.into());
331 TestSquare::<PackedAESBinaryField4x8b>::test_square(a_val.into());
332 }
333
334 #[test]
335 fn test_square_packed_64(a_val in proptest::prelude::any::<u64>()) {
336 use $crate::arch::packed_64::*;
337 use $crate::arch::packed_aes_64::*;
338
339 TestSquare::<PackedBinaryField64x1b>::test_square(a_val.into());
340 TestSquare::<PackedAESBinaryField8x8b>::test_square(a_val.into());
341 }
342
343 #[test]
344 fn test_square_packed_128(a_val in proptest::prelude::any::<u128>()) {
345 use $crate::arch::packed_128::*;
346 use $crate::arch::packed_aes_128::*;
347 use $crate::arch::packed_ghash_128::*;
348
349 TestSquare::<PackedBinaryField128x1b>::test_square(a_val.into());
350 TestSquare::<PackedAESBinaryField16x8b>::test_square(a_val.into());
351 TestSquare::<PackedBinaryGhash1x128b>::test_square(a_val.into());
352 }
353
354 #[test]
355 fn test_square_packed_256(a_val in proptest::prelude::any::<[u128; 2]>()) {
356 use $crate::arch::packed_256::*;
357 use $crate::arch::packed_aes_256::*;
358 use $crate::arch::packed_ghash_256::*;
359
360 TestSquare::<PackedBinaryField256x1b>::test_square(a_val.into());
361 TestSquare::<PackedAESBinaryField32x8b>::test_square(a_val.into());
362 TestSquare::<PackedBinaryGhash2x128b>::test_square(a_val.into());
363 }
364
365 #[test]
366 fn test_square_packed_512(a_val in proptest::prelude::any::<[u128; 4]>()) {
367 use $crate::arch::packed_512::*;
368 use $crate::arch::packed_aes_512::*;
369 use $crate::arch::packed_ghash_512::*;
370
371 TestSquare::<PackedBinaryField512x1b>::test_square(a_val.into());
372 TestSquare::<PackedAESBinaryField64x8b>::test_square(a_val.into());
373 TestSquare::<PackedBinaryGhash4x128b>::test_square(a_val.into());
374 }
375 }
376 };
377 }
378
379 macro_rules! define_invert_tests {
382 ($invert_func:path, $constraint:path) => {
383 $crate::packed_binary_field::test_utils::define_check_packed_inverse!(
384 $invert_func,
385 $constraint
386 );
387
388 proptest::proptest! {
389 #[test]
390 fn test_invert_packed_8(a_val in proptest::prelude::any::<u8>()) {
391 use $crate::arch::packed_8::*;
392 use $crate::arch::packed_aes_8::*;
393
394 TestInvert::<PackedBinaryField8x1b>::test_invert(a_val.into());
395 TestInvert::<PackedAESBinaryField1x8b>::test_invert(a_val.into());
396 }
397
398 #[test]
399 fn test_invert_packed_16(a_val in proptest::prelude::any::<u16>()) {
400 use $crate::arch::packed_16::*;
401 use $crate::arch::packed_aes_16::*;
402
403 TestInvert::<PackedBinaryField16x1b>::test_invert(a_val.into());
404 TestInvert::<PackedAESBinaryField2x8b>::test_invert(a_val.into());
405 }
406
407 #[test]
408 fn test_invert_packed_32(a_val in proptest::prelude::any::<u32>()) {
409 use $crate::arch::packed_32::*;
410 use $crate::arch::packed_aes_32::*;
411
412 TestInvert::<PackedBinaryField32x1b>::test_invert(a_val.into());
413 TestInvert::<PackedAESBinaryField4x8b>::test_invert(a_val.into());
414 }
415
416 #[test]
417 fn test_invert_packed_64(a_val in proptest::prelude::any::<u64>()) {
418 use $crate::arch::packed_64::*;
419 use $crate::arch::packed_aes_64::*;
420
421 TestInvert::<PackedBinaryField64x1b>::test_invert(a_val.into());
422 TestInvert::<PackedAESBinaryField8x8b>::test_invert(a_val.into());
423 }
424
425 #[test]
426 fn test_invert_packed_128(a_val in proptest::prelude::any::<u128>()) {
427 use $crate::arch::packed_128::*;
428 use $crate::arch::packed_aes_128::*;
429 use $crate::arch::packed_ghash_128::*;
430
431 TestInvert::<PackedBinaryField128x1b>::test_invert(a_val.into());
432 TestInvert::<PackedAESBinaryField16x8b>::test_invert(a_val.into());
433 TestInvert::<PackedBinaryGhash1x128b>::test_invert(a_val.into());
434 }
435
436 #[test]
437 fn test_invert_packed_256(a_val in proptest::prelude::any::<[u128; 2]>()) {
438 use $crate::arch::packed_256::*;
439 use $crate::arch::packed_aes_256::*;
440 use $crate::arch::packed_ghash_256::*;
441
442 TestInvert::<PackedBinaryField256x1b>::test_invert(a_val.into());
443 TestInvert::<PackedAESBinaryField32x8b>::test_invert(a_val.into());
444 TestInvert::<PackedBinaryGhash2x128b>::test_invert(a_val.into());
445 }
446
447 #[test]
448 fn test_invert_packed_512(a_val in proptest::prelude::any::<[u128; 4]>()) {
449 use $crate::arch::packed_512::*;
450 use $crate::arch::packed_aes_512::*;
451 use $crate::arch::packed_ghash_512::*;
452
453 TestInvert::<PackedBinaryField512x1b>::test_invert(a_val.into());
454 TestInvert::<PackedAESBinaryField64x8b>::test_invert(a_val.into());
455 TestInvert::<PackedBinaryGhash4x128b>::test_invert(a_val.into());
456 }
457 }
458 };
459 }
460
461 macro_rules! define_transformation_tests {
464 ($constraint:path) => {
465 $crate::packed_binary_field::test_utils::define_check_packed_transformation!(
466 $constraint
467 );
468
469 proptest::proptest! {
470 #[test]
471 fn test_transformation_packed_1(a_val in 0..2u8) {
472 use crate::arch::packed_1::*;
473
474 TestTransformation::<PackedBinaryField1x1b>::test_transformation($crate::underlier::U1::new_unchecked(a_val).into());
475 }
476
477 #[test]
478 fn test_transformation_packed_2(a_val in 0..4u8) {
479 use crate::arch::packed_2::*;
480
481 TestTransformation::<PackedBinaryField2x1b>::test_transformation($crate::underlier::U2::new_unchecked(a_val).into());
482 }
483
484 #[test]
485 fn test_transformation_packed_4(a_val in 0..16u8) {
486 use crate::arch::packed_4::*;
487
488 TestTransformation::<PackedBinaryField4x1b>::test_transformation($crate::underlier::U4::new_unchecked(a_val).into());
489 }
490
491 #[test]
492 fn test_transformation_packed_8(a_val in proptest::prelude::any::<u8>()) {
493 use crate::arch::packed_8::*;
494 use crate::arch::packed_aes_8::*;
495
496 TestTransformation::<PackedBinaryField8x1b>::test_transformation(a_val.into());
497 TestTransformation::<PackedAESBinaryField1x8b>::test_transformation(a_val.into());
498 }
499
500 #[test]
501 fn test_transformation_packed_16(a_val in proptest::prelude::any::<u16>()) {
502 use crate::arch::packed_16::*;
503 use crate::arch::packed_aes_16::*;
504
505 TestTransformation::<PackedBinaryField16x1b>::test_transformation(a_val.into());
506 TestTransformation::<PackedAESBinaryField2x8b>::test_transformation(a_val.into());
507 }
508
509 #[test]
510 fn test_transformation_packed_32(a_val in proptest::prelude::any::<u32>()) {
511 use crate::arch::packed_32::*;
512 use crate::arch::packed_aes_32::*;
513
514 TestTransformation::<PackedBinaryField32x1b>::test_transformation(a_val.into());
515 TestTransformation::<PackedAESBinaryField4x8b>::test_transformation(a_val.into());
516 }
517
518 #[test]
519 fn test_transformation_packed_64(a_val in proptest::prelude::any::<u64>()) {
520 use $crate::arch::packed_64::*;
521 use $crate::arch::packed_aes_64::*;
522
523 TestTransformation::<PackedBinaryField64x1b>::test_transformation(a_val.into());
524 TestTransformation::<PackedAESBinaryField8x8b>::test_transformation(a_val.into());
525 }
526
527 #[test]
528 fn test_transformation_packed_128(a_val in proptest::prelude::any::<u128>()) {
529 use $crate::arch::packed_128::*;
530 use $crate::arch::packed_aes_128::*;
531 use $crate::arch::packed_ghash_128::*;
532
533 TestTransformation::<PackedBinaryField128x1b>::test_transformation(a_val.into());
534 TestTransformation::<PackedAESBinaryField16x8b>::test_transformation(a_val.into());
535 TestTransformation::<PackedBinaryGhash1x128b>::test_transformation(a_val.into());
536 }
537
538 #[test]
539 fn test_transformation_packed_256(a_val in proptest::prelude::any::<[u128; 2]>()) {
540 use $crate::arch::packed_256::*;
541 use $crate::arch::packed_aes_256::*;
542 use $crate::arch::packed_ghash_256::*;
543
544 TestTransformation::<PackedBinaryField256x1b>::test_transformation(a_val.into());
545 TestTransformation::<PackedAESBinaryField32x8b>::test_transformation(a_val.into());
546 TestTransformation::<PackedBinaryGhash2x128b>::test_transformation(a_val.into());
547 }
548
549 #[test]
550 fn test_transformation_packed_512(a_val in proptest::prelude::any::<[u128; 4]>()) {
551 use $crate::arch::packed_512::*;
552 use $crate::arch::packed_aes_512::*;
553 use $crate::arch::packed_ghash_512::*;
554
555 TestTransformation::<PackedBinaryField512x1b>::test_transformation(a_val.into());
556 TestTransformation::<PackedAESBinaryField64x8b>::test_transformation(a_val.into());
557 TestTransformation::<PackedBinaryGhash4x128b>::test_transformation(a_val.into());
558 }
559 }
560 };
561 }
562
563 pub(crate) use define_invert_tests;
564 pub(crate) use define_multiply_tests;
565 pub(crate) use define_square_tests;
566 pub(crate) use define_transformation_tests;
567
568 #[allow(unused)]
570 pub const fn implements_transformation_factory<
571 P1: PackedField<Scalar: BinaryField>,
572 P2: PackedTransformationFactory<P1>,
573 >() {
574 }
575
576 pub fn check_interleave<P: PackedField + WithUnderlier>(
577 lhs: P::Underlier,
578 rhs: P::Underlier,
579 log_block_len: usize,
580 ) {
581 let lhs = P::from_underlier(lhs);
582 let rhs = P::from_underlier(rhs);
583 let (a, b) = lhs.interleave(rhs, log_block_len);
584 let block_len = 1 << log_block_len;
585 for i in (0..P::WIDTH).step_by(block_len * 2) {
586 for j in 0..block_len {
587 assert_eq!(a.get(i + j), lhs.get(i + j));
588 assert_eq!(a.get(i + j + block_len), rhs.get(i + j));
589
590 assert_eq!(b.get(i + j), lhs.get(i + j + block_len));
591 assert_eq!(b.get(i + j + block_len), rhs.get(i + j + block_len));
592 }
593 }
594 }
595
596 pub fn check_interleave_all_heights<P: PackedField + WithUnderlier>(
597 lhs: P::Underlier,
598 rhs: P::Underlier,
599 ) {
600 for log_block_len in 0..P::LOG_WIDTH {
601 check_interleave::<P>(lhs, rhs, log_block_len);
602 }
603 }
604
605 pub fn check_unzip<P: PackedField + WithUnderlier>(
606 lhs: P::Underlier,
607 rhs: P::Underlier,
608 log_block_len: usize,
609 ) {
610 let lhs = P::from_underlier(lhs);
611 let rhs = P::from_underlier(rhs);
612 let block_len = 1 << log_block_len;
613 let (a, b) = lhs.unzip(rhs, log_block_len);
614 for i in (0..P::WIDTH / 2).step_by(block_len) {
615 for j in 0..block_len {
616 assert_eq!(
617 a.get(i + j),
618 lhs.get(2 * i + j),
619 "i: {}, j: {}, log_block_len: {}, P: {:?}",
620 i,
621 j,
622 log_block_len,
623 P::zero()
624 );
625 assert_eq!(
626 b.get(i + j),
627 lhs.get(2 * i + j + block_len),
628 "i: {}, j: {}, log_block_len: {}, P: {:?}",
629 i,
630 j,
631 log_block_len,
632 P::zero()
633 );
634 }
635 }
636
637 for i in (0..P::WIDTH / 2).step_by(block_len) {
638 for j in 0..block_len {
639 assert_eq!(
640 a.get(i + j + P::WIDTH / 2),
641 rhs.get(2 * i + j),
642 "i: {}, j: {}, log_block_len: {}, P: {:?}",
643 i,
644 j,
645 log_block_len,
646 P::zero()
647 );
648 assert_eq!(b.get(i + j + P::WIDTH / 2), rhs.get(2 * i + j + block_len));
649 }
650 }
651 }
652
653 pub fn check_transpose_all_heights<P: PackedField + WithUnderlier>(
654 lhs: P::Underlier,
655 rhs: P::Underlier,
656 ) {
657 for log_block_len in 0..P::LOG_WIDTH {
658 check_unzip::<P>(lhs, rhs, log_block_len);
659 }
660 }
661}
662
663#[cfg(test)]
664mod tests {
665 use std::{iter::repeat_with, ops::Mul};
666
667 use binius_utils::{DeserializeBytes, SerializeBytes, bytes::BytesMut};
668 use proptest::prelude::*;
669 use rand::prelude::*;
670 use test_utils::check_interleave_all_heights;
671
672 use super::{
673 test_utils::{
674 define_invert_tests, define_multiply_tests, define_square_tests,
675 define_transformation_tests,
676 },
677 *,
678 };
679 use crate::{
680 PackedBinaryGhash1x128b, PackedBinaryGhash2x128b, PackedBinaryGhash4x128b, PackedField,
681 Random,
682 linear_transformation::PackedTransformationFactory,
683 test_utils::check_transpose_all_heights,
684 underlier::{U2, U4},
685 };
686
687 fn test_add_packed<P: PackedField + From<u128>>(a_val: u128, b_val: u128) {
688 let a = P::from(a_val);
689 let b = P::from(b_val);
690 let c = a + b;
691 for i in 0..P::WIDTH {
692 assert_eq!(c.get(i), a.get(i) + b.get(i));
693 }
694 }
695
696 fn test_mul_packed<P: PackedField>(a: P, b: P) {
697 let c = a * b;
698 for i in 0..P::WIDTH {
699 assert_eq!(c.get(i), a.get(i) * b.get(i));
700 }
701 }
702
703 fn test_mul_packed_random<P: PackedField>() {
704 let mut rng = StdRng::seed_from_u64(0);
705 test_mul_packed(P::random(&mut rng), P::random(&mut rng))
706 }
707
708 fn test_set_then_get<P: PackedField>() {
709 let mut rng = StdRng::seed_from_u64(0);
710 let mut elem = P::random(&mut rng);
711
712 let scalars = repeat_with(|| P::Scalar::random(&mut rng))
713 .take(P::WIDTH)
714 .collect::<Vec<_>>();
715
716 for (i, val) in scalars.iter().enumerate() {
717 elem.set(i, *val);
718 }
719 for (i, val) in scalars.iter().enumerate() {
720 assert_eq!(elem.get(i), *val);
721 }
722 }
723
724 fn test_serialize_then_deserialize<P: PackedField + DeserializeBytes + SerializeBytes>() {
725 let mut buffer = BytesMut::new();
726 let mut rng = StdRng::seed_from_u64(0);
727 let packed = P::random(&mut rng);
728 packed.serialize(&mut buffer).unwrap();
729
730 let mut read_buffer = buffer.freeze();
731
732 assert_eq!(P::deserialize(&mut read_buffer).unwrap(), packed);
733 }
734
735 #[test]
736 fn test_set_then_get_128b() {
737 test_set_then_get::<PackedBinaryGhash1x128b>();
738 test_set_then_get::<PackedBinaryGhash2x128b>();
739 test_set_then_get::<PackedBinaryGhash4x128b>();
740 }
741
742 #[test]
743 fn test_serialize_then_deserialize_128b() {
744 test_serialize_then_deserialize::<PackedBinaryGhash1x128b>();
745 test_serialize_then_deserialize::<PackedBinaryGhash2x128b>();
746 test_serialize_then_deserialize::<PackedBinaryGhash4x128b>();
747 }
748
749 #[test]
750 fn test_serialize_deserialize_different_packing_width() {
751 let mut rng = StdRng::seed_from_u64(0);
752
753 let packed0 = PackedBinaryGhash1x128b::random(&mut rng);
754 let packed1 = PackedBinaryGhash1x128b::random(&mut rng);
755
756 let mut buffer = BytesMut::new();
757 packed0.serialize(&mut buffer).unwrap();
758 packed1.serialize(&mut buffer).unwrap();
759
760 let mut read_buffer = buffer.freeze();
761 let packed01 = PackedBinaryGhash2x128b::deserialize(&mut read_buffer).unwrap();
762
763 assert!(
764 packed01
765 .iter()
766 .zip([packed0, packed1])
767 .all(|(x, y)| x == y.get(0))
768 );
769 }
770
771 proptest! {
773 #[test]
774 fn test_add_packed_128x1b(a_val in any::<u128>(), b_val in any::<u128>()) {
775 test_add_packed::<PackedBinaryField128x1b>(a_val, b_val)
776 }
777
778 #[test]
779 fn test_add_packed_16x8b(a_val in any::<u128>(), b_val in any::<u128>()) {
780 test_add_packed::<PackedAESBinaryField16x8b>(a_val, b_val)
781 }
782
783 #[test]
784 fn test_add_packed_1x128b(a_val in any::<u128>(), b_val in any::<u128>()) {
785 test_add_packed::<PackedBinaryGhash1x128b>(a_val, b_val)
786 }
787 }
788
789 #[test]
790 fn test_mul_packed_256x1b() {
791 test_mul_packed_random::<PackedBinaryField256x1b>()
792 }
793
794 #[test]
795 fn test_mul_packed_32x8b() {
796 test_mul_packed_random::<PackedAESBinaryField32x8b>()
797 }
798
799 #[test]
800 fn test_mul_packed_2x128b() {
801 test_mul_packed_random::<PackedBinaryGhash2x128b>()
802 }
803
804 #[test]
805 fn test_iter_size_hint() {
806 assert_valid_iterator_with_exact_size_hint::<PackedBinaryField128x1b>();
807 }
808
809 fn assert_valid_iterator_with_exact_size_hint<P: PackedField>() {
810 assert_eq!(P::default().iter().size_hint(), (P::WIDTH, Some(P::WIDTH)));
811 assert_eq!(P::default().into_iter().size_hint(), (P::WIDTH, Some(P::WIDTH)));
812 assert_eq!(P::default().iter().count(), P::WIDTH);
813 assert_eq!(P::default().into_iter().count(), P::WIDTH);
814 }
815
816 define_multiply_tests!(Mul::mul, PackedField);
817
818 define_square_tests!(PackedField::square, PackedField);
819
820 define_invert_tests!(PackedField::invert_or_zero, PackedField);
821
822 #[allow(unused)]
823 trait SelfTransformationFactory: PackedTransformationFactory<Self> {}
824
825 impl<T: PackedTransformationFactory<T>> SelfTransformationFactory for T {}
826
827 define_transformation_tests!(SelfTransformationFactory);
828
829 proptest! {
830 #[test]
831 fn test_interleave_2b(a_val in 0u8..3, b_val in 0u8..3) {
832 check_interleave_all_heights::<PackedBinaryField2x1b>(U2::new(a_val), U2::new(b_val));
833 }
834
835 #[test]
836 fn test_interleave_4b(a_val in 0u8..16, b_val in 0u8..16) {
837 check_interleave_all_heights::<PackedBinaryField4x1b>(U4::new(a_val), U4::new(b_val));
838 }
839
840 #[test]
841 fn test_interleave_8b(a_val in 0u8.., b_val in 0u8..) {
842 check_interleave_all_heights::<PackedBinaryField8x1b>(a_val, b_val);
843 check_interleave_all_heights::<PackedAESBinaryField1x8b>(a_val, b_val);
844 }
845
846 #[test]
847 fn test_interleave_16b(a_val in 0u16.., b_val in 0u16..) {
848 check_interleave_all_heights::<PackedBinaryField16x1b>(a_val, b_val);
849 check_interleave_all_heights::<PackedAESBinaryField2x8b>(a_val, b_val);
850 }
851
852 #[test]
853 fn test_interleave_32b(a_val in 0u32.., b_val in 0u32..) {
854 check_interleave_all_heights::<PackedBinaryField32x1b>(a_val, b_val);
855 check_interleave_all_heights::<PackedAESBinaryField4x8b>(a_val, b_val);
856 }
857
858 #[test]
859 fn test_interleave_64b(a_val in 0u64.., b_val in 0u64..) {
860 check_interleave_all_heights::<PackedBinaryField64x1b>(a_val, b_val);
861 check_interleave_all_heights::<PackedAESBinaryField8x8b>(a_val, b_val);
862 }
863
864 #[test]
865 #[allow(clippy::useless_conversion)] fn test_interleave_128b(a_val in 0u128.., b_val in 0u128..) {
867 check_interleave_all_heights::<PackedBinaryField128x1b>(a_val.into(), b_val.into());
868 check_interleave_all_heights::<PackedAESBinaryField16x8b>(a_val.into(), b_val.into());
869 check_interleave_all_heights::<PackedBinaryGhash1x128b>(a_val.into(), b_val.into());
870 }
871
872 #[test]
873 fn test_interleave_256b(a_val in any::<[u128; 2]>(), b_val in any::<[u128; 2]>()) {
874 check_interleave_all_heights::<PackedBinaryField256x1b>(a_val.into(), b_val.into());
875 check_interleave_all_heights::<PackedAESBinaryField32x8b>(a_val.into(), b_val.into());
876 check_interleave_all_heights::<PackedBinaryGhash2x128b>(a_val.into(), b_val.into());
877 }
878
879 #[test]
880 fn test_interleave_512b(a_val in any::<[u128; 4]>(), b_val in any::<[u128; 4]>()) {
881 check_interleave_all_heights::<PackedBinaryField512x1b>(a_val.into(), b_val.into());
882 check_interleave_all_heights::<PackedAESBinaryField64x8b>(a_val.into(), b_val.into());
883 check_interleave_all_heights::<PackedBinaryGhash4x128b>(a_val.into(), b_val.into());
884 }
885
886 #[test]
887 fn check_transpose_2b(a_val in 0u8..3, b_val in 0u8..3) {
888 check_transpose_all_heights::<PackedBinaryField2x1b>(U2::new(a_val), U2::new(b_val));
889 }
890
891 #[test]
892 fn check_transpose_4b(a_val in 0u8..16, b_val in 0u8..16) {
893 check_transpose_all_heights::<PackedBinaryField4x1b>(U4::new(a_val), U4::new(b_val));
894 }
895
896 #[test]
897 fn check_transpose_8b(a_val in 0u8.., b_val in 0u8..) {
898 check_transpose_all_heights::<PackedBinaryField8x1b>(a_val, b_val);
899 check_transpose_all_heights::<PackedAESBinaryField1x8b>(a_val, b_val);
900 }
901
902 #[test]
903 fn check_transpose_16b(a_val in 0u16.., b_val in 0u16..) {
904 check_transpose_all_heights::<PackedBinaryField16x1b>(a_val, b_val);
905 check_transpose_all_heights::<PackedAESBinaryField2x8b>(a_val, b_val);
906 }
907
908 #[test]
909 fn check_transpose_32b(a_val in 0u32.., b_val in 0u32..) {
910 check_transpose_all_heights::<PackedBinaryField32x1b>(a_val, b_val);
911 check_transpose_all_heights::<PackedAESBinaryField4x8b>(a_val, b_val);
912 }
913
914 #[test]
915 fn check_transpose_64b(a_val in 0u64.., b_val in 0u64..) {
916 check_transpose_all_heights::<PackedBinaryField64x1b>(a_val, b_val);
917 check_transpose_all_heights::<PackedAESBinaryField8x8b>(a_val, b_val);
918 }
919
920 #[test]
921 #[allow(clippy::useless_conversion)] fn check_transpose_128b(a_val in 0u128.., b_val in 0u128..) {
923 check_transpose_all_heights::<PackedBinaryField128x1b>(a_val.into(), b_val.into());
924 check_transpose_all_heights::<PackedAESBinaryField16x8b>(a_val.into(), b_val.into());
925 check_transpose_all_heights::<PackedBinaryGhash1x128b>(a_val.into(), b_val.into());
926 }
927
928 #[test]
929 fn check_transpose_256b(a_val in any::<[u128; 2]>(), b_val in any::<[u128; 2]>()) {
930 check_transpose_all_heights::<PackedBinaryField256x1b>(a_val.into(), b_val.into());
931 check_transpose_all_heights::<PackedAESBinaryField32x8b>(a_val.into(), b_val.into());
932 check_transpose_all_heights::<PackedBinaryGhash2x128b>(a_val.into(), b_val.into());
933 }
934
935 #[test]
936 fn check_transpose_512b(a_val in any::<[u128; 4]>(), b_val in any::<[u128; 4]>()) {
937 check_transpose_all_heights::<PackedBinaryField512x1b>(a_val.into(), b_val.into());
938 check_transpose_all_heights::<PackedAESBinaryField64x8b>(a_val.into(), b_val.into());
939 check_transpose_all_heights::<PackedBinaryGhash4x128b>(a_val.into(), b_val.into());
940 }
941 }
942}