1#![no_std]
4
5extern crate alloc;
6
7pub mod bench_func;
8pub mod dft_testing;
9pub mod extension_testing;
10pub mod from_integer_tests;
11pub mod packedfield_testing;
12
13use alloc::vec::Vec;
14use core::array;
15
16pub use bench_func::*;
17pub use dft_testing::*;
18pub use extension_testing::*;
19use num_bigint::BigUint;
20use p3_field::{
21 ExtensionField, Field, PackedValue, PrimeCharacteristicRing, PrimeField32, PrimeField64,
22 TwoAdicField,
23};
24use p3_util::iter_array_chunks_padded;
25pub use packedfield_testing::*;
26use rand::distr::{Distribution, StandardUniform};
27use rand::rngs::SmallRng;
28use rand::{Rng, SeedableRng};
29
30#[allow(clippy::eq_op)]
31pub fn test_ring_with_eq<R: PrimeCharacteristicRing + Copy + Eq>(zeros: &[R], ones: &[R])
32where
33 StandardUniform: Distribution<R> + Distribution<[R; 16]>,
34{
35 let mut rng = SmallRng::seed_from_u64(1);
38 let x = rng.random::<R>();
39 let y = rng.random::<R>();
40 let z = rng.random::<R>();
41 assert_eq!(R::ONE + R::NEG_ONE, R::ZERO, "Error 1 + (-1) =/= 0");
42 assert_eq!(R::NEG_ONE + R::TWO, R::ONE, "Error -1 + 2 =/= 1");
43 assert_eq!(x + (-x), R::ZERO, "Error x + (-x) =/= 0");
44 assert_eq!(R::ONE + R::ONE, R::TWO, "Error 1 + 1 =/= 2");
45 assert_eq!(-(-x), x, "Error when testing double negation");
46 assert_eq!(x + x, x * R::TWO, "Error when comparing x * 2 to x + x");
47 assert_eq!(
48 x * R::TWO,
49 x.double(),
50 "Error when comparing x.double() to x * 2"
51 );
52
53 for zero in zeros.iter().copied() {
55 assert_eq!(zero, R::ZERO);
56 assert_eq!(x + zero, x, "Error when testing additive identity right.");
57 assert_eq!(zero + x, x, "Error when testing additive identity left.");
58 assert_eq!(x - zero, x, "Error when testing subtracting zero.");
59 assert_eq!(zero - x, -x, "Error when testing subtracting from zero.");
60 assert_eq!(
61 x * zero,
62 zero,
63 "Error when testing right multiplication by 0."
64 );
65 assert_eq!(
66 zero * x,
67 zero,
68 "Error when testing left multiplication by 0."
69 );
70 }
71
72 for one in ones.iter().copied() {
74 assert_eq!(one, R::ONE);
75 assert_eq!(one * one, one);
76 assert_eq!(
77 x * one,
78 x,
79 "Error when testing multiplicative identity right."
80 );
81 assert_eq!(
82 one * x,
83 x,
84 "Error when testing multiplicative identity left."
85 );
86 }
87
88 assert_eq!(
89 x * R::NEG_ONE,
90 -x,
91 "Error when testing right multiplication by -1."
92 );
93 assert_eq!(
94 R::NEG_ONE * x,
95 -x,
96 "Error when testing left multiplication by -1."
97 );
98 assert_eq!(x * x, x.square(), "Error when testing x * x = x.square()");
99 assert_eq!(
100 x * x * x,
101 x.cube(),
102 "Error when testing x * x * x = x.cube()"
103 );
104 assert_eq!(x + y, y + x, "Error when testing commutativity of addition");
105 assert_eq!(
106 (x - y),
107 -(y - x),
108 "Error when testing anticommutativity of sub."
109 );
110 assert_eq!(
111 x * y,
112 y * x,
113 "Error when testing commutativity of multiplication."
114 );
115 assert_eq!(
116 x + (y + z),
117 (x + y) + z,
118 "Error when testing associativity of addition"
119 );
120 assert_eq!(
121 x * (y * z),
122 (x * y) * z,
123 "Error when testing associativity of multiplication."
124 );
125 assert_eq!(
126 x - (y - z),
127 (x - y) + z,
128 "Error when testing subtraction and addition"
129 );
130 assert_eq!(
131 x - (y + z),
132 (x - y) - z,
133 "Error when testing subtraction and addition"
134 );
135 assert_eq!(
136 (x + y) - z,
137 x + (y - z),
138 "Error when testing subtraction and addition"
139 );
140 assert_eq!(
141 x * (-y),
142 -(x * y),
143 "Error when testing distributivity of mul and right neg."
144 );
145 assert_eq!(
146 (-x) * y,
147 -(x * y),
148 "Error when testing distributivity of mul and left neg."
149 );
150
151 assert_eq!(
152 x * (y + z),
153 x * y + x * z,
154 "Error when testing distributivity of add and left mul."
155 );
156 assert_eq!(
157 (x + y) * z,
158 x * z + y * z,
159 "Error when testing distributivity of add and right mul."
160 );
161 assert_eq!(
162 x * (y - z),
163 x * y - x * z,
164 "Error when testing distributivity of sub and left mul."
165 );
166 assert_eq!(
167 (x - y) * z,
168 x * z - y * z,
169 "Error when testing distributivity of sub and right mul."
170 );
171
172 let vec1: [R; 64] = rng.random();
173 let vec2: [R; 64] = rng.random();
174 test_sums(&vec1[..16].try_into().unwrap());
175 test_dot_product(&vec1, &vec2);
176
177 assert_eq!(
178 x.exp_const_u64::<0>(),
179 R::ONE,
180 "Error when comparing x.exp_const_u64::<0> to R::ONE."
181 );
182 assert_eq!(
183 x.exp_const_u64::<1>(),
184 x,
185 "Error when comparing x.exp_const_u64::<3> to x."
186 );
187 assert_eq!(
188 x.exp_const_u64::<2>(),
189 x * x,
190 "Error when comparing x.exp_const_u64::<3> to x*x."
191 );
192 assert_eq!(
193 x.exp_const_u64::<3>(),
194 x * x * x,
195 "Error when comparing x.exp_const_u64::<3> to x*x*x."
196 );
197 assert_eq!(
198 x.exp_const_u64::<4>(),
199 x * x * x * x,
200 "Error when comparing x.exp_const_u64::<3> to x*x*x*x."
201 );
202 assert_eq!(
203 x.exp_const_u64::<5>(),
204 x * x * x * x * x,
205 "Error when comparing x.exp_const_u64::<5> to x*x*x*x*x."
206 );
207 assert_eq!(
208 x.exp_const_u64::<6>(),
209 x * x * x * x * x * x,
210 "Error when comparing x.exp_const_u64::<7> to x*x*x*x*x*x."
211 );
212 assert_eq!(
213 x.exp_const_u64::<7>(),
214 x * x * x * x * x * x * x,
215 "Error when comparing x.exp_const_u64::<7> to x*x*x*x*x*x*x."
216 );
217
218 test_binary_ops(zeros, ones, x, y, z);
219}
220
221pub fn test_inv_div<F: Field>()
222where
223 StandardUniform: Distribution<F>,
224{
225 let mut rng = SmallRng::seed_from_u64(1);
226 let x = rng.random::<F>();
227 let y = rng.random::<F>();
228 let z = rng.random::<F>();
229 assert_eq!(x, x.halve() * F::TWO);
230 assert_eq!(x * x.inverse(), F::ONE);
231 assert_eq!(x.inverse() * x, F::ONE);
232 assert_eq!(x.square().inverse(), x.inverse().square());
233 assert_eq!((x / y) * y, x);
234 assert_eq!(x / (y * z), (x / y) / z);
235 assert_eq!((x * y) / z, x * (y / z));
236}
237
238pub fn test_mul_2exp_u64<R: PrimeCharacteristicRing + Eq>()
239where
240 StandardUniform: Distribution<R>,
241{
242 let mut rng = SmallRng::seed_from_u64(1);
243 let x = rng.random::<R>();
244 assert_eq!(x.mul_2exp_u64(0), x);
245 assert_eq!(x.mul_2exp_u64(1), x.double());
246 for i in 0..128 {
247 assert_eq!(
248 x.clone().mul_2exp_u64(i),
249 x.clone() * R::from_u128(1_u128 << i)
250 );
251 }
252}
253
254pub fn test_div_2exp_u64<F: Field>()
255where
256 StandardUniform: Distribution<F>,
257{
258 let mut rng = SmallRng::seed_from_u64(1);
259 let x = rng.random::<F>();
260 assert_eq!(x.div_2exp_u64(0), x);
261 assert_eq!(x.div_2exp_u64(1), x.halve());
262 for i in 0..128 {
263 assert_eq!(x.mul_2exp_u64(i).div_2exp_u64(i), x);
264 assert_eq!(
265 x.div_2exp_u64(i),
266 x * F::from_prime_subfield(F::PrimeSubfield::from_u128(1_u128 << i).inverse())
268 );
269 }
270}
271
272pub fn test_add_slice<F: Field>()
273where
274 StandardUniform: Distribution<F>,
275{
276 let mut rng = SmallRng::seed_from_u64(1);
277 let lengths = [
278 F::Packing::WIDTH - 1,
279 F::Packing::WIDTH,
280 (F::Packing::WIDTH - 1) + (F::Packing::WIDTH << 10),
281 ];
282 for len in lengths {
283 let mut slice_1: Vec<_> = (&mut rng).sample_iter(StandardUniform).take(len).collect();
284 let slice_1_copy = slice_1.clone();
285 let slice_2: Vec<_> = (&mut rng).sample_iter(StandardUniform).take(len).collect();
286
287 F::add_slices(&mut slice_1, &slice_2);
288 for i in 0..len {
289 assert_eq!(slice_1[i], slice_1_copy[i] + slice_2[i]);
290 }
291 }
292}
293
294pub fn test_inverse<F: Field>()
295where
296 StandardUniform: Distribution<F>,
297{
298 assert_eq!(None, F::ZERO.try_inverse());
299 assert_eq!(Some(F::ONE), F::ONE.try_inverse());
300 let mut rng = SmallRng::seed_from_u64(1);
301 for _ in 0..1000 {
302 let x = rng.random::<F>();
303 if !x.is_zero() && !x.is_one() {
304 let z = x.inverse();
305 assert_ne!(x, z);
306 assert_eq!(x * z, F::ONE);
307 }
308 }
309}
310
311pub fn test_dot_product<R: PrimeCharacteristicRing + Eq + Copy>(u: &[R; 64], v: &[R; 64]) {
312 let mut dot = R::ZERO;
313 assert_eq!(
314 dot,
315 R::dot_product::<0>(u[..0].try_into().unwrap(), v[..0].try_into().unwrap())
316 );
317 dot += u[0] * v[0];
318 assert_eq!(
319 dot,
320 R::dot_product::<1>(u[..1].try_into().unwrap(), v[..1].try_into().unwrap())
321 );
322 dot += u[1] * v[1];
323 assert_eq!(
324 dot,
325 R::dot_product::<2>(u[..2].try_into().unwrap(), v[..2].try_into().unwrap())
326 );
327 dot += u[2] * v[2];
328 assert_eq!(
329 dot,
330 R::dot_product::<3>(u[..3].try_into().unwrap(), v[..3].try_into().unwrap())
331 );
332 dot += u[3] * v[3];
333 assert_eq!(
334 dot,
335 R::dot_product::<4>(u[..4].try_into().unwrap(), v[..4].try_into().unwrap())
336 );
337 dot += u[4] * v[4];
338 assert_eq!(
339 dot,
340 R::dot_product::<5>(u[..5].try_into().unwrap(), v[..5].try_into().unwrap())
341 );
342 dot += u[5] * v[5];
343 assert_eq!(
344 dot,
345 R::dot_product::<6>(u[..6].try_into().unwrap(), v[..6].try_into().unwrap())
346 );
347 dot += u[6] * v[6];
348 assert_eq!(
349 dot,
350 R::dot_product::<7>(u[..7].try_into().unwrap(), v[..7].try_into().unwrap())
351 );
352 dot += u[7] * v[7];
353 assert_eq!(
354 dot,
355 R::dot_product::<8>(u[..8].try_into().unwrap(), v[..8].try_into().unwrap())
356 );
357 dot += u[8] * v[8];
358 assert_eq!(
359 dot,
360 R::dot_product::<9>(u[..9].try_into().unwrap(), v[..9].try_into().unwrap())
361 );
362 dot += u[9] * v[9];
363 assert_eq!(
364 dot,
365 R::dot_product::<10>(u[..10].try_into().unwrap(), v[..10].try_into().unwrap())
366 );
367 dot += u[10] * v[10];
368 assert_eq!(
369 dot,
370 R::dot_product::<11>(u[..11].try_into().unwrap(), v[..11].try_into().unwrap())
371 );
372 dot += u[11] * v[11];
373 assert_eq!(
374 dot,
375 R::dot_product::<12>(u[..12].try_into().unwrap(), v[..12].try_into().unwrap())
376 );
377 dot += u[12] * v[12];
378 assert_eq!(
379 dot,
380 R::dot_product::<13>(u[..13].try_into().unwrap(), v[..13].try_into().unwrap())
381 );
382 dot += u[13] * v[13];
383 assert_eq!(
384 dot,
385 R::dot_product::<14>(u[..14].try_into().unwrap(), v[..14].try_into().unwrap())
386 );
387 dot += u[14] * v[14];
388 assert_eq!(
389 dot,
390 R::dot_product::<15>(u[..15].try_into().unwrap(), v[..15].try_into().unwrap())
391 );
392 dot += u[15] * v[15];
393 assert_eq!(
394 dot,
395 R::dot_product::<16>(u[..16].try_into().unwrap(), v[..16].try_into().unwrap())
396 );
397
398 let dot_64: R = u
399 .iter()
400 .zip(v.iter())
401 .fold(R::ZERO, |acc, (&lhs, &rhs)| acc + (lhs * rhs));
402 assert_eq!(dot_64, R::dot_product::<64>(u, v));
403}
404
405pub fn test_sums<R: PrimeCharacteristicRing + Eq + Copy>(u: &[R; 16]) {
406 let mut sum = R::ZERO;
407 assert_eq!(sum, R::sum_array::<0>(u[..0].try_into().unwrap()));
408 assert_eq!(sum, u[..0].iter().copied().sum());
409 sum += u[0];
410 assert_eq!(sum, R::sum_array::<1>(u[..1].try_into().unwrap()));
411 assert_eq!(sum, u[..1].iter().copied().sum());
412 sum += u[1];
413 assert_eq!(sum, R::sum_array::<2>(u[..2].try_into().unwrap()));
414 assert_eq!(sum, u[..2].iter().copied().sum());
415 sum += u[2];
416 assert_eq!(sum, R::sum_array::<3>(u[..3].try_into().unwrap()));
417 assert_eq!(sum, u[..3].iter().copied().sum());
418 sum += u[3];
419 assert_eq!(sum, R::sum_array::<4>(u[..4].try_into().unwrap()));
420 assert_eq!(sum, u[..4].iter().copied().sum());
421 sum += u[4];
422 assert_eq!(sum, R::sum_array::<5>(u[..5].try_into().unwrap()));
423 assert_eq!(sum, u[..5].iter().copied().sum());
424 sum += u[5];
425 assert_eq!(sum, R::sum_array::<6>(u[..6].try_into().unwrap()));
426 assert_eq!(sum, u[..6].iter().copied().sum());
427 sum += u[6];
428 assert_eq!(sum, R::sum_array::<7>(u[..7].try_into().unwrap()));
429 assert_eq!(sum, u[..7].iter().copied().sum());
430 sum += u[7];
431 assert_eq!(sum, R::sum_array::<8>(u[..8].try_into().unwrap()));
432 assert_eq!(sum, u[..8].iter().copied().sum());
433 sum += u[8];
434 assert_eq!(sum, R::sum_array::<9>(u[..9].try_into().unwrap()));
435 assert_eq!(sum, u[..9].iter().copied().sum());
436 sum += u[9];
437 assert_eq!(sum, R::sum_array::<10>(u[..10].try_into().unwrap()));
438 assert_eq!(sum, u[..10].iter().copied().sum());
439 sum += u[10];
440 assert_eq!(sum, R::sum_array::<11>(u[..11].try_into().unwrap()));
441 assert_eq!(sum, u[..11].iter().copied().sum());
442 sum += u[11];
443 assert_eq!(sum, R::sum_array::<12>(u[..12].try_into().unwrap()));
444 assert_eq!(sum, u[..12].iter().copied().sum());
445 sum += u[12];
446 assert_eq!(sum, R::sum_array::<13>(u[..13].try_into().unwrap()));
447 assert_eq!(sum, u[..13].iter().copied().sum());
448 sum += u[13];
449 assert_eq!(sum, R::sum_array::<14>(u[..14].try_into().unwrap()));
450 assert_eq!(sum, u[..14].iter().copied().sum());
451 sum += u[14];
452 assert_eq!(sum, R::sum_array::<15>(u[..15].try_into().unwrap()));
453 assert_eq!(sum, u[..15].iter().copied().sum());
454 sum += u[15];
455 assert_eq!(sum, R::sum_array::<16>(u));
456 assert_eq!(sum, u.iter().copied().sum());
457}
458
459pub fn test_binary_ops<R: PrimeCharacteristicRing + Eq + Copy>(
460 zeros: &[R],
461 ones: &[R],
462 x: R,
463 y: R,
464 z: R,
465) {
466 for zero in zeros {
467 for one in ones {
468 assert_eq!(one.xor(one), R::ZERO, "Error when testing xor(1, 1) = 0.");
469 assert_eq!(zero.xor(one), R::ONE, "Error when testing xor(0, 1) = 1.");
470 assert_eq!(one.xor(zero), R::ONE, "Error when testing xor(1, 0) = 1.");
471 assert_eq!(zero.xor(zero), R::ZERO, "Error when testing xor(0, 0) = 0.");
472 assert_eq!(one.andn(one), R::ZERO, "Error when testing andn(1, 1) = 0.");
473 assert_eq!(zero.andn(one), R::ONE, "Error when testing andn(0, 1) = 1.");
474 assert_eq!(
475 one.andn(zero),
476 R::ZERO,
477 "Error when testing andn(1, 0) = 0."
478 );
479 assert_eq!(
480 zero.andn(zero),
481 R::ZERO,
482 "Error when testing andn(0, 0) = 0."
483 );
484 assert_eq!(
485 zero.bool_check(),
486 R::ZERO,
487 "Error when testing bool_check(0) = 0."
488 );
489 assert_eq!(
490 one.bool_check(),
491 R::ZERO,
492 "Error when testing bool_check(1) = 0."
493 );
494 }
495 }
496
497 assert_eq!(
498 R::ONE.xor(&R::NEG_ONE),
499 R::TWO,
500 "Error when testing xor(1, -1) = 2."
501 );
502 assert_eq!(
503 R::NEG_ONE.xor(&R::ONE),
504 R::TWO,
505 "Error when testing xor(-1, 1) = 2."
506 );
507 assert_eq!(
508 R::NEG_ONE.xor(&R::NEG_ONE),
509 R::from_i8(-4),
510 "Error when testing xor(-1, -1) = -4."
511 );
512 assert_eq!(
513 R::ONE.andn(&R::NEG_ONE),
514 R::ZERO,
515 "Error when testing andn(1, -1) = 0."
516 );
517 assert_eq!(
518 R::NEG_ONE.andn(&R::ONE),
519 R::TWO,
520 "Error when testing andn(-1, 1) = 2."
521 );
522 assert_eq!(
523 R::NEG_ONE.andn(&R::NEG_ONE),
524 -R::TWO,
525 "Error when testing andn(-1, -1) = -2."
526 );
527
528 assert_eq!(x.xor(&y), x + y - x * y.double(), "Error when testing xor.");
529
530 assert_eq!(x.andn(&y), (R::ONE - x) * y, "Error when testing andn.");
531
532 assert_eq!(
533 x.xor3(&y, &z),
534 x + y + z - (x * y + x * z + y * z).double() + x * y * z.double().double(),
535 "Error when testing xor3."
536 );
537}
538
539pub(crate) fn exp_biguint<F: Field>(x: F, exponent: &BigUint) -> F {
545 let digits = exponent.to_u64_digits();
546 let size = digits.len();
547
548 let mut power = F::ONE;
549
550 let bases = (0..size).map(|i| x.exp_power_of_2(64 * i));
551 digits
552 .iter()
553 .zip(bases)
554 .for_each(|(digit, base)| power *= base.exp_u64(*digit));
555 power
556}
557
558pub fn test_generator<F: Field>(multiplicative_group_factors: &[(BigUint, u32)]) {
561 let product: BigUint = multiplicative_group_factors
568 .iter()
569 .map(|(factor, exponent)| factor.pow(*exponent))
570 .product();
571 assert_eq!(product + BigUint::from(1u32), F::order());
572
573 let mut partial_products: Vec<F> = (0..=multiplicative_group_factors.len())
576 .map(|i| {
577 let mut generator_power = F::GENERATOR;
578 multiplicative_group_factors
579 .iter()
580 .enumerate()
581 .for_each(|(j, (factor, exponent))| {
582 let modified_exponent = if i == j { exponent - 1 } else { *exponent };
583 for _ in 0..modified_exponent {
584 generator_power = exp_biguint(generator_power, factor);
585 }
586 });
587 generator_power
588 })
589 .collect();
590
591 assert_eq!(partial_products.pop().unwrap(), F::ONE);
592
593 for elem in partial_products.into_iter() {
594 assert_ne!(elem, F::ONE);
595 }
596}
597
598pub fn test_two_adic_generator_consistency<F: TwoAdicField>() {
599 let log_n = F::TWO_ADICITY;
600 let g = F::two_adic_generator(log_n);
601 for bits in 0..=log_n {
602 assert_eq!(g.exp_power_of_2(bits), F::two_adic_generator(log_n - bits));
603 }
604}
605
606pub fn test_ef_two_adic_generator_consistency<
607 F: TwoAdicField,
608 EF: TwoAdicField + ExtensionField<F>,
609>() {
610 assert_eq!(
611 Into::<EF>::into(F::two_adic_generator(F::TWO_ADICITY)),
612 EF::two_adic_generator(F::TWO_ADICITY)
613 );
614}
615
616pub fn test_into_bytes_32<F: PrimeField32>(zeros: &[F], ones: &[F])
617where
618 StandardUniform: Distribution<F>,
619{
620 let mut rng = SmallRng::seed_from_u64(1);
621 let x = rng.random::<F>();
622
623 assert_eq!(
624 x.into_bytes().into_iter().collect::<Vec<_>>(),
625 x.to_unique_u32().to_le_bytes()
626 );
627 for one in ones {
628 assert_eq!(
629 one.into_bytes().into_iter().collect::<Vec<_>>(),
630 F::ONE.to_unique_u32().to_le_bytes()
631 );
632 }
633 for zero in zeros {
634 assert_eq!(zero.into_bytes().into_iter().collect::<Vec<_>>(), [0; 4]);
635 }
636}
637
638pub fn test_into_bytes_64<F: PrimeField64>(zeros: &[F], ones: &[F])
639where
640 StandardUniform: Distribution<F>,
641{
642 let mut rng = SmallRng::seed_from_u64(1);
643 let x = rng.random::<F>();
644
645 assert_eq!(
646 x.into_bytes().into_iter().collect::<Vec<_>>(),
647 x.to_unique_u64().to_le_bytes()
648 );
649 for one in ones {
650 assert_eq!(
651 one.into_bytes().into_iter().collect::<Vec<_>>(),
652 F::ONE.to_unique_u64().to_le_bytes()
653 );
654 }
655 for zero in zeros {
656 assert_eq!(zero.into_bytes().into_iter().collect::<Vec<_>>(), [0; 8]);
657 }
658}
659
660pub fn test_into_stream<F: Field>()
661where
662 StandardUniform: Distribution<[F; 16]>,
663{
664 let mut rng = SmallRng::seed_from_u64(1);
665 let xs: [F; 16] = rng.random();
666
667 let byte_vec = F::into_byte_stream(xs).into_iter().collect::<Vec<_>>();
668 let u32_vec = F::into_u32_stream(xs).into_iter().collect::<Vec<_>>();
669 let u64_vec = F::into_u64_stream(xs).into_iter().collect::<Vec<_>>();
670
671 let expected_bytes = xs
672 .into_iter()
673 .flat_map(|x| x.into_bytes())
674 .collect::<Vec<_>>();
675 let expected_u32s = iter_array_chunks_padded(byte_vec.iter().copied(), 0)
676 .map(u32::from_le_bytes)
677 .collect::<Vec<_>>();
678 let expected_u64s = iter_array_chunks_padded(byte_vec.iter().copied(), 0)
679 .map(u64::from_le_bytes)
680 .collect::<Vec<_>>();
681
682 assert_eq!(byte_vec, expected_bytes);
683 assert_eq!(u32_vec, expected_u32s);
684 assert_eq!(u64_vec, expected_u64s);
685
686 let ys: [F; 16] = rng.random();
687 let zs: [F; 16] = rng.random();
688
689 let combs: [[F; 3]; 16] = array::from_fn(|i| [xs[i], ys[i], zs[i]]);
690
691 let byte_vec_ys = F::into_byte_stream(ys).into_iter().collect::<Vec<_>>();
692 let byte_vec_zs = F::into_byte_stream(zs).into_iter().collect::<Vec<_>>();
693 let u32_vec_ys = F::into_u32_stream(ys).into_iter().collect::<Vec<_>>();
694 let u32_vec_zs = F::into_u32_stream(zs).into_iter().collect::<Vec<_>>();
695 let u64_vec_ys = F::into_u64_stream(ys).into_iter().collect::<Vec<_>>();
696 let u64_vec_zs = F::into_u64_stream(zs).into_iter().collect::<Vec<_>>();
697
698 let combined_bytes = F::into_parallel_byte_streams(combs)
699 .into_iter()
700 .collect::<Vec<_>>();
701 let combined_u32s = F::into_parallel_u32_streams(combs)
702 .into_iter()
703 .collect::<Vec<_>>();
704 let combined_u64s = F::into_parallel_u64_streams(combs)
705 .into_iter()
706 .collect::<Vec<_>>();
707
708 let expected_combined_bytes: Vec<[u8; 3]> = (0..byte_vec.len())
709 .map(|i| [byte_vec[i], byte_vec_ys[i], byte_vec_zs[i]])
710 .collect();
711 let expected_combined_u32s: Vec<[u32; 3]> = (0..u32_vec.len())
712 .map(|i| [u32_vec[i], u32_vec_ys[i], u32_vec_zs[i]])
713 .collect();
714 let expected_combined_u64s: Vec<[u64; 3]> = (0..u64_vec.len())
715 .map(|i| [u64_vec[i], u64_vec_ys[i], u64_vec_zs[i]])
716 .collect();
717
718 assert_eq!(combined_bytes, expected_combined_bytes);
719 assert_eq!(combined_u32s, expected_combined_u32s);
720 assert_eq!(combined_u64s, expected_combined_u64s);
721}
722
723#[macro_export]
724macro_rules! test_field {
725 ($field:ty, $zeros: expr, $ones: expr, $factors: expr) => {
726 mod field_tests {
727 #[test]
728 fn test_ring_with_eq() {
729 $crate::test_ring_with_eq::<$field>($zeros, $ones);
730 }
731 #[test]
732 fn test_inv_div() {
733 $crate::test_inv_div::<$field>();
734 }
735 #[test]
736 fn test_inverse() {
737 $crate::test_inverse::<$field>();
738 }
739 #[test]
740 fn test_generator() {
741 $crate::test_generator::<$field>($factors);
742 }
743 #[test]
744 fn test_mul_2exp_u64() {
745 $crate::test_mul_2exp_u64::<$field>();
746 }
747 #[test]
748 fn test_div_2exp_u64() {
749 $crate::test_div_2exp_u64::<$field>();
750 }
751 #[test]
752 fn test_streaming() {
753 $crate::test_into_stream::<$field>();
754 }
755 }
756
757 mod trivial_extension_tests {
760 #[test]
761 fn test_to_from_trivial_extension() {
762 $crate::test_to_from_extension_field::<$field, $field>();
763 }
764
765 #[test]
766 fn test_trivial_packed_extension() {
767 $crate::test_packed_extension::<$field, $field>();
768 }
769 }
770 };
771}
772
773#[macro_export]
774macro_rules! test_prime_field {
775 ($field:ty) => {
776 mod from_integer_small_tests {
777 use p3_field::integers::QuotientMap;
778 use p3_field::{Field, PrimeCharacteristicRing};
779
780 #[test]
781 fn test_small_integer_conversions() {
782 $crate::generate_from_small_int_tests!(
783 $field,
784 [
785 u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize
786 ]
787 );
788 }
789
790 #[test]
791 fn test_small_signed_integer_conversions() {
792 $crate::generate_from_small_neg_int_tests!(
793 $field,
794 [i8, i16, i32, i64, i128, isize]
795 );
796 }
797 }
798 };
799}
800
801#[macro_export]
802macro_rules! test_prime_field_64 {
803 ($field:ty, $zeros: expr, $ones: expr) => {
804 mod from_integer_tests_prime_field_64 {
805 use p3_field::integers::QuotientMap;
806 use p3_field::{Field, PrimeCharacteristicRing, PrimeField64, RawDataSerializable};
807 use rand::rngs::SmallRng;
808 use rand::{Rng, SeedableRng};
809
810 #[test]
811 fn test_as_canonical_u64() {
812 let mut rng = SmallRng::seed_from_u64(1);
813 let x: u64 = rng.random();
814 let x_mod_order = x % <$field>::ORDER_U64;
815
816 assert_eq!(<$field>::ZERO.as_canonical_u64(), 0);
817 assert_eq!(<$field>::ONE.as_canonical_u64(), 1);
818 assert_eq!(<$field>::TWO.as_canonical_u64(), 2 % <$field>::ORDER_U64);
819 assert_eq!(
820 <$field>::NEG_ONE.as_canonical_u64(),
821 <$field>::ORDER_U64 - 1
822 );
823
824 assert_eq!(
825 <$field>::from_int(<$field>::ORDER_U64).as_canonical_u64(),
826 0
827 );
828 assert_eq!(<$field>::from_int(x).as_canonical_u64(), x_mod_order);
829 assert_eq!(
830 unsafe { <$field>::from_canonical_unchecked(x_mod_order).as_canonical_u64() },
831 x_mod_order
832 );
833 }
834
835 #[test]
836 fn test_as_unique_u64() {
837 assert_ne!(
838 <$field>::ZERO.to_unique_u64(),
839 <$field>::ONE.to_unique_u64()
840 );
841 assert_ne!(
842 <$field>::ZERO.to_unique_u64(),
843 <$field>::NEG_ONE.to_unique_u64()
844 );
845 assert_eq!(
846 <$field>::from_int(<$field>::ORDER_U64).to_unique_u64(),
847 <$field>::ZERO.to_unique_u64()
848 );
849 }
850
851 #[test]
852 fn test_large_unsigned_integer_conversions() {
853 $crate::generate_from_large_u_int_tests!($field, <$field>::ORDER_U64, [u64, u128]);
854 }
855
856 #[test]
857 fn test_large_signed_integer_conversions() {
858 $crate::generate_from_large_i_int_tests!($field, <$field>::ORDER_U64, [i64, i128]);
859 }
860
861 #[test]
862 fn test_raw_data_serializable() {
863 if <$field>::NUM_BYTES == 8 {
866 $crate::test_into_bytes_64::<$field>($zeros, $ones);
867 }
868 }
869 }
870 };
871}
872
873#[macro_export]
874macro_rules! test_prime_field_32 {
875 ($field:ty, $zeros: expr, $ones: expr) => {
876 mod from_integer_tests_prime_field_32 {
877 use p3_field::integers::QuotientMap;
878 use p3_field::{Field, PrimeCharacteristicRing, PrimeField32, PrimeField64};
879 use rand::rngs::SmallRng;
880 use rand::{Rng, SeedableRng};
881
882 #[test]
883 fn test_as_canonical_u32() {
884 let mut rng = SmallRng::seed_from_u64(1);
885 let x: u32 = rng.random();
886 let x_mod_order = x % <$field>::ORDER_U32;
887
888 for zero in $zeros {
889 assert_eq!(zero.as_canonical_u32(), 0);
890 assert_eq!(zero.to_unique_u32() as u64, zero.to_unique_u64());
891 }
892 for one in $ones {
893 assert_eq!(one.as_canonical_u32(), 1);
894 assert_eq!(one.to_unique_u32() as u64, one.to_unique_u64());
895 }
896 assert_eq!(<$field>::TWO.as_canonical_u32(), 2 % <$field>::ORDER_U32);
897 assert_eq!(
898 <$field>::NEG_ONE.as_canonical_u32(),
899 <$field>::ORDER_U32 - 1
900 );
901 assert_eq!(
902 <$field>::from_int(<$field>::ORDER_U32).as_canonical_u32(),
903 0
904 );
905 assert_eq!(<$field>::from_int(x).as_canonical_u32(), x_mod_order);
906 assert_eq!(
907 <$field>::from_int(x).to_unique_u32() as u64,
908 <$field>::from_int(x).to_unique_u64()
909 );
910 assert_eq!(
911 unsafe { <$field>::from_canonical_unchecked(x_mod_order).as_canonical_u32() },
912 x_mod_order
913 );
914 }
915
916 #[test]
917 fn test_as_unique_u32() {
918 assert_ne!(
919 <$field>::ZERO.to_unique_u32(),
920 <$field>::ONE.to_unique_u32()
921 );
922 assert_ne!(
923 <$field>::ZERO.to_unique_u32(),
924 <$field>::NEG_ONE.to_unique_u32()
925 );
926 assert_eq!(
927 <$field>::from_int(<$field>::ORDER_U32).to_unique_u32(),
928 <$field>::ZERO.to_unique_u32()
929 );
930 }
931
932 #[test]
933 fn test_large_unsigned_integer_conversions() {
934 $crate::generate_from_large_u_int_tests!(
935 $field,
936 <$field>::ORDER_U32,
937 [u32, u64, u128]
938 );
939 }
940
941 #[test]
942 fn test_large_signed_integer_conversions() {
943 $crate::generate_from_large_i_int_tests!(
944 $field,
945 <$field>::ORDER_U32,
946 [i32, i64, i128]
947 );
948 }
949
950 #[test]
951 fn test_raw_data_serializable() {
952 $crate::test_into_bytes_32::<$field>($zeros, $ones);
953 }
954 }
955 };
956}
957
958#[macro_export]
959macro_rules! test_two_adic_field {
960 ($field:ty) => {
961 mod two_adic_field_tests {
962 #[test]
963 fn test_two_adic_consistency() {
964 $crate::test_two_adic_generator_consistency::<$field>();
965 }
966
967 #[test]
970 fn test_two_adic_generator_consistency_as_trivial_extension() {
971 $crate::test_ef_two_adic_generator_consistency::<$field, $field>();
972 }
973 }
974 };
975}
976
977#[macro_export]
978macro_rules! test_extension_field {
979 ($field:ty, $ef:ty) => {
980 mod extension_field_tests {
981 #[test]
982 fn test_to_from_extension() {
983 $crate::test_to_from_extension_field::<$field, $ef>();
984 }
985
986 #[test]
987 fn test_galois_extension() {
988 $crate::test_galois_extension::<$field, $ef>();
989 }
990
991 #[test]
992 fn test_packed_extension() {
993 $crate::test_packed_extension::<$field, $ef>();
994 }
995 }
996 };
997}
998
999#[macro_export]
1000macro_rules! test_two_adic_extension_field {
1001 ($field:ty, $ef:ty) => {
1002 use $crate::test_two_adic_field;
1003
1004 test_two_adic_field!($ef);
1005
1006 mod two_adic_extension_field_tests {
1007
1008 #[test]
1009 fn test_ef_two_adic_generator_consistency() {
1010 $crate::test_ef_two_adic_generator_consistency::<$field, $ef>();
1011 }
1012 }
1013 };
1014}