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