starknet_types_core/felt/
mod.rs

1#[cfg(feature = "alloc")]
2mod alloc_impls;
3#[cfg(feature = "arbitrary")]
4mod arbitrary;
5#[cfg(test)]
6mod felt_arbitrary;
7mod non_zero;
8#[cfg(feature = "num-traits")]
9mod num_traits_impl;
10#[cfg(feature = "papyrus-serialization")]
11mod papyrus_serialization;
12#[cfg(feature = "parity-scale-codec")]
13mod parity_scale_codec;
14#[cfg(feature = "prime-bigint")]
15mod prime_bigint;
16mod primitive_conversions;
17#[cfg(feature = "serde")]
18mod serde;
19#[cfg(feature = "zeroize")]
20mod zeroize;
21
22use lambdaworks_math::errors::CreationError;
23pub use non_zero::{FeltIsZeroError, NonZeroFelt};
24
25#[cfg(feature = "prime-bigint")]
26pub use prime_bigint::CAIRO_PRIME_BIGINT;
27
28use core::ops::{Add, Mul, Neg};
29use core::str::FromStr;
30
31use num_bigint::{BigInt, BigUint, Sign};
32use num_integer::Integer;
33use num_traits::{One, Zero};
34pub use primitive_conversions::PrimitiveFromFeltError;
35
36#[cfg(feature = "alloc")]
37pub extern crate alloc;
38
39use lambdaworks_math::{
40    field::{
41        element::FieldElement, fields::fft_friendly::stark_252_prime_field::Stark252PrimeField,
42    },
43    traits::ByteConversion,
44    unsigned_integer::element::UnsignedInteger,
45};
46
47/// Definition of the Field Element type.
48#[repr(transparent)]
49#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
50pub struct Felt(pub(crate) FieldElement<Stark252PrimeField>);
51
52#[derive(Debug)]
53pub struct FromStrError(CreationError);
54
55#[cfg(feature = "std")]
56impl std::error::Error for FromStrError {}
57
58impl core::fmt::Display for FromStrError {
59    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
60        write!(f, "failed to create Felt from string: ")?;
61        match self.0 {
62            CreationError::InvalidHexString => write!(f, "invalid hex string"),
63            CreationError::InvalidDecString => write!(f, "invalid dec string"),
64            CreationError::HexStringIsTooBig => write!(f, "hex string too big"),
65            CreationError::EmptyString => write!(f, "empty string"),
66        }
67    }
68}
69
70impl Felt {
71    /// [Felt] constant that's equal to 0.
72    pub const ZERO: Self = Self(FieldElement::<Stark252PrimeField>::from_hex_unchecked("0"));
73
74    /// [Felt] constant that's equal to 1.
75    pub const ONE: Self = Self(FieldElement::<Stark252PrimeField>::from_hex_unchecked("1"));
76
77    /// [Felt] constant that's equal to 2.
78    pub const TWO: Self = Self(FieldElement::<Stark252PrimeField>::from_hex_unchecked("2"));
79
80    /// [Felt] constant that's equal to 3.
81    pub const THREE: Self = Self(FieldElement::<Stark252PrimeField>::from_hex_unchecked("3"));
82
83    /// Maximum value of [Felt]. Equals to 2^251 + 17 * 2^192.
84    pub const MAX: Self = Self(FieldElement::<Stark252PrimeField>::const_from_raw(
85        UnsignedInteger::from_limbs([544, 0, 0, 32]),
86    ));
87
88    /// 2 ** 251
89    pub const ELEMENT_UPPER_BOUND: Felt = Felt::from_raw([
90        576459263475450960,
91        18446744073709255680,
92        160989183,
93        18446743986131435553,
94    ]);
95
96    /// Creates a new [Felt] from the raw internal representation.
97    /// See [UnsignedInteger] to understand how it works under the hood.
98    pub const fn from_raw(val: [u64; 4]) -> Self {
99        Self(FieldElement::<Stark252PrimeField>::const_from_raw(
100            UnsignedInteger::from_limbs(val),
101        ))
102    }
103
104    pub const fn from_hex_unchecked(val: &str) -> Self {
105        Self(FieldElement::<Stark252PrimeField>::from_hex_unchecked(val))
106    }
107
108    /// Creates a new [Felt] from its big-endian representation in a [u8; 32] array.
109    /// This is as performant as [from_bytes_le](Felt::from_bytes_le).
110    pub fn from_bytes_be(bytes: &[u8; 32]) -> Self {
111        FieldElement::from_bytes_be(bytes)
112            .map(Self)
113            .expect("from_bytes_be shouldn't fail for these many bytes")
114    }
115
116    /// Creates a new [Felt] from its little-endian representation in a [u8; 32] array.
117    /// This is as performant as [from_bytes_le](Felt::from_bytes_be).
118    pub fn from_bytes_le(bytes: &[u8; 32]) -> Self {
119        FieldElement::from_bytes_le(bytes)
120            .map(Self)
121            .expect("from_bytes_le shouldn't fail for these many bytes")
122    }
123
124    /// Creates a new [Felt] from its big-endian representation in a [u8] slice.
125    /// This is as performant as [from_bytes_le](Felt::from_bytes_le_slice).
126    /// All bytes in the slice are consumed, as if first creating a big integer
127    /// from them, but the conversion is performed in constant space on the stack.
128    pub fn from_bytes_be_slice(bytes: &[u8]) -> Self {
129        // NB: lambdaworks ignores the remaining bytes when len > 32, so we loop
130        // multiplying by BASE, effectively decomposing in base 2^256 to build
131        // digits with a length of 32 bytes. This is analogous to splitting the
132        // number `xyz` as `x * 10^2 + y * 10^1 + z * 10^0`.
133        const BASE: Felt = Felt(FieldElement::<Stark252PrimeField>::const_from_raw(
134            UnsignedInteger::from_limbs([
135                576413109808302096,
136                18446744073700081664,
137                5151653887,
138                18446741271209837569,
139            ]),
140        ));
141        // Sanity check; gets removed in release builds.
142        debug_assert_eq!(BASE, Felt::TWO.pow(256u32));
143
144        let mut factor = Self::ONE;
145        let mut res = Self::ZERO;
146        let chunks = bytes.rchunks_exact(32);
147        let remainder = chunks.remainder();
148
149        for chunk in chunks {
150            let digit =
151                Self::from_bytes_be(&chunk.try_into().expect("conversion to same-sized array"));
152            res += digit * factor;
153            factor *= BASE;
154        }
155
156        if remainder.is_empty() {
157            return res;
158        }
159
160        let mut remainder = remainder.iter().rev().cloned();
161        let buf: [u8; 32] = core::array::from_fn(move |_| remainder.next().unwrap_or_default());
162        let digit = Self::from_bytes_le(&buf);
163        res += digit * factor;
164
165        res
166    }
167
168    /// Creates a new [Felt] from its little-endian representation in a [u8] slice.
169    /// This is as performant as [from_bytes_be](Felt::from_bytes_be_slice).
170    /// All bytes in the slice are consumed, as if first creating a big integer
171    /// from them, but the conversion is performed in constant space on the stack.
172    pub fn from_bytes_le_slice(bytes: &[u8]) -> Self {
173        // NB: lambdaworks ignores the remaining bytes when len > 32, so we loop
174        // multiplying by BASE, effectively decomposing in base 2^256 to build
175        // digits with a length of 32 bytes. This is analogous to splitting the
176        // number `xyz` as `x * 10^2 + y * 10^1 + z * 10^0`.
177        const BASE: Felt = Felt(FieldElement::<Stark252PrimeField>::const_from_raw(
178            UnsignedInteger::from_limbs([
179                576413109808302096,
180                18446744073700081664,
181                5151653887,
182                18446741271209837569,
183            ]),
184        ));
185        // Sanity check; gets removed in release builds.
186        debug_assert_eq!(BASE, Felt::TWO.pow(256u32));
187
188        let mut factor = Self::ONE;
189        let mut res = Self::ZERO;
190        let chunks = bytes.chunks_exact(32);
191        let remainder = chunks.remainder();
192
193        for chunk in chunks {
194            let digit =
195                Self::from_bytes_le(&chunk.try_into().expect("conversion to same-sized array"));
196            res += digit * factor;
197            factor *= BASE;
198        }
199
200        if remainder.is_empty() {
201            return res;
202        }
203
204        let mut remainder = remainder.iter().cloned();
205        let buf: [u8; 32] = core::array::from_fn(move |_| remainder.next().unwrap_or_default());
206        let digit = Self::from_bytes_le(&buf);
207        res += digit * factor;
208
209        res
210    }
211
212    /// Converts to big-endian byte representation in a [u8] array.
213    /// This is as performant as [to_bytes_le](Felt::to_bytes_le)
214    pub fn to_bytes_be(&self) -> [u8; 32] {
215        self.0.to_bytes_be()
216    }
217
218    /// Converts to little-endian byte representation in a [u8] array.
219    /// This is as performant as [to_bytes_be](Felt::to_bytes_be)
220    pub fn to_bytes_le(&self) -> [u8; 32] {
221        self.0.to_bytes_le()
222    }
223
224    /// Converts to little-endian bit representation.
225    pub fn to_bits_le(&self) -> [bool; 256] {
226        self.0.to_bits_le()
227    }
228
229    /// Converts to big-endian bit representation.
230    pub fn to_bits_be(&self) -> [bool; 256] {
231        let mut bits = self.0.to_bits_le();
232        bits.reverse();
233        bits
234    }
235
236    /// Finite field division.
237    pub fn field_div(&self, rhs: &NonZeroFelt) -> Self {
238        Self(self.0 / rhs.0)
239    }
240
241    /// Truncated quotient between `self` and `rhs`.
242    pub fn floor_div(&self, rhs: &NonZeroFelt) -> Self {
243        Self(FieldElement::from(
244            &(self.0.representative().div_rem(&rhs.0.representative())).0,
245        ))
246    }
247
248    /// Quotient and remainder between `self` and `rhs`.
249    pub fn div_rem(&self, rhs: &NonZeroFelt) -> (Self, Self) {
250        let (q, r) = self.0.representative().div_rem(&rhs.0.representative());
251        (Self(FieldElement::from(&q)), Self(FieldElement::from(&r)))
252    }
253
254    /// Multiplicative inverse inside field.
255    pub fn inverse(&self) -> Option<Self> {
256        self.0.inv().map(Self).ok()
257    }
258
259    /// Finds the square root. There may be 2 roots for each square, and the lower one is returned.
260    pub fn sqrt(&self) -> Option<Self> {
261        let (root_1, root_2) = self.0.sqrt()?;
262        Some(Self(core::cmp::min(root_1, root_2)))
263    }
264
265    /// Raises `self` to the power of 2.
266    pub fn square(&self) -> Self {
267        Self(self.0.square())
268    }
269
270    /// Doubles the point `self`
271    pub fn double(&self) -> Self {
272        Self(self.0.double())
273    }
274
275    /// Raises `self` to the power of `exponent`.
276    pub fn pow(&self, exponent: impl Into<u128>) -> Self {
277        Self(self.0.pow(exponent.into()))
278    }
279
280    /// Raises `self` to the power of `exponent`.
281    pub fn pow_felt(&self, exponent: &Felt) -> Self {
282        Self(self.0.pow(exponent.0.representative()))
283    }
284
285    // Implemention taken from Jonathan Lei's starknet-rs
286    // https://github.com/xJonathanLEI/starknet-rs/blob/a3a0050f80e90bd40303256a85783f4b5b18258c/starknet-crypto/src/fe_utils.rs#L20
287    /// Modular multiplication between `self` and `rhs` in modulo `p`.
288    pub fn mul_mod(&self, rhs: &Self, p: &NonZeroFelt) -> Self {
289        let multiplicand = BigInt::from_bytes_be(num_bigint::Sign::Plus, &self.to_bytes_be());
290        let multiplier = BigInt::from_bytes_be(num_bigint::Sign::Plus, &rhs.to_bytes_be());
291        let modulus = BigInt::from_bytes_be(num_bigint::Sign::Plus, &p.0.to_bytes_be());
292
293        let result = multiplicand.mul(multiplier).mod_floor(&modulus);
294
295        let (_, buffer) = result.to_bytes_be();
296        let mut result = [0u8; 32];
297
298        result[(32 - buffer.len())..].copy_from_slice(&buffer[..]);
299
300        Felt::from_bytes_be(&result)
301    }
302
303    // Implemention taken from Jonathan Lei's starknet-rs
304    // https://github.com/xJonathanLEI/starknet-rs/blob/a3a0050f80e90bd40303256a85783f4b5b18258c/starknet-crypto/src/fe_utils.rs#L46
305    /// Multiplicative inverse of `self` in modulo `p`.
306    pub fn mod_inverse(&self, p: &NonZeroFelt) -> Option<Self> {
307        let operand = BigInt::from_bytes_be(num_bigint::Sign::Plus, &self.0.to_bytes_be());
308        let modulus = BigInt::from_bytes_be(num_bigint::Sign::Plus, &p.0.to_bytes_be());
309
310        let extended_gcd = operand.extended_gcd(&modulus);
311        if extended_gcd.gcd != BigInt::one() {
312            return None;
313        }
314        let result = if extended_gcd.x < BigInt::zero() {
315            extended_gcd.x + modulus
316        } else {
317            extended_gcd.x
318        };
319
320        let (_, buffer) = result.to_bytes_be();
321        let mut result = [0u8; 32];
322        result[(32 - buffer.len())..].copy_from_slice(&buffer[..]);
323
324        Some(Felt::from_bytes_be(&result))
325    }
326
327    /// Remainder of dividing `self` by `n` as integers.
328    pub fn mod_floor(&self, n: &NonZeroFelt) -> Self {
329        self.div_rem(n).1
330    }
331
332    /// Parse a hex-encoded number into `Felt`.
333    pub fn from_hex(hex_string: &str) -> Result<Self, FromStrError> {
334        FieldElement::from_hex(hex_string)
335            .map(Self)
336            .map_err(FromStrError)
337    }
338
339    /// Parse a decimal-encoded number into `Felt`.
340    pub fn from_dec_str(dec_string: &str) -> Result<Self, FromStrError> {
341        if dec_string.starts_with('-') {
342            UnsignedInteger::from_dec_str(dec_string.strip_prefix('-').unwrap())
343                .map(|x| Self(FieldElement::from(&x)).neg())
344                .map_err(FromStrError)
345        } else {
346            UnsignedInteger::from_dec_str(dec_string)
347                .map(|x| Self(FieldElement::from(&x)))
348                .map_err(FromStrError)
349        }
350    }
351
352    /// Returns the internal representation of a felt and reverses it to match
353    /// starknet-rs mont representation
354    pub fn to_raw_reversed(&self) -> [u64; 4] {
355        let mut res = self.0.to_raw().limbs;
356        res.reverse();
357        res
358    }
359
360    /// Returns the internal representation of a felt
361    pub fn to_raw(&self) -> [u64; 4] {
362        self.0.to_raw().limbs
363    }
364    /// Convert `self`'s representative into an array of `u64` digits,
365    /// least significant digits first.
366    pub fn to_le_digits(&self) -> [u64; 4] {
367        let mut limbs = self.0.representative().limbs;
368        limbs.reverse();
369        limbs
370    }
371
372    /// Convert `self`'s representative into an array of `u64` digits,
373    /// most significant digits first.
374    pub fn to_be_digits(&self) -> [u64; 4] {
375        self.0.representative().limbs
376    }
377
378    /// Count the minimum number of bits needed to express `self`'s representative.
379    pub fn bits(&self) -> usize {
380        self.0.representative().bits_le()
381    }
382
383    pub fn to_biguint(&self) -> BigUint {
384        let big_digits = self
385            .to_le_digits()
386            .into_iter()
387            .flat_map(|limb| [limb as u32, (limb >> 32) as u32])
388            .collect();
389        BigUint::new(big_digits)
390    }
391
392    pub fn to_bigint(&self) -> BigInt {
393        self.to_biguint().into()
394    }
395}
396
397/// Defaults to [Felt::ZERO].
398impl Default for Felt {
399    fn default() -> Self {
400        Self(FieldElement::<Stark252PrimeField>::zero())
401    }
402}
403
404impl AsRef<Felt> for Felt {
405    fn as_ref(&self) -> &Felt {
406        self
407    }
408}
409
410impl From<&BigInt> for Felt {
411    fn from(bigint: &BigInt) -> Felt {
412        let (sign, bytes) = bigint.to_bytes_le();
413        let felt = Felt::from_bytes_le_slice(&bytes);
414        if sign == Sign::Minus {
415            felt.neg()
416        } else {
417            felt
418        }
419    }
420}
421
422impl From<BigInt> for Felt {
423    fn from(bigint: BigInt) -> Felt {
424        Self::from(&bigint)
425    }
426}
427
428impl From<&BigUint> for Felt {
429    fn from(biguint: &BigUint) -> Felt {
430        Felt::from_bytes_le_slice(&biguint.to_bytes_le())
431    }
432}
433
434impl From<BigUint> for Felt {
435    fn from(biguint: BigUint) -> Felt {
436        Self::from(&biguint)
437    }
438}
439
440impl FromStr for Felt {
441    type Err = FromStrError;
442
443    /// Converts a hex (0x-prefixed) or decimal string to a [Felt].
444    /// e.g., '0x123abc' or '1337'.
445    fn from_str(s: &str) -> Result<Self, Self::Err> {
446        if s.starts_with("0x") {
447            Felt::from_hex(s)
448        } else {
449            Felt::from_dec_str(s)
450        }
451    }
452}
453
454impl Add<&Felt> for u64 {
455    type Output = Option<u64>;
456
457    fn add(self, rhs: &Felt) -> Option<u64> {
458        const PRIME_DIGITS_BE_HI: [u64; 3] =
459            [0x0800000000000011, 0x0000000000000000, 0x0000000000000000];
460        const PRIME_MINUS_U64_MAX_DIGITS_BE_HI: [u64; 3] =
461            [0x0800000000000010, 0xffffffffffffffff, 0xffffffffffffffff];
462
463        // Match with the 64 bits digits in big-endian order to
464        // characterize how the sum will behave.
465        match rhs.to_be_digits() {
466            // All digits are `0`, so the sum is simply `self`.
467            [0, 0, 0, 0] => Some(self),
468            // A single digit means this is effectively the sum of two `u64` numbers.
469            [0, 0, 0, low] => self.checked_add(low),
470            // Now we need to compare the 3 most significant digits.
471            // There are two relevant cases from now on, either `rhs` behaves like a
472            // substraction of a `u64` or the result of the sum falls out of range.
473
474            // The 3 MSB only match the prime for Felt::max_value(), which is -1
475            // in the signed field, so this is equivalent to substracting 1 to `self`.
476            [hi @ .., _] if hi == PRIME_DIGITS_BE_HI => self.checked_sub(1),
477
478            // For the remaining values between `[-u64::MAX..0]` (where `{0, -1}` have
479            // already been covered) the MSB matches that of `PRIME - u64::MAX`.
480            // Because we're in the negative number case, we count down. Because `0`
481            // and `-1` correspond to different MSBs, `0` and `1` in the LSB are less
482            // than `-u64::MAX`, the smallest value we can add to (read, substract its
483            // magnitude from) a `u64` number, meaning we exclude them from the valid
484            // case.
485            // For the remaining range, we take the absolute value module-2 while
486            // correcting by substracting `1` (note we actually substract `2` because
487            // the absolute value itself requires substracting `1`.
488            [hi @ .., low] if hi == PRIME_MINUS_U64_MAX_DIGITS_BE_HI && low >= 2 => {
489                (self).checked_sub(u64::MAX - (low - 2))
490            }
491            // Any other case will result in an addition that is out of bounds, so
492            // the addition fails, returning `None`.
493            _ => None,
494        }
495    }
496}
497
498mod arithmetic {
499    use core::{
500        iter,
501        ops::{self, Neg},
502    };
503
504    use super::*;
505
506    /// Field addition. Never overflows/underflows.
507    impl ops::AddAssign<Felt> for Felt {
508        fn add_assign(&mut self, rhs: Felt) {
509            self.0 += rhs.0
510        }
511    }
512
513    /// Field addition. Never overflows/underflows.
514    impl ops::AddAssign<&Felt> for Felt {
515        fn add_assign(&mut self, rhs: &Felt) {
516            self.0 += rhs.0
517        }
518    }
519
520    /// Field addition. Never overflows/underflows.
521    impl ops::Add<Felt> for Felt {
522        type Output = Felt;
523
524        fn add(self, rhs: Felt) -> Self::Output {
525            Self(self.0 + rhs.0)
526        }
527    }
528
529    /// Field addition. Never overflows/underflows.
530    impl ops::Add<&Felt> for Felt {
531        type Output = Felt;
532
533        fn add(self, rhs: &Felt) -> Self::Output {
534            Self(self.0 + rhs.0)
535        }
536    }
537
538    /// Field addition. Never overflows/underflows.
539    impl ops::Add<Felt> for &Felt {
540        type Output = Felt;
541
542        fn add(self, rhs: Felt) -> Self::Output {
543            Felt(self.0 + rhs.0)
544        }
545    }
546
547    /// Field addition. Never overflows/underflows.
548    impl ops::Add<&Felt> for &Felt {
549        type Output = Felt;
550
551        fn add(self, rhs: &Felt) -> Self::Output {
552            Felt(self.0 + rhs.0)
553        }
554    }
555
556    /// Field addition. Never overflows/underflows.
557    impl ops::Add<u64> for Felt {
558        type Output = Felt;
559
560        fn add(self, rhs: u64) -> Self::Output {
561            self + Felt::from(rhs)
562        }
563    }
564
565    /// Field addition. Never overflows/underflows.
566    impl ops::Add<u64> for &Felt {
567        type Output = Felt;
568
569        fn add(self, rhs: u64) -> Self::Output {
570            self + Felt::from(rhs)
571        }
572    }
573
574    /// Field subtraction. Never overflows/underflows.
575    impl ops::SubAssign<Felt> for Felt {
576        fn sub_assign(&mut self, rhs: Felt) {
577            self.0 = self.0 - rhs.0
578        }
579    }
580
581    /// Field subtraction. Never overflows/underflows.
582    impl ops::SubAssign<&Felt> for Felt {
583        fn sub_assign(&mut self, rhs: &Felt) {
584            self.0 = self.0 - rhs.0
585        }
586    }
587
588    /// Field subtraction. Never overflows/underflows.
589    impl ops::Sub<Felt> for Felt {
590        type Output = Felt;
591
592        fn sub(self, rhs: Felt) -> Self::Output {
593            Self(self.0 - rhs.0)
594        }
595    }
596
597    /// Field subtraction. Never overflows/underflows.
598    impl ops::Sub<&Felt> for Felt {
599        type Output = Felt;
600
601        fn sub(self, rhs: &Felt) -> Self::Output {
602            Self(self.0 - rhs.0)
603        }
604    }
605
606    /// Field subtraction. Never overflows/underflows.
607    impl ops::Sub<Felt> for &Felt {
608        type Output = Felt;
609
610        fn sub(self, rhs: Felt) -> Self::Output {
611            Felt(self.0 - rhs.0)
612        }
613    }
614
615    /// Field subtraction. Never overflows/underflows.
616    impl ops::Sub<&Felt> for &Felt {
617        type Output = Felt;
618
619        fn sub(self, rhs: &Felt) -> Self::Output {
620            Felt(self.0 - rhs.0)
621        }
622    }
623
624    /// Field subtraction. Never overflows/underflows.
625    #[allow(clippy::suspicious_arithmetic_impl)]
626    impl ops::Sub<Felt> for u64 {
627        type Output = Option<u64>;
628        fn sub(self, rhs: Felt) -> Self::Output {
629            self + &rhs.neg()
630        }
631    }
632
633    /// Field subtraction. Never overflows/underflows.
634    #[allow(clippy::suspicious_arithmetic_impl)]
635    impl ops::Sub<&Felt> for u64 {
636        type Output = Option<u64>;
637        fn sub(self, rhs: &Felt) -> Self::Output {
638            self + &rhs.neg()
639        }
640    }
641
642    /// Field subtraction. Never overflows/underflows.
643    impl ops::Sub<u64> for Felt {
644        type Output = Felt;
645        fn sub(self, rhs: u64) -> Self::Output {
646            self - Self::from(rhs)
647        }
648    }
649
650    /// Field subtraction. Never overflows/underflows.
651    impl ops::Sub<u64> for &Felt {
652        type Output = Felt;
653        fn sub(self, rhs: u64) -> Self::Output {
654            self - Felt::from(rhs)
655        }
656    }
657
658    /// Field multiplication. Never overflows/underflows.
659    impl ops::MulAssign<Felt> for Felt {
660        fn mul_assign(&mut self, rhs: Felt) {
661            self.0 = self.0 * rhs.0
662        }
663    }
664
665    /// Field multiplication. Never overflows/underflows.
666    impl ops::MulAssign<&Felt> for Felt {
667        fn mul_assign(&mut self, rhs: &Felt) {
668            self.0 = self.0 * rhs.0
669        }
670    }
671
672    /// Field multiplication. Never overflows/underflows.
673    impl ops::Mul<Felt> for Felt {
674        type Output = Felt;
675
676        fn mul(self, rhs: Felt) -> Self::Output {
677            Self(self.0 * rhs.0)
678        }
679    }
680
681    /// Field multiplication. Never overflows/underflows.
682    impl ops::Mul<&Felt> for Felt {
683        type Output = Felt;
684
685        fn mul(self, rhs: &Felt) -> Self::Output {
686            Self(self.0 * rhs.0)
687        }
688    }
689
690    /// Field multiplication. Never overflows/underflows.
691    impl ops::Mul<Felt> for &Felt {
692        type Output = Felt;
693
694        fn mul(self, rhs: Felt) -> Self::Output {
695            Felt(self.0 * rhs.0)
696        }
697    }
698
699    /// Field multiplication. Never overflows/underflows.
700    impl ops::Mul<&Felt> for &Felt {
701        type Output = Felt;
702
703        fn mul(self, rhs: &Felt) -> Self::Output {
704            Felt(self.0 * rhs.0)
705        }
706    }
707
708    // [ops::Div] not implemented by design to prevent misuse. Use [Felt::floor_div] or
709    // [Felt::field_div] instead.
710
711    impl ops::Neg for Felt {
712        type Output = Felt;
713
714        fn neg(self) -> Self::Output {
715            Self(self.0.neg())
716        }
717    }
718
719    impl ops::Neg for &Felt {
720        type Output = Felt;
721
722        fn neg(self) -> Self::Output {
723            Felt(self.0.neg())
724        }
725    }
726
727    impl iter::Sum for Felt {
728        fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
729            let mut base = Self::ZERO;
730            iter.for_each(|addend| base += addend);
731            base
732        }
733    }
734
735    impl<'a> iter::Sum<&'a Felt> for Felt {
736        fn sum<I: Iterator<Item = &'a Felt>>(iter: I) -> Self {
737            let mut base = Self::ZERO;
738            iter.for_each(|addend| base += addend);
739            base
740        }
741    }
742}
743
744mod formatting {
745
746    use core::fmt;
747
748    use super::*;
749
750    /// Represents [Felt] in decimal by default.
751    impl fmt::Display for Felt {
752        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
753            write!(f, "{}", self.to_biguint())
754        }
755    }
756
757    impl fmt::Debug for Felt {
758        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
759            write!(f, "{}", self.0)
760        }
761    }
762}
763
764#[cfg(test)]
765mod test {
766    use super::alloc::{format, string::String, vec::Vec};
767    use super::felt_arbitrary::nonzero_felt;
768    use super::*;
769    use core::ops::Shl;
770    use num_traits::Num;
771    use proptest::prelude::*;
772    use regex::Regex;
773
774    #[test]
775    fn test_debug_format() {
776        assert_eq!(format!("{:?}", Felt::ONE), "0x1");
777        assert_eq!(format!("{:?}", Felt::from(2)), "0x2");
778        assert_eq!(format!("{:?}", Felt::from(12345)), "0x3039");
779    }
780
781    // Helper function to generate a vector of bits for testing purposes
782    fn generate_be_bits(x: &Felt) -> Vec<bool> {
783        // Initialize an empty vector to store the expected bits
784        let mut bits = Vec::new();
785
786        // Iterate over each limb in the representative of x
787        for limb in x.0.representative().limbs {
788            // Convert the limb to a sequence of 8 bytes (u8) in big-endian
789            let bytes = limb.to_be_bytes();
790
791            // Iterate over each byte
792            for byte in &bytes {
793                // Iterate over each bit of the byte
794                for i in 0..8 {
795                    // Extract the i-th bit of the byte
796                    let bit = (*byte >> (7 - i)) & 1;
797
798                    // Push the bit into the expected_bits vector
799                    bits.push(bit == 1);
800                }
801            }
802        }
803
804        bits
805    }
806
807    proptest! {
808        #[test]
809        fn new_in_range(ref x in any::<[u8; 32]>()) {
810            let x_be = Felt::from_bytes_be(x);
811            prop_assert!(x_be < Felt::MAX);
812            let x_le = Felt::from_bytes_le(x);
813            prop_assert!(x_le < Felt::MAX);
814        }
815
816        #[test]
817        fn to_be_bytes(ref x in any::<Felt>()) {
818            let bytes = x.to_bytes_be();
819            let y = &Felt::from_bytes_be(&bytes);
820            prop_assert_eq!(x, y);
821        }
822
823        #[test]
824        fn to_le_bytes(ref x in any::<Felt>()) {
825            let bytes = x.to_bytes_le();
826            let y = &Felt::from_bytes_le(&bytes);
827            prop_assert_eq!(x, y);
828        }
829
830        #[test]
831        fn to_bits_le(ref x in any::<Felt>()) {
832            // Generate the little-endian representation of Felt type x
833            let bits: Vec<bool> = x.to_bits_le().into_iter().collect();
834
835            // Get the expected bits in big-endian order
836            let mut expected_bits = generate_be_bits(x);
837
838            // Reverse the expected_bits to convert from big-endian to little-endian
839            expected_bits.reverse();
840
841            // Assert that the generated bits match the expected bits
842            prop_assert_eq!(bits, expected_bits);
843        }
844
845        #[test]
846        fn to_bits_be(ref x in any::<Felt>()) {
847            // Generate the big-endian representation of Felt type x
848            let bits: Vec<bool> = x.to_bits_be().into_iter().collect();
849
850            // Get the expected bits in big-endian order
851            let expected_bits = generate_be_bits(x);
852
853            // Assert that the generated bits match the expected bits
854            prop_assert_eq!(bits, expected_bits);
855        }
856
857        #[test]
858        fn from_bytes_le_slice_works_for_all_lengths(x in 0..1000usize) {
859            let bytes: [u8; 1000] = core::array::from_fn(|i| i as u8);
860            let expected = bytes.iter()
861                .enumerate()
862                .map(|(i, x)| Felt::from(*x) * Felt::from(256).pow(i as u64))
863                .take(x)
864                .sum::<Felt>();
865            let x = Felt::from_bytes_le_slice(&bytes[0..x]);
866            prop_assert_eq!(x, expected, "x={:x} expected={:x}", x, expected);
867        }
868
869        #[test]
870        fn from_bytes_be_slice_works_for_all_lengths(x in 0..1000usize) {
871            let bytes: [u8; 1000] = core::array::from_fn(|i| i as u8);
872            let expected = bytes.iter()
873                .rev()
874                .enumerate()
875                .map(|(i, x)| Felt::from(*x) * Felt::from(256).pow(i as u64))
876                .take(x)
877                .sum::<Felt>();
878            let x = Felt::from_bytes_be_slice(&bytes[1000-x..1000]);
879            prop_assert_eq!(x, expected, "x={:x} expected={:x}", x, expected);
880        }
881
882        #[test]
883        fn from_bytes_le_in_range(ref x in any::<[u8; 32]>()) {
884            let x = Felt::from_bytes_le(x);
885            prop_assert!(x <= Felt::MAX);
886        }
887
888        #[test]
889        fn from_bytes_be_in_range(ref x in any::<[u8; 32]>()) {
890            let x = Felt::from_bytes_be(x);
891            prop_assert!(x <= Felt::MAX);
892        }
893
894        #[test]
895        fn neg_in_range(x in any::<Felt>()) {
896            prop_assert!(-x <= Felt::MAX);
897        }
898
899        #[test]
900        fn sub(ref x in any::<Felt>(), ref y in any::<Felt>()) {
901            // x - y
902            prop_assert!(x - y <= Felt::MAX);
903            prop_assert_eq!(Felt::MAX + x - y + Felt::ONE, x - y);
904            // y - x
905            prop_assert!(y - x <= Felt::MAX);
906            prop_assert_eq!(Felt::MAX + y - x + Felt::ONE, y - x);
907        }
908
909        #[test]
910        fn sub_assign_in_range(mut x in any::<Felt>(), y in any::<Felt>()) {
911            x -= y;
912            prop_assert!(x <= Felt::MAX);
913            // test reference variant
914            x -= &y;
915            prop_assert!(x <= Felt::MAX);
916        }
917
918        #[test]
919        fn mul(ref x in any::<Felt>(), ref y in any::<Felt>()) {
920            prop_assert_eq!(x * y, y * x);
921            prop_assert!(x * y <= Felt::MAX);
922        }
923
924        #[test]
925        fn mul_assign_in_range(mut x in any::<Felt>(), y in any::<Felt>()) {
926            x *= y;
927            prop_assert!(x <= Felt::MAX);
928            // test reference variant
929            x *= &y;
930            prop_assert!(x <= Felt::MAX);
931        }
932
933        #[test]
934        fn mod_floor_in_range(x in any::<Felt>(), n in nonzero_felt()) {
935            let nzn = NonZeroFelt(n.0);
936            let x_mod_n = x.mod_floor(&nzn);
937            prop_assert!(x_mod_n <= Felt::MAX);
938            prop_assert!(x_mod_n < n);
939        }
940
941        #[test]
942        fn field_div_is_mul_inv(x in any::<Felt>(), y in nonzero_felt()) {
943            let q = x.field_div(&NonZeroFelt(y.0));
944            prop_assert!(q <= Felt::MAX);
945            prop_assert_eq!(q * y, x);
946        }
947
948        #[test]
949        fn floor_div_is_mul_inv(x in any::<Felt>(), y in nonzero_felt()) {
950            let x = Felt(FieldElement::from(&x.0.representative().shl(127)));
951            let y = Felt(FieldElement::from(&y.0.representative().shl(127)));
952            let q = x.field_div(&NonZeroFelt(y.0));
953            prop_assert!(q <= Felt::MAX);
954            prop_assert_eq!(q * y, x);
955        }
956
957        #[test]
958        fn pow_in_range(base in any::<Felt>(), exp in 0..u128::MAX){
959            prop_assert!(base.pow(exp) <= Felt::MAX);
960        }
961
962        #[test]
963        fn add_in_range(x in any::<Felt>(), y in any::<Felt>()){
964            prop_assert!(x + y <= Felt::MAX);
965        }
966
967        #[test]
968        fn zero_additive_identity(x in any::<Felt>()) {
969            prop_assert_eq!(x, x + Felt::ZERO);
970            prop_assert_eq!(x, Felt::ZERO + x);
971        }
972
973        #[test]
974        fn one_multiplicative_identity(x in any::<Felt>()) {
975            prop_assert_eq!(x, x * Felt::ONE);
976            prop_assert_eq!(x, Felt::ONE * x);
977        }
978
979        #[test]
980        fn sqrt_in_range(x in any::<Felt>()) {
981            // we use x = x' * x' so x has a square root
982            prop_assert!((x * x).sqrt().unwrap() <= Felt::MAX);
983        }
984
985        #[test]
986        fn sqrt_is_inv_square(x in any::<Felt>()) {
987            // we use x = x' * x' so x has a square root
988            let sqrt = (x * x).sqrt().unwrap();
989            prop_assert!( sqrt == x || -sqrt == x)
990        }
991
992        #[test]
993        fn double_in_range(x in any::<Felt>()) {
994            prop_assert!(x.double() == x + x);
995        }
996
997         #[test]
998        fn square_in_range(x in any::<Felt>()) {
999            prop_assert!(x.square() <= Felt::MAX);
1000        }
1001
1002        #[test]
1003        fn square_x_is_x_mul_x(x in any::<Felt>()) {
1004            prop_assert_eq!(x.square(), x * x);
1005        }
1006
1007        #[test]
1008        fn square_is_inv_sqrt(x in any::<Felt>()) {
1009            let sqrt = x.square().sqrt().unwrap();
1010            prop_assert!( sqrt == x || -sqrt == x)
1011        }
1012
1013        #[test]
1014        fn multiplying_by_inverse_yields_multiplicative_neutral(x in nonzero_felt()) {
1015            prop_assert_eq!(x * x.inverse().unwrap(), Felt::ONE )
1016        }
1017
1018        #[test]
1019        fn inverse_mod_of_zero_is_none(p in nonzero_felt()) {
1020            let nzp = NonZeroFelt(p.0);
1021            prop_assert!(Felt::ZERO.mod_inverse(&nzp).is_none());
1022        }
1023
1024        #[test]
1025        fn inverse_mod_in_range(x in nonzero_felt(), p in nonzero_felt()) {
1026            let nzp = NonZeroFelt(p.0);
1027            let Some(result) = x.mod_inverse(&nzp) else { return Ok(()) };
1028
1029            prop_assert!(result <= Felt::MAX);
1030            prop_assert!(result < p);
1031            prop_assert!(result.mul_mod(&x, &nzp) == Felt::ONE);
1032        }
1033
1034        #[test]
1035        fn mul_mod_in_range(x in any::<Felt>(), y in any::<Felt>(), p in nonzero_felt()) {
1036            let nzp = NonZeroFelt(p.0);
1037            prop_assert!(x.mul_mod(&y, &nzp) <= Felt::MAX);
1038            prop_assert!(x.mul_mod(&y, &nzp) < p);
1039        }
1040
1041        #[test]
1042        fn to_raw_reversed(mut x in any::<[u64; 4]>()) {
1043            let felt = Felt::from_raw(x);
1044            x.reverse();
1045            prop_assert_eq!(felt.to_raw_reversed(), x);
1046        }
1047
1048        #[test]
1049        fn to_raw(x in any::<[u64; 4]>()) {
1050            let felt = Felt::from_raw(x);
1051            prop_assert_eq!(felt.to_raw(), x);
1052        }
1053        #[test]
1054        fn felt_from_bigint(mut x in any::<[u8; 32]>()) {
1055            x[0] = 0;
1056            let bigint = BigInt::from_bytes_be(Sign::Plus, &x);
1057            let felt_from_ref: Felt = (&bigint).into();
1058            let felt: Felt = bigint.into();
1059            prop_assert_eq!(felt_from_ref, felt);
1060            prop_assert_eq!(felt_from_ref.to_bytes_be(), x);
1061            prop_assert_eq!(felt.to_bytes_be(), x);
1062        }
1063
1064        #[test]
1065        fn felt_from_biguint(mut x in any::<[u8; 32]>()) {
1066            x[0] = 0;
1067            let biguint = BigUint::from_bytes_be( &x);
1068            let felt_from_ref: Felt = (&biguint).into();
1069            let felt: Felt = biguint.into();
1070            prop_assert_eq!(felt_from_ref, felt);
1071            prop_assert_eq!(felt_from_ref.to_bytes_be(), x);
1072            prop_assert_eq!(felt.to_bytes_be(), x);
1073        }
1074        #[test]
1075        fn iter_sum(a in any::<Felt>(), b in any::<Felt>(), c in any::<Felt>()) {
1076            prop_assert_eq!([a, b, c].iter().sum::<Felt>(), a + b + c);
1077            prop_assert_eq!([a, b, c].iter().map(Clone::clone).sum::<Felt>(), a + b + c);
1078        }
1079
1080        #[test]
1081        fn felt_to_fixed_hex_string(a in any::<Felt>()) {
1082            prop_assert_eq!(a.to_fixed_hex_string().len(), 66);
1083            let re = Regex::new(r"^0x([0-9a-fA-F]{64})$").unwrap();
1084            prop_assert!(re.is_match(&a.to_fixed_hex_string()));
1085        }
1086    }
1087
1088    #[test]
1089    fn constant_zero() {
1090        let mut zero_bytes = 0_u64.to_le_bytes().to_vec();
1091        zero_bytes.extend_from_slice(&[0; 24]);
1092        assert_eq!(Felt::ZERO.to_bytes_le().to_vec(), zero_bytes);
1093    }
1094
1095    #[test]
1096    fn constant_one() {
1097        let mut one_bytes = 1_u64.to_le_bytes().to_vec();
1098        one_bytes.extend_from_slice(&[0; 24]);
1099        assert_eq!(Felt::ONE.to_bytes_le().to_vec(), one_bytes);
1100    }
1101
1102    #[test]
1103    fn constant_two() {
1104        let mut two_bytes = 2_u64.to_le_bytes().to_vec();
1105        two_bytes.extend_from_slice(&[0; 24]);
1106        assert_eq!(Felt::TWO.to_bytes_le().to_vec(), two_bytes);
1107    }
1108
1109    #[test]
1110    fn constant_three() {
1111        let mut three_bytes = 3_u64.to_le_bytes().to_vec();
1112        three_bytes.extend_from_slice(&[0; 24]);
1113        assert_eq!(Felt::THREE.to_bytes_le().to_vec(), three_bytes);
1114    }
1115
1116    #[test]
1117    fn constant_max() {
1118        let max_bytes = [
1119            8, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1120            0, 0, 0,
1121        ];
1122        assert_eq!(Felt::MAX.to_bytes_be(), max_bytes);
1123    }
1124
1125    #[test]
1126    fn felt_from_raw() {
1127        let zero_bytes = [0; 4];
1128        assert_eq!(Felt::from_raw(zero_bytes), Felt::ZERO);
1129        let one_raw = [
1130            576460752303422960,
1131            18446744073709551615,
1132            18446744073709551615,
1133            18446744073709551585,
1134        ];
1135        assert_eq!(Felt::from_raw(one_raw), Felt::ONE);
1136        let nineteen_raw = [
1137            576460752303413168,
1138            18446744073709551615,
1139            18446744073709551615,
1140            18446744073709551009,
1141        ];
1142        assert_eq!(Felt::from_raw(nineteen_raw), Felt::from(19));
1143    }
1144
1145    #[test]
1146    fn felt_from_hex_unchecked() {
1147        assert_eq!(Felt::from_hex_unchecked("0"), Felt::from(0));
1148        assert_eq!(Felt::from_hex_unchecked("1"), Felt::from(1));
1149        assert_eq!(Felt::from_hex_unchecked("0x2"), Felt::from(2));
1150        assert_eq!(Felt::from_hex_unchecked("0x0000000003"), Felt::from(3));
1151        assert_eq!(Felt::from_hex_unchecked("000004"), Felt::from(4));
1152        assert_eq!(Felt::from_hex_unchecked("0x05b"), Felt::from(91));
1153        assert_eq!(Felt::from_hex_unchecked("A"), Felt::from(10));
1154    }
1155    #[test]
1156    fn mul_operations() {
1157        assert_eq!(Felt::ONE * Felt::THREE, Felt::THREE);
1158        assert_eq!(Felt::ZERO * Felt::MAX, Felt::ZERO);
1159        assert_eq!(
1160            Felt(FieldElement::from(200)) * Felt::THREE,
1161            Felt(FieldElement::from(600))
1162        );
1163        assert_eq!(Felt::MAX * Felt::TWO, Felt::MAX - Felt::ONE);
1164    }
1165
1166    #[test]
1167    fn add_operations() {
1168        assert_eq!(Felt::ONE + Felt::TWO, Felt::THREE);
1169        assert_eq!(Felt::ZERO + Felt::MAX, Felt::MAX);
1170        assert_eq!(
1171            Felt(FieldElement::from(200)) + Felt::THREE,
1172            Felt(FieldElement::from(203))
1173        );
1174        assert_eq!(Felt::MAX + Felt::TWO, Felt::ONE);
1175    }
1176
1177    #[test]
1178    fn sub_operations() {
1179        assert_eq!(Felt::TWO - Felt::ONE, Felt::ONE);
1180        assert_eq!(Felt::MAX - Felt::ZERO, Felt::MAX);
1181        assert_eq!(
1182            Felt(FieldElement::from(200)) - Felt::THREE,
1183            Felt(FieldElement::from(197))
1184        );
1185        assert_eq!(Felt::ZERO - Felt::ONE, Felt::MAX);
1186    }
1187
1188    #[test]
1189    fn pow_operations() {
1190        assert_eq!(Felt::ONE.pow(5u32), Felt::ONE);
1191        assert_eq!(Felt::ZERO.pow(5u32), Felt::ZERO);
1192        assert_eq!(Felt::THREE.pow(0u32), Felt::ONE);
1193        assert_eq!(
1194            Felt(FieldElement::from(200)).pow(4u32),
1195            Felt(FieldElement::from(1600000000))
1196        );
1197        assert_eq!(Felt::MAX.pow(9u32), Felt::MAX);
1198    }
1199
1200    #[test]
1201    fn display_lower_hex() {
1202        assert_eq!(format!("{:#x}", Felt::ZERO), format!("{:#x}", 0_u64));
1203        assert_eq!(format!("{:#x}", Felt::TWO), format!("{:#x}", 2_u64));
1204        assert_eq!(format!("{:#x}", Felt::THREE), format!("{:#x}", 3_u64));
1205        assert_eq!(
1206            format!("{:#x}", Felt(FieldElement::from(200))),
1207            format!("{:#x}", 200_u64)
1208        );
1209        assert_eq!(
1210            format!("{:#x}", Felt::MAX),
1211            String::from("0x800000000000011000000000000000000000000000000000000000000000000")
1212        );
1213    }
1214
1215    #[test]
1216    fn display_upper_hex() {
1217        assert_eq!(format!("{:#X}", Felt::ZERO), format!("{:#X}", 0_u64));
1218        assert_eq!(format!("{:#X}", Felt::TWO), format!("{:#X}", 2_u64));
1219        assert_eq!(format!("{:#X}", Felt::THREE), format!("{:#X}", 3_u64));
1220        assert_eq!(
1221            format!("{:#X}", Felt(FieldElement::from(200))),
1222            format!("{:#X}", 200_u64)
1223        );
1224        assert_eq!(
1225            format!("{:#X}", Felt::MAX),
1226            String::from("0x800000000000011000000000000000000000000000000000000000000000000")
1227        );
1228    }
1229
1230    #[test]
1231    fn display_decimal() {
1232        assert_eq!(format!("{}", Felt::ZERO), format!("{}", 0_u64));
1233        assert_eq!(format!("{}", Felt::TWO), format!("{}", 2_u64));
1234        assert_eq!(format!("{}", Felt::THREE), format!("{}", 3_u64));
1235        assert_eq!(
1236            format!("{}", Felt(FieldElement::from(200))),
1237            format!("{}", 200_u64)
1238        );
1239        assert_eq!(
1240            format!("{}", Felt::MAX),
1241            String::from(
1242                "3618502788666131213697322783095070105623107215331596699973092056135872020480"
1243            )
1244        );
1245    }
1246
1247    #[test]
1248    fn inverse_and_mul_mod() {
1249        let nzps: Vec<NonZeroFelt> = [
1250            Felt::from(5_i32).try_into().unwrap(),
1251            Felt::from_hex("0x5").unwrap().try_into().unwrap(),
1252            Felt::from_hex("0x1234").unwrap().try_into().unwrap(),
1253            Felt::from_hex("0xabcdef123").unwrap().try_into().unwrap(),
1254            Felt::from_hex("0xffffffffffffff")
1255                .unwrap()
1256                .try_into()
1257                .unwrap(),
1258            Felt::from_hex("0xfffffffffffffffffffffffffffffff")
1259                .unwrap()
1260                .try_into()
1261                .unwrap(),
1262            Felt::MAX.try_into().unwrap(),
1263        ]
1264        .to_vec();
1265        let nums = [
1266            Felt::from_hex("0x0").unwrap(),
1267            Felt::from_hex("0x1").unwrap(),
1268            Felt::from_hex("0x2").unwrap(),
1269            Felt::from_hex("0x5").unwrap(),
1270            Felt::from_hex("0x123abc").unwrap(),
1271            Felt::from_hex("0xabcdef9812367312").unwrap(),
1272            Felt::from_hex("0xffffffffffffffffffffffffffffff").unwrap(),
1273            Felt::from_hex("0xffffffffffffffffffffffffffffffffffffffffff").unwrap(),
1274            Felt::MAX,
1275        ];
1276
1277        for felt in nums {
1278            for nzp in nzps.iter() {
1279                let result = felt.mod_inverse(nzp);
1280                if result.is_some() {
1281                    assert_eq!(result.unwrap().mul_mod(&felt, nzp), Felt::ONE);
1282                }
1283            }
1284        }
1285    }
1286
1287    #[test]
1288    fn check_mul_mod() {
1289        let x = Felt::from_dec_str(
1290            "3618502788666131213697322783095070105623107215331596699973092056135872020480",
1291        )
1292        .unwrap();
1293        let y = Felt::from_dec_str("46118400291").unwrap();
1294        let p: NonZeroFelt = Felt::from_dec_str("123987312893120893724347692364")
1295            .unwrap()
1296            .try_into()
1297            .unwrap();
1298        let expected_result = Felt::from_dec_str("68082278891996790254001523512").unwrap();
1299
1300        assert_eq!(x.mul_mod(&y, &p), expected_result);
1301    }
1302
1303    #[test]
1304    fn felt_to_bigints() {
1305        let numbers_str = [
1306            "0x0",
1307            "0x1",
1308            "0x10",
1309            "0x8000000000000110000000000",
1310            "0xffffffffffffff",
1311            "0xffffffffefff12380777abcd",
1312        ];
1313
1314        for number_str in numbers_str {
1315            assert_eq!(
1316                Felt::from_hex(number_str).unwrap().to_bigint(),
1317                BigInt::from_str_radix(&number_str[2..], 16).unwrap()
1318            );
1319
1320            assert_eq!(
1321                Felt::from_hex(number_str).unwrap().to_biguint(),
1322                BigUint::from_str_radix(&number_str[2..], 16).unwrap()
1323            );
1324        }
1325    }
1326
1327    #[test]
1328    fn bool_into_felt() {
1329        let zero: Felt = false.into();
1330        let one: Felt = true.into();
1331        assert_eq!(one, Felt::ONE);
1332        assert_eq!(zero, Felt::ZERO);
1333    }
1334}