openzeppelin_crypto/field/
fp.rs

1//! This module contains the implementation of a prime field element [`Fp`],
2//! altogether with exact implementations [`Fp64`] for 64-bit, [`Fp128`] for
3//! 128-bit elements and so on.
4//!
5//! Finite field element [`Fp`] wraps a biginteger element in [motgomery form],
6//! which is used for efficient multiplication and division.
7//!
8//! Note that implementation of `Ord` for [`Fp`] compares field elements viewing
9//! them as integers in the range `0, 1, ..., P::MODULUS - 1`.
10//! However, other implementations of `PrimeField` might choose a different
11//! ordering, and as such, users should use this `Ord` for applications where
12//! any ordering suffices (like in a `BTreeMap`), and not in applications
13//! where a particular ordering is required.
14//!
15//! [motgomery form]: https://en.wikipedia.org/wiki/Montgomery_modular_multiplication
16use alloc::string::ToString;
17use core::{
18    cmp::Ordering,
19    fmt::{Debug, Display, Formatter},
20    iter::{Product, Sum},
21    marker::PhantomData,
22    ops::{
23        Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign,
24    },
25};
26
27use educe::Educe;
28use num_traits::{One, Zero};
29
30use crate::{
31    arithmetic::{
32        limb,
33        uint::{Uint, WideUint},
34        BigInteger,
35    },
36    const_for, const_for_unroll6,
37    field::{group::AdditiveGroup, prime::PrimeField, Field},
38};
39
40/// A trait that specifies the configuration of a prime field.
41/// Also specifies how to perform arithmetic on field elements.
42pub trait FpParams<const N: usize>: Send + Sync + 'static + Sized {
43    /// The modulus of the field.
44    const MODULUS: Uint<N>;
45
46    /// A multiplicative generator of the field.
47    /// [`Self::GENERATOR`] is an element having multiplicative order
48    /// `MODULUS - 1`.
49    const GENERATOR: Fp<Self, N>;
50
51    /// `MODULUS` has a spare bit in the most significant limb.
52    const HAS_MODULUS_SPARE_BIT: bool = Self::MODULUS.limbs[N - 1] >> 63 == 0;
53
54    /// `INV = -MODULUS^{-1} mod 2^64`
55    const INV: u64 = inv::<Self, N>();
56
57    /// Let `M` be the power of 2^64 nearest to [`Self::MODULUS`] size.
58    ///
59    /// Then `R = M % MODULUS` or `R = (M - 1) % MODULUS + 1` for convenience of
60    /// multiplication.
61    const R: Uint<N> = WideUint::new(Uint::<N>::MAX, Uint::<N>::ZERO)
62        .rem(&Self::MODULUS)
63        .wrapping_add(&Uint::ONE);
64
65    /// `R2 = R^2 % MODULUS` or `R2 = (R^2 - 1) % MODULUS + 1` for convenience
66    /// of multiplication.
67    const R2: Uint<N> = WideUint::new(Uint::<N>::MAX, Uint::<N>::MAX)
68        .rem(&Self::MODULUS)
69        .wrapping_add(&Uint::ONE);
70
71    /// Set `a += b`.
72    #[inline(always)]
73    fn add_assign(a: &mut Fp<Self, N>, b: &Fp<Self, N>) {
74        // This cannot exceed the backing capacity.
75        let c = a.montgomery_form.checked_add_assign(&b.montgomery_form);
76        // However, it may need to be reduced
77        if Self::HAS_MODULUS_SPARE_BIT {
78            *a = a.subtract_modulus();
79        } else {
80            *a = a.carrying_sub_modulus(c);
81        }
82    }
83
84    /// Set `a -= b`.
85    #[inline(always)]
86    fn sub_assign(a: &mut Fp<Self, N>, b: &Fp<Self, N>) {
87        // If `other` is larger than `self`, add the modulus to `self` first.
88        if b.montgomery_form > a.montgomery_form {
89            a.montgomery_form.checked_add_assign(&Self::MODULUS);
90        }
91        a.montgomery_form.checked_sub_assign(&b.montgomery_form);
92    }
93
94    /// Set `a = a + a`.
95    #[inline(always)]
96    fn double_in_place(a: &mut Fp<Self, N>) {
97        // This cannot exceed the backing capacity.
98        let c = a.montgomery_form.checked_mul2_assign();
99        // However, it may need to be reduced.
100        if Self::HAS_MODULUS_SPARE_BIT {
101            *a = a.subtract_modulus();
102        } else {
103            *a = a.carrying_sub_modulus(c);
104        }
105    }
106
107    /// Set `a = -a`;
108    #[inline(always)]
109    fn neg_in_place(a: &mut Fp<Self, N>) {
110        if !a.is_zero() {
111            let mut tmp = Self::MODULUS;
112            tmp.checked_sub_assign(&a.montgomery_form);
113            a.montgomery_form = tmp;
114        }
115    }
116
117    /// Set `a *= b`.
118    ///
119    /// This modular multiplication algorithm uses Montgomery
120    /// reduction for efficient implementation.
121    #[inline(always)]
122    fn mul_assign(a: &mut Fp<Self, N>, b: &Fp<Self, N>) {
123        *a = Fp::<Self, N>::mul(a, b);
124    }
125
126    /// Set `a *= a`.
127    #[inline(always)]
128    fn square_in_place(a: &mut Fp<Self, N>) {
129        *a = Fp::<Self, N>::mul(a, a);
130    }
131
132    /// Compute `a^{-1}` if `a` is not zero.
133    ///
134    /// Guajardo, Kumar, Paar, Pelzl.
135    /// Efficient Software-Implementation of Finite Fields with Applications to
136    /// Cryptography [reference].
137    /// Algorithm 16 (BEA for Inversion in Fp).
138    ///
139    /// [reference]: https://www.sandeep.de/my/papers/2006_ActaApplMath_EfficientSoftFiniteF.pdf
140    #[must_use]
141    #[inline(always)]
142    fn inverse(a: &Fp<Self, N>) -> Option<Fp<Self, N>> {
143        if a.is_zero() {
144            return None;
145        }
146
147        let one = Uint::ONE;
148
149        let mut u = a.montgomery_form;
150        let mut v = Self::MODULUS;
151        let mut b = Fp::new_unchecked(Self::R2); // Avoids unnecessary reduction step.
152        let mut c = Fp::zero();
153
154        while u != one && v != one {
155            while u.is_even() {
156                u.div2_assign();
157
158                if b.montgomery_form.is_even() {
159                    b.montgomery_form.div2_assign();
160                } else {
161                    let carry =
162                        b.montgomery_form.checked_add_assign(&Self::MODULUS);
163                    b.montgomery_form.div2_assign();
164                    if !Self::HAS_MODULUS_SPARE_BIT && carry {
165                        b.montgomery_form.limbs[N - 1] |= 1 << 63;
166                    }
167                }
168            }
169
170            while v.is_even() {
171                v.div2_assign();
172
173                if c.montgomery_form.is_even() {
174                    c.montgomery_form.div2_assign();
175                } else {
176                    let carry =
177                        c.montgomery_form.checked_add_assign(&Self::MODULUS);
178                    c.montgomery_form.div2_assign();
179                    if !Self::HAS_MODULUS_SPARE_BIT && carry {
180                        c.montgomery_form.limbs[N - 1] |= 1 << 63;
181                    }
182                }
183            }
184
185            if v < u {
186                u.checked_sub_assign(&v);
187                b -= &c;
188            } else {
189                v.checked_sub_assign(&u);
190                c -= &b;
191            }
192        }
193
194        if u == one {
195            Some(b)
196        } else {
197            Some(c)
198        }
199    }
200
201    /// Construct a field element from an integer.
202    ///
203    /// By the end element will be converted to a montgomery form and reduced.
204    #[must_use]
205    #[inline(always)]
206    fn from_bigint(num: Uint<N>) -> Fp<Self, N> {
207        Fp::<Self, N>::from_bigint(num)
208    }
209
210    /// Convert a field element to an integer less than [`Self::MODULUS`].
211    #[must_use]
212    #[inline(always)]
213    fn into_bigint(elem: Fp<Self, N>) -> Uint<N> {
214        elem.into_bigint()
215    }
216}
217
218/// Compute `-M^{-1} mod 2^64`.
219#[must_use]
220pub const fn inv<T: FpParams<N>, const N: usize>() -> u64 {
221    // We compute this as follows.
222    // First, MODULUS mod 2^64 is just the lower 64 bits of MODULUS.
223    // Hence MODULUS mod 2^64 = MODULUS.0[0] mod 2^64.
224    //
225    // Next, computing the inverse mod 2^64 involves exponentiating by
226    // the multiplicative group order, which is euler_totient(2^64) - 1.
227    // Now, euler_totient(2^64) = 1 << 63, and so
228    // euler_totient(2^64) - 1 = (1 << 63) - 1 = 1111111... (63 digits).
229    // We compute this powering via standard square and multiply.
230    let mut inv = 1u64;
231    const_for!((_i in 0..63) {
232        // Square
233        inv = inv.wrapping_mul(inv);
234        // Multiply
235        inv = inv.wrapping_mul(T::MODULUS.limbs[0]);
236    });
237    inv.wrapping_neg()
238}
239
240/// Represents an element of the prime field `F_p`, where `p == P::MODULUS`.
241///
242/// This type can represent elements in any field of size at most N * 64 bits.
243#[derive(Educe)]
244#[educe(Default, Clone, Copy, PartialEq, Eq, Hash)]
245pub struct Fp<P: FpParams<N>, const N: usize> {
246    /// Contains the element in Montgomery form for efficient multiplication.
247    /// To convert an element to a [`Uint`], use [`FpParams::into_bigint`]
248    /// or `into`.
249    montgomery_form: Uint<N>,
250    #[doc(hidden)]
251    phantom: PhantomData<P>,
252}
253
254/// Declare [`Fp`] types for different bit sizes.
255macro_rules! declare_fp {
256    ($fp:ident, $limbs:ident, $bits:expr) => {
257        #[doc = "Finite field with max"]
258        #[doc = stringify!($bits)]
259        #[doc = "bits size element."]
260        pub type $fp<P> = $crate::field::fp::Fp<
261            P,
262            {
263                usize::div_ceil(
264                    $bits,
265                    $crate::arithmetic::limb::Limb::BITS as usize,
266                )
267            },
268        >;
269
270        #[doc = "Number of limbs in the field with"]
271        #[doc = stringify!($bits)]
272        #[doc = "bits size element."]
273        pub const $limbs: usize = usize::div_ceil(
274            $bits,
275            $crate::arithmetic::limb::Limb::BITS as usize,
276        );
277    };
278}
279
280declare_fp!(Fp64, LIMBS_64, 64);
281declare_fp!(Fp128, LIMBS_128, 128);
282declare_fp!(Fp192, LIMBS_192, 192);
283declare_fp!(Fp256, LIMBS_256, 256);
284declare_fp!(Fp320, LIMBS_320, 320);
285declare_fp!(Fp384, LIMBS_384, 384);
286declare_fp!(Fp448, LIMBS_448, 448);
287declare_fp!(Fp512, LIMBS_512, 512);
288declare_fp!(Fp576, LIMBS_576, 576);
289declare_fp!(Fp640, LIMBS_640, 640);
290declare_fp!(Fp704, LIMBS_704, 704);
291declare_fp!(Fp768, LIMBS_768, 768);
292declare_fp!(Fp832, LIMBS_832, 832);
293
294impl<P: FpParams<N>, const N: usize> Fp<P, N> {
295    /// A multiplicative generator of the field.
296    /// [`Self::GENERATOR`] is an element having multiplicative order
297    /// `MODULUS - 1`.
298    ///
299    /// Every element of the field should be represented as `GENERATOR^i`
300    pub const GENERATOR: Fp<P, N> = P::GENERATOR;
301    /// Multiplicative identity of the field, i.e., the element `e`
302    /// such that, for all elements `f` of the field, `e * f = f`.
303    pub const ONE: Fp<P, N> = Fp::new_unchecked(P::R);
304    /// Additive identity of the field, i.e., the element `e`
305    /// such that, for all elements `f` of the field, `e + f = f`.
306    pub const ZERO: Fp<P, N> = Fp::new_unchecked(Uint { limbs: [0; N] });
307
308    /// Construct a new field element from [`Uint`].
309    ///
310    /// Unlike [`Self::new`], this method does not perform Montgomery reduction.
311    /// This method should be used only when constructing an element from an
312    /// integer that has already been put in Montgomery form.
313    #[must_use]
314    #[inline(always)]
315    pub const fn new_unchecked(element: Uint<N>) -> Self {
316        Self { montgomery_form: element, phantom: PhantomData }
317    }
318
319    #[doc(hidden)]
320    #[inline(always)]
321    #[must_use]
322    pub const fn is_ge_modulus(&self) -> bool {
323        self.montgomery_form.ge(&P::MODULUS)
324    }
325
326    #[inline(always)]
327    const fn subtract_modulus(mut self) -> Self {
328        if self.is_ge_modulus() {
329            self.montgomery_form =
330                self.montgomery_form.wrapping_sub(&P::MODULUS);
331        }
332        self
333    }
334
335    /// Construct a new field element from its underlying
336    /// [`struct@Uint`] data type.
337    #[inline]
338    #[must_use]
339    pub const fn new(element: Uint<N>) -> Self {
340        let r = Self { montgomery_form: element, phantom: PhantomData };
341        if r.is_zero() {
342            r
343        } else {
344            Fp::<P, N>::mul(
345                &r,
346                &Fp { montgomery_form: P::R2, phantom: PhantomData },
347            )
348        }
349    }
350
351    /// Multiply `self` to `rhs` and return the result (constant).
352    ///
353    /// Implements the Montgomery multiplication algorithm [reference].
354    ///
355    /// [reference]: https://en.wikipedia.org/wiki/Montgomery_modular_multiplication
356    #[inline(always)]
357    #[must_use]
358    pub const fn mul(&self, rhs: &Self) -> Self {
359        let (carry, result) = self.mul_without_cond_subtract(rhs);
360        if P::HAS_MODULUS_SPARE_BIT {
361            result.subtract_modulus()
362        } else {
363            result.carrying_sub_modulus(carry)
364        }
365    }
366
367    /// Negate `self` and return the result (constant).
368    #[inline(always)]
369    #[must_use]
370    pub const fn neg(self) -> Self {
371        if self.is_zero() {
372            return self;
373        }
374
375        // Should not overflow. Montgomery should always be less than modulus.
376        let (res, _) = Self::MODULUS.checked_sub(&self.montgomery_form);
377        Fp::new_unchecked(res)
378    }
379
380    /// Returns true if this number is zero (constant).
381    #[must_use]
382    pub const fn is_zero(&self) -> bool {
383        self.montgomery_form.is_zero()
384    }
385
386    /// Subtract modulus from `self` with carry and return the result.
387    #[inline(always)]
388    const fn carrying_sub_modulus(mut self, carry: bool) -> Self {
389        if carry || self.is_ge_modulus() {
390            self.montgomery_form =
391                self.montgomery_form.wrapping_sub(&P::MODULUS);
392        }
393        self
394    }
395
396    #[inline(always)]
397    const fn mul_without_cond_subtract(&self, other: &Self) -> (bool, Self) {
398        let (lo, hi) =
399            self.montgomery_form.widening_mul(&other.montgomery_form);
400
401        let (carry, res) = Self::widening_montgomery_reduction(lo, hi);
402        (carry, Self::new_unchecked(res))
403    }
404
405    /// Apply the Montgomery reduction to composite number represented as `lo`
406    /// and `hi`.
407    /// Returns `carry` and the result of the reduction.
408    ///
409    /// Algorithm 14.32 in Handbook of Applied Cryptography [reference].
410    ///
411    /// [reference]: https://cacr.uwaterloo.ca/hac/about/chap14.pdf
412    #[inline(always)]
413    const fn widening_montgomery_reduction(
414        mut lo: Uint<N>,
415        mut hi: Uint<N>,
416    ) -> (bool, Uint<N>) {
417        let mut carry2 = false;
418        const_for_unroll6!((i in 0..N) {
419            let tmp = lo.limbs[i].wrapping_mul(P::INV);
420
421            let (_, mut carry) = limb::mac(lo.limbs[i], tmp, P::MODULUS.limbs[0]);
422
423            const_for_unroll6!((j in 1..N) {
424                let k = i + j;
425                if k >= N {
426                    (hi.limbs[k - N], carry) = limb::carrying_mac(
427                        hi.limbs[k - N],
428                        tmp,
429                        P::MODULUS.limbs[j],
430                        carry
431                    );
432                } else {
433                    (lo.limbs[k], carry) = limb::carrying_mac(
434                        lo.limbs[k],
435                        tmp,
436                        P::MODULUS.limbs[j],
437                        carry
438                    );
439                }
440            });
441            (hi.limbs[i], carry2) = limb::adc(hi.limbs[i], carry, carry2);
442        });
443
444        (carry2, hi)
445    }
446
447    /// Apply the Montgomery reduction to `self`.
448    /// Returns the result of the reduction (carry not needed).
449    /// Compare to [`Self::widening_montgomery_reduction`] doesn't use loop
450    /// "unroll" optimization, since it is assumed to be called just to
451    /// convert back to normal representation.
452    ///
453    /// Algorithm 14.32 in Handbook of Applied Cryptography [reference].
454    ///
455    /// [reference]: https://cacr.uwaterloo.ca/hac/about/chap14.pdf
456    #[inline(always)]
457    const fn montgomery_reduction(self) -> Uint<N> {
458        let mut limbs = self.montgomery_form.limbs;
459        const_for!((i in 0..N) {
460            let k = limbs[i].wrapping_mul(P::INV);
461
462            let (_, mut carry) = limb::mac(limbs[i], k, Self::MODULUS.limbs[0]);
463            const_for!((j in 1..N) {
464                (limbs[(j + i) % N], carry) = limb::carrying_mac(
465                    limbs[(j + i) % N],
466                    k,
467                    Self::MODULUS.limbs[j],
468                    carry,
469                );
470            });
471            limbs[i % N] = carry;
472        });
473        Uint::new(limbs)
474    }
475
476    /// Construct `Self` from the other [`Fp`] element of different size
477    /// (constant).
478    ///
479    /// # Panics
480    ///
481    /// * If `value` is bigger than `Self` maximum size.
482    #[must_use]
483    pub const fn from_fp<P2: FpParams<N2>, const N2: usize>(
484        value: Fp<P2, N2>,
485    ) -> Self {
486        let value = value.into_bigint();
487        let uint = Uint::<N>::from_uint(value);
488        Self::from_bigint(uint)
489    }
490
491    /// Construct a field element from an integer (constant).
492    ///
493    /// By the end element will be converted to a montgomery form and reduced.
494    #[must_use]
495    #[inline(always)]
496    pub const fn from_bigint(num: Uint<N>) -> Self {
497        let elem = Fp::new_unchecked(num);
498        if elem.is_zero() {
499            elem
500        } else {
501            Fp::<P, N>::mul(&elem, &Fp::new_unchecked(P::R2))
502        }
503    }
504
505    /// Convert a field element to an integer less than [`Self::MODULUS`]
506    /// (constant).
507    #[must_use]
508    #[inline(always)]
509    pub const fn into_bigint(self) -> Uint<N> {
510        self.montgomery_reduction()
511    }
512}
513
514impl<P: FpParams<N>, const N: usize> Debug for Fp<P, N> {
515    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
516        Debug::fmt(&self.into_bigint(), f)
517    }
518}
519
520impl<P: FpParams<N>, const N: usize> Zero for Fp<P, N> {
521    #[inline]
522    fn zero() -> Self {
523        Self::ZERO
524    }
525
526    #[inline]
527    fn is_zero(&self) -> bool {
528        *self == Self::ZERO
529    }
530}
531
532impl<P: FpParams<N>, const N: usize> One for Fp<P, N> {
533    #[inline]
534    fn one() -> Self {
535        Self::ONE
536    }
537
538    #[inline]
539    fn is_one(&self) -> bool {
540        *self == Self::ONE
541    }
542}
543
544impl<P: FpParams<N>, const N: usize> AdditiveGroup for Fp<P, N> {
545    type Scalar = Self;
546
547    const ZERO: Self = Self::ZERO;
548
549    #[inline]
550    fn double(&self) -> Self {
551        let mut temp = *self;
552        temp.double_in_place();
553        temp
554    }
555
556    #[inline]
557    fn double_in_place(&mut self) -> &mut Self {
558        P::double_in_place(self);
559        self
560    }
561
562    #[inline]
563    fn neg_in_place(&mut self) -> &mut Self {
564        P::neg_in_place(self);
565        self
566    }
567}
568
569impl<P: FpParams<N>, const N: usize> Field for Fp<P, N> {
570    const ONE: Self = Fp::new_unchecked(P::R);
571
572    fn extension_degree() -> usize {
573        1
574    }
575
576    #[inline]
577    fn square(&self) -> Self {
578        let mut temp = *self;
579        temp.square_in_place();
580        temp
581    }
582
583    #[inline]
584    fn square_in_place(&mut self) -> &mut Self {
585        P::square_in_place(self);
586        self
587    }
588
589    #[inline]
590    fn inverse(&self) -> Option<Self> {
591        P::inverse(self)
592    }
593
594    fn inverse_in_place(&mut self) -> Option<&mut Self> {
595        if let Some(inverse) = self.inverse() {
596            *self = inverse;
597            Some(self)
598        } else {
599            None
600        }
601    }
602}
603
604impl<P: FpParams<N>, const N: usize> PrimeField for Fp<P, N> {
605    type BigInt = Uint<N>;
606
607    const HAS_MODULUS_SPARE_BIT: bool = P::HAS_MODULUS_SPARE_BIT;
608    const MODULUS: Self::BigInt = P::MODULUS;
609    const MODULUS_BIT_SIZE: usize = <Uint<N> as BigInteger>::BITS;
610
611    #[inline]
612    fn from_bigint(repr: Self::BigInt) -> Self {
613        P::from_bigint(repr)
614    }
615
616    #[inline]
617    fn into_bigint(self) -> Uint<N> {
618        P::into_bigint(self)
619    }
620}
621
622impl<P: FpParams<N>, const N: usize> Ord for Fp<P, N> {
623    fn cmp(&self, other: &Self) -> Ordering {
624        self.into_bigint().cmp(&other.into_bigint())
625    }
626}
627
628impl<P: FpParams<N>, const N: usize> PartialOrd for Fp<P, N> {
629    #[inline]
630    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
631        Some(self.cmp(other))
632    }
633}
634
635/// Auto implements conversion from unsigned integer of type `$int` to [`Fp`].
636macro_rules! impl_fp_from_unsigned_int {
637    ($int:ty) => {
638        impl<P: FpParams<N>, const N: usize> From<$int> for Fp<P, N> {
639            fn from(other: $int) -> Self {
640                Fp::from_bigint(Uint::from(other))
641            }
642        }
643    };
644}
645
646/// Auto implements conversion from signed integer of type `$int` to [`Fp`].
647macro_rules! impl_fp_from_signed_int {
648    ($int:ty) => {
649        impl<P: FpParams<N>, const N: usize> From<$int> for Fp<P, N> {
650            fn from(other: $int) -> Self {
651                let abs = other.unsigned_abs().into();
652                if other.is_positive() {
653                    abs
654                } else {
655                    -abs
656                }
657            }
658        }
659    };
660}
661
662impl_fp_from_unsigned_int!(u128);
663impl_fp_from_unsigned_int!(u64);
664impl_fp_from_unsigned_int!(u32);
665impl_fp_from_unsigned_int!(u16);
666impl_fp_from_unsigned_int!(u8);
667
668impl_fp_from_signed_int!(i128);
669impl_fp_from_signed_int!(i64);
670impl_fp_from_signed_int!(i32);
671impl_fp_from_signed_int!(i16);
672impl_fp_from_signed_int!(i8);
673
674impl<P: FpParams<N>, const N: usize> From<bool> for Fp<P, N> {
675    fn from(other: bool) -> Self {
676        u8::from(other).into()
677    }
678}
679
680/// Auto implements conversion from [`Fp`] to integer of type `$int`.
681///
682/// Conversion is available only for a single limb field elements,
683/// i.e. `N = 1`.
684macro_rules! impl_int_from_fp {
685    ($int:ty) => {
686        impl<P: FpParams<1>> From<Fp<P, 1>> for $int {
687            fn from(other: Fp<P, 1>) -> Self {
688                let uint = other.into_bigint();
689                let words = uint.as_limbs();
690                <$int>::try_from(words[0]).unwrap_or_else(|_| {
691                    panic!("should convert to {}", stringify!($int))
692                })
693            }
694        }
695    };
696}
697
698impl_int_from_fp!(u128);
699impl_int_from_fp!(u64);
700impl_int_from_fp!(u32);
701impl_int_from_fp!(u16);
702impl_int_from_fp!(u8);
703impl_int_from_fp!(i128);
704impl_int_from_fp!(i64);
705impl_int_from_fp!(i32);
706impl_int_from_fp!(i16);
707impl_int_from_fp!(i8);
708
709/// Outputs a string containing the value of `self`,
710/// represented as a decimal without leading zeroes.
711impl<P: FpParams<N>, const N: usize> Display for Fp<P, N> {
712    #[inline]
713    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
714        let str = self.into_bigint().to_string();
715        write!(f, "{str}")
716    }
717}
718
719impl<P: FpParams<N>, const N: usize> Neg for Fp<P, N> {
720    type Output = Self;
721
722    #[inline]
723    fn neg(mut self) -> Self {
724        P::neg_in_place(&mut self);
725        self
726    }
727}
728
729impl<P: FpParams<N>, const N: usize> Add<&Fp<P, N>> for Fp<P, N> {
730    type Output = Self;
731
732    #[inline]
733    fn add(mut self, other: &Self) -> Self {
734        self.add_assign(other);
735        self
736    }
737}
738
739impl<P: FpParams<N>, const N: usize> Sub<&Fp<P, N>> for Fp<P, N> {
740    type Output = Self;
741
742    #[inline]
743    fn sub(mut self, other: &Self) -> Self {
744        self.sub_assign(other);
745        self
746    }
747}
748
749impl<P: FpParams<N>, const N: usize> Mul<&Fp<P, N>> for Fp<P, N> {
750    type Output = Self;
751
752    #[inline]
753    fn mul(mut self, other: &Self) -> Self {
754        self.mul_assign(other);
755        self
756    }
757}
758
759impl<P: FpParams<N>, const N: usize> Div<&Fp<P, N>> for Fp<P, N> {
760    type Output = Self;
761
762    #[inline]
763    fn div(mut self, other: &Self) -> Self {
764        // Returns `self * other.inverse()` if `other.inverse()` is `Some`, and
765        // panics otherwise.
766        self.mul_assign(&other.inverse().expect("should not divide by zero"));
767        self
768    }
769}
770
771impl<P: FpParams<N>, const N: usize> Add<&Fp<P, N>> for &Fp<P, N> {
772    type Output = Fp<P, N>;
773
774    #[inline]
775    fn add(self, other: &Fp<P, N>) -> Fp<P, N> {
776        let mut result = *self;
777        result.add_assign(other);
778        result
779    }
780}
781
782impl<P: FpParams<N>, const N: usize> Sub<&Fp<P, N>> for &Fp<P, N> {
783    type Output = Fp<P, N>;
784
785    #[inline]
786    fn sub(self, other: &Fp<P, N>) -> Fp<P, N> {
787        let mut result = *self;
788        result.sub_assign(other);
789        result
790    }
791}
792
793impl<P: FpParams<N>, const N: usize> Mul<&Fp<P, N>> for &Fp<P, N> {
794    type Output = Fp<P, N>;
795
796    #[inline]
797    fn mul(self, other: &Fp<P, N>) -> Fp<P, N> {
798        let mut result = *self;
799        result.mul_assign(other);
800        result
801    }
802}
803
804impl<P: FpParams<N>, const N: usize> Div<&Fp<P, N>> for &Fp<P, N> {
805    type Output = Fp<P, N>;
806
807    #[inline]
808    fn div(self, other: &Fp<P, N>) -> Fp<P, N> {
809        let mut result = *self;
810        result.div_assign(other);
811        result
812    }
813}
814
815impl<P: FpParams<N>, const N: usize> AddAssign<&Self> for Fp<P, N> {
816    #[inline]
817    fn add_assign(&mut self, other: &Self) {
818        P::add_assign(self, other);
819    }
820}
821
822impl<P: FpParams<N>, const N: usize> SubAssign<&Self> for Fp<P, N> {
823    #[inline]
824    fn sub_assign(&mut self, other: &Self) {
825        P::sub_assign(self, other);
826    }
827}
828
829impl<P: FpParams<N>, const N: usize> Add<Self> for Fp<P, N> {
830    type Output = Self;
831
832    #[inline]
833    fn add(mut self, other: Self) -> Self {
834        self.add_assign(&other);
835        self
836    }
837}
838
839impl<P: FpParams<N>, const N: usize> Add<&mut Self> for Fp<P, N> {
840    type Output = Self;
841
842    #[inline]
843    fn add(mut self, other: &mut Self) -> Self {
844        self.add_assign(&*other);
845        self
846    }
847}
848
849impl<P: FpParams<N>, const N: usize> Sub<Self> for Fp<P, N> {
850    type Output = Self;
851
852    #[inline]
853    fn sub(mut self, other: Self) -> Self {
854        self.sub_assign(&other);
855        self
856    }
857}
858
859impl<P: FpParams<N>, const N: usize> Sub<&mut Self> for Fp<P, N> {
860    type Output = Self;
861
862    #[inline]
863    fn sub(mut self, other: &mut Self) -> Self {
864        self.sub_assign(&*other);
865        self
866    }
867}
868
869impl<P: FpParams<N>, const N: usize> Sum<Self> for Fp<P, N> {
870    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
871        iter.fold(Self::zero(), Add::add)
872    }
873}
874
875impl<'a, P: FpParams<N>, const N: usize> Sum<&'a Self> for Fp<P, N> {
876    fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
877        iter.fold(Self::zero(), Add::add)
878    }
879}
880
881impl<P: FpParams<N>, const N: usize> AddAssign<Self> for Fp<P, N> {
882    #[inline]
883    fn add_assign(&mut self, other: Self) {
884        self.add_assign(&other);
885    }
886}
887
888impl<P: FpParams<N>, const N: usize> SubAssign<Self> for Fp<P, N> {
889    #[inline]
890    fn sub_assign(&mut self, other: Self) {
891        self.sub_assign(&other);
892    }
893}
894
895impl<P: FpParams<N>, const N: usize> AddAssign<&mut Self> for Fp<P, N> {
896    #[inline]
897    fn add_assign(&mut self, other: &mut Self) {
898        self.add_assign(&*other);
899    }
900}
901
902impl<P: FpParams<N>, const N: usize> SubAssign<&mut Self> for Fp<P, N> {
903    #[inline]
904    fn sub_assign(&mut self, other: &mut Self) {
905        self.sub_assign(&*other);
906    }
907}
908
909impl<P: FpParams<N>, const N: usize> MulAssign<&Self> for Fp<P, N> {
910    #[inline]
911    fn mul_assign(&mut self, other: &Self) {
912        P::mul_assign(self, other);
913    }
914}
915
916impl<P: FpParams<N>, const N: usize> DivAssign<&Self> for Fp<P, N> {
917    #[inline]
918    fn div_assign(&mut self, other: &Self) {
919        // Returns `self * other.inverse()` if `other.inverse()` is `Some`, and
920        // panics otherwise.
921        self.mul_assign(&other.inverse().expect("should not divide by zero"));
922    }
923}
924
925impl<P: FpParams<N>, const N: usize> Mul<Self> for Fp<P, N> {
926    type Output = Self;
927
928    #[inline]
929    fn mul(mut self, other: Self) -> Self {
930        self.mul_assign(&other);
931        self
932    }
933}
934
935impl<P: FpParams<N>, const N: usize> Div<Self> for Fp<P, N> {
936    type Output = Self;
937
938    #[inline]
939    fn div(mut self, other: Self) -> Self {
940        use DivAssign;
941        self.div_assign(&other);
942        self
943    }
944}
945
946impl<P: FpParams<N>, const N: usize> Mul<&mut Self> for Fp<P, N> {
947    type Output = Self;
948
949    #[inline]
950    fn mul(mut self, other: &mut Self) -> Self {
951        self.mul_assign(&*other);
952        self
953    }
954}
955
956impl<P: FpParams<N>, const N: usize> Div<&mut Self> for Fp<P, N> {
957    type Output = Self;
958
959    #[inline]
960    fn div(mut self, other: &mut Self) -> Self {
961        self.div_assign(&*other);
962        self
963    }
964}
965
966impl<P: FpParams<N>, const N: usize> Product<Self> for Fp<P, N> {
967    fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
968        iter.fold(Self::one(), Mul::mul)
969    }
970}
971
972impl<'a, P: FpParams<N>, const N: usize> Product<&'a Self> for Fp<P, N> {
973    fn product<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
974        iter.fold(Self::one(), Mul::mul)
975    }
976}
977
978impl<P: FpParams<N>, const N: usize> MulAssign<Self> for Fp<P, N> {
979    #[inline]
980    fn mul_assign(&mut self, other: Self) {
981        self.mul_assign(&other);
982    }
983}
984
985impl<P: FpParams<N>, const N: usize> DivAssign<&mut Self> for Fp<P, N> {
986    #[inline]
987    fn div_assign(&mut self, other: &mut Self) {
988        self.div_assign(&*other);
989    }
990}
991
992impl<P: FpParams<N>, const N: usize> MulAssign<&mut Self> for Fp<P, N> {
993    #[inline]
994    fn mul_assign(&mut self, other: &mut Self) {
995        self.mul_assign(&*other);
996    }
997}
998
999impl<P: FpParams<N>, const N: usize> DivAssign<Self> for Fp<P, N> {
1000    #[inline]
1001    fn div_assign(&mut self, other: Self) {
1002        self.div_assign(&other);
1003    }
1004}
1005
1006impl<P: FpParams<N>, const N: usize> zeroize::Zeroize for Fp<P, N> {
1007    // The phantom data does not contain element-specific data
1008    // and thus does not need to be zeroized.
1009    fn zeroize(&mut self) {
1010        self.montgomery_form.zeroize();
1011    }
1012}
1013
1014impl<P: FpParams<N>, const N: usize> From<Fp<P, N>> for Uint<N> {
1015    #[inline]
1016    fn from(fp: Fp<P, N>) -> Self {
1017        fp.into_bigint()
1018    }
1019}
1020
1021impl<P: FpParams<N>, const N: usize> From<Uint<N>> for Fp<P, N> {
1022    #[inline]
1023    fn from(int: Uint<N>) -> Self {
1024        Self::from_bigint(int)
1025    }
1026}
1027
1028/// This macro converts a string base-10 number to a field element.
1029#[macro_export]
1030macro_rules! fp_from_num {
1031    ($num:literal) => {
1032        $crate::field::fp::Fp::new($crate::arithmetic::uint::from_str_radix(
1033            $num, 10,
1034        ))
1035    };
1036}
1037
1038/// This macro converts a string hex number to a field element.
1039#[macro_export]
1040macro_rules! fp_from_hex {
1041    ($num:literal) => {{
1042        $crate::field::fp::Fp::new($crate::arithmetic::uint::from_str_hex($num))
1043    }};
1044}
1045
1046#[cfg(test)]
1047mod tests {
1048    use proptest::prelude::*;
1049
1050    use super::*;
1051    use crate::{
1052        arithmetic::uint::{U256, U512, U64},
1053        field::{
1054            fp::{Fp64, FpParams, LIMBS_64},
1055            group::AdditiveGroup,
1056        },
1057        fp_from_num, from_num,
1058    };
1059
1060    type Field64 = Fp64<Fp64Param>;
1061    struct Fp64Param;
1062    impl FpParams<LIMBS_64> for Fp64Param {
1063        const GENERATOR: Fp64<Fp64Param> = fp_from_num!("3");
1064        const MODULUS: U64 = from_num!("1000003"); // Prime number
1065    }
1066
1067    const MODULUS: i128 = 1000003; // Prime number
1068
1069    #[test]
1070    fn add() {
1071        proptest!(|(a: i64, b: i64)| {
1072            let res = Field64::from(a) + Field64::from(b);
1073            let res: i128 = res.into();
1074            let a = i128::from(a);
1075            let b = i128::from(b);
1076            prop_assert_eq!(res, (a + b).rem_euclid(MODULUS));
1077        });
1078    }
1079
1080    #[test]
1081    fn double() {
1082        proptest!(|(a: i64)| {
1083            let res = Field64::from(a).double();
1084            let res: i128 = res.into();
1085            let a = i128::from(a);
1086            prop_assert_eq!(res, (a + a).rem_euclid(MODULUS));
1087        });
1088    }
1089
1090    #[test]
1091    fn sub() {
1092        proptest!(|(a: i64, b: i64)| {
1093            let res = Field64::from(a) - Field64::from(b);
1094            let res: i128 = res.into();
1095            let a = i128::from(a);
1096            let b = i128::from(b);
1097            prop_assert_eq!(res, (a - b).rem_euclid(MODULUS));
1098        });
1099    }
1100
1101    #[test]
1102    fn mul() {
1103        proptest!(|(a: i64, b: i64)| {
1104            let res = Field64::from(a) * Field64::from(b);
1105            let res: i128 = res.into();
1106            let a = i128::from(a);
1107            let b = i128::from(b);
1108            prop_assert_eq!(res, (a * b).rem_euclid(MODULUS));
1109        });
1110    }
1111
1112    #[test]
1113    fn square() {
1114        proptest!(|(a: i64)| {
1115            let res = Field64::from(a).square();
1116            let res: i128 = res.into();
1117            let a = i128::from(a);
1118            prop_assert_eq!(res, (a * a).rem_euclid(MODULUS));
1119        });
1120    }
1121
1122    prop_compose! {
1123        fn non_zero_modulo_i64()(
1124            b in 1..i64::MAX
1125        ) -> i64 {
1126            if i128::from(b) % MODULUS == 0 {
1127                b + 1
1128            } else {
1129                b
1130            }
1131        }
1132    }
1133
1134    #[test]
1135    fn div() {
1136        proptest!(|(a: i64, b in non_zero_modulo_i64())| {
1137            let res = Field64::from(a) / Field64::from(b);
1138            let res: i128 = res.into();
1139            let a = i128::from(a);
1140            let b = i128::from(b);
1141            // a / b = res mod M => res * b = a mod M
1142            prop_assert_eq!((res * b).rem_euclid(MODULUS), a.rem_euclid(MODULUS));
1143        });
1144    }
1145
1146    /// Compute a^b in an expensive and iterative way.
1147    fn dumb_pow(a: i128, b: i128) -> i128 {
1148        (0..b).fold(1, |acc, _| (acc * a).rem_euclid(MODULUS))
1149    }
1150
1151    #[test]
1152    fn pow() {
1153        proptest!(|(a: i64, b in 0_u32..1000)| {
1154            let res = Field64::from(a).pow(b);
1155            let res: i128 = res.into();
1156            let a = i128::from(a);
1157            let b = i128::from(b);
1158            prop_assert_eq!(res, dumb_pow(a, b));
1159        });
1160    }
1161
1162    #[test]
1163    fn neg() {
1164        proptest!(|(a: i64)| {
1165            let res = -Field64::from(a);
1166            let res: i128 = res.into();
1167            let a = i128::from(a);
1168            prop_assert_eq!(res, (-a).rem_euclid(MODULUS));
1169        });
1170    }
1171
1172    #[test]
1173    fn one() {
1174        proptest!(|(a: i64)| {
1175            let res = Field64::one();
1176            let res: i128 = res.into();
1177            prop_assert_eq!(res, 1);
1178
1179            let res = Field64::one() * Field64::from(a);
1180            let res: i128 = res.into();
1181            let a: i128 = a.into();
1182            prop_assert_eq!(res, a.rem_euclid(MODULUS));
1183        });
1184    }
1185
1186    #[test]
1187    fn zero() {
1188        proptest!(|(a: i64)| {
1189            let res = Field64::zero();
1190            let res: i128 = res.into();
1191            prop_assert_eq!(res, 0);
1192
1193            let res = Field64::zero() + Field64::from(a);
1194            let res: i128 = res.into();
1195            let a: i128 = a.into();
1196            prop_assert_eq!(res, a.rem_euclid(MODULUS));
1197        });
1198    }
1199
1200    #[test]
1201    fn from_fp() {
1202        /// Test `256-bit` scalar
1203        pub(crate) type Scalar = Fp256<Fp256Param>;
1204
1205        pub(crate) struct Fp256Param;
1206        impl FpParams<LIMBS_256> for Fp256Param {
1207            const GENERATOR: Fp256<Self> = fp_from_num!("2");
1208            const MODULUS: U256 = from_num!("7237005577332262213973186563042994240857116359379907606001950938285454250989");
1209        }
1210
1211        /// Test `256-bit` scalar with the same modulus as [`Scalar`].
1212        pub(crate) type WideScalar = Fp512<Fp512Param>;
1213
1214        pub(crate) struct Fp512Param;
1215        impl FpParams<LIMBS_512> for Fp512Param {
1216            const GENERATOR: Fp512<Self> = fp_from_num!("2");
1217            const MODULUS: U512 = from_num!("7237005577332262213973186563042994240857116359379907606001950938285454250989");
1218        }
1219
1220        // Check that conversion between scalars with different bit size, but
1221        // with the same modulus works.
1222        proptest!(|(limbs: [u64; 4])|{
1223            let number = U256::new(limbs);
1224            let expected_scalar = Scalar::from(number);
1225            let wide_scalar = WideScalar::from_fp(expected_scalar);
1226            let scalar = Scalar::from_fp(wide_scalar);
1227
1228            assert_eq!(scalar, expected_scalar);
1229        });
1230    }
1231}