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 let empty: [R; 0] = [];
227 let product_result: R = empty.into_iter().product();
228 assert_eq!(
229 product_result,
230 R::ONE,
231 "Product of empty iterator should return ONE, not ZERO"
232 );
233}
234
235pub fn test_inv_div<F: Field>()
236where
237 StandardUniform: Distribution<F>,
238{
239 let mut rng = SmallRng::seed_from_u64(1);
240 let x = rng.random::<F>();
241 let y = rng.random::<F>();
242 let z = rng.random::<F>();
243 assert_eq!(F::TWO.inverse(), F::ONE.halve());
244 assert_eq!(x * x.inverse(), F::ONE);
245 assert_eq!(x.inverse() * x, F::ONE);
246 assert_eq!(x.square().inverse(), x.inverse().square());
247 assert_eq!((x / y) * y, x);
248 assert_eq!(x / (y * z), (x / y) / z);
249 assert_eq!((x * y) / z, x * (y / z));
250}
251
252pub fn test_mul_2exp_u64<R: PrimeCharacteristicRing + Eq>()
253where
254 StandardUniform: Distribution<R>,
255{
256 let mut rng = SmallRng::seed_from_u64(1);
257 let x = rng.random::<R>();
258 assert_eq!(x.mul_2exp_u64(0), x);
259 assert_eq!(x.mul_2exp_u64(1), x.double());
260 for i in 0..128 {
261 assert_eq!(
262 x.clone().mul_2exp_u64(i),
263 x.clone() * R::from_u128(1_u128 << i)
264 );
265 }
266 for i in 128..256 {
268 assert_eq!(x.clone().mul_2exp_u64(i), x.clone() * R::TWO.exp_u64(i));
269 }
270}
271
272pub fn test_div_2exp_u64<R: PrimeCharacteristicRing + Eq>()
273where
274 StandardUniform: Distribution<R>,
275{
276 let mut rng = SmallRng::seed_from_u64(1);
277 let x = rng.random::<R>();
278 assert_eq!(x.div_2exp_u64(0), x);
279 assert_eq!(x.div_2exp_u64(1), x.halve());
280 for i in 0..128 {
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::from_u128(1_u128 << i).inverse())
286 );
287 }
288 for i in 128..256 {
290 assert_eq!(x.mul_2exp_u64(i).div_2exp_u64(i), x);
291 assert_eq!(
292 x.div_2exp_u64(i),
293 x.clone() * R::from_prime_subfield(R::PrimeSubfield::TWO.inverse().exp_u64(i))
295 );
296 }
297}
298
299pub fn test_add_slice<F: Field>()
300where
301 StandardUniform: Distribution<F>,
302{
303 let mut rng = SmallRng::seed_from_u64(1);
304 let lengths = [
305 F::Packing::WIDTH - 1,
306 F::Packing::WIDTH,
307 (F::Packing::WIDTH - 1) + (F::Packing::WIDTH << 10),
308 ];
309 for len in lengths {
310 let mut slice_1: Vec<_> = (&mut rng).sample_iter(StandardUniform).take(len).collect();
311 let slice_1_copy = slice_1.clone();
312 let slice_2: Vec<_> = (&mut rng).sample_iter(StandardUniform).take(len).collect();
313
314 F::add_slices(&mut slice_1, &slice_2);
315 for i in 0..len {
316 assert_eq!(slice_1[i], slice_1_copy[i] + slice_2[i]);
317 }
318 }
319}
320
321pub fn test_inverse<F: Field>()
322where
323 StandardUniform: Distribution<F>,
324{
325 assert_eq!(None, F::ZERO.try_inverse());
326 assert_eq!(Some(F::ONE), F::ONE.try_inverse());
327 let mut rng = SmallRng::seed_from_u64(1);
328 for _ in 0..1000 {
329 let x = rng.random::<F>();
330 if !x.is_zero() && !x.is_one() {
331 let z = x.inverse();
332 assert_ne!(x, z);
333 assert_eq!(x * z, F::ONE);
334 }
335 }
336}
337
338pub fn test_field_json_serialization<F>(values: &[F])
344where
345 F: PrimeCharacteristicRing + Serialize + DeserializeOwned + Eq,
346{
347 for value in values {
348 let serialized = serde_json::to_string(value).expect("Failed to serialize field element");
350 let deserialized: F =
351 serde_json::from_str(&serialized).expect("Failed to deserialize field element");
352 assert_eq!(
353 *value, deserialized,
354 "Single round-trip serialization failed"
355 );
356
357 let serialized_again = serde_json::to_string(&deserialized)
359 .expect("Failed to serialize field element (second time)");
360 let deserialized_again: F = serde_json::from_str(&serialized_again)
361 .expect("Failed to deserialize field element (second time)");
362 assert_eq!(
363 *value, deserialized_again,
364 "Double round-trip serialization failed"
365 );
366 assert_eq!(
367 deserialized, deserialized_again,
368 "Deserialized values should be equal"
369 );
370 }
371}
372
373pub fn test_prime_field_32_json_deserialization_boundaries<F>(accepts_order_repr: bool)
378where
379 F: PrimeField32 + Serialize + DeserializeOwned + Eq,
380{
381 let zero: F = serde_json::from_str("0").expect("Failed to deserialize zero");
382 assert_eq!(zero, F::ZERO, "Deserializing 0 should produce ZERO");
383
384 let original: F = serde_json::from_str("42").expect("Failed to deserialize test value");
385 let serialized = serde_json::to_string(&original).expect("Failed to serialize test value");
386 let deserialized: F =
387 serde_json::from_str(&serialized).expect("Failed to deserialize serialized test value");
388 assert_eq!(
389 deserialized, original,
390 "Round-trip serialization should preserve the value"
391 );
392
393 let max_valid = if accepts_order_repr {
394 F::ORDER_U32
395 } else {
396 F::ORDER_U32 - 1
397 };
398 let max_valid_json = serde_json::to_string(&max_valid).expect("Failed to encode max valid u32");
399 let max_valid_result: Result<F, _> = serde_json::from_str(&max_valid_json);
400 assert!(
401 max_valid_result.is_ok(),
402 "Expected max valid representation to deserialize successfully"
403 );
404
405 if let Some(first_invalid) = max_valid.checked_add(1) {
406 let first_invalid_json =
407 serde_json::to_string(&first_invalid).expect("Failed to encode first invalid value");
408 let first_invalid_result: Result<F, _> = serde_json::from_str(&first_invalid_json);
409 assert!(
410 first_invalid_result.is_err(),
411 "Expected first out-of-range representation to fail deserialization"
412 );
413 }
414
415 if max_valid != u32::MAX {
416 let max_u32_json = serde_json::to_string(&u32::MAX).expect("Failed to encode u32::MAX");
417 let max_u32_result: Result<F, _> = serde_json::from_str(&max_u32_json);
418 assert!(
419 max_u32_result.is_err(),
420 "Expected u32::MAX to fail deserialization"
421 );
422 }
423}
424
425pub fn test_dot_product<R: PrimeCharacteristicRing + Eq + Copy>(u: &[R; 64], v: &[R; 64]) {
426 let mut dot = R::ZERO;
427 assert_eq!(
428 dot,
429 R::dot_product::<0>(u[..0].try_into().unwrap(), v[..0].try_into().unwrap())
430 );
431 dot += u[0] * v[0];
432 assert_eq!(
433 dot,
434 R::dot_product::<1>(u[..1].try_into().unwrap(), v[..1].try_into().unwrap())
435 );
436 dot += u[1] * v[1];
437 assert_eq!(
438 dot,
439 R::dot_product::<2>(u[..2].try_into().unwrap(), v[..2].try_into().unwrap())
440 );
441 dot += u[2] * v[2];
442 assert_eq!(
443 dot,
444 R::dot_product::<3>(u[..3].try_into().unwrap(), v[..3].try_into().unwrap())
445 );
446 dot += u[3] * v[3];
447 assert_eq!(
448 dot,
449 R::dot_product::<4>(u[..4].try_into().unwrap(), v[..4].try_into().unwrap())
450 );
451 dot += u[4] * v[4];
452 assert_eq!(
453 dot,
454 R::dot_product::<5>(u[..5].try_into().unwrap(), v[..5].try_into().unwrap())
455 );
456 dot += u[5] * v[5];
457 assert_eq!(
458 dot,
459 R::dot_product::<6>(u[..6].try_into().unwrap(), v[..6].try_into().unwrap())
460 );
461 dot += u[6] * v[6];
462 assert_eq!(
463 dot,
464 R::dot_product::<7>(u[..7].try_into().unwrap(), v[..7].try_into().unwrap())
465 );
466 dot += u[7] * v[7];
467 assert_eq!(
468 dot,
469 R::dot_product::<8>(u[..8].try_into().unwrap(), v[..8].try_into().unwrap())
470 );
471 dot += u[8] * v[8];
472 assert_eq!(
473 dot,
474 R::dot_product::<9>(u[..9].try_into().unwrap(), v[..9].try_into().unwrap())
475 );
476 dot += u[9] * v[9];
477 assert_eq!(
478 dot,
479 R::dot_product::<10>(u[..10].try_into().unwrap(), v[..10].try_into().unwrap())
480 );
481 dot += u[10] * v[10];
482 assert_eq!(
483 dot,
484 R::dot_product::<11>(u[..11].try_into().unwrap(), v[..11].try_into().unwrap())
485 );
486 dot += u[11] * v[11];
487 assert_eq!(
488 dot,
489 R::dot_product::<12>(u[..12].try_into().unwrap(), v[..12].try_into().unwrap())
490 );
491 dot += u[12] * v[12];
492 assert_eq!(
493 dot,
494 R::dot_product::<13>(u[..13].try_into().unwrap(), v[..13].try_into().unwrap())
495 );
496 dot += u[13] * v[13];
497 assert_eq!(
498 dot,
499 R::dot_product::<14>(u[..14].try_into().unwrap(), v[..14].try_into().unwrap())
500 );
501 dot += u[14] * v[14];
502 assert_eq!(
503 dot,
504 R::dot_product::<15>(u[..15].try_into().unwrap(), v[..15].try_into().unwrap())
505 );
506 dot += u[15] * v[15];
507 assert_eq!(
508 dot,
509 R::dot_product::<16>(u[..16].try_into().unwrap(), v[..16].try_into().unwrap())
510 );
511
512 let dot_64: R = u
513 .iter()
514 .zip(v.iter())
515 .fold(R::ZERO, |acc, (&lhs, &rhs)| acc + (lhs * rhs));
516 assert_eq!(dot_64, R::dot_product::<64>(u, v));
517}
518
519pub fn test_sums<R: PrimeCharacteristicRing + Eq + Copy>(u: &[R; 16]) {
520 let mut sum = R::ZERO;
521 assert_eq!(sum, R::sum_array::<0>(u[..0].try_into().unwrap()));
522 assert_eq!(sum, u[..0].iter().copied().sum());
523 sum += u[0];
524 assert_eq!(sum, R::sum_array::<1>(u[..1].try_into().unwrap()));
525 assert_eq!(sum, u[..1].iter().copied().sum());
526 sum += u[1];
527 assert_eq!(sum, R::sum_array::<2>(u[..2].try_into().unwrap()));
528 assert_eq!(sum, u[..2].iter().copied().sum());
529 sum += u[2];
530 assert_eq!(sum, R::sum_array::<3>(u[..3].try_into().unwrap()));
531 assert_eq!(sum, u[..3].iter().copied().sum());
532 sum += u[3];
533 assert_eq!(sum, R::sum_array::<4>(u[..4].try_into().unwrap()));
534 assert_eq!(sum, u[..4].iter().copied().sum());
535 sum += u[4];
536 assert_eq!(sum, R::sum_array::<5>(u[..5].try_into().unwrap()));
537 assert_eq!(sum, u[..5].iter().copied().sum());
538 sum += u[5];
539 assert_eq!(sum, R::sum_array::<6>(u[..6].try_into().unwrap()));
540 assert_eq!(sum, u[..6].iter().copied().sum());
541 sum += u[6];
542 assert_eq!(sum, R::sum_array::<7>(u[..7].try_into().unwrap()));
543 assert_eq!(sum, u[..7].iter().copied().sum());
544 sum += u[7];
545 assert_eq!(sum, R::sum_array::<8>(u[..8].try_into().unwrap()));
546 assert_eq!(sum, u[..8].iter().copied().sum());
547 sum += u[8];
548 assert_eq!(sum, R::sum_array::<9>(u[..9].try_into().unwrap()));
549 assert_eq!(sum, u[..9].iter().copied().sum());
550 sum += u[9];
551 assert_eq!(sum, R::sum_array::<10>(u[..10].try_into().unwrap()));
552 assert_eq!(sum, u[..10].iter().copied().sum());
553 sum += u[10];
554 assert_eq!(sum, R::sum_array::<11>(u[..11].try_into().unwrap()));
555 assert_eq!(sum, u[..11].iter().copied().sum());
556 sum += u[11];
557 assert_eq!(sum, R::sum_array::<12>(u[..12].try_into().unwrap()));
558 assert_eq!(sum, u[..12].iter().copied().sum());
559 sum += u[12];
560 assert_eq!(sum, R::sum_array::<13>(u[..13].try_into().unwrap()));
561 assert_eq!(sum, u[..13].iter().copied().sum());
562 sum += u[13];
563 assert_eq!(sum, R::sum_array::<14>(u[..14].try_into().unwrap()));
564 assert_eq!(sum, u[..14].iter().copied().sum());
565 sum += u[14];
566 assert_eq!(sum, R::sum_array::<15>(u[..15].try_into().unwrap()));
567 assert_eq!(sum, u[..15].iter().copied().sum());
568 sum += u[15];
569 assert_eq!(sum, R::sum_array::<16>(u));
570 assert_eq!(sum, u.iter().copied().sum());
571}
572
573pub fn test_binary_ops<R: PrimeCharacteristicRing + Eq + Copy>(
574 zeros: &[R],
575 ones: &[R],
576 x: R,
577 y: R,
578 z: R,
579) {
580 for zero in zeros {
581 for one in ones {
582 assert_eq!(one.xor(one), R::ZERO, "Error when testing xor(1, 1) = 0.");
583 assert_eq!(zero.xor(one), R::ONE, "Error when testing xor(0, 1) = 1.");
584 assert_eq!(one.xor(zero), R::ONE, "Error when testing xor(1, 0) = 1.");
585 assert_eq!(zero.xor(zero), R::ZERO, "Error when testing xor(0, 0) = 0.");
586 assert_eq!(one.andn(one), R::ZERO, "Error when testing andn(1, 1) = 0.");
587 assert_eq!(zero.andn(one), R::ONE, "Error when testing andn(0, 1) = 1.");
588 assert_eq!(
589 one.andn(zero),
590 R::ZERO,
591 "Error when testing andn(1, 0) = 0."
592 );
593 assert_eq!(
594 zero.andn(zero),
595 R::ZERO,
596 "Error when testing andn(0, 0) = 0."
597 );
598 assert_eq!(
599 zero.bool_check(),
600 R::ZERO,
601 "Error when testing bool_check(0) = 0."
602 );
603 assert_eq!(
604 one.bool_check(),
605 R::ZERO,
606 "Error when testing bool_check(1) = 0."
607 );
608 }
609 }
610
611 assert_eq!(
612 R::ONE.xor(&R::NEG_ONE),
613 R::TWO,
614 "Error when testing xor(1, -1) = 2."
615 );
616 assert_eq!(
617 R::NEG_ONE.xor(&R::ONE),
618 R::TWO,
619 "Error when testing xor(-1, 1) = 2."
620 );
621 assert_eq!(
622 R::NEG_ONE.xor(&R::NEG_ONE),
623 R::from_i8(-4),
624 "Error when testing xor(-1, -1) = -4."
625 );
626 assert_eq!(
627 R::ONE.andn(&R::NEG_ONE),
628 R::ZERO,
629 "Error when testing andn(1, -1) = 0."
630 );
631 assert_eq!(
632 R::NEG_ONE.andn(&R::ONE),
633 R::TWO,
634 "Error when testing andn(-1, 1) = 2."
635 );
636 assert_eq!(
637 R::NEG_ONE.andn(&R::NEG_ONE),
638 -R::TWO,
639 "Error when testing andn(-1, -1) = -2."
640 );
641
642 assert_eq!(x.xor(&y), x + y - x * y.double(), "Error when testing xor.");
643
644 assert_eq!(x.andn(&y), (R::ONE - x) * y, "Error when testing andn.");
645
646 assert_eq!(
647 x.xor3(&y, &z),
648 x + y + z - (x * y + x * z + y * z).double() + x * y * z.double().double(),
649 "Error when testing xor3."
650 );
651}
652
653pub fn test_powers_collect<F: Field>() {
655 let small_powers_serial = [0, 1, 2, 3, 4, 15];
657 let small_powers_packed = [16, 17];
659 let powers_of_two = [5, 6, 7, 8, 9, 10, 13];
661
662 let num_powers_tests: Vec<usize> = small_powers_serial
663 .into_iter()
664 .chain(small_powers_packed)
665 .chain(powers_of_two.iter().flat_map(|exp| {
666 let n = 1 << exp;
668 [n - 1, n, n + 1]
669 }))
670 .collect();
671
672 let base = F::TWO;
673 let shift = F::GENERATOR;
674
675 let expected_iter = successors(Some(shift), |prev| Some(*prev * base));
677
678 for num_powers in num_powers_tests {
679 let expected: Vec<_> = expected_iter.clone().take(num_powers).collect();
680 let actual = base.shifted_powers(shift).collect_n(num_powers);
681 assert_eq!(
682 expected, actual,
683 "Got different powers when taking {num_powers}"
684 );
685 }
686}
687
688pub(crate) fn exp_biguint<F: Field>(x: F, exponent: &BigUint) -> F {
694 let digits = exponent.to_u64_digits();
695 let size = digits.len();
696
697 let mut power = F::ONE;
698
699 let bases = (0..size).map(|i| x.exp_power_of_2(64 * i));
700 digits
701 .iter()
702 .zip(bases)
703 .for_each(|(digit, base)| power *= base.exp_u64(*digit));
704 power
705}
706
707pub fn test_generator<F: Field>(multiplicative_group_factors: &[(BigUint, u32)]) {
710 let product: BigUint = multiplicative_group_factors
717 .iter()
718 .map(|(factor, exponent)| factor.pow(*exponent))
719 .product();
720 assert_eq!(product + BigUint::from(1u32), F::order());
721
722 let mut partial_products: Vec<F> = (0..=multiplicative_group_factors.len())
725 .map(|i| {
726 let mut generator_power = F::GENERATOR;
727 multiplicative_group_factors
728 .iter()
729 .enumerate()
730 .for_each(|(j, (factor, exponent))| {
731 let modified_exponent = if i == j { exponent - 1 } else { *exponent };
732 for _ in 0..modified_exponent {
733 generator_power = exp_biguint(generator_power, factor);
734 }
735 });
736 generator_power
737 })
738 .collect();
739
740 assert_eq!(partial_products.pop().unwrap(), F::ONE);
741
742 for elem in partial_products.into_iter() {
743 assert_ne!(elem, F::ONE);
744 }
745}
746
747pub fn test_two_adic_generator_consistency<F: TwoAdicField>() {
748 let log_n = F::TWO_ADICITY;
749 let g = F::two_adic_generator(log_n);
750 for bits in 0..=log_n {
751 assert_eq!(g.exp_power_of_2(bits), F::two_adic_generator(log_n - bits));
752 }
753}
754
755pub fn test_two_adic_point_collection<F: TwoAdicField>() {
756 let log_n = F::TWO_ADICITY.min(15);
757 for bits in 0..=log_n {
758 let group = TwoAdicMultiplicativeCoset::new(F::ONE, bits).unwrap();
759 let points = group.iter().collect();
760 #[allow(clippy::map_identity)]
762 let points_expected = group.iter().map(|x| x).collect::<Vec<_>>();
763 assert_eq!(points, points_expected);
764 }
765}
766
767pub fn test_ef_two_adic_generator_consistency<
768 F: TwoAdicField,
769 EF: TwoAdicField + ExtensionField<F>,
770>() {
771 assert_eq!(
772 Into::<EF>::into(F::two_adic_generator(F::TWO_ADICITY)),
773 EF::two_adic_generator(F::TWO_ADICITY)
774 );
775}
776
777pub fn test_into_bytes_32<F: PrimeField32>(zeros: &[F], ones: &[F])
778where
779 StandardUniform: Distribution<F>,
780{
781 let mut rng = SmallRng::seed_from_u64(1);
782 let x = rng.random::<F>();
783
784 assert_eq!(
785 x.into_bytes().into_iter().collect::<Vec<_>>(),
786 x.to_unique_u32().to_le_bytes()
787 );
788 for one in ones {
789 assert_eq!(
790 one.into_bytes().into_iter().collect::<Vec<_>>(),
791 F::ONE.to_unique_u32().to_le_bytes()
792 );
793 }
794 for zero in zeros {
795 assert_eq!(zero.into_bytes().into_iter().collect::<Vec<_>>(), [0; 4]);
796 }
797}
798
799pub fn test_into_bytes_64<F: PrimeField64>(zeros: &[F], ones: &[F])
800where
801 StandardUniform: Distribution<F>,
802{
803 let mut rng = SmallRng::seed_from_u64(1);
804 let x = rng.random::<F>();
805
806 assert_eq!(
807 x.into_bytes().into_iter().collect::<Vec<_>>(),
808 x.to_unique_u64().to_le_bytes()
809 );
810 for one in ones {
811 assert_eq!(
812 one.into_bytes().into_iter().collect::<Vec<_>>(),
813 F::ONE.to_unique_u64().to_le_bytes()
814 );
815 }
816 for zero in zeros {
817 assert_eq!(zero.into_bytes().into_iter().collect::<Vec<_>>(), [0; 8]);
818 }
819}
820
821pub fn test_into_stream<F: Field>()
822where
823 StandardUniform: Distribution<[F; 16]>,
824{
825 let mut rng = SmallRng::seed_from_u64(1);
826 let xs: [F; 16] = rng.random();
827
828 let byte_vec = F::into_byte_stream(xs).into_iter().collect::<Vec<_>>();
829 let u32_vec = F::into_u32_stream(xs).into_iter().collect::<Vec<_>>();
830 let u64_vec = F::into_u64_stream(xs).into_iter().collect::<Vec<_>>();
831
832 let expected_bytes = xs
833 .into_iter()
834 .flat_map(|x| x.into_bytes())
835 .collect::<Vec<_>>();
836 let expected_u32s = iter_array_chunks_padded(byte_vec.iter().copied(), 0)
837 .map(u32::from_le_bytes)
838 .collect::<Vec<_>>();
839 let expected_u64s = iter_array_chunks_padded(byte_vec.iter().copied(), 0)
840 .map(u64::from_le_bytes)
841 .collect::<Vec<_>>();
842
843 assert_eq!(byte_vec, expected_bytes);
844 assert_eq!(u32_vec, expected_u32s);
845 assert_eq!(u64_vec, expected_u64s);
846
847 let ys: [F; 16] = rng.random();
848 let zs: [F; 16] = rng.random();
849
850 let combs: [[F; 3]; 16] = array::from_fn(|i| [xs[i], ys[i], zs[i]]);
851
852 let byte_vec_ys = F::into_byte_stream(ys).into_iter().collect::<Vec<_>>();
853 let byte_vec_zs = F::into_byte_stream(zs).into_iter().collect::<Vec<_>>();
854 let u32_vec_ys = F::into_u32_stream(ys).into_iter().collect::<Vec<_>>();
855 let u32_vec_zs = F::into_u32_stream(zs).into_iter().collect::<Vec<_>>();
856 let u64_vec_ys = F::into_u64_stream(ys).into_iter().collect::<Vec<_>>();
857 let u64_vec_zs = F::into_u64_stream(zs).into_iter().collect::<Vec<_>>();
858
859 let combined_bytes = F::into_parallel_byte_streams(combs)
860 .into_iter()
861 .collect::<Vec<_>>();
862 let combined_u32s = F::into_parallel_u32_streams(combs)
863 .into_iter()
864 .collect::<Vec<_>>();
865 let combined_u64s = F::into_parallel_u64_streams(combs)
866 .into_iter()
867 .collect::<Vec<_>>();
868
869 let expected_combined_bytes: Vec<[u8; 3]> = (0..byte_vec.len())
870 .map(|i| [byte_vec[i], byte_vec_ys[i], byte_vec_zs[i]])
871 .collect();
872 let expected_combined_u32s: Vec<[u32; 3]> = (0..u32_vec.len())
873 .map(|i| [u32_vec[i], u32_vec_ys[i], u32_vec_zs[i]])
874 .collect();
875 let expected_combined_u64s: Vec<[u64; 3]> = (0..u64_vec.len())
876 .map(|i| [u64_vec[i], u64_vec_ys[i], u64_vec_zs[i]])
877 .collect();
878
879 assert_eq!(combined_bytes, expected_combined_bytes);
880 assert_eq!(combined_u32s, expected_combined_u32s);
881 assert_eq!(combined_u64s, expected_combined_u64s);
882}
883
884#[macro_export]
885macro_rules! test_ring_with_eq {
886 ($ring:ty, $zeros: expr, $ones: expr) => {
887 mod ring_tests {
888 use p3_field::PrimeCharacteristicRing;
889
890 #[test]
891 fn test_ring_with_eq() {
892 $crate::test_ring_with_eq::<$ring>($zeros, $ones);
893 }
894 #[test]
895 fn test_mul_2exp_u64() {
896 $crate::test_mul_2exp_u64::<$ring>();
897 }
898 #[test]
899 fn test_div_2exp_u64() {
900 $crate::test_div_2exp_u64::<$ring>();
901 }
902 }
903 };
904}
905
906#[macro_export]
907macro_rules! test_field {
908 ($field:ty, $zeros: expr, $ones: expr, $factors: expr) => {
909 $crate::test_ring_with_eq!($field, $zeros, $ones);
910
911 mod field_tests {
912 #[test]
913 fn test_inv_div() {
914 $crate::test_inv_div::<$field>();
915 }
916 #[test]
917 fn test_inverse() {
918 $crate::test_inverse::<$field>();
919 }
920 #[test]
921 fn test_generator() {
922 $crate::test_generator::<$field>($factors);
923 }
924 #[test]
925 fn test_streaming() {
926 $crate::test_into_stream::<$field>();
927 }
928 #[test]
929 fn test_powers_collect() {
930 $crate::test_powers_collect::<$field>();
931 }
932 }
933
934 mod trivial_extension_tests {
937 #[test]
938 fn test_to_from_trivial_extension() {
939 $crate::test_to_from_extension_field::<$field, $field>();
940 }
941
942 #[test]
943 fn test_trivial_packed_extension() {
944 $crate::test_packed_extension::<$field, $field>();
945 }
946 }
947 };
948}
949
950#[macro_export]
951macro_rules! test_prime_field {
952 ($field:ty) => {
953 mod from_integer_small_tests {
954 use p3_field::integers::QuotientMap;
955 use p3_field::{Field, PrimeCharacteristicRing};
956
957 #[test]
958 fn test_small_integer_conversions() {
959 $crate::generate_from_small_int_tests!(
960 $field,
961 [
962 u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize
963 ]
964 );
965 }
966
967 #[test]
968 fn test_small_signed_integer_conversions() {
969 $crate::generate_from_small_neg_int_tests!(
970 $field,
971 [i8, i16, i32, i64, i128, isize]
972 );
973 }
974 }
975 };
976}
977
978#[macro_export]
979macro_rules! test_prime_field_64 {
980 ($field:ty, $zeros: expr, $ones: expr) => {
981 mod from_integer_tests_prime_field_64 {
982 use p3_field::integers::QuotientMap;
983 use p3_field::{Field, PrimeCharacteristicRing, PrimeField64, RawDataSerializable};
984 use rand::rngs::SmallRng;
985 use rand::{Rng, SeedableRng};
986
987 #[test]
988 fn test_as_canonical_u64() {
989 let mut rng = SmallRng::seed_from_u64(1);
990 let x: u64 = rng.random();
991 let x_mod_order = x % <$field>::ORDER_U64;
992
993 assert_eq!(<$field>::ZERO.as_canonical_u64(), 0);
994 assert_eq!(<$field>::ONE.as_canonical_u64(), 1);
995 assert_eq!(<$field>::TWO.as_canonical_u64(), 2 % <$field>::ORDER_U64);
996 assert_eq!(
997 <$field>::NEG_ONE.as_canonical_u64(),
998 <$field>::ORDER_U64 - 1
999 );
1000
1001 assert_eq!(
1002 <$field>::from_int(<$field>::ORDER_U64).as_canonical_u64(),
1003 0
1004 );
1005 assert_eq!(<$field>::from_int(x).as_canonical_u64(), x_mod_order);
1006 assert_eq!(
1007 unsafe { <$field>::from_canonical_unchecked(x_mod_order).as_canonical_u64() },
1008 x_mod_order
1009 );
1010 }
1011
1012 #[test]
1013 fn test_as_unique_u64() {
1014 assert_ne!(
1015 <$field>::ZERO.to_unique_u64(),
1016 <$field>::ONE.to_unique_u64()
1017 );
1018 assert_ne!(
1019 <$field>::ZERO.to_unique_u64(),
1020 <$field>::NEG_ONE.to_unique_u64()
1021 );
1022 assert_eq!(
1023 <$field>::from_int(<$field>::ORDER_U64).to_unique_u64(),
1024 <$field>::ZERO.to_unique_u64()
1025 );
1026 }
1027
1028 #[test]
1029 fn test_large_unsigned_integer_conversions() {
1030 $crate::generate_from_large_u_int_tests!($field, <$field>::ORDER_U64, [u64, u128]);
1031 }
1032
1033 #[test]
1034 fn test_large_signed_integer_conversions() {
1035 $crate::generate_from_large_i_int_tests!($field, <$field>::ORDER_U64, [i64, i128]);
1036 }
1037
1038 #[test]
1039 fn test_raw_data_serializable() {
1040 if <$field>::NUM_BYTES == 8 {
1043 $crate::test_into_bytes_64::<$field>($zeros, $ones);
1044 }
1045 }
1046 }
1047 };
1048}
1049
1050#[macro_export]
1051macro_rules! test_prime_field_32 {
1052 ($field:ty, $zeros: expr, $ones: expr) => {
1053 mod from_integer_tests_prime_field_32 {
1054 use p3_field::integers::QuotientMap;
1055 use p3_field::{Field, PrimeCharacteristicRing, PrimeField32, PrimeField64};
1056 use rand::rngs::SmallRng;
1057 use rand::{Rng, SeedableRng};
1058
1059 #[test]
1060 fn test_as_canonical_u32() {
1061 let mut rng = SmallRng::seed_from_u64(1);
1062 let x: u32 = rng.random();
1063 let x_mod_order = x % <$field>::ORDER_U32;
1064
1065 for zero in $zeros {
1066 assert_eq!(zero.as_canonical_u32(), 0);
1067 assert_eq!(zero.to_unique_u32() as u64, zero.to_unique_u64());
1068 }
1069 for one in $ones {
1070 assert_eq!(one.as_canonical_u32(), 1);
1071 assert_eq!(one.to_unique_u32() as u64, one.to_unique_u64());
1072 }
1073 assert_eq!(<$field>::TWO.as_canonical_u32(), 2 % <$field>::ORDER_U32);
1074 assert_eq!(
1075 <$field>::NEG_ONE.as_canonical_u32(),
1076 <$field>::ORDER_U32 - 1
1077 );
1078 assert_eq!(
1079 <$field>::from_int(<$field>::ORDER_U32).as_canonical_u32(),
1080 0
1081 );
1082 assert_eq!(<$field>::from_int(x).as_canonical_u32(), x_mod_order);
1083 assert_eq!(
1084 <$field>::from_int(x).to_unique_u32() as u64,
1085 <$field>::from_int(x).to_unique_u64()
1086 );
1087 assert_eq!(
1088 unsafe { <$field>::from_canonical_unchecked(x_mod_order).as_canonical_u32() },
1089 x_mod_order
1090 );
1091 }
1092
1093 #[test]
1094 fn test_as_unique_u32() {
1095 assert_ne!(
1096 <$field>::ZERO.to_unique_u32(),
1097 <$field>::ONE.to_unique_u32()
1098 );
1099 assert_ne!(
1100 <$field>::ZERO.to_unique_u32(),
1101 <$field>::NEG_ONE.to_unique_u32()
1102 );
1103 assert_eq!(
1104 <$field>::from_int(<$field>::ORDER_U32).to_unique_u32(),
1105 <$field>::ZERO.to_unique_u32()
1106 );
1107 }
1108
1109 #[test]
1110 fn test_large_unsigned_integer_conversions() {
1111 $crate::generate_from_large_u_int_tests!(
1112 $field,
1113 <$field>::ORDER_U32,
1114 [u32, u64, u128]
1115 );
1116 }
1117
1118 #[test]
1119 fn test_large_signed_integer_conversions() {
1120 $crate::generate_from_large_i_int_tests!(
1121 $field,
1122 <$field>::ORDER_U32,
1123 [i32, i64, i128]
1124 );
1125 }
1126
1127 #[test]
1128 fn test_raw_data_serializable() {
1129 $crate::test_into_bytes_32::<$field>($zeros, $ones);
1130 }
1131
1132 #[test]
1133 fn test_json_deserialization_boundaries() {
1134 let accepts_order_repr = $zeros.len() > 1;
1135 $crate::test_prime_field_32_json_deserialization_boundaries::<$field>(
1136 accepts_order_repr,
1137 );
1138 }
1139 }
1140 };
1141}
1142
1143#[macro_export]
1144macro_rules! test_two_adic_field {
1145 ($field:ty) => {
1146 mod two_adic_field_tests {
1147 #[test]
1148 fn test_two_adic_consistency() {
1149 $crate::test_two_adic_generator_consistency::<$field>();
1150 $crate::test_two_adic_point_collection::<$field>();
1151 }
1152
1153 #[test]
1156 fn test_two_adic_generator_consistency_as_trivial_extension() {
1157 $crate::test_ef_two_adic_generator_consistency::<$field, $field>();
1158 }
1159 }
1160 };
1161}
1162
1163#[macro_export]
1164macro_rules! test_extension_field {
1165 ($field:ty, $ef:ty) => {
1166 mod extension_field_tests {
1167 #[test]
1168 fn test_to_from_extension() {
1169 $crate::test_to_from_extension_field::<$field, $ef>();
1170 }
1171
1172 #[test]
1173 fn test_galois_extension() {
1174 $crate::test_galois_extension::<$field, $ef>();
1175 }
1176
1177 #[test]
1178 fn test_packed_extension() {
1179 $crate::test_packed_extension::<$field, $ef>();
1180 }
1181 }
1182 };
1183}
1184
1185#[macro_export]
1186macro_rules! test_two_adic_extension_field {
1187 ($field:ty, $ef:ty) => {
1188 use $crate::test_two_adic_field;
1189
1190 test_two_adic_field!($ef);
1191
1192 mod two_adic_extension_field_tests {
1193
1194 #[test]
1195 fn test_ef_two_adic_generator_consistency() {
1196 $crate::test_ef_two_adic_generator_consistency::<$field, $ef>();
1197 }
1198 }
1199 };
1200}
1201
1202#[macro_export]
1203macro_rules! test_frobenius {
1204 ($field:ty, $ef:ty) => {
1205 mod frobenius_tests {
1206 #[test]
1207 fn test_frobenius_fixes_base_field() {
1208 $crate::test_frobenius_fixes_base_field::<$field, $ef>();
1209 }
1210
1211 #[test]
1212 fn test_frobenius_multiplicative() {
1213 $crate::test_frobenius_multiplicative::<$field, $ef>();
1214 }
1215
1216 #[test]
1217 fn test_frobenius_additive() {
1218 $crate::test_frobenius_additive::<$field, $ef>();
1219 }
1220 }
1221 };
1222}