1use crate::errors::CreationError;
2use crate::field::element::FieldElement;
3use crate::field::errors::FieldError;
4use crate::field::traits::{HasDefaultTranscript, IsPrimeField};
5#[cfg(feature = "alloc")]
6use crate::traits::AsBytes;
7use crate::traits::ByteConversion;
8use crate::{
9 field::traits::IsField, unsigned_integer::element::UnsignedInteger,
10 unsigned_integer::montgomery::MontgomeryAlgorithms,
11};
12
13use core::fmt::Debug;
14use core::marker::PhantomData;
15
16pub type U384PrimeField<M> = MontgomeryBackendPrimeField<M, 6>;
17pub type U256PrimeField<M> = MontgomeryBackendPrimeField<M, 4>;
18pub type U64PrimeField<M> = MontgomeryBackendPrimeField<M, 1>;
19
20pub trait IsModulus<U>: Debug {
24 const MODULUS: U;
25}
26
27#[cfg_attr(
28 any(
29 feature = "lambdaworks-serde-binary",
30 feature = "lambdaworks-serde-string"
31 ),
32 derive(serde::Serialize, serde::Deserialize)
33)]
34#[derive(Clone, Debug, Hash, Copy)]
35pub struct MontgomeryBackendPrimeField<M, const NUM_LIMBS: usize> {
36 phantom: PhantomData<M>,
37}
38
39impl<M, const NUM_LIMBS: usize> MontgomeryBackendPrimeField<M, NUM_LIMBS>
40where
41 M: IsModulus<UnsignedInteger<NUM_LIMBS>>,
42{
43 pub const R2: UnsignedInteger<NUM_LIMBS> = Self::compute_r2_parameter(&M::MODULUS);
44 pub const MU: u64 = Self::compute_mu_parameter(&M::MODULUS);
45 pub const ZERO: UnsignedInteger<NUM_LIMBS> = UnsignedInteger::from_u64(0);
46 pub const ONE: UnsignedInteger<NUM_LIMBS> = MontgomeryAlgorithms::cios(
47 &UnsignedInteger::from_u64(1),
48 &Self::R2,
49 &M::MODULUS,
50 &Self::MU,
51 );
52 const MODULUS_HAS_ONE_SPARE_BIT: bool = Self::modulus_has_one_spare_bit();
53
54 const fn compute_mu_parameter(modulus: &UnsignedInteger<NUM_LIMBS>) -> u64 {
61 let mut y = 1;
62 let word_size = 64;
63 let mut i: usize = 2;
64 while i <= word_size {
65 let (_, lo) = UnsignedInteger::mul(modulus, &UnsignedInteger::from_u64(y));
66 let least_significant_limb = lo.limbs[NUM_LIMBS - 1];
67 if (least_significant_limb << (word_size - i)) >> (word_size - i) != 1 {
68 y += 1 << (i - 1);
69 }
70 i += 1;
71 }
72 y.wrapping_neg()
73 }
74
75 const fn compute_r2_parameter(
77 modulus: &UnsignedInteger<NUM_LIMBS>,
78 ) -> UnsignedInteger<NUM_LIMBS> {
79 let word_size = 64;
80 let mut l: usize = 0;
81 let zero = UnsignedInteger::from_u64(0);
82 while l < NUM_LIMBS * word_size {
84 if UnsignedInteger::const_ne(&modulus.const_shr(l), &zero) {
85 break;
86 }
87 l += 1;
88 }
89 let mut c = UnsignedInteger::from_u64(1).const_shl(l);
90
91 let mut i: usize = 1;
94 while i <= 2 * NUM_LIMBS * word_size - l {
95 let (double_c, overflow) = UnsignedInteger::add(&c, &c);
96 c = if UnsignedInteger::const_le(modulus, &double_c) || overflow {
97 UnsignedInteger::sub(&double_c, modulus).0
98 } else {
99 double_c
100 };
101 i += 1;
102 }
103 c
104 }
105
106 #[inline(always)]
110 const fn modulus_has_one_spare_bit() -> bool {
111 M::MODULUS.limbs[0] < (1u64 << 63) - 1
112 }
113}
114
115impl<M, const NUM_LIMBS: usize> IsField for MontgomeryBackendPrimeField<M, NUM_LIMBS>
116where
117 M: IsModulus<UnsignedInteger<NUM_LIMBS>> + Clone + Debug,
118{
119 type BaseType = UnsignedInteger<NUM_LIMBS>;
120
121 #[inline(always)]
122 fn add(a: &Self::BaseType, b: &Self::BaseType) -> Self::BaseType {
123 let (sum, overflow) = UnsignedInteger::add(a, b);
124 if Self::MODULUS_HAS_ONE_SPARE_BIT {
125 if sum >= M::MODULUS {
126 sum - M::MODULUS
127 } else {
128 sum
129 }
130 } else if overflow || sum >= M::MODULUS {
131 let (diff, _) = UnsignedInteger::sub(&sum, &M::MODULUS);
132 diff
133 } else {
134 sum
135 }
136 }
137
138 #[inline(always)]
139 fn mul(a: &Self::BaseType, b: &Self::BaseType) -> Self::BaseType {
140 if Self::MODULUS_HAS_ONE_SPARE_BIT {
141 MontgomeryAlgorithms::cios_optimized_for_moduli_with_one_spare_bit(
142 a,
143 b,
144 &M::MODULUS,
145 &Self::MU,
146 )
147 } else {
148 MontgomeryAlgorithms::cios(a, b, &M::MODULUS, &Self::MU)
149 }
150 }
151
152 #[inline(always)]
153 fn square(a: &UnsignedInteger<NUM_LIMBS>) -> UnsignedInteger<NUM_LIMBS> {
154 MontgomeryAlgorithms::sos_square(a, &M::MODULUS, &Self::MU)
155 }
156
157 #[inline(always)]
158 fn sub(a: &Self::BaseType, b: &Self::BaseType) -> Self::BaseType {
159 if b <= a {
160 a - b
161 } else {
162 M::MODULUS - (b - a)
163 }
164 }
165
166 #[inline(always)]
167 fn neg(a: &Self::BaseType) -> Self::BaseType {
168 if a == &Self::ZERO {
169 *a
170 } else {
171 M::MODULUS - a
172 }
173 }
174
175 #[inline(always)]
176 fn inv(a: &Self::BaseType) -> Result<Self::BaseType, FieldError> {
177 if a == &Self::ZERO {
178 Err(FieldError::InvZeroError)
179 } else {
180 let one: UnsignedInteger<NUM_LIMBS> = UnsignedInteger::from_u64(1);
187 let modulus: UnsignedInteger<NUM_LIMBS> = M::MODULUS;
188 let modulus_has_spare_bits = M::MODULUS.limbs[0] >> 63 == 0;
189
190 let mut u: UnsignedInteger<NUM_LIMBS> = *a;
191 let mut v = M::MODULUS;
192 let mut b = Self::R2; let mut c = Self::zero();
194
195 while u != one && v != one {
196 while u.limbs[NUM_LIMBS - 1] & 1 == 0 {
197 u >>= 1;
198 if b.limbs[NUM_LIMBS - 1] & 1 == 0 {
199 b >>= 1;
200 } else {
201 let carry;
202 (b, carry) = UnsignedInteger::<NUM_LIMBS>::add(&b, &modulus);
203 b >>= 1;
204 if !modulus_has_spare_bits && carry {
205 b.limbs[0] |= 1 << 63;
206 }
207 }
208 }
209
210 while v.limbs[NUM_LIMBS - 1] & 1 == 0 {
211 v >>= 1;
212
213 if c.limbs[NUM_LIMBS - 1] & 1 == 0 {
214 c >>= 1;
215 } else {
216 let carry;
217 (c, carry) = UnsignedInteger::<NUM_LIMBS>::add(&c, &modulus);
218 c >>= 1;
219 if !modulus_has_spare_bits && carry {
220 c.limbs[0] |= 1 << 63;
221 }
222 }
223 }
224
225 if v <= u {
226 u = u - v;
227 if b < c {
228 b = modulus - c + b;
229 } else {
230 b = b - c;
231 }
232 } else {
233 v = v - u;
234 if c < b {
235 c = modulus - b + c;
236 } else {
237 c = c - b;
238 }
239 }
240 }
241
242 if u == one {
243 Ok(b)
244 } else {
245 Ok(c)
246 }
247 }
248 }
249
250 #[inline(always)]
251 fn div(a: &Self::BaseType, b: &Self::BaseType) -> Result<Self::BaseType, FieldError> {
252 let b_inv = &Self::inv(b)?;
253 Ok(Self::mul(a, b_inv))
254 }
255
256 #[inline(always)]
257 fn eq(a: &Self::BaseType, b: &Self::BaseType) -> bool {
258 a == b
259 }
260
261 #[inline(always)]
262 fn zero() -> Self::BaseType {
263 Self::ZERO
264 }
265
266 #[inline(always)]
267 fn one() -> Self::BaseType {
268 Self::ONE
269 }
270
271 #[inline(always)]
272 fn from_u64(x: u64) -> Self::BaseType {
273 MontgomeryAlgorithms::cios(
274 &UnsignedInteger::from_u64(x),
275 &Self::R2,
276 &M::MODULUS,
277 &Self::MU,
278 )
279 }
280
281 #[inline(always)]
282 fn from_base_type(x: Self::BaseType) -> Self::BaseType {
283 MontgomeryAlgorithms::cios(&x, &Self::R2, &M::MODULUS, &Self::MU)
284 }
285}
286
287impl<M, const NUM_LIMBS: usize> IsPrimeField for MontgomeryBackendPrimeField<M, NUM_LIMBS>
288where
289 M: IsModulus<UnsignedInteger<NUM_LIMBS>> + Clone + Debug,
290{
291 type RepresentativeType = Self::BaseType;
292
293 fn representative(x: &Self::BaseType) -> Self::RepresentativeType {
294 MontgomeryAlgorithms::cios(x, &UnsignedInteger::from_u64(1), &M::MODULUS, &Self::MU)
295 }
296
297 fn field_bit_size() -> usize {
298 let mut evaluated_bit = NUM_LIMBS * 64 - 1;
299 let max_element = M::MODULUS - UnsignedInteger::<NUM_LIMBS>::from_u64(1);
300 let one = UnsignedInteger::from_u64(1);
301
302 while ((max_element >> evaluated_bit) & one) != one {
303 evaluated_bit -= 1;
304 }
305
306 evaluated_bit + 1
307 }
308
309 fn from_hex(hex_string: &str) -> Result<Self::BaseType, CreationError> {
310 let integer = Self::BaseType::from_hex(hex_string)?;
311 if integer > M::MODULUS {
312 return Err(CreationError::RepresentativeOutOfRange);
313 }
314
315 Ok(MontgomeryAlgorithms::cios(
316 &integer,
317 &MontgomeryBackendPrimeField::<M, NUM_LIMBS>::R2,
318 &M::MODULUS,
319 &MontgomeryBackendPrimeField::<M, NUM_LIMBS>::MU,
320 ))
321 }
322
323 #[cfg(feature = "std")]
324 fn to_hex(x: &Self::BaseType) -> String {
325 Self::BaseType::to_hex(x)
326 }
327}
328
329impl<M, const NUM_LIMBS: usize> FieldElement<MontgomeryBackendPrimeField<M, NUM_LIMBS>> where
330 M: IsModulus<UnsignedInteger<NUM_LIMBS>> + Clone + Debug
331{
332}
333
334impl<M, const NUM_LIMBS: usize> ByteConversion
335 for FieldElement<MontgomeryBackendPrimeField<M, NUM_LIMBS>>
336where
337 M: IsModulus<UnsignedInteger<NUM_LIMBS>> + Clone + Debug,
338{
339 #[cfg(feature = "alloc")]
340 fn to_bytes_be(&self) -> alloc::vec::Vec<u8> {
341 MontgomeryAlgorithms::cios(
342 self.value(),
343 &UnsignedInteger::from_u64(1),
344 &M::MODULUS,
345 &MontgomeryBackendPrimeField::<M, NUM_LIMBS>::MU,
346 )
347 .to_bytes_be()
348 }
349
350 #[cfg(feature = "alloc")]
351 fn to_bytes_le(&self) -> alloc::vec::Vec<u8> {
352 MontgomeryAlgorithms::cios(
353 self.value(),
354 &UnsignedInteger::from_u64(1),
355 &M::MODULUS,
356 &MontgomeryBackendPrimeField::<M, NUM_LIMBS>::MU,
357 )
358 .to_bytes_le()
359 }
360
361 fn from_bytes_be(bytes: &[u8]) -> Result<Self, crate::errors::ByteConversionError> {
362 let value = UnsignedInteger::from_bytes_be(bytes)?;
363 Ok(Self::new(value))
364 }
365
366 fn from_bytes_le(bytes: &[u8]) -> Result<Self, crate::errors::ByteConversionError> {
367 let value = UnsignedInteger::from_bytes_le(bytes)?;
368 Ok(Self::new(value))
369 }
370}
371
372#[cfg(feature = "alloc")]
373impl<M, const NUM_LIMBS: usize> AsBytes for FieldElement<MontgomeryBackendPrimeField<M, NUM_LIMBS>>
374where
375 M: IsModulus<UnsignedInteger<NUM_LIMBS>> + Clone + Debug,
376{
377 fn as_bytes(&self) -> alloc::vec::Vec<u8> {
378 self.value().to_bytes_be()
379 }
380}
381
382#[cfg(feature = "alloc")]
383impl<M, const NUM_LIMBS: usize> From<FieldElement<MontgomeryBackendPrimeField<M, NUM_LIMBS>>>
384 for alloc::vec::Vec<u8>
385where
386 M: IsModulus<UnsignedInteger<NUM_LIMBS>> + Clone + Debug,
387{
388 fn from(value: FieldElement<MontgomeryBackendPrimeField<M, NUM_LIMBS>>) -> alloc::vec::Vec<u8> {
389 value.value().to_bytes_be()
390 }
391}
392
393impl<M, const NUM_LIMBS: usize> HasDefaultTranscript for MontgomeryBackendPrimeField<M, NUM_LIMBS>
394where
395 M: IsModulus<UnsignedInteger<NUM_LIMBS>> + Clone + Debug,
396{
397 fn get_random_field_element_from_rng(
401 rng: &mut impl rand::Rng,
402 ) -> FieldElement<MontgomeryBackendPrimeField<M, NUM_LIMBS>> {
403 let mut buffer = [0u8; 6 * 8];
404 let first_non_zero_limb_index = M::MODULUS
405 .limbs
406 .iter()
407 .position(|&x| x != 0)
408 .expect("modulus should be non-zero");
409 let mask = u64::MAX >> M::MODULUS.limbs[first_non_zero_limb_index].leading_zeros();
410
411 let bits_start_idx = first_non_zero_limb_index * 8;
412 let bits_end_idx = NUM_LIMBS * 8;
413 let mut uint_sample;
414
415 loop {
416 let sample_bytes = &mut buffer[bits_start_idx..bits_end_idx];
417 rng.fill(sample_bytes);
418
419 uint_sample = UnsignedInteger::from_bytes_be(&buffer).unwrap();
420
421 uint_sample.limbs[first_non_zero_limb_index] &= mask;
422
423 if uint_sample < M::MODULUS {
424 break;
425 }
426 }
427
428 FieldElement::new(MontgomeryBackendPrimeField::<M, NUM_LIMBS>::from_base_type(
429 uint_sample,
430 ))
431 }
432}
433
434#[cfg(test)]
435mod tests_u384_prime_fields {
436 use crate::field::element::FieldElement;
437 use crate::field::errors::FieldError;
438 use crate::field::fields::fft_friendly::stark_252_prime_field::Stark252PrimeField;
439 use crate::field::fields::montgomery_backed_prime_fields::{
440 IsModulus, U256PrimeField, U384PrimeField,
441 };
442 use crate::field::traits::HasDefaultTranscript;
443 use crate::field::traits::IsField;
444 use crate::field::traits::IsPrimeField;
445 #[cfg(feature = "alloc")]
446 use crate::traits::ByteConversion;
447 use crate::unsigned_integer::element::U384;
448 use crate::unsigned_integer::element::{UnsignedInteger, U256};
449
450 use rand::Rng;
451 use rand_chacha::{rand_core::SeedableRng, ChaCha20Rng};
452
453 #[derive(Clone, Debug)]
454 struct U384Modulus23;
455 impl IsModulus<U384> for U384Modulus23 {
456 const MODULUS: U384 = UnsignedInteger::from_u64(23);
457 }
458
459 type U384F23 = U384PrimeField<U384Modulus23>;
460 type U384F23Element = FieldElement<U384F23>;
461
462 #[test]
463 fn u384_mod_23_uses_5_bits() {
464 assert_eq!(U384F23::field_bit_size(), 5);
465 }
466
467 #[test]
468 fn stark_252_prime_field_uses_252_bits() {
469 assert_eq!(Stark252PrimeField::field_bit_size(), 252);
470 }
471
472 #[test]
473 fn u256_mod_2_uses_1_bit() {
474 #[derive(Clone, Debug)]
475 struct U256Modulus1;
476 impl IsModulus<U256> for U256Modulus1 {
477 const MODULUS: U256 = UnsignedInteger::from_u64(2);
478 }
479 type U256OneField = U256PrimeField<U256Modulus1>;
480 assert_eq!(U256OneField::field_bit_size(), 1);
481 }
482
483 #[test]
484 fn u256_with_first_bit_set_uses_256_bit() {
485 #[derive(Clone, Debug)]
486 struct U256ModulusBig;
487 impl IsModulus<U256> for U256ModulusBig {
488 const MODULUS: U256 = UnsignedInteger::from_hex_unchecked(
489 "F0000000F0000000F0000000F0000000F0000000F0000000F0000000F0000000",
490 );
491 }
492 type U256OneField = U256PrimeField<U256ModulusBig>;
493 assert_eq!(U256OneField::field_bit_size(), 256);
494 }
495
496 #[test]
497 fn montgomery_backend_primefield_compute_r2_parameter() {
498 let r2: U384 = UnsignedInteger {
499 limbs: [0, 0, 0, 0, 0, 6],
500 };
501 assert_eq!(U384F23::R2, r2);
502 }
503
504 #[test]
505 fn montgomery_backend_primefield_compute_mu_parameter() {
506 assert_eq!(U384F23::MU, 3208129404123400281);
507 }
508
509 #[test]
510 fn montgomery_backend_primefield_compute_zero_parameter() {
511 let zero: U384 = UnsignedInteger {
512 limbs: [0, 0, 0, 0, 0, 0],
513 };
514 assert_eq!(U384F23::ZERO, zero);
515 }
516
517 #[test]
518 fn montgomery_backend_primefield_from_u64() {
519 let a: U384 = UnsignedInteger {
520 limbs: [0, 0, 0, 0, 0, 17],
521 };
522 assert_eq!(U384F23::from_u64(770_u64), a);
523 }
524
525 #[test]
526 fn montgomery_backend_primefield_representative() {
527 let a: U384 = UnsignedInteger {
528 limbs: [0, 0, 0, 0, 0, 11],
529 };
530 assert_eq!(U384F23::representative(&U384F23::from_u64(770_u64)), a);
531 }
532
533 #[test]
534 fn montgomery_backend_multiplication_works_0() {
535 let x = U384F23Element::from(11_u64);
536 let y = U384F23Element::from(10_u64);
537 let c = U384F23Element::from(110_u64);
538 assert_eq!(x * y, c);
539 }
540
541 #[test]
542 #[cfg(feature = "lambdaworks-serde-string")]
543 fn montgomery_backend_serialization_deserialization() {
544 let x = U384F23Element::from(11_u64);
545 let x_serialized = serde_json::to_string(&x).unwrap();
546 let x_deserialized: U384F23Element = serde_json::from_str(&x_serialized).unwrap();
547 assert_eq!(x_deserialized, x);
549 }
550
551 #[test]
552 fn doubling() {
553 assert_eq!(
554 U384F23Element::from(2).double(),
555 U384F23Element::from(2) + U384F23Element::from(2),
556 );
557 }
558
559 const ORDER: usize = 23;
560 #[test]
561 fn two_plus_one_is_three() {
562 assert_eq!(
563 U384F23Element::from(2) + U384F23Element::from(1),
564 U384F23Element::from(3)
565 );
566 }
567
568 #[test]
569 fn max_order_plus_1_is_0() {
570 assert_eq!(
571 U384F23Element::from((ORDER - 1) as u64) + U384F23Element::from(1),
572 U384F23Element::from(0)
573 );
574 }
575
576 #[test]
577 fn when_comparing_13_and_13_they_are_equal() {
578 let a: U384F23Element = U384F23Element::from(13);
579 let b: U384F23Element = U384F23Element::from(13);
580 assert_eq!(a, b);
581 }
582
583 #[test]
584 fn when_comparing_13_and_8_they_are_different() {
585 let a: U384F23Element = U384F23Element::from(13);
586 let b: U384F23Element = U384F23Element::from(8);
587 assert_ne!(a, b);
588 }
589
590 #[test]
591 fn mul_neutral_element() {
592 let a: U384F23Element = U384F23Element::from(1);
593 let b: U384F23Element = U384F23Element::from(2);
594 assert_eq!(a * b, U384F23Element::from(2));
595 }
596
597 #[test]
598 fn mul_2_3_is_6() {
599 let a: U384F23Element = U384F23Element::from(2);
600 let b: U384F23Element = U384F23Element::from(3);
601 assert_eq!(a * b, U384F23Element::from(6));
602 }
603
604 #[test]
605 fn mul_order_minus_1() {
606 let a: U384F23Element = U384F23Element::from((ORDER - 1) as u64);
607 let b: U384F23Element = U384F23Element::from((ORDER - 1) as u64);
608 assert_eq!(a * b, U384F23Element::from(1));
609 }
610
611 #[test]
612 fn inv_0_error() {
613 let result = U384F23Element::from(0).inv();
614 assert!(matches!(result, Err(FieldError::InvZeroError)))
615 }
616
617 #[test]
618 fn inv_2() {
619 let a: U384F23Element = U384F23Element::from(2);
620 assert_eq!(&a * a.inv().unwrap(), U384F23Element::from(1));
621 }
622
623 #[test]
624 fn pow_2_3() {
625 assert_eq!(U384F23Element::from(2).pow(3_u64), U384F23Element::from(8))
626 }
627
628 #[test]
629 fn pow_p_minus_1() {
630 assert_eq!(
631 U384F23Element::from(2).pow(ORDER - 1),
632 U384F23Element::from(1)
633 )
634 }
635
636 #[test]
637 fn div_1() {
638 assert_eq!(
639 (U384F23Element::from(2) / U384F23Element::from(1)).unwrap(),
640 U384F23Element::from(2)
641 )
642 }
643
644 #[test]
645 fn div_4_2() {
646 assert_eq!(
647 (U384F23Element::from(4) / U384F23Element::from(2)).unwrap(),
648 U384F23Element::from(2)
649 )
650 }
651
652 #[test]
653 fn three_inverse() {
654 let a = U384F23Element::from(3);
655 let expected = U384F23Element::from(8);
656 assert_eq!(a.inv().unwrap(), expected)
657 }
658
659 #[test]
660 fn div_4_3() {
661 assert_eq!(
662 (U384F23Element::from(4) / U384F23Element::from(3)).unwrap() * U384F23Element::from(3),
663 U384F23Element::from(4)
664 )
665 }
666
667 #[test]
668 fn two_plus_its_additive_inv_is_0() {
669 let two = U384F23Element::from(2);
670
671 assert_eq!(&two + (-&two), U384F23Element::from(0))
672 }
673
674 #[test]
675 fn four_minus_three_is_1() {
676 let four = U384F23Element::from(4);
677 let three = U384F23Element::from(3);
678
679 assert_eq!(four - three, U384F23Element::from(1))
680 }
681
682 #[test]
683 fn zero_minus_1_is_order_minus_1() {
684 let zero = U384F23Element::from(0);
685 let one = U384F23Element::from(1);
686
687 assert_eq!(zero - one, U384F23Element::from((ORDER - 1) as u64))
688 }
689
690 #[test]
691 fn neg_zero_is_zero() {
692 let zero = U384F23Element::from(0);
693
694 assert_eq!(-&zero, zero);
695 }
696
697 #[test]
698 fn test_random_field_element_from_rng_0() {
699 let mut rng = <ChaCha20Rng as SeedableRng>::from_seed([1; 32]);
701 let mut expected_rng = rng.clone();
702
703 let mut buffer = [0u8; 48];
704 let sample_bytes = &mut buffer[40..];
705 expected_rng.fill(sample_bytes);
706
707 let mut expected_uint = UnsignedInteger::from_bytes_be(&buffer).unwrap();
708
709 expected_uint.limbs[5] &= 31_u64;
710
711 let expected = FieldElement::new(U384F23::from_base_type(expected_uint));
712
713 let result = U384F23::get_random_field_element_from_rng(&mut rng);
714
715 assert_eq!(result, expected);
716 }
717
718 #[test]
719 fn test_random_field_element_from_rng_1() {
720 let mut rng = <ChaCha20Rng as SeedableRng>::from_seed([5; 32]);
722 let mut expected_rng = rng.clone();
723
724 let mut buffer = [0u8; 48];
725 let sample_bytes = &mut buffer[40..];
726 expected_rng.fill(sample_bytes);
727
728 let mut expected_uint = UnsignedInteger::from_bytes_be(&buffer).unwrap();
729
730 expected_uint.limbs[5] &= 31_u64;
731
732 let expected = FieldElement::new(U384F23::from_base_type(expected_uint));
733
734 let result = U384F23::get_random_field_element_from_rng(&mut rng);
735
736 assert_ne!(result, expected);
737 }
738
739 #[derive(Clone, Debug)]
741 struct U384ModulusP1;
742 impl IsModulus<U384> for U384ModulusP1 {
743 const MODULUS: U384 = UnsignedInteger {
744 limbs: [
745 0,
746 0,
747 0,
748 3450888597,
749 5754816256417943771,
750 15923941673896418529,
751 ],
752 };
753 }
754
755 type U384FP1 = U384PrimeField<U384ModulusP1>;
756 type U384FP1Element = FieldElement<U384FP1>;
757
758 #[test]
759 fn montgomery_prime_field_from_bad_hex_errs() {
760 assert!(U384FP1Element::from_hex("0xTEST").is_err());
761 }
762
763 #[test]
764 fn montgomery_prime_field_addition_works_0() {
765 let x = U384FP1Element::new(UnsignedInteger::from_hex_unchecked(
766 "05ed176deb0e80b4deb7718cdaa075165f149c",
767 ));
768 let y = U384FP1Element::new(UnsignedInteger::from_hex_unchecked(
769 "5f103b0bd4397d4df560eb559f38353f80eeb6",
770 ));
771 let c = U384FP1Element::new(UnsignedInteger::from_hex_unchecked(
772 "64fd5279bf47fe02d4185ce279d8aa55e00352",
773 ));
774 assert_eq!(x + y, c);
775 }
776
777 #[test]
778 fn montgomery_prime_field_multiplication_works_0() {
779 let x = U384FP1Element::new(UnsignedInteger::from_hex_unchecked(
780 "05ed176deb0e80b4deb7718cdaa075165f149c",
781 ));
782 let y = U384FP1Element::new(UnsignedInteger::from_hex_unchecked(
783 "5f103b0bd4397d4df560eb559f38353f80eeb6",
784 ));
785 let c = U384FP1Element::new(UnsignedInteger::from_hex_unchecked(
786 "73d23e8d462060dc23d5c15c00fc432d95621a3c",
787 ));
788 assert_eq!(x * y, c);
789 }
790
791 #[derive(Clone, Debug)]
793 struct U384ModulusP2;
794 impl IsModulus<U384> for U384ModulusP2 {
795 const MODULUS: U384 = UnsignedInteger {
796 limbs: [
797 18446744073709551615,
798 18446744073709551615,
799 18446744073709551615,
800 18446744073709551615,
801 18446744073709551615,
802 18446744073709551275,
803 ],
804 };
805 }
806
807 type U384FP2 = U384PrimeField<U384ModulusP2>;
808 type U384FP2Element = FieldElement<U384FP2>;
809
810 #[test]
811 fn montgomery_prime_field_addition_works_1() {
812 let x = U384FP2Element::new(UnsignedInteger::from_hex_unchecked(
813 "05ed176deb0e80b4deb7718cdaa075165f149c",
814 ));
815 let y = U384FP2Element::new(UnsignedInteger::from_hex_unchecked(
816 "5f103b0bd4397d4df560eb559f38353f80eeb6",
817 ));
818 let c = U384FP2Element::new(UnsignedInteger::from_hex_unchecked(
819 "64fd5279bf47fe02d4185ce279d8aa55e00352",
820 ));
821 assert_eq!(x + y, c);
822 }
823
824 #[test]
825 fn montgomery_prime_field_multiplication_works_1() {
826 let x = U384FP2Element::one();
827 let y = U384FP2Element::new(UnsignedInteger::from_hex_unchecked(
828 "5f103b0bd4397d4df560eb559f38353f80eeb6",
829 ));
830 assert_eq!(&y * x, y);
831 }
832
833 #[test]
834 #[cfg(feature = "alloc")]
835 fn to_bytes_from_bytes_be_is_the_identity() {
836 let x = U384FP2Element::new(UnsignedInteger::from_hex_unchecked(
837 "5f103b0bd4397d4df560eb559f38353f80eeb6",
838 ));
839 assert_eq!(U384FP2Element::from_bytes_be(&x.to_bytes_be()).unwrap(), x);
840 }
841
842 #[test]
843 #[cfg(feature = "alloc")]
844 fn from_bytes_to_bytes_be_is_the_identity_for_one() {
845 let bytes = [
846 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
847 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
848 ];
849 assert_eq!(
850 U384FP2Element::from_bytes_be(&bytes).unwrap().to_bytes_be(),
851 bytes
852 );
853 }
854
855 #[test]
856 #[cfg(feature = "alloc")]
857 fn to_bytes_from_bytes_le_is_the_identity() {
858 let x = U384FP2Element::new(UnsignedInteger::from_hex_unchecked(
859 "5f103b0bd4397d4df560eb559f38353f80eeb6",
860 ));
861 assert_eq!(U384FP2Element::from_bytes_le(&x.to_bytes_le()).unwrap(), x);
862 }
863
864 #[test]
865 #[cfg(feature = "alloc")]
866 fn from_bytes_to_bytes_le_is_the_identity_for_one() {
867 let bytes = [
868 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
869 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
870 ];
871 assert_eq!(
872 U384FP2Element::from_bytes_le(&bytes).unwrap().to_bytes_le(),
873 bytes
874 );
875 }
876}
877
878#[cfg(test)]
879mod tests_u256_prime_fields {
880 use crate::field::element::FieldElement;
881 use crate::field::errors::FieldError;
882 use crate::field::fields::montgomery_backed_prime_fields::{IsModulus, U256PrimeField};
883 use crate::field::traits::HasDefaultTranscript;
884 use crate::field::traits::IsField;
885 use crate::field::traits::IsPrimeField;
886 #[cfg(feature = "alloc")]
887 use crate::traits::ByteConversion;
888 use crate::unsigned_integer::element::U256;
889 use crate::unsigned_integer::element::{UnsignedInteger, U64};
890 use rand::Rng;
891 use rand_chacha::{rand_core::SeedableRng, ChaCha20Rng};
892
893 use super::U64PrimeField;
894
895 #[derive(Clone, Debug)]
896 struct U256Modulus29;
897 impl IsModulus<U256> for U256Modulus29 {
898 const MODULUS: U256 = UnsignedInteger::from_u64(29);
899 }
900
901 type U256F29 = U256PrimeField<U256Modulus29>;
902 type U256F29Element = FieldElement<U256F29>;
903
904 #[test]
905 fn montgomery_backend_primefield_compute_r2_parameter() {
906 let r2: U256 = UnsignedInteger {
907 limbs: [0, 0, 0, 24],
908 };
909 assert_eq!(U256F29::R2, r2);
910 }
911
912 #[test]
913 fn montgomery_backend_primefield_compute_mu_parameter() {
914 assert_eq!(U256F29::MU, 14630176334321368523);
916 }
917
918 #[test]
919 fn montgomery_backend_primefield_compute_zero_parameter() {
920 let zero: U256 = UnsignedInteger {
921 limbs: [0, 0, 0, 0],
922 };
923 assert_eq!(U256F29::ZERO, zero);
924 }
925
926 #[test]
927 fn montgomery_backend_primefield_from_u64() {
928 let a: U256 = UnsignedInteger {
930 limbs: [0, 0, 0, 24],
931 };
932 assert_eq!(U256F29::from_u64(770_u64), a);
933 }
934
935 #[test]
936 fn montgomery_backend_primefield_representative() {
937 let a: U256 = UnsignedInteger {
939 limbs: [0, 0, 0, 16],
940 };
941 assert_eq!(U256F29::representative(&U256F29::from_u64(770_u64)), a);
942 }
943
944 #[test]
945 fn montgomery_backend_multiplication_works_0() {
946 let x = U256F29Element::from(11_u64);
947 let y = U256F29Element::from(10_u64);
948 let c = U256F29Element::from(110_u64);
949 assert_eq!(x * y, c);
950 }
951
952 #[test]
953 fn doubling() {
954 assert_eq!(
955 U256F29Element::from(2).double(),
956 U256F29Element::from(2) + U256F29Element::from(2),
957 );
958 }
959
960 const ORDER: usize = 29;
961 #[test]
962 fn two_plus_one_is_three() {
963 assert_eq!(
964 U256F29Element::from(2) + U256F29Element::from(1),
965 U256F29Element::from(3)
966 );
967 }
968
969 #[test]
970 fn max_order_plus_1_is_0() {
971 assert_eq!(
972 U256F29Element::from((ORDER - 1) as u64) + U256F29Element::from(1),
973 U256F29Element::from(0)
974 );
975 }
976
977 #[test]
978 fn when_comparing_13_and_13_they_are_equal() {
979 let a: U256F29Element = U256F29Element::from(13);
980 let b: U256F29Element = U256F29Element::from(13);
981 assert_eq!(a, b);
982 }
983
984 #[test]
985 fn when_comparing_13_and_8_they_are_different() {
986 let a: U256F29Element = U256F29Element::from(13);
987 let b: U256F29Element = U256F29Element::from(8);
988 assert_ne!(a, b);
989 }
990
991 #[test]
992 fn mul_neutral_element() {
993 let a: U256F29Element = U256F29Element::from(1);
994 let b: U256F29Element = U256F29Element::from(2);
995 assert_eq!(a * b, U256F29Element::from(2));
996 }
997
998 #[test]
999 fn mul_2_3_is_6() {
1000 let a: U256F29Element = U256F29Element::from(2);
1001 let b: U256F29Element = U256F29Element::from(3);
1002 assert_eq!(a * b, U256F29Element::from(6));
1003 }
1004
1005 #[test]
1006 fn mul_order_minus_1() {
1007 let a: U256F29Element = U256F29Element::from((ORDER - 1) as u64);
1008 let b: U256F29Element = U256F29Element::from((ORDER - 1) as u64);
1009 assert_eq!(a * b, U256F29Element::from(1));
1010 }
1011
1012 #[test]
1013 fn inv_0_error() {
1014 let result = U256F29Element::from(0).inv();
1015 assert!(matches!(result, Err(FieldError::InvZeroError)));
1016 }
1017
1018 #[test]
1019 fn inv_2() {
1020 let a: U256F29Element = U256F29Element::from(2);
1021 assert_eq!(&a * a.inv().unwrap(), U256F29Element::from(1));
1022 }
1023
1024 #[test]
1025 fn pow_2_3() {
1026 assert_eq!(U256F29Element::from(2).pow(3_u64), U256F29Element::from(8))
1027 }
1028
1029 #[test]
1030 fn pow_p_minus_1() {
1031 assert_eq!(
1032 U256F29Element::from(2).pow(ORDER - 1),
1033 U256F29Element::from(1)
1034 )
1035 }
1036
1037 #[test]
1038 fn div_1() {
1039 assert_eq!(
1040 (U256F29Element::from(2) / U256F29Element::from(1)).unwrap(),
1041 U256F29Element::from(2)
1042 )
1043 }
1044
1045 #[test]
1046 fn div_4_2() {
1047 let a = U256F29Element::from(4);
1048 let b = U256F29Element::from(2);
1049 assert_eq!((a / &b).unwrap(), b)
1050 }
1051
1052 #[test]
1053 fn div_4_3() {
1054 assert_eq!(
1055 (U256F29Element::from(4) / U256F29Element::from(3)).unwrap() * U256F29Element::from(3),
1056 U256F29Element::from(4)
1057 )
1058 }
1059
1060 #[test]
1061 fn two_plus_its_additive_inv_is_0() {
1062 let two = U256F29Element::from(2);
1063
1064 assert_eq!(&two + (-&two), U256F29Element::from(0))
1065 }
1066
1067 #[test]
1068 fn four_minus_three_is_1() {
1069 let four = U256F29Element::from(4);
1070 let three = U256F29Element::from(3);
1071
1072 assert_eq!(four - three, U256F29Element::from(1))
1073 }
1074
1075 #[test]
1076 fn zero_minus_1_is_order_minus_1() {
1077 let zero = U256F29Element::from(0);
1078 let one = U256F29Element::from(1);
1079
1080 assert_eq!(zero - one, U256F29Element::from((ORDER - 1) as u64))
1081 }
1082
1083 #[test]
1084 fn neg_zero_is_zero() {
1085 let zero = U256F29Element::from(0);
1086
1087 assert_eq!(-&zero, zero);
1088 }
1089
1090 #[test]
1091 fn test_random_field_element_from_rng_0() {
1092 let mut rng = <ChaCha20Rng as SeedableRng>::from_seed([1; 32]);
1094 let mut expected_rng = rng.clone();
1095
1096 let mut buffer = [0u8; 48];
1097 let sample_bytes = &mut buffer[24..32];
1098 expected_rng.fill(sample_bytes);
1099
1100 let mut expected_uint = UnsignedInteger::from_bytes_be(&buffer).unwrap();
1101
1102 expected_uint.limbs[3] &= 31_u64;
1103
1104 let expected = FieldElement::new(U256F29::from_base_type(expected_uint));
1105
1106 let result = U256F29::get_random_field_element_from_rng(&mut rng);
1107
1108 assert_eq!(result, expected);
1109 }
1110
1111 #[test]
1112 fn test_random_field_element_from_rng_1() {
1113 let mut rng = <ChaCha20Rng as SeedableRng>::from_seed([5; 32]);
1115 let mut expected_rng = rng.clone();
1116
1117 let mut buffer = [0u8; 48];
1118 let sample_bytes = &mut buffer[24..32];
1119 expected_rng.fill(sample_bytes);
1120
1121 let mut expected_uint = UnsignedInteger::from_bytes_be(&buffer).unwrap();
1122
1123 expected_uint.limbs[3] &= 31_u64;
1124
1125 let expected = FieldElement::new(U256F29::from_base_type(expected_uint));
1126
1127 let result = U256F29::get_random_field_element_from_rng(&mut rng);
1128
1129 assert_ne!(result, expected);
1130 }
1131
1132 #[derive(Clone, Debug)]
1133 struct U256ModulusP1;
1134 impl IsModulus<U256> for U256ModulusP1 {
1135 const MODULUS: U256 = UnsignedInteger {
1136 limbs: [
1137 8366,
1138 8155137382671976874,
1139 227688614771682406,
1140 15723111795979912613,
1141 ],
1142 };
1143 }
1144
1145 type U256FP1 = U256PrimeField<U256ModulusP1>;
1146 type U256FP1Element = FieldElement<U256FP1>;
1147
1148 #[test]
1149 fn montgomery_prime_field_addition_works_0() {
1150 let x = U256FP1Element::new(UnsignedInteger::from_hex_unchecked(
1151 "93e712950bf3fe589aa030562a44b1cec66b09192c4bcf705a5",
1152 ));
1153 let y = U256FP1Element::new(UnsignedInteger::from_hex_unchecked(
1154 "10a712235c1f6b4172a1e35da6aef1a7ec6b09192c4bb88cfa5",
1155 ));
1156 let c = U256FP1Element::new(UnsignedInteger::from_hex_unchecked(
1157 "a48e24b86813699a0d4213b3d0f3a376b2d61232589787fd54a",
1158 ));
1159 assert_eq!(x + y, c);
1160 }
1161
1162 #[test]
1163 fn montgomery_prime_field_multiplication_works_0() {
1164 let x = U256FP1Element::new(UnsignedInteger::from_hex_unchecked(
1165 "93e712950bf3fe589aa030562a44b1cec66b09192c4bcf705a5",
1166 ));
1167 let y = U256FP1Element::new(UnsignedInteger::from_hex_unchecked(
1168 "10a712235c1f6b4172a1e35da6aef1a7ec6b09192c4bb88cfa5",
1169 ));
1170 let c = U256FP1Element::new(UnsignedInteger::from_hex_unchecked(
1171 "7808e74c3208d9a66791ef9cc15a46acc9951ee312102684021",
1172 ));
1173 assert_eq!(x * y, c);
1174 }
1175
1176 #[derive(Clone, Debug)]
1178 struct ModulusP2;
1179 impl IsModulus<U256> for ModulusP2 {
1180 const MODULUS: U256 = UnsignedInteger {
1181 limbs: [
1182 18446744073709551615,
1183 18446744073709551615,
1184 18446744073709551615,
1185 18446744073709551427,
1186 ],
1187 };
1188 }
1189
1190 type FP2 = U256PrimeField<ModulusP2>;
1191 type FP2Element = FieldElement<FP2>;
1192
1193 #[test]
1194 fn montgomery_prime_field_addition_works_1() {
1195 let x = FP2Element::new(UnsignedInteger::from_hex_unchecked(
1196 "acbbb7ca01c65cfffffc72815b397fff9ab130ad53a5ffffffb8f21b207dfedf",
1197 ));
1198 let y = FP2Element::new(UnsignedInteger::from_hex_unchecked(
1199 "d65ddbe509d3fffff21f494c588cbdbfe43e929b0543e3ffffffffffffffff43",
1200 ));
1201 let c = FP2Element::new(UnsignedInteger::from_hex_unchecked(
1202 "831993af0b9a5cfff21bbbcdb3c63dbf7eefc34858e9e3ffffb8f21b207dfedf",
1203 ));
1204 assert_eq!(x + y, c);
1205 }
1206
1207 #[test]
1208 fn montgomery_prime_field_multiplication_works_1() {
1209 let x = FP2Element::new(UnsignedInteger::from_hex_unchecked(
1210 "acbbb7ca01c65cfffffc72815b397fff9ab130ad53a5ffffffb8f21b207dfedf",
1211 ));
1212 let y = FP2Element::new(UnsignedInteger::from_hex_unchecked(
1213 "d65ddbe509d3fffff21f494c588cbdbfe43e929b0543e3ffffffffffffffff43",
1214 ));
1215 let c = FP2Element::new(UnsignedInteger::from_hex_unchecked(
1216 "2b1e80d553ecab2e4d41eb53c4c8ad89ebacac6cf6b91dcf2213f311093aa05d",
1217 ));
1218 assert_eq!(&y * x, c);
1219 }
1220
1221 #[test]
1222 #[cfg(feature = "alloc")]
1223 fn to_bytes_from_bytes_be_is_the_identity() {
1224 let x = FP2Element::new(UnsignedInteger::from_hex_unchecked(
1225 "5f103b0bd4397d4df560eb559f38353f80eeb6",
1226 ));
1227 assert_eq!(FP2Element::from_bytes_be(&x.to_bytes_be()).unwrap(), x);
1228 }
1229
1230 #[test]
1231 #[cfg(feature = "alloc")]
1232 fn from_bytes_to_bytes_be_is_the_identity_for_one() {
1233 let bytes = [
1234 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1235 0, 0, 1,
1236 ];
1237 assert_eq!(
1238 FP2Element::from_bytes_be(&bytes).unwrap().to_bytes_be(),
1239 bytes
1240 );
1241 }
1242
1243 #[test]
1244 #[cfg(feature = "alloc")]
1245 fn to_bytes_from_bytes_le_is_the_identity() {
1246 let x = FP2Element::new(UnsignedInteger::from_hex_unchecked(
1247 "5f103b0bd4397d4df560eb559f38353f80eeb6",
1248 ));
1249 assert_eq!(FP2Element::from_bytes_le(&x.to_bytes_le()).unwrap(), x);
1250 }
1251
1252 #[test]
1253 #[cfg(feature = "alloc")]
1254 fn from_bytes_to_bytes_le_is_the_identity_for_one() {
1255 let bytes = [
1256 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1257 0, 0, 0,
1258 ];
1259 assert_eq!(
1260 FP2Element::from_bytes_le(&bytes).unwrap().to_bytes_le(),
1261 bytes
1262 );
1263 }
1264
1265 #[test]
1266 #[cfg(feature = "alloc")]
1267 fn creating_a_field_element_from_its_representative_returns_the_same_element_1() {
1268 let change = U256::from_u64(1);
1269 let f1 = U256FP1Element::new(U256ModulusP1::MODULUS + change);
1270 let f2 = U256FP1Element::new(f1.representative());
1271 assert_eq!(f1, f2);
1272 }
1273
1274 #[test]
1275 fn creating_a_field_element_from_its_representative_returns_the_same_element_2() {
1276 let change = U256::from_u64(27);
1277 let f1 = U256F29Element::new(U256Modulus29::MODULUS + change);
1278 let f2 = U256F29Element::new(f1.representative());
1279 assert_eq!(f1, f2);
1280 }
1281
1282 #[test]
1283 fn creating_a_field_element_from_hex_works_1() {
1284 let a = U256FP1Element::from_hex_unchecked("eb235f6144d9e91f4b14");
1285 let b = U256FP1Element::new(U256 {
1286 limbs: [0, 0, 60195, 6872850209053821716],
1287 });
1288 assert_eq!(a, b);
1289 }
1290
1291 #[test]
1292 fn creating_a_field_element_from_hex_too_big_errors() {
1293 let a = U256FP1Element::from_hex(&"f".repeat(65));
1294 assert!(a.is_err());
1295 assert_eq!(
1296 a.unwrap_err(),
1297 crate::errors::CreationError::HexStringIsTooBig
1298 )
1299 }
1300
1301 #[test]
1302 fn creating_a_field_element_from_hex_bigger_than_modulus_errors() {
1303 let a = U256FP1Element::from_hex(&"f".repeat(64));
1305 assert!(a.is_err());
1306 assert_eq!(
1307 a.unwrap_err(),
1308 crate::errors::CreationError::RepresentativeOutOfRange
1309 )
1310 }
1311
1312 #[test]
1313 fn creating_a_field_element_from_hex_works_2() {
1314 let a = U256F29Element::from_hex_unchecked("aa");
1315 let b = U256F29Element::from(25);
1316 assert_eq!(a, b);
1317 }
1318
1319 #[test]
1320 fn creating_a_field_element_from_hex_works_3() {
1321 let a = U256F29Element::from_hex_unchecked("1d");
1322 let b = U256F29Element::zero();
1323 assert_eq!(a, b);
1324 }
1325
1326 #[cfg(feature = "std")]
1327 #[test]
1328 fn to_hex_test_works_1() {
1329 let a = U256FP1Element::from_hex_unchecked("eb235f6144d9e91f4b14");
1330 let b = U256FP1Element::new(U256 {
1331 limbs: [0, 0, 60195, 6872850209053821716],
1332 });
1333
1334 assert_eq!(U256FP1Element::to_hex(&a), U256FP1Element::to_hex(&b));
1335 }
1336
1337 #[cfg(feature = "std")]
1338 #[test]
1339 fn to_hex_test_works_2() {
1340 let a = U256F29Element::from_hex_unchecked("1d");
1341 let b = U256F29Element::zero();
1342
1343 assert_eq!(U256F29Element::to_hex(&a), U256F29Element::to_hex(&b));
1344 }
1345
1346 #[cfg(feature = "std")]
1347 #[test]
1348 fn to_hex_test_works_3() {
1349 let a = U256F29Element::from_hex_unchecked("aa");
1350 let b = U256F29Element::from(25);
1351
1352 assert_eq!(U256F29Element::to_hex(&a), U256F29Element::to_hex(&b));
1353 }
1354
1355 #[derive(Clone, Debug)]
1357 struct GoldilocksModulus;
1358 impl IsModulus<U64> for GoldilocksModulus {
1359 const MODULUS: U64 = UnsignedInteger {
1360 limbs: [18446744069414584321],
1361 };
1362 }
1363
1364 type GoldilocksField = U64PrimeField<GoldilocksModulus>;
1365 type GoldilocksElement = FieldElement<GoldilocksField>;
1366
1367 #[derive(Clone, Debug)]
1368 struct SecpModulus;
1369 impl IsModulus<U256> for SecpModulus {
1370 const MODULUS: U256 = UnsignedInteger::from_hex_unchecked(
1371 "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F",
1372 );
1373 }
1374 type SecpMontField = U256PrimeField<SecpModulus>;
1375 type SecpMontElement = FieldElement<SecpMontField>;
1376
1377 #[test]
1378 fn secp256k1_minus_three_pow_2_is_9_with_all_operations() {
1379 let minus_3 = -SecpMontElement::from_hex_unchecked("0x3");
1380 let minus_3_mul_minus_3 = &minus_3 * &minus_3;
1381 let minus_3_squared = minus_3.square();
1382 let minus_3_pow_2 = minus_3.pow(2_u32);
1383 let nine = SecpMontElement::from_hex_unchecked("0x9");
1384
1385 assert_eq!(minus_3_mul_minus_3, nine);
1386 assert_eq!(minus_3_squared, nine);
1387 assert_eq!(minus_3_pow_2, nine);
1388 }
1389
1390 #[test]
1391 fn secp256k1_inv_works() {
1392 let a = SecpMontElement::from_hex_unchecked("0x456");
1393 let a_inv = a.inv().unwrap();
1394
1395 assert_eq!(a * a_inv, SecpMontElement::one());
1396 }
1397
1398 #[test]
1399 fn test_cios_overflow_case() {
1400 let a = GoldilocksElement::from(732582227915286439);
1401 let b = GoldilocksElement::from(3906369333256140342);
1402 let expected_sum = GoldilocksElement::from(4638951561171426781);
1403 assert_eq!(a + b, expected_sum);
1404 }
1405}