starknet_ff/
lib.rs

1#![cfg_attr(not(feature = "std"), no_std)]
2#![allow(clippy::comparison_chain)]
3
4#[cfg(all(not(feature = "std"), any(test, feature = "alloc")))]
5#[cfg_attr(test, macro_use)]
6extern crate alloc;
7
8use core::{
9    fmt, ops,
10    str::{self, FromStr},
11};
12
13use crate::fr::Fr;
14
15use ark_ff::{
16    fields::{Field, Fp256, PrimeField},
17    BigInteger, BigInteger256,
18};
19use crypto_bigint::{CheckedAdd, CheckedMul, NonZero, Zero, U256};
20
21mod fr;
22
23const U256_BYTE_COUNT: usize = 32;
24
25#[derive(Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash)]
26pub struct FieldElement {
27    inner: Fr,
28}
29
30mod from_str_error {
31
32    #[derive(Debug)]
33    pub enum FromStrError {
34        InvalidCharacter,
35        OutOfRange,
36    }
37
38    #[cfg(feature = "std")]
39    impl std::error::Error for FromStrError {}
40
41    impl core::fmt::Display for FromStrError {
42        fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
43            match self {
44                Self::InvalidCharacter => write!(f, "invalid character"),
45                Self::OutOfRange => write!(f, "number out of range"),
46            }
47        }
48    }
49}
50pub use from_str_error::FromStrError;
51
52mod from_bytes_slice_error {
53
54    #[derive(Debug)]
55    pub enum FromByteSliceError {
56        InvalidLength,
57        OutOfRange,
58    }
59
60    #[cfg(feature = "std")]
61    impl std::error::Error for FromByteSliceError {}
62
63    impl core::fmt::Display for FromByteSliceError {
64        fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
65            match self {
66                Self::InvalidLength => write!(f, "invalid length"),
67                Self::OutOfRange => write!(f, "number out of range"),
68            }
69        }
70    }
71}
72pub use from_bytes_slice_error::FromByteSliceError;
73
74mod from_byte_array_error {
75    #[derive(Debug)]
76    pub struct FromByteArrayError;
77
78    #[cfg(feature = "std")]
79    impl std::error::Error for FromByteArrayError {}
80
81    impl core::fmt::Display for FromByteArrayError {
82        fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
83            write!(f, "number out of range")
84        }
85    }
86}
87pub use from_byte_array_error::FromByteArrayError;
88
89mod value_out_of_range_error {
90    #[derive(Debug)]
91    pub struct ValueOutOfRangeError;
92
93    #[cfg(feature = "std")]
94    impl std::error::Error for ValueOutOfRangeError {}
95
96    impl core::fmt::Display for ValueOutOfRangeError {
97        fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
98            write!(f, "field element value out of range")
99        }
100    }
101}
102pub use value_out_of_range_error::ValueOutOfRangeError;
103
104struct InnerDebug<'a>(pub &'a FieldElement);
105
106impl FieldElement {
107    /// [FieldElement] constant that's equal to 0
108    pub const ZERO: FieldElement = FieldElement::from_mont([0, 0, 0, 0]);
109
110    /// [FieldElement] constant that's equal to 1
111    pub const ONE: FieldElement = FieldElement::from_mont([
112        18446744073709551585,
113        18446744073709551615,
114        18446744073709551615,
115        576460752303422960,
116    ]);
117
118    /// [FieldElement] constant that's equal to 2
119    pub const TWO: FieldElement = FieldElement::from_mont([
120        18446744073709551553,
121        18446744073709551615,
122        18446744073709551615,
123        576460752303422416,
124    ]);
125
126    /// [FieldElement] constant that's equal to 3
127    pub const THREE: FieldElement = FieldElement::from_mont([
128        18446744073709551521,
129        18446744073709551615,
130        18446744073709551615,
131        576460752303421872,
132    ]);
133
134    /// Maximum value of [FieldElement]. Equals to 2^251 + 17 * 2^192.
135    pub const MAX: FieldElement = FieldElement::from_mont([32, 0, 0, 544]);
136
137    /// Create a new [FieldElement] from its Montgomery representation
138    pub const fn from_mont(data: [u64; 4]) -> Self {
139        Self {
140            inner: Fp256::new_unchecked(BigInteger256::new(data)),
141        }
142    }
143
144    pub fn from_dec_str(value: &str) -> Result<Self, FromStrError> {
145        // Ported from:
146        //   https://github.com/paritytech/parity-common/blob/b37d0b312d39fa47c61c4430b30ca87d90e45a08/uint/src/uint.rs#L599
147
148        let mut res = U256::ZERO;
149        for b in value.bytes().map(|b| b.wrapping_sub(b'0')) {
150            if b > 9 {
151                return Err(FromStrError::InvalidCharacter);
152            }
153            let r = {
154                let product = res.checked_mul(&U256::from_u8(10));
155                if product.is_some().into() {
156                    product.unwrap()
157                } else {
158                    return Err(FromStrError::OutOfRange);
159                }
160            };
161            let r = {
162                let sum = r.checked_add(&U256::from_u8(b));
163                if sum.is_some().into() {
164                    sum.unwrap()
165                } else {
166                    return Err(FromStrError::OutOfRange);
167                }
168            };
169            res = r;
170        }
171
172        Fr::from_bigint(u256_to_biginteger256(&res))
173            .map(|inner| Self { inner })
174            .ok_or(FromStrError::OutOfRange)
175    }
176
177    pub fn from_hex_be(value: &str) -> Result<Self, FromStrError> {
178        let value = value.trim_start_matches("0x");
179
180        let hex_chars_len = value.len();
181        let expected_hex_length = U256_BYTE_COUNT * 2;
182
183        let parsed_bytes: [u8; U256_BYTE_COUNT] = if hex_chars_len == expected_hex_length {
184            let mut buffer = [0u8; U256_BYTE_COUNT];
185            hex::decode_to_slice(value, &mut buffer).map_err(|_| FromStrError::InvalidCharacter)?;
186            buffer
187        } else if hex_chars_len < expected_hex_length {
188            let mut padded_hex = str::repeat("0", expected_hex_length - hex_chars_len);
189            padded_hex.push_str(value);
190
191            let mut buffer = [0u8; U256_BYTE_COUNT];
192            hex::decode_to_slice(&padded_hex, &mut buffer)
193                .map_err(|_| FromStrError::InvalidCharacter)?;
194            buffer
195        } else {
196            return Err(FromStrError::OutOfRange);
197        };
198
199        match Self::from_bytes_be(&parsed_bytes) {
200            Ok(value) => Ok(value),
201            Err(_) => Err(FromStrError::OutOfRange),
202        }
203    }
204
205    /// Attempts to convert a big-endian byte representation of a field element into an element of
206    /// this prime field. Returns error if the input is not canonical (is not smaller than the
207    /// field's modulus).
208    ///
209    /// ### Arguments
210    ///
211    /// * `bytes`: The byte array in **big endian** format
212    pub fn from_bytes_be(bytes: &[u8; 32]) -> Result<Self, FromByteArrayError> {
213        Self::from_byte_slice(bytes).ok_or(FromByteArrayError)
214    }
215
216    /// Same as `from_bytes_be` except this function takes a slice.
217    pub fn from_byte_slice_be(bytes: &[u8]) -> Result<Self, FromByteSliceError> {
218        if bytes.len() > U256_BYTE_COUNT {
219            Err(FromByteSliceError::InvalidLength)
220        } else {
221            let mut buffer = [0u8; U256_BYTE_COUNT];
222            buffer[(U256_BYTE_COUNT - bytes.len())..].copy_from_slice(bytes);
223            Self::from_byte_slice(&buffer).ok_or(FromByteSliceError::OutOfRange)
224        }
225    }
226
227    /// Interprets the field element as a decimal number of a certain decimal places.
228    #[cfg(feature = "bigdecimal")]
229    pub fn to_big_decimal<D: Into<i64>>(&self, decimals: D) -> bigdecimal::BigDecimal {
230        use num_bigint::{BigInt, Sign};
231
232        bigdecimal::BigDecimal::new(
233            BigInt::from_bytes_be(Sign::Plus, &self.to_bytes_be()),
234            decimals.into(),
235        )
236    }
237
238    /// Transforms [FieldElement] into little endian bit representation.
239    pub fn to_bits_le(self) -> [bool; 256] {
240        let mut bits = [false; 256];
241        for (ind_element, element) in self.inner.into_bigint().0.iter().enumerate() {
242            for ind_bit in 0..64 {
243                bits[ind_element * 64 + ind_bit] = (element >> ind_bit) & 1 == 1;
244            }
245        }
246
247        bits
248    }
249
250    /// Convert the field element into a big-endian byte representation
251    pub fn to_bytes_be(&self) -> [u8; 32] {
252        let mut buffer = [0u8; 32];
253        buffer.copy_from_slice(&self.inner.into_bigint().to_bytes_be());
254
255        buffer
256    }
257
258    /// Transforms [FieldElement] into its Montgomery representation
259    pub const fn into_mont(self) -> [u64; 4] {
260        self.inner.0 .0
261    }
262
263    pub fn invert(&self) -> Option<FieldElement> {
264        self.inner.inverse().map(|inner| Self { inner })
265    }
266
267    pub fn sqrt(&self) -> Option<FieldElement> {
268        self.inner.sqrt().map(|inner| Self { inner })
269    }
270
271    pub fn double(&self) -> FieldElement {
272        *self + *self
273    }
274
275    /// Performs a floor division. It's not implemented as the `Div` trait on purpose to
276    /// distinguish from the "felt division".
277    pub fn floor_div(&self, rhs: FieldElement) -> FieldElement {
278        let lhs: U256 = self.into();
279        let rhs: U256 = (&rhs).into();
280        let is_rhs_zero: bool = rhs.is_zero().into();
281
282        if !is_rhs_zero {
283            let rhs = NonZero::from_uint(rhs);
284
285            let div_result = lhs.div_rem(&rhs);
286            let (quotient, _) = div_result;
287
288            // It's safe to unwrap here since `rem` is never out of range
289            FieldElement {
290                inner: Fr::from_bigint(u256_to_biginteger256(&quotient)).unwrap(),
291            }
292        } else {
293            // TODO: add `checked_floor_div` for panic-less use
294            panic!("division by zero");
295        }
296    }
297
298    /// For internal use only. The input must be of length [U256_BYTE_COUNT].
299    fn from_byte_slice(bytes: &[u8]) -> Option<Self> {
300        let mut bits = [false; U256_BYTE_COUNT * 8];
301        for (ind_byte, byte) in bytes.iter().enumerate() {
302            for ind_bit in 0..8 {
303                bits[ind_byte * 8 + ind_bit] = (byte >> (7 - ind_bit)) & 1 == 1;
304            }
305        }
306
307        // No need to check range as `from_bigint` already does that
308        let big_int = BigInteger256::from_bits_be(&bits);
309        Fr::from_bigint(big_int).map(|inner| Self { inner })
310    }
311}
312
313impl Default for FieldElement {
314    fn default() -> Self {
315        Self::ZERO
316    }
317}
318
319impl AsRef<FieldElement> for FieldElement {
320    fn as_ref(&self) -> &FieldElement {
321        self
322    }
323}
324
325impl ops::Add<FieldElement> for FieldElement {
326    type Output = FieldElement;
327
328    fn add(self, rhs: FieldElement) -> Self::Output {
329        FieldElement {
330            inner: self.inner + rhs.inner,
331        }
332    }
333}
334
335impl ops::AddAssign<FieldElement> for FieldElement {
336    fn add_assign(&mut self, rhs: FieldElement) {
337        self.inner = self.inner + rhs.inner;
338    }
339}
340
341impl ops::Sub<FieldElement> for FieldElement {
342    type Output = FieldElement;
343
344    fn sub(self, rhs: FieldElement) -> Self::Output {
345        FieldElement {
346            inner: self.inner - rhs.inner,
347        }
348    }
349}
350
351impl ops::SubAssign<FieldElement> for FieldElement {
352    fn sub_assign(&mut self, rhs: FieldElement) {
353        self.inner = self.inner - rhs.inner;
354    }
355}
356
357impl ops::Mul<FieldElement> for FieldElement {
358    type Output = FieldElement;
359
360    fn mul(self, rhs: FieldElement) -> Self::Output {
361        FieldElement {
362            inner: self.inner * rhs.inner,
363        }
364    }
365}
366
367impl ops::MulAssign<FieldElement> for FieldElement {
368    fn mul_assign(&mut self, rhs: FieldElement) {
369        self.inner = self.inner * rhs.inner;
370    }
371}
372
373impl ops::Neg for FieldElement {
374    type Output = FieldElement;
375
376    fn neg(self) -> Self::Output {
377        FieldElement { inner: -self.inner }
378    }
379}
380
381impl ops::Rem<FieldElement> for FieldElement {
382    type Output = FieldElement;
383
384    fn rem(self, rhs: FieldElement) -> Self::Output {
385        if self.inner < rhs.inner {
386            return self;
387        }
388
389        let lhs: U256 = (&self).into();
390        let rhs: U256 = (&rhs).into();
391        let is_rhs_zero: bool = rhs.is_zero().into();
392
393        if !is_rhs_zero {
394            let rhs = NonZero::from_uint(rhs);
395
396            let (_, rem) = lhs.div_rem(&rhs);
397
398            // It's safe to unwrap here since `rem` is never out of range
399            FieldElement {
400                inner: Fr::from_bigint(u256_to_biginteger256(&rem)).unwrap(),
401            }
402        } else {
403            // TODO: add `checked_rem` for panic-less use
404            panic!("division by zero");
405        }
406    }
407}
408
409impl ops::BitAnd<FieldElement> for FieldElement {
410    type Output = FieldElement;
411
412    fn bitand(self, rhs: FieldElement) -> Self::Output {
413        let lhs: U256 = (&self).into();
414        let rhs: U256 = (&rhs).into();
415
416        // It's safe to unwrap here since the result is never out of range
417        FieldElement {
418            inner: Fr::from_bigint(u256_to_biginteger256(&(lhs & rhs))).unwrap(),
419        }
420    }
421}
422
423impl ops::BitOr<FieldElement> for FieldElement {
424    type Output = FieldElement;
425
426    fn bitor(self, rhs: FieldElement) -> Self::Output {
427        let lhs: U256 = (&self).into();
428        let rhs: U256 = (&rhs).into();
429
430        // It's safe to unwrap here since the result is never out of range
431        FieldElement {
432            inner: Fr::from_bigint(u256_to_biginteger256(&(lhs | rhs))).unwrap(),
433        }
434    }
435}
436
437impl core::iter::Sum for FieldElement {
438    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
439        let mut sum = Self::ZERO;
440        iter.for_each(|item| {
441            sum += item;
442        });
443        sum
444    }
445}
446
447impl<'a> core::iter::Sum<&'a FieldElement> for FieldElement {
448    fn sum<I: Iterator<Item = &'a FieldElement>>(iter: I) -> Self {
449        iter.copied().sum()
450    }
451}
452
453impl fmt::Debug for FieldElement {
454    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
455        f.debug_struct("FieldElement")
456            .field("inner", &InnerDebug(self))
457            .finish()
458    }
459}
460
461impl fmt::Display for FieldElement {
462    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
463        // Ported from:
464        //   https://github.com/paritytech/parity-common/blob/b37d0b312d39fa47c61c4430b30ca87d90e45a08/uint/src/uint.rs#L1650
465
466        let repr: U256 = self.into();
467
468        if repr.is_zero().into() {
469            return write!(f, "0");
470        }
471
472        let mut buf = [0u8; 4 * 20];
473        let mut i = buf.len() - 1;
474        let mut current = repr;
475        let ten = U256::from_u8(10u8);
476
477        loop {
478            let digit = if current < ten {
479                current.to_words()[0] as u8
480            } else {
481                (current.checked_rem(&ten)).unwrap().to_words()[0] as u8
482            };
483            buf[i] = digit + b'0';
484            current = current.checked_div(&ten).unwrap();
485            if current.is_zero().into() {
486                break;
487            }
488            i -= 1;
489        }
490
491        // sequence of `'0'..'9'` chars is guaranteed to be a valid UTF8 string
492        let s = unsafe { str::from_utf8_unchecked(&buf[i..]) };
493        f.pad_integral(true, "", s)
494    }
495}
496
497impl fmt::LowerHex for FieldElement {
498    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
499        let repr: U256 = self.into();
500
501        let width = if f.sign_aware_zero_pad() {
502            f.width().unwrap().min(64)
503        } else {
504            1
505        };
506        if f.alternate() {
507            write!(f, "0x")?;
508        }
509        let mut latch = false;
510        let mut ind_nibble = 0;
511        for ch in u256_to_u64_array(&repr).iter().rev() {
512            for x in 0..16 {
513                let nibble = (ch & (15u64 << ((15 - x) * 4) as u64)) >> (((15 - x) * 4) as u64);
514                if !latch {
515                    latch = nibble != 0 || (64 - ind_nibble <= width);
516                }
517                if latch {
518                    write!(f, "{nibble:x}")?;
519                }
520                ind_nibble += 1;
521            }
522        }
523        Ok(())
524    }
525}
526
527impl fmt::UpperHex for FieldElement {
528    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
529        let repr: U256 = self.into();
530
531        let width = if f.sign_aware_zero_pad() {
532            f.width().unwrap().min(64)
533        } else {
534            1
535        };
536        if f.alternate() {
537            write!(f, "0x")?;
538        }
539        let mut latch = false;
540        let mut ind_nibble = 0;
541        for ch in u256_to_u64_array(&repr).iter().rev() {
542            for x in 0..16 {
543                let nibble = (ch & (15u64 << ((15 - x) * 4) as u64)) >> (((15 - x) * 4) as u64);
544                if !latch {
545                    latch = nibble != 0 || (64 - ind_nibble <= width);
546                }
547                if latch {
548                    write!(f, "{nibble:X}")?;
549                }
550                ind_nibble += 1;
551            }
552        }
553        Ok(())
554    }
555}
556
557#[cfg(feature = "serde")]
558mod serde_field_element {
559    #[cfg(feature = "std")]
560    use core::fmt::{Formatter, Result as FmtResult};
561
562    use super::*;
563    #[cfg(not(feature = "std"))]
564    use alloc::{
565        fmt::{Formatter, Result as FmtResult},
566        string::ToString,
567    };
568    use serde::{de::Visitor, Deserialize, Serialize};
569
570    struct FieldElementVisitor;
571
572    impl Serialize for FieldElement {
573        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
574        where
575            S: serde::Serializer,
576        {
577            serializer.serialize_str(&ToString::to_string(&self))
578        }
579    }
580
581    impl<'de> Deserialize<'de> for FieldElement {
582        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
583        where
584            D: serde::Deserializer<'de>,
585        {
586            deserializer.deserialize_str(FieldElementVisitor)
587        }
588    }
589
590    impl<'de> Visitor<'de> for FieldElementVisitor {
591        type Value = FieldElement;
592
593        fn expecting(&self, formatter: &mut Formatter) -> FmtResult {
594            write!(formatter, "string")
595        }
596
597        fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
598        where
599            E: serde::de::Error,
600        {
601            FieldElement::from_str(v).map_err(serde::de::Error::custom)
602        }
603    }
604}
605
606impl From<u8> for FieldElement {
607    fn from(value: u8) -> Self {
608        Self {
609            inner: Fr::from_bigint(BigInteger256::new([value as u64, 0, 0, 0])).unwrap(),
610        }
611    }
612}
613
614impl From<u16> for FieldElement {
615    fn from(value: u16) -> Self {
616        Self {
617            inner: Fr::from_bigint(BigInteger256::new([value as u64, 0, 0, 0])).unwrap(),
618        }
619    }
620}
621
622impl From<u32> for FieldElement {
623    fn from(value: u32) -> Self {
624        Self {
625            inner: Fr::from_bigint(BigInteger256::new([value as u64, 0, 0, 0])).unwrap(),
626        }
627    }
628}
629
630impl From<u64> for FieldElement {
631    fn from(value: u64) -> Self {
632        Self {
633            inner: Fr::from_bigint(BigInteger256::new([value, 0, 0, 0])).unwrap(),
634        }
635    }
636}
637
638impl From<u128> for FieldElement {
639    fn from(value: u128) -> Self {
640        let low = value % (u64::MAX as u128 + 1);
641        let high = value / (u64::MAX as u128 + 1);
642
643        Self {
644            inner: Fr::from_bigint(BigInteger256::new([low as u64, high as u64, 0, 0])).unwrap(),
645        }
646    }
647}
648
649impl From<usize> for FieldElement {
650    fn from(value: usize) -> Self {
651        Self {
652            inner: Fr::from_bigint(BigInteger256::new([value as u64, 0, 0, 0])).unwrap(),
653        }
654    }
655}
656
657impl FromStr for FieldElement {
658    type Err = FromStrError;
659
660    fn from_str(s: &str) -> Result<Self, Self::Err> {
661        if s.starts_with("0x") {
662            FieldElement::from_hex_be(s)
663        } else {
664            FieldElement::from_dec_str(s)
665        }
666    }
667}
668
669impl TryFrom<FieldElement> for u8 {
670    type Error = ValueOutOfRangeError;
671
672    fn try_from(value: FieldElement) -> Result<Self, Self::Error> {
673        let repr = value.inner.into_bigint().0;
674        if repr[0] > u8::MAX as u64 || repr[1] > 0 || repr[2] > 0 || repr[3] > 0 {
675            Err(ValueOutOfRangeError)
676        } else {
677            Ok(repr[0] as u8)
678        }
679    }
680}
681
682impl TryFrom<FieldElement> for u16 {
683    type Error = ValueOutOfRangeError;
684
685    fn try_from(value: FieldElement) -> Result<Self, Self::Error> {
686        let repr = value.inner.into_bigint().0;
687        if repr[0] > u16::MAX as u64 || repr[1] > 0 || repr[2] > 0 || repr[3] > 0 {
688            Err(ValueOutOfRangeError)
689        } else {
690            Ok(repr[0] as u16)
691        }
692    }
693}
694
695impl TryFrom<FieldElement> for u32 {
696    type Error = ValueOutOfRangeError;
697
698    fn try_from(value: FieldElement) -> Result<Self, Self::Error> {
699        let repr = value.inner.into_bigint().0;
700        if repr[0] > u32::MAX as u64 || repr[1] > 0 || repr[2] > 0 || repr[3] > 0 {
701            Err(ValueOutOfRangeError)
702        } else {
703            Ok(repr[0] as u32)
704        }
705    }
706}
707
708impl TryFrom<FieldElement> for u64 {
709    type Error = ValueOutOfRangeError;
710
711    fn try_from(value: FieldElement) -> Result<Self, Self::Error> {
712        let repr = value.inner.into_bigint().0;
713        if repr[1] > 0 || repr[2] > 0 || repr[3] > 0 {
714            Err(ValueOutOfRangeError)
715        } else {
716            Ok(repr[0])
717        }
718    }
719}
720
721impl TryFrom<FieldElement> for u128 {
722    type Error = ValueOutOfRangeError;
723
724    fn try_from(value: FieldElement) -> Result<Self, Self::Error> {
725        let repr = value.inner.into_bigint().0;
726        if repr[2] > 0 || repr[3] > 0 {
727            Err(ValueOutOfRangeError)
728        } else {
729            Ok((repr[0] as u128) + (repr[1] as u128) * (u64::MAX as u128 + 1))
730        }
731    }
732}
733
734impl From<&FieldElement> for U256 {
735    #[cfg(target_pointer_width = "64")]
736    fn from(value: &FieldElement) -> Self {
737        U256::from_words(value.inner.into_bigint().0)
738    }
739
740    #[cfg(target_pointer_width = "32")]
741    fn from(value: &FieldElement) -> Self {
742        U256::from_words(unsafe {
743            core::mem::transmute::<[u64; 4], [u32; 8]>(value.inner.into_bigint().0)
744        })
745    }
746}
747
748impl<'a> fmt::Debug for InnerDebug<'a> {
749    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
750        write!(f, "{:#064x}", self.0)
751    }
752}
753
754#[inline]
755fn u256_to_biginteger256(num: &U256) -> BigInteger256 {
756    BigInteger256::new(u256_to_u64_array(num))
757}
758
759#[cfg(target_pointer_width = "64")]
760#[inline]
761fn u256_to_u64_array(num: &U256) -> [u64; 4] {
762    num.to_words()
763}
764
765#[cfg(target_pointer_width = "32")]
766#[inline]
767fn u256_to_u64_array(num: &U256) -> [u64; 4] {
768    unsafe { core::mem::transmute::<[u32; 8], [u64; 4]>(num.to_words()) }
769}
770
771#[cfg(test)]
772mod tests {
773    use super::*;
774
775    #[test]
776    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
777    fn test_default_value() {
778        assert_eq!(FieldElement::default(), FieldElement::ZERO)
779    }
780
781    #[test]
782    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
783    fn test_dec_fmt() {
784        let nums = [
785            "0",
786            "1",
787            "10",
788            "11",
789            "3618502788666131213697322783095070105623107215331596699973092056135872020480",
790        ];
791
792        for num in nums.iter() {
793            assert_eq!(
794                &format!("{}", FieldElement::from_dec_str(num).unwrap()),
795                num
796            );
797        }
798    }
799
800    #[test]
801    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
802    fn test_zero_padded_hex_fmt() {
803        let fe = FieldElement::from_hex_be("0x1234abcd").unwrap();
804
805        assert_eq!(format!("{fe:011x}"), "0001234abcd");
806        assert_eq!(format!("{fe:011X}"), "0001234ABCD");
807        assert_eq!(format!("{fe:08x}"), "1234abcd");
808        assert_eq!(format!("{fe:06x}"), "1234abcd");
809        assert_eq!(format!("{fe:#x}"), "0x1234abcd");
810        assert_eq!(
811            format!("{fe:#064x}"),
812            "0x000000000000000000000000000000000000000000000000000000001234abcd"
813        );
814
815        // Ignore if requesting more than 64 nibbles (or should we not?)
816        assert_eq!(
817            format!("{fe:#0100x}"),
818            "0x000000000000000000000000000000000000000000000000000000001234abcd"
819        );
820    }
821
822    #[test]
823    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
824    fn test_addition() {
825        let additions = [
826            ["1", "1", "2"],
827            [
828                "3618502788666131213697322783095070105623107215331596699973092056135872020480",
829                "1",
830                "0",
831            ],
832        ];
833
834        for item in additions.iter() {
835            let mut lhs = FieldElement::from_dec_str(item[0]).unwrap();
836            let rhs = FieldElement::from_dec_str(item[1]).unwrap();
837            let result = FieldElement::from_dec_str(item[2]).unwrap();
838            assert_eq!(lhs + rhs, result);
839
840            lhs += rhs;
841            assert_eq!(lhs, result);
842        }
843    }
844
845    #[test]
846    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
847    fn test_subtraction() {
848        let subtractions = [
849            ["10", "7", "3"],
850            [
851                "0",
852                "3618502788666131213697322783095070105623107215331596699973092056135872020480",
853                "1",
854            ],
855        ];
856
857        for item in subtractions.iter() {
858            let mut lhs = FieldElement::from_dec_str(item[0]).unwrap();
859            let rhs = FieldElement::from_dec_str(item[1]).unwrap();
860            let result = FieldElement::from_dec_str(item[2]).unwrap();
861            assert_eq!(lhs - rhs, result);
862
863            lhs -= rhs;
864            assert_eq!(lhs, result);
865        }
866    }
867
868    #[test]
869    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
870    fn test_multiplication() {
871        let multiplications = [
872            ["2", "3", "6"],
873            [
874                "3618502788666131213697322783095070105623107215331596699973092056135872020480",
875                "3618502788666131213697322783095070105623107215331596699973092056135872020480",
876                "1",
877            ],
878            [
879                "3141592653589793238462643383279502884197169399375105820974944592307",
880                "8164062862089986280348253421170679821480865132823066470938446095505",
881                "514834056922159274131066670130609582664841480950767778400381816737396274242",
882            ],
883        ];
884
885        for item in multiplications.iter() {
886            let mut lhs = FieldElement::from_dec_str(item[0]).unwrap();
887            let rhs = FieldElement::from_dec_str(item[1]).unwrap();
888            let result = FieldElement::from_dec_str(item[2]).unwrap();
889            assert_eq!(lhs * rhs, result);
890
891            lhs *= rhs;
892            assert_eq!(lhs, result);
893        }
894    }
895
896    #[test]
897    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
898    fn test_remainder() {
899        let remainders = [["123456", "100", "56"], ["7", "3", "1"], ["3", "6", "3"]];
900
901        for item in remainders.iter() {
902            assert_eq!(
903                FieldElement::from_dec_str(item[0]).unwrap()
904                    % FieldElement::from_dec_str(item[1]).unwrap(),
905                FieldElement::from_dec_str(item[2]).unwrap()
906            );
907        }
908    }
909
910    #[test]
911    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
912    fn test_bitwise_and() {
913        let operands = [[123456_u64, 567890], [613221132151, 4523451]];
914
915        for item in operands.iter() {
916            let lhs: FieldElement = item[0].into();
917            let rhs: FieldElement = item[1].into();
918            assert_eq!(lhs & rhs, (item[0] & item[1]).into());
919        }
920    }
921
922    #[test]
923    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
924    fn test_bitwise_or() {
925        let operands = [[123456_u64, 567890], [613221132151, 4523451]];
926
927        for item in operands.iter() {
928            let lhs: FieldElement = item[0].into();
929            let rhs: FieldElement = item[1].into();
930            assert_eq!(lhs | rhs, (item[0] | item[1]).into());
931        }
932    }
933
934    #[test]
935    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
936    fn test_iter_sum() {
937        let elements = [FieldElement::ONE, FieldElement::TWO, FieldElement::THREE];
938
939        assert_eq!(
940            elements.iter().sum::<FieldElement>(),
941            FieldElement::from_dec_str("6").unwrap()
942        );
943        assert_eq!(
944            elements.into_iter().sum::<FieldElement>(),
945            FieldElement::from_dec_str("6").unwrap()
946        );
947    }
948
949    #[test]
950    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
951    fn test_floor_division() {
952        let quotients = [["123456", "100", "1234"], ["7", "3", "2"], ["3", "6", "0"]];
953
954        for item in quotients.iter() {
955            assert_eq!(
956                FieldElement::from_dec_str(item[0])
957                    .unwrap()
958                    .floor_div(FieldElement::from_dec_str(item[1]).unwrap()),
959                FieldElement::from_dec_str(item[2]).unwrap()
960            );
961        }
962    }
963
964    #[test]
965    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
966    fn test_to_primitives() {
967        let fe_256: FieldElement = 256u16.into();
968
969        if u8::try_from(fe_256).is_ok() {
970            panic!("invalid conversion");
971        }
972
973        assert_eq!(u16::try_from(fe_256).unwrap(), 256u16);
974        assert_eq!(u32::try_from(fe_256).unwrap(), 256u32);
975        assert_eq!(u64::try_from(fe_256).unwrap(), 256u64);
976    }
977
978    #[test]
979    #[cfg(feature = "bigdecimal")]
980    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
981    fn test_to_big_decimal() {
982        use bigdecimal::{BigDecimal, Num};
983
984        let nums = [
985            (
986                "134500",
987                5,
988                BigDecimal::from_str_radix("1.345", 10).unwrap(),
989            ),
990            (
991                "134500",
992                0,
993                BigDecimal::from_str_radix("134500", 10).unwrap(),
994            ),
995            (
996                "134500",
997                10,
998                BigDecimal::from_str_radix("0.00001345", 10).unwrap(),
999            ),
1000        ];
1001
1002        for num in nums.into_iter() {
1003            assert_eq!(
1004                FieldElement::from_dec_str(num.0)
1005                    .unwrap()
1006                    .to_big_decimal(num.1),
1007                num.2
1008            );
1009        }
1010    }
1011
1012    #[test]
1013    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
1014    fn test_from_str() {
1015        let nums = [
1016            ("134500", "0x20d64"),
1017            ("9999999999999999", "0x2386f26fc0ffff"),
1018        ];
1019
1020        for num in nums.into_iter() {
1021            assert_eq!(
1022                num.0.parse::<FieldElement>().unwrap(),
1023                num.1.parse::<FieldElement>().unwrap(),
1024            );
1025        }
1026    }
1027
1028    #[test]
1029    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
1030    fn test_from_byte_slice_be() {
1031        let nums = [("25800", [100u8, 200u8])];
1032
1033        for num in nums.into_iter() {
1034            assert_eq!(
1035                num.0.parse::<FieldElement>().unwrap(),
1036                FieldElement::from_byte_slice_be(&num.1).unwrap()
1037            );
1038        }
1039    }
1040
1041    #[test]
1042    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
1043    fn test_u8_conversion() {
1044        let nums = [u8::MAX, u8::MAX / 3 * 2, u8::MAX / 3];
1045
1046        for num in nums.into_iter() {
1047            let felt: FieldElement = num.into();
1048            assert_eq!(format!("{}", felt), format!("{}", num));
1049
1050            let back_to_num: u8 = felt.try_into().unwrap();
1051            assert_eq!(num, back_to_num);
1052        }
1053    }
1054
1055    #[test]
1056    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
1057    fn test_u16_conversion() {
1058        let nums = [u16::MAX, u16::MAX / 3 * 2, u16::MAX / 3];
1059
1060        for num in nums.into_iter() {
1061            let felt: FieldElement = num.into();
1062            assert_eq!(format!("{}", felt), format!("{}", num));
1063
1064            let back_to_num: u16 = felt.try_into().unwrap();
1065            assert_eq!(num, back_to_num);
1066        }
1067    }
1068
1069    #[test]
1070    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
1071    fn test_u32_conversion() {
1072        let nums = [u32::MAX, u32::MAX / 3 * 2, u32::MAX / 3];
1073
1074        for num in nums.into_iter() {
1075            let felt: FieldElement = num.into();
1076            assert_eq!(format!("{}", felt), format!("{}", num));
1077
1078            let back_to_num: u32 = felt.try_into().unwrap();
1079            assert_eq!(num, back_to_num);
1080        }
1081    }
1082
1083    #[test]
1084    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
1085    fn test_u64_conversion() {
1086        let nums = [u64::MAX, u64::MAX / 3 * 2, u64::MAX / 3];
1087
1088        for num in nums.into_iter() {
1089            let felt: FieldElement = num.into();
1090            assert_eq!(format!("{}", felt), format!("{}", num));
1091
1092            let back_to_num: u64 = felt.try_into().unwrap();
1093            assert_eq!(num, back_to_num);
1094        }
1095    }
1096
1097    #[test]
1098    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
1099    fn test_u128_conversion() {
1100        let nums = [u128::MAX, u128::MAX / 3 * 2, u128::MAX / 3];
1101
1102        for num in nums.into_iter() {
1103            let felt: FieldElement = num.into();
1104            assert_eq!(format!("{}", felt), format!("{}", num));
1105
1106            let back_to_num: u128 = felt.try_into().unwrap();
1107            assert_eq!(num, back_to_num);
1108        }
1109    }
1110}