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