lambdaworks_math/field/fields/
montgomery_backed_prime_fields.rs

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
20/// This trait is necessary for us to be able to use unsigned integer types bigger than
21/// `u128` (the biggest native `unit`) as constant generics.
22/// This trait should be removed when Rust supports this feature.
23pub 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    /// Computes `- modulus^{-1} mod 2^{64}`
55    /// This algorithm is given  by Dussé and Kaliski Jr. in
56    /// "S. R. Dussé and B. S. Kaliski Jr. A cryptographic library for the Motorola
57    /// DSP56000. In I. Damgård, editor, Advances in Cryptology – EUROCRYPT’90,
58    /// volume 473 of Lecture Notes in Computer Science, pages 230–244. Springer,
59    /// Heidelberg, May 1991."
60    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    /// Computes 2^{384 * 2} modulo `modulus`
76    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        // Define `c` as the largest power of 2 smaller than `modulus`
83        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        // Double `c` and reduce modulo `modulus` until getting
92        // `2^{2 * number_limbs * word_size}` mod `modulus`
93        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    /// Checks whether the most significant limb of the modulus is at
107    /// most `0x7FFFFFFFFFFFFFFE`. This check is useful since special
108    /// optimizations exist for this kind of moduli.
109    #[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            // Guajardo Kumar Paar Pelzl
181            // Efficient Software-Implementation of Finite Fields with Applications to
182            // Cryptography
183            // Algorithm 16 (BEA for Inversion in Fp)
184
185            //These can be done with const  functions
186            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; // Avoids unnecessary reduction step.
193            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    /// # Panics
398    ///
399    /// This function will panic if NUM_LIMBS is greater than 6.
400    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_serialized, "{\"value\":\"0xb\"}"); // serialization is no longer as hex string
548        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        // This seed generates a sample that is less than the modulus;
700        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        // This seed generates a sample that is grater than the modulus;
721        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    // FP1
740    #[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    // FP2
792    #[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        // modular multiplicative inverse
915        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        // (770*2**(256))%29
929        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        // 770%29
938        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        // This seed generates a sample that is less than the modulus;
1093        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        // This seed generates a sample that is grater than the modulus;
1114        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    // FP2
1177    #[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        // A number that consists of 255 1s is bigger than the `U256FP1` modulus
1304        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    // Goldilocks
1356    #[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}