ark_ff_optimized/
fp31.rs

1//! An implementation of a 31-bit Mersenne prime (no 2^k roots of unity for k>1)
2//! field with modulus `2^31 - 1`. Mersenne primes have a fast reductions to to
3//! their binary representation.
4//!
5//! This field and its implementation has a couple of attractive properties:
6//! * Addition never overflows a 32-bit int.
7//! * Efficient for GPUs which optimize throughput for 32-bit and 16-bit arithmetic.
8//! * Field arithmetic in this field can be implemented using a few 32-bit
9//!   addition, subtractions, and shifts.
10
11use ark_ff::{BigInt, FftField, Field, LegendreSymbol, One, PrimeField, SqrtPrecomputation, Zero};
12use ark_serialize::{
13    buffer_byte_size, CanonicalDeserialize, CanonicalDeserializeWithFlags, CanonicalSerialize,
14    CanonicalSerializeWithFlags, Compress, EmptyFlags, Flags, SerializationError, Valid, Validate,
15};
16use ark_std::string::ToString;
17use core::{
18    fmt::{Debug, Display, Formatter},
19    hash::Hash,
20    iter::{Product, Sum},
21    ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign},
22    str::FromStr,
23};
24
25/// Field modulus `p = 2^31 - 1`
26const MODULUS: u32 = 2_147_483_647;
27
28const MODULUS_BIT_SIZE: u32 = 31;
29
30#[derive(Clone, Copy, Default)]
31pub struct Fp(pub u32);
32
33impl Fp {
34    #[doc(hidden)]
35    #[inline]
36    const fn is_gt_modulus(self) -> bool {
37        self.0 > MODULUS
38    }
39    const fn is_geq_modulus(self) -> bool {
40        self.0 >= MODULUS
41    }
42
43    const fn add_assign(&mut self, rhs: Self) {
44        self.0 += rhs.0;
45        self.0 = (self.0 & MODULUS) + (self.0 >> 31);
46    }
47
48    const fn sub_assign(&mut self, rhs: Self) {
49        self.0 += MODULUS - rhs.0;
50        self.0 = (self.0 & MODULUS) + (self.0 >> 31);
51    }
52
53    #[inline]
54    const fn mul(self, rhs: Self) -> Self {
55        let t = self.0 as u64 * (rhs.0 << 1) as u64;
56        // we want to truncate here
57        #[allow(clippy::cast_possible_truncation)]
58        let t0 = t as u32 >> 1;
59        let t1 = (t >> 32) as u32;
60        let x = t0 + t1;
61        Self((x & MODULUS) + (x >> 31))
62    }
63
64    #[inline]
65    const fn sq(self) -> Self {
66        self.mul(self)
67    }
68
69    const fn sqn(mut self, n: u32) -> Self {
70        let mut i = 0;
71        while i < n {
72            self = self.sq();
73            i += 1;
74        }
75        self
76    }
77
78    const fn is_zero(self) -> bool {
79        self.0 == 0 || self.0 == MODULUS
80    }
81
82    const fn into_integer(self) -> u32 {
83        if self.is_zero() {
84            0
85        } else {
86            self.0
87        }
88    }
89}
90
91impl Field for Fp {
92    type BasePrimeField = Self;
93    type BasePrimeFieldIter = core::iter::Once<Self::BasePrimeField>;
94
95    const SQRT_PRECOMP: Option<SqrtPrecomputation<Self>> = Some(SqrtPrecomputation::Case3Mod4 {
96        modulus_plus_one_div_four: &[(MODULUS as u64 + 1) / 4],
97    });
98
99    const ZERO: Self = Self(0);
100
101    const ONE: Self = Self(1);
102
103    fn extension_degree() -> u64 {
104        1
105    }
106
107    fn from_base_prime_field(elem: Self::BasePrimeField) -> Self {
108        elem
109    }
110
111    fn to_base_prime_field_elements(&self) -> Self::BasePrimeFieldIter {
112        core::iter::once(*self)
113    }
114
115    fn from_base_prime_field_elems(elems: &[Self::BasePrimeField]) -> Option<Self> {
116        if elems.len() != usize::try_from(Self::extension_degree()).unwrap() {
117            return None;
118        }
119        Some(elems[0])
120    }
121
122    #[inline]
123    fn double(&self) -> Self {
124        let mut temp = *self;
125        temp.double_in_place();
126        temp
127    }
128
129    #[inline]
130    fn double_in_place(&mut self) -> &mut Self {
131        let x = self.0 << 1;
132        self.0 = (x & MODULUS) + (self.0 >> 30);
133        self
134    }
135
136    #[inline]
137    fn neg_in_place(&mut self) -> &mut Self {
138        self.0 = MODULUS - self.0;
139        self
140    }
141
142    #[inline]
143    fn characteristic() -> &'static [u64] {
144        const _MODULUS: &[u64] = &[MODULUS as u64];
145        _MODULUS
146    }
147
148    #[inline]
149    fn sum_of_products<const T: usize>(a: &[Self; T], b: &[Self; T]) -> Self {
150        a.iter().zip(b).map(|(&a, b)| a * b).sum()
151    }
152
153    #[inline]
154    fn from_random_bytes_with_flags<F: Flags>(_bytes: &[u8]) -> Option<(Self, F)> {
155        todo!()
156    }
157
158    #[inline]
159    fn square(&self) -> Self {
160        let mut temp = *self;
161        temp.square_in_place();
162        temp
163    }
164
165    fn square_in_place(&mut self) -> &mut Self {
166        *self = self.sq();
167        self
168    }
169
170    #[inline]
171    #[allow(clippy::just_underscores_and_digits, clippy::similar_names)]
172    fn inverse(&self) -> Option<Self> {
173        if self.is_zero() {
174            None
175        } else {
176            // Used addchains
177            let t100 = Self::sqn(*self, 2);
178            let t101 = Self::mul(*self, t100);
179            let t1010 = Self::sq(t101);
180            let t1111 = Self::mul(t101, t1010);
181            let t1111000 = Self::sqn(t1111, 3);
182            let t1111101 = Self::mul(t101, t1111000);
183            let t11111010 = Self::sq(t1111101);
184            let t11111111 = Self::mul(t101, t11111010);
185            let x16 = Self::mul(Self::sqn(t11111111, 8), t11111111);
186            let x24 = Self::mul(Self::sqn(x16, 8), t11111111);
187            Some(Self::mul(Self::sqn(x24, 7), t1111101))
188        }
189    }
190
191    fn inverse_in_place(&mut self) -> Option<&mut Self> {
192        self.inverse().map(|inverse| {
193            *self = inverse;
194            self
195        })
196    }
197
198    /// The Frobenius map has no effect in a prime field.
199    #[inline]
200    fn frobenius_map_in_place(&mut self, _: usize) {}
201
202    #[inline]
203    fn legendre(&self) -> LegendreSymbol {
204        let s = self.pow([(u64::from(MODULUS) - 1) / 2]);
205        if s.is_zero() {
206            LegendreSymbol::Zero
207        } else if s.is_one() {
208            LegendreSymbol::QuadraticResidue
209        } else {
210            LegendreSymbol::QuadraticNonResidue
211        }
212    }
213}
214
215impl PrimeField for Fp {
216    type BigInt = BigInt<1>;
217    const MODULUS: Self::BigInt = BigInt([MODULUS as u64]);
218    const MODULUS_MINUS_ONE_DIV_TWO: Self::BigInt = Self::MODULUS.divide_by_2_round_down();
219    const MODULUS_BIT_SIZE: u32 = Self::MODULUS.const_num_bits();
220    const TRACE: Self::BigInt = Self::MODULUS.two_adic_coefficient();
221    const TRACE_MINUS_ONE_DIV_TWO: Self::BigInt = Self::TRACE.divide_by_2_round_down();
222
223    #[inline]
224    fn from_bigint(r: BigInt<1>) -> Option<Self> {
225        Some(Self::from(r.0[0]))
226    }
227
228    fn into_bigint(self) -> BigInt<1> {
229        BigInt([self.into_integer().into()])
230    }
231}
232
233impl FftField for Fp {
234    const GENERATOR: Self = Self(3);
235    const TWO_ADICITY: u32 = 1;
236    const TWO_ADIC_ROOT_OF_UNITY: Self = Self(MODULUS - 1);
237    const SMALL_SUBGROUP_BASE: Option<u32> = None;
238    const SMALL_SUBGROUP_BASE_ADICITY: Option<u32> = None;
239    const LARGE_SUBGROUP_ROOT_OF_UNITY: Option<Self> = None;
240}
241
242impl zeroize::Zeroize for Fp {
243    fn zeroize(&mut self) {
244        self.0.zeroize();
245    }
246}
247
248impl Debug for Fp {
249    fn fmt(&self, f: &mut Formatter<'_>) -> ark_std::fmt::Result {
250        ark_std::fmt::Debug::fmt(&self.into_integer(), f)
251    }
252}
253
254impl Zero for Fp {
255    #[inline]
256    fn zero() -> Self {
257        Self::ZERO
258    }
259
260    #[inline]
261    fn is_zero(&self) -> bool {
262        (*self).is_zero()
263    }
264}
265
266impl One for Fp {
267    #[inline]
268    fn one() -> Self {
269        Self::ONE
270    }
271
272    #[inline]
273    fn is_one(&self) -> bool {
274        *self == Self::ONE
275    }
276}
277
278impl PartialEq for Fp {
279    fn eq(&self, other: &Self) -> bool {
280        self.0 == other.0 || (self.is_zero() && other.is_zero())
281    }
282}
283
284impl Hash for Fp {
285    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
286        self.into_integer().hash(state);
287    }
288}
289
290impl Eq for Fp {}
291
292/// Note that this implementation of `Ord` compares field elements viewing
293/// them as integers in the range 0, 1, ..., `P::MODULUS` - 1. However, other
294/// implementations of `PrimeField` might choose a different ordering, and
295/// as such, users should use this `Ord` for applications where
296/// any ordering suffices (like in a `BTreeMap`), and not in applications
297/// where a particular ordering is required.
298impl Ord for Fp {
299    #[inline]
300    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
301        self.into_integer().cmp(&other.into_integer())
302    }
303}
304
305/// Note that this implementation of `PartialOrd` compares field elements
306/// viewing them as integers in the range 0, 1, ..., `P::MODULUS` - 1. However,
307/// other implementations of `PrimeField` might choose a different ordering, and
308/// as such, users should use this `PartialOrd` for applications where
309/// any ordering suffices (like in a `BTreeMap`), and not in applications
310/// where a particular ordering is required.
311impl PartialOrd for Fp {
312    #[inline]
313    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
314        Some(self.cmp(other))
315    }
316}
317
318impl From<num_bigint::BigUint> for Fp {
319    fn from(other: num_bigint::BigUint) -> Self {
320        (other % MODULUS)
321            .to_u32_digits()
322            .iter()
323            .copied()
324            .map(Self::from)
325            .sum()
326    }
327}
328
329impl From<Fp> for num_bigint::BigUint {
330    fn from(fp: Fp) -> Self {
331        fp.into_integer().into()
332    }
333}
334
335impl From<BigInt<1>> for Fp {
336    fn from(other: BigInt<1>) -> Self {
337        other.0[0].into()
338    }
339}
340
341impl From<Fp> for BigInt<1> {
342    fn from(fp: Fp) -> Self {
343        Self([fp.into_integer().into()])
344    }
345}
346
347// TODO: change all the From implementations
348impl From<u128> for Fp {
349    fn from(other: u128) -> Self {
350        #[allow(clippy::cast_possible_truncation)]
351        Self((other % u128::from(MODULUS)) as u32)
352    }
353}
354
355impl From<i128> for Fp {
356    fn from(other: i128) -> Self {
357        let abs = Self::from(other.unsigned_abs());
358        if other.is_positive() {
359            abs
360        } else {
361            -abs
362        }
363    }
364}
365
366impl From<bool> for Fp {
367    fn from(other: bool) -> Self {
368        Self(u32::from(other))
369    }
370}
371
372impl From<u64> for Fp {
373    fn from(other: u64) -> Self {
374        #[allow(clippy::cast_possible_truncation)]
375        Self((other % u64::from(MODULUS)) as u32)
376    }
377}
378
379impl From<i64> for Fp {
380    fn from(other: i64) -> Self {
381        let abs = Self::from(other.unsigned_abs());
382        if other.is_positive() {
383            abs
384        } else {
385            -abs
386        }
387    }
388}
389
390impl From<u32> for Fp {
391    fn from(other: u32) -> Self {
392        Self(other % MODULUS)
393    }
394}
395
396impl From<i32> for Fp {
397    fn from(other: i32) -> Self {
398        let abs = Self::from(other.unsigned_abs());
399        if other.is_positive() {
400            abs
401        } else {
402            -abs
403        }
404    }
405}
406
407impl From<u16> for Fp {
408    fn from(other: u16) -> Self {
409        Self(other.into())
410    }
411}
412
413impl From<i16> for Fp {
414    fn from(other: i16) -> Self {
415        let abs = Self::from(other.unsigned_abs());
416        if other.is_positive() {
417            abs
418        } else {
419            -abs
420        }
421    }
422}
423
424impl From<u8> for Fp {
425    fn from(other: u8) -> Self {
426        Self(other.into())
427    }
428}
429
430impl From<i8> for Fp {
431    fn from(other: i8) -> Self {
432        let abs = Self::from(other.unsigned_abs());
433        if other.is_positive() {
434            abs
435        } else {
436            -abs
437        }
438    }
439}
440
441impl ark_std::rand::distributions::Distribution<Fp> for ark_std::rand::distributions::Standard {
442    #[inline]
443    fn sample<R: ark_std::rand::Rng + ?Sized>(&self, rng: &mut R) -> Fp {
444        loop {
445            let mut tmp = Fp(rng.sample(Self));
446
447            // Mask away the unused bits at the beginning.
448            let mask = u32::MAX >> (32 - MODULUS_BIT_SIZE);
449            tmp.0 &= mask;
450
451            // TODO: check make sure the distrobution for 0 is right since 2^31 - 1 and 0 represent 0
452            if !tmp.is_geq_modulus() {
453                return tmp;
454            }
455        }
456    }
457}
458
459// TODO:
460impl CanonicalSerializeWithFlags for Fp {
461    fn serialize_with_flags<W: ark_std::io::Write, F: Flags>(
462        &self,
463        mut writer: W,
464        flags: F,
465    ) -> Result<(), SerializationError> {
466        // All reasonable `Flags` should be less than 8 bits in size
467        // (256 values are enough for anyone!)
468        if F::BIT_SIZE > 8 {
469            return Err(SerializationError::NotEnoughSpace);
470        }
471
472        let b = self.into_integer().to_le_bytes();
473        // TODO: Double check this
474        // Mask out the bits of the last byte that correspond to the flag.
475        writer.write_all(&[b[0], b[1], b[2], b[3], flags.u8_bitmask()])?;
476        Ok(())
477    }
478
479    // Let `m = 8 * n` for some `n` be the smallest multiple of 8 greater
480    // than `P::MODULUS_BIT_SIZE`.
481    // If `(m - P::MODULUS_BIT_SIZE) >= F::BIT_SIZE` , then this method returns `n`;
482    // otherwise, it returns `n + 1`.
483    fn serialized_size_with_flags<F: Flags>(&self) -> usize {
484        buffer_byte_size(MODULUS_BIT_SIZE as usize + F::BIT_SIZE)
485    }
486}
487
488impl CanonicalSerialize for Fp {
489    #[inline]
490    fn serialize_with_mode<W: ark_std::io::Write>(
491        &self,
492        writer: W,
493        _compress: Compress,
494    ) -> Result<(), SerializationError> {
495        self.serialize_with_flags(writer, EmptyFlags)
496    }
497
498    #[inline]
499    fn serialized_size(&self, _compress: Compress) -> usize {
500        self.serialized_size_with_flags::<EmptyFlags>()
501    }
502}
503
504impl CanonicalDeserializeWithFlags for Fp {
505    fn deserialize_with_flags<R: ark_std::io::Read, F: Flags>(
506        mut reader: R,
507    ) -> Result<(Self, F), SerializationError> {
508        // All reasonable `Flags` should be less than 8 bits in size
509        // (256 values are enough for anyone!)
510        if F::BIT_SIZE > 8 {
511            return Err(SerializationError::NotEnoughSpace);
512        }
513        // Calculate the number of bytes required to represent a field element
514        // serialized with `flags`.
515        let mut b = [0u8; 5];
516        reader.read_exact(&mut b)?;
517        let flags = F::from_u8_remove_flags(&mut b[b.len() - 1])
518            .ok_or(SerializationError::UnexpectedFlags)?;
519        let self_integer = u32::from_le_bytes(b[0..4].try_into().unwrap());
520        Ok((Self(self_integer), flags))
521    }
522}
523
524impl Valid for Fp {
525    fn check(&self) -> Result<(), SerializationError> {
526        Ok(())
527    }
528}
529
530impl CanonicalDeserialize for Fp {
531    fn deserialize_with_mode<R: ark_std::io::Read>(
532        reader: R,
533        _compress: Compress,
534        _validate: Validate,
535    ) -> Result<Self, SerializationError> {
536        Self::deserialize_with_flags::<R, EmptyFlags>(reader).map(|(r, _)| r)
537    }
538}
539
540impl FromStr for Fp {
541    type Err = ();
542
543    /// Interpret a string of numbers as a (congruent) prime field element.
544    /// Does not accept unnecessary leading zeroes or a blank string.
545    fn from_str(s: &str) -> Result<Self, Self::Err> {
546        if s.is_empty() {
547            return Err(());
548        }
549
550        if s == "0" {
551            return Ok(Self::zero());
552        }
553
554        let mut res = Self::zero();
555
556        let ten = Self(10);
557
558        let mut first_digit = true;
559
560        for c in s.chars() {
561            match c.to_digit(10) {
562                Some(c) => {
563                    if first_digit {
564                        if c == 0 {
565                            return Err(());
566                        }
567
568                        first_digit = false;
569                    }
570
571                    res.mul_assign(&ten);
572                    let digit = Self::from(u64::from(c));
573                    res.add_assign(digit);
574                }
575                None => {
576                    return Err(());
577                }
578            }
579        }
580        if res.is_gt_modulus() {
581            Err(())
582        } else {
583            Ok(res)
584        }
585    }
586}
587
588/// Outputs a string containing the value of `self`,
589/// represented as a decimal without leading zeroes.
590impl Display for Fp {
591    #[inline]
592    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
593        let string = self.into_integer().to_string();
594        write!(f, "{}", string.trim_start_matches('0'))
595    }
596}
597
598impl Neg for Fp {
599    type Output = Self;
600    #[inline]
601    #[must_use]
602    fn neg(mut self) -> Self {
603        Self::neg_in_place(&mut self);
604        self
605    }
606}
607
608impl<'a> Add<&'a Self> for Fp {
609    type Output = Self;
610
611    #[inline]
612    fn add(mut self, other: &Self) -> Self {
613        self.add_assign(*other);
614        self
615    }
616}
617
618impl<'a> Sub<&'a Self> for Fp {
619    type Output = Self;
620
621    #[inline]
622    fn sub(mut self, other: &Self) -> Self {
623        self.sub_assign(*other);
624        self
625    }
626}
627
628impl<'a> Mul<&'a Self> for Fp {
629    type Output = Self;
630
631    #[inline]
632    fn mul(mut self, other: &Self) -> Self {
633        self.mul_assign(other);
634        self
635    }
636}
637
638impl<'a> Div<&'a Self> for Fp {
639    type Output = Self;
640
641    /// Returns `self * other.inverse()` if `other.inverse()` is `Some`, and
642    /// panics otherwise.
643    #[inline]
644    fn div(mut self, other: &Self) -> Self {
645        self.mul_assign(&other.inverse().unwrap());
646        self
647    }
648}
649
650impl<'a, 'b> Add<&'b Fp> for &'a Fp {
651    type Output = Fp;
652
653    #[inline]
654    fn add(self, other: &'b Fp) -> Fp {
655        let mut result = *self;
656        result.add_assign(*other);
657        result
658    }
659}
660
661impl<'a, 'b> Sub<&'b Fp> for &'a Fp {
662    type Output = Fp;
663
664    #[inline]
665    fn sub(self, other: &Fp) -> Fp {
666        let mut result = *self;
667        result.sub_assign(*other);
668        result
669    }
670}
671
672impl<'a, 'b> Mul<&'b Fp> for &'a Fp {
673    type Output = Fp;
674
675    #[inline]
676    fn mul(self, other: &Fp) -> Fp {
677        let mut result = *self;
678        result.mul_assign(other);
679        result
680    }
681}
682
683impl<'a, 'b> Div<&'b Fp> for &'a Fp {
684    type Output = Fp;
685
686    #[inline]
687    fn div(self, other: &Fp) -> Fp {
688        let mut result = *self;
689        result.div_assign(other);
690        result
691    }
692}
693
694impl<'a> AddAssign<&'a Self> for Fp {
695    #[inline]
696    fn add_assign(&mut self, other: &Self) {
697        Self::add_assign(self, *other);
698    }
699}
700
701impl<'a> SubAssign<&'a Self> for Fp {
702    #[inline]
703    fn sub_assign(&mut self, other: &Self) {
704        Self::sub_assign(self, *other);
705    }
706}
707
708impl<'a> AddAssign<&'a mut Self> for Fp {
709    #[inline]
710    fn add_assign(&mut self, other: &mut Self) {
711        Self::add_assign(self, *other);
712    }
713}
714
715impl<'a> SubAssign<&'a mut Self> for Fp {
716    #[inline]
717    fn sub_assign(&mut self, other: &mut Self) {
718        Self::sub_assign(self, *other);
719    }
720}
721
722impl AddAssign<Self> for Fp {
723    #[inline]
724    fn add_assign(&mut self, other: Self) {
725        Self::add_assign(self, other);
726    }
727}
728
729impl SubAssign<Self> for Fp {
730    #[inline]
731    fn sub_assign(&mut self, other: Self) {
732        Self::sub_assign(self, other);
733    }
734}
735
736impl Mul<Self> for Fp {
737    type Output = Self;
738
739    #[inline]
740    fn mul(mut self, other: Self) -> Self {
741        self.mul_assign(&other);
742        self
743    }
744}
745
746impl Div<Self> for Fp {
747    type Output = Self;
748
749    #[inline]
750    fn div(mut self, other: Self) -> Self {
751        self.div_assign(&other);
752        self
753    }
754}
755
756impl Add<Self> for Fp {
757    type Output = Self;
758
759    #[inline]
760    fn add(mut self, other: Self) -> Self {
761        self.add_assign(other);
762        self
763    }
764}
765
766impl Sub<Self> for Fp {
767    type Output = Self;
768
769    #[inline]
770    fn sub(mut self, other: Self) -> Self {
771        self.sub_assign(other);
772        self
773    }
774}
775
776impl<'a> Add<&'a mut Self> for Fp {
777    type Output = Self;
778
779    #[inline]
780    fn add(self, other: &'a mut Self) -> Self {
781        let mut result = self;
782        result.add_assign(*other);
783        result
784    }
785}
786
787impl<'a> Sub<&'a mut Self> for Fp {
788    type Output = Self;
789
790    #[inline]
791    fn sub(self, other: &'a mut Self) -> Self {
792        let mut result = self;
793        result.sub_assign(*other);
794        result
795    }
796}
797
798impl<'a> Mul<&'a mut Self> for Fp {
799    type Output = Self;
800
801    #[inline]
802    fn mul(mut self, other: &'a mut Self) -> Self {
803        self.mul_assign(&*other);
804        self
805    }
806}
807
808impl<'a> Div<&'a mut Self> for Fp {
809    type Output = Self;
810
811    #[inline]
812    fn div(mut self, other: &'a mut Self) -> Self {
813        self.div_assign(&*other);
814        self
815    }
816}
817
818impl Product<Self> for Fp {
819    fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
820        iter.fold(Self::one(), core::ops::Mul::mul)
821    }
822}
823
824impl<'a> Product<&'a Self> for Fp {
825    fn product<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
826        iter.fold(Self::one(), Mul::mul)
827    }
828}
829
830impl Sum<Self> for Fp {
831    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
832        iter.fold(Self::zero(), core::ops::Add::add)
833    }
834}
835
836impl<'a> Sum<&'a Self> for Fp {
837    fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
838        iter.fold(Self::zero(), core::ops::Add::add)
839    }
840}
841
842impl MulAssign<Self> for Fp {
843    #[inline]
844    fn mul_assign(&mut self, other: Self) {
845        self.mul_assign(&other);
846    }
847}
848
849impl DivAssign<Self> for Fp {
850    #[inline]
851    fn div_assign(&mut self, other: Self) {
852        self.div_assign(&other);
853    }
854}
855
856impl<'a> MulAssign<&'a Self> for Fp {
857    #[inline]
858    fn mul_assign(&mut self, other: &'a Self) {
859        *self = Self::mul(*self, *other);
860    }
861}
862
863impl<'a> MulAssign<&'a mut Self> for Fp {
864    #[inline]
865    fn mul_assign(&mut self, other: &'a mut Self) {
866        self.mul_assign(&*other);
867    }
868}
869
870impl<'a> DivAssign<&'a mut Self> for Fp {
871    #[inline]
872    fn div_assign(&mut self, other: &'a mut Self) {
873        self.div_assign(&*other);
874    }
875}
876
877/// Computes `self *= other.inverse()` if `other.inverse()` is `Some`, and
878/// panics otherwise.
879impl<'a> DivAssign<&'a Self> for Fp {
880    #[inline]
881    fn div_assign(&mut self, other: &Self) {
882        self.mul_assign(&other.inverse().unwrap());
883    }
884}
885
886#[cfg(test)]
887mod tests {
888    use super::Fp as TestField;
889    use ark_algebra_test_templates::test_field;
890
891    test_field!(generated; TestField; prime);
892}