pasta_curves/fields/
fp.rs

1use core::fmt;
2use core::ops::{Add, Mul, Neg, Sub};
3
4use ff::{Field, FromUniformBytes, PrimeField, WithSmallOrderMulGroup};
5use rand::RngCore;
6use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
7
8#[cfg(feature = "sqrt-table")]
9use lazy_static::lazy_static;
10
11#[cfg(feature = "bits")]
12use ff::{FieldBits, PrimeFieldBits};
13
14use crate::arithmetic::{adc, mac, sbb, SqrtTableHelpers};
15
16#[cfg(feature = "sqrt-table")]
17use crate::arithmetic::SqrtTables;
18
19/// This represents an element of $\mathbb{F}_p$ where
20///
21/// `p = 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001`
22///
23/// is the base field of the Pallas curve.
24// The internal representation of this type is four 64-bit unsigned
25// integers in little-endian order. `Fp` values are always in
26// Montgomery form; i.e., Fp(a) = aR mod p, with R = 2^256.
27#[derive(Clone, Copy, Eq)]
28#[repr(transparent)]
29pub struct Fp(pub(crate) [u64; 4]);
30
31impl fmt::Debug for Fp {
32    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
33        let tmp = self.to_repr();
34        write!(f, "0x")?;
35        for &b in tmp.iter().rev() {
36            write!(f, "{:02x}", b)?;
37        }
38        Ok(())
39    }
40}
41
42impl From<bool> for Fp {
43    fn from(bit: bool) -> Fp {
44        if bit {
45            Fp::one()
46        } else {
47            Fp::zero()
48        }
49    }
50}
51
52impl From<u64> for Fp {
53    fn from(val: u64) -> Fp {
54        Fp([val, 0, 0, 0]) * R2
55    }
56}
57
58impl ConstantTimeEq for Fp {
59    fn ct_eq(&self, other: &Self) -> Choice {
60        self.0[0].ct_eq(&other.0[0])
61            & self.0[1].ct_eq(&other.0[1])
62            & self.0[2].ct_eq(&other.0[2])
63            & self.0[3].ct_eq(&other.0[3])
64    }
65}
66
67impl PartialEq for Fp {
68    #[inline]
69    fn eq(&self, other: &Self) -> bool {
70        self.ct_eq(other).unwrap_u8() == 1
71    }
72}
73
74impl core::cmp::Ord for Fp {
75    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
76        let left = self.to_repr();
77        let right = other.to_repr();
78        left.iter()
79            .zip(right.iter())
80            .rev()
81            .find_map(|(left_byte, right_byte)| match left_byte.cmp(right_byte) {
82                core::cmp::Ordering::Equal => None,
83                res => Some(res),
84            })
85            .unwrap_or(core::cmp::Ordering::Equal)
86    }
87}
88
89impl core::cmp::PartialOrd for Fp {
90    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
91        Some(self.cmp(other))
92    }
93}
94
95impl ConditionallySelectable for Fp {
96    fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
97        Fp([
98            u64::conditional_select(&a.0[0], &b.0[0], choice),
99            u64::conditional_select(&a.0[1], &b.0[1], choice),
100            u64::conditional_select(&a.0[2], &b.0[2], choice),
101            u64::conditional_select(&a.0[3], &b.0[3], choice),
102        ])
103    }
104}
105
106/// Constant representing the modulus
107/// p = 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001
108const MODULUS: Fp = Fp([
109    0x992d30ed00000001,
110    0x224698fc094cf91b,
111    0x0000000000000000,
112    0x4000000000000000,
113]);
114
115/// The modulus as u32 limbs.
116#[cfg(not(target_pointer_width = "64"))]
117const MODULUS_LIMBS_32: [u32; 8] = [
118    0x0000_0001,
119    0x992d_30ed,
120    0x094c_f91b,
121    0x2246_98fc,
122    0x0000_0000,
123    0x0000_0000,
124    0x0000_0000,
125    0x4000_0000,
126];
127
128impl<'a> Neg for &'a Fp {
129    type Output = Fp;
130
131    #[inline]
132    fn neg(self) -> Fp {
133        self.neg()
134    }
135}
136
137impl Neg for Fp {
138    type Output = Fp;
139
140    #[inline]
141    fn neg(self) -> Fp {
142        -&self
143    }
144}
145
146impl<'a, 'b> Sub<&'b Fp> for &'a Fp {
147    type Output = Fp;
148
149    #[inline]
150    fn sub(self, rhs: &'b Fp) -> Fp {
151        self.sub(rhs)
152    }
153}
154
155impl<'a, 'b> Add<&'b Fp> for &'a Fp {
156    type Output = Fp;
157
158    #[inline]
159    fn add(self, rhs: &'b Fp) -> Fp {
160        self.add(rhs)
161    }
162}
163
164impl<'a, 'b> Mul<&'b Fp> for &'a Fp {
165    type Output = Fp;
166
167    #[inline]
168    fn mul(self, rhs: &'b Fp) -> Fp {
169        self.mul(rhs)
170    }
171}
172
173impl_binops_additive!(Fp, Fp);
174impl_binops_multiplicative!(Fp, Fp);
175
176impl<T: ::core::borrow::Borrow<Fp>> ::core::iter::Sum<T> for Fp {
177    fn sum<I: Iterator<Item = T>>(iter: I) -> Self {
178        iter.fold(Self::ZERO, |acc, item| acc + item.borrow())
179    }
180}
181
182impl<T: ::core::borrow::Borrow<Fp>> ::core::iter::Product<T> for Fp {
183    fn product<I: Iterator<Item = T>>(iter: I) -> Self {
184        iter.fold(Self::ONE, |acc, item| acc * item.borrow())
185    }
186}
187
188/// INV = -(p^{-1} mod 2^64) mod 2^64
189const INV: u64 = 0x992d30ecffffffff;
190
191/// R = 2^256 mod p
192const R: Fp = Fp([
193    0x34786d38fffffffd,
194    0x992c350be41914ad,
195    0xffffffffffffffff,
196    0x3fffffffffffffff,
197]);
198
199/// R^2 = 2^512 mod p
200const R2: Fp = Fp([
201    0x8c78ecb30000000f,
202    0xd7d30dbd8b0de0e7,
203    0x7797a99bc3c95d18,
204    0x096d41af7b9cb714,
205]);
206
207/// R^3 = 2^768 mod p
208const R3: Fp = Fp([
209    0xf185a5993a9e10f9,
210    0xf6a68f3b6ac5b1d1,
211    0xdf8d1014353fd42c,
212    0x2ae309222d2d9910,
213]);
214
215/// `GENERATOR = 5 mod p` is a generator of the `p - 1` order multiplicative
216/// subgroup, or in other words a primitive root of the field.
217const GENERATOR: Fp = Fp::from_raw([
218    0x0000_0000_0000_0005,
219    0x0000_0000_0000_0000,
220    0x0000_0000_0000_0000,
221    0x0000_0000_0000_0000,
222]);
223
224const S: u32 = 32;
225
226/// GENERATOR^t where t * 2^s + 1 = p
227/// with t odd. In other words, this
228/// is a 2^s root of unity.
229const ROOT_OF_UNITY: Fp = Fp::from_raw([
230    0xbdad6fabd87ea32f,
231    0xea322bf2b7bb7584,
232    0x362120830561f81a,
233    0x2bce74deac30ebda,
234]);
235
236/// GENERATOR^{2^s} where t * 2^s + 1 = p
237/// with t odd. In other words, this
238/// is a t root of unity.
239const DELTA: Fp = Fp::from_raw([
240    0x6a6ccd20dd7b9ba2,
241    0xf5e4f3f13eee5636,
242    0xbd455b7112a5049d,
243    0x0a757d0f0006ab6c,
244]);
245
246/// `(t - 1) // 2` where t * 2^s + 1 = p with t odd.
247#[cfg(any(test, not(feature = "sqrt-table")))]
248const T_MINUS1_OVER2: [u64; 4] = [
249    0x04a6_7c8d_cc96_9876,
250    0x0000_0000_1123_4c7e,
251    0x0000_0000_0000_0000,
252    0x0000_0000_2000_0000,
253];
254
255impl Default for Fp {
256    #[inline]
257    fn default() -> Self {
258        Self::zero()
259    }
260}
261
262impl Fp {
263    /// Returns zero, the additive identity.
264    #[inline]
265    pub const fn zero() -> Fp {
266        Fp([0, 0, 0, 0])
267    }
268
269    /// Returns one, the multiplicative identity.
270    #[inline]
271    pub const fn one() -> Fp {
272        R
273    }
274
275    /// Doubles this field element.
276    #[inline]
277    pub const fn double(&self) -> Fp {
278        // TODO: This can be achieved more efficiently with a bitshift.
279        self.add(self)
280    }
281
282    fn from_u512(limbs: [u64; 8]) -> Fp {
283        // We reduce an arbitrary 512-bit number by decomposing it into two 256-bit digits
284        // with the higher bits multiplied by 2^256. Thus, we perform two reductions
285        //
286        // 1. the lower bits are multiplied by R^2, as normal
287        // 2. the upper bits are multiplied by R^2 * 2^256 = R^3
288        //
289        // and computing their sum in the field. It remains to see that arbitrary 256-bit
290        // numbers can be placed into Montgomery form safely using the reduction. The
291        // reduction works so long as the product is less than R=2^256 multiplied by
292        // the modulus. This holds because for any `c` smaller than the modulus, we have
293        // that (2^256 - 1)*c is an acceptable product for the reduction. Therefore, the
294        // reduction always works so long as `c` is in the field; in this case it is either the
295        // constant `R2` or `R3`.
296        let d0 = Fp([limbs[0], limbs[1], limbs[2], limbs[3]]);
297        let d1 = Fp([limbs[4], limbs[5], limbs[6], limbs[7]]);
298        // Convert to Montgomery form
299        d0 * R2 + d1 * R3
300    }
301
302    /// Converts from an integer represented in little endian
303    /// into its (congruent) `Fp` representation.
304    pub const fn from_raw(val: [u64; 4]) -> Self {
305        (&Fp(val)).mul(&R2)
306    }
307
308    /// Squares this element.
309    #[cfg_attr(not(feature = "uninline-portable"), inline)]
310    pub const fn square(&self) -> Fp {
311        let (r1, carry) = mac(0, self.0[0], self.0[1], 0);
312        let (r2, carry) = mac(0, self.0[0], self.0[2], carry);
313        let (r3, r4) = mac(0, self.0[0], self.0[3], carry);
314
315        let (r3, carry) = mac(r3, self.0[1], self.0[2], 0);
316        let (r4, r5) = mac(r4, self.0[1], self.0[3], carry);
317
318        let (r5, r6) = mac(r5, self.0[2], self.0[3], 0);
319
320        let r7 = r6 >> 63;
321        let r6 = (r6 << 1) | (r5 >> 63);
322        let r5 = (r5 << 1) | (r4 >> 63);
323        let r4 = (r4 << 1) | (r3 >> 63);
324        let r3 = (r3 << 1) | (r2 >> 63);
325        let r2 = (r2 << 1) | (r1 >> 63);
326        let r1 = r1 << 1;
327
328        let (r0, carry) = mac(0, self.0[0], self.0[0], 0);
329        let (r1, carry) = adc(0, r1, carry);
330        let (r2, carry) = mac(r2, self.0[1], self.0[1], carry);
331        let (r3, carry) = adc(0, r3, carry);
332        let (r4, carry) = mac(r4, self.0[2], self.0[2], carry);
333        let (r5, carry) = adc(0, r5, carry);
334        let (r6, carry) = mac(r6, self.0[3], self.0[3], carry);
335        let (r7, _) = adc(0, r7, carry);
336
337        Fp::montgomery_reduce(r0, r1, r2, r3, r4, r5, r6, r7)
338    }
339
340    #[allow(clippy::too_many_arguments)]
341    #[cfg_attr(not(feature = "uninline-portable"), inline(always))]
342    const fn montgomery_reduce(
343        r0: u64,
344        r1: u64,
345        r2: u64,
346        r3: u64,
347        r4: u64,
348        r5: u64,
349        r6: u64,
350        r7: u64,
351    ) -> Self {
352        // The Montgomery reduction here is based on Algorithm 14.32 in
353        // Handbook of Applied Cryptography
354        // <http://cacr.uwaterloo.ca/hac/about/chap14.pdf>.
355
356        let k = r0.wrapping_mul(INV);
357        let (_, carry) = mac(r0, k, MODULUS.0[0], 0);
358        let (r1, carry) = mac(r1, k, MODULUS.0[1], carry);
359        let (r2, carry) = mac(r2, k, MODULUS.0[2], carry);
360        let (r3, carry) = mac(r3, k, MODULUS.0[3], carry);
361        let (r4, carry2) = adc(r4, 0, carry);
362
363        let k = r1.wrapping_mul(INV);
364        let (_, carry) = mac(r1, k, MODULUS.0[0], 0);
365        let (r2, carry) = mac(r2, k, MODULUS.0[1], carry);
366        let (r3, carry) = mac(r3, k, MODULUS.0[2], carry);
367        let (r4, carry) = mac(r4, k, MODULUS.0[3], carry);
368        let (r5, carry2) = adc(r5, carry2, carry);
369
370        let k = r2.wrapping_mul(INV);
371        let (_, carry) = mac(r2, k, MODULUS.0[0], 0);
372        let (r3, carry) = mac(r3, k, MODULUS.0[1], carry);
373        let (r4, carry) = mac(r4, k, MODULUS.0[2], carry);
374        let (r5, carry) = mac(r5, k, MODULUS.0[3], carry);
375        let (r6, carry2) = adc(r6, carry2, carry);
376
377        let k = r3.wrapping_mul(INV);
378        let (_, carry) = mac(r3, k, MODULUS.0[0], 0);
379        let (r4, carry) = mac(r4, k, MODULUS.0[1], carry);
380        let (r5, carry) = mac(r5, k, MODULUS.0[2], carry);
381        let (r6, carry) = mac(r6, k, MODULUS.0[3], carry);
382        let (r7, _) = adc(r7, carry2, carry);
383
384        // Result may be within MODULUS of the correct value
385        (&Fp([r4, r5, r6, r7])).sub(&MODULUS)
386    }
387
388    /// Multiplies `rhs` by `self`, returning the result.
389    #[cfg_attr(not(feature = "uninline-portable"), inline)]
390    pub const fn mul(&self, rhs: &Self) -> Self {
391        // Schoolbook multiplication
392
393        let (r0, carry) = mac(0, self.0[0], rhs.0[0], 0);
394        let (r1, carry) = mac(0, self.0[0], rhs.0[1], carry);
395        let (r2, carry) = mac(0, self.0[0], rhs.0[2], carry);
396        let (r3, r4) = mac(0, self.0[0], rhs.0[3], carry);
397
398        let (r1, carry) = mac(r1, self.0[1], rhs.0[0], 0);
399        let (r2, carry) = mac(r2, self.0[1], rhs.0[1], carry);
400        let (r3, carry) = mac(r3, self.0[1], rhs.0[2], carry);
401        let (r4, r5) = mac(r4, self.0[1], rhs.0[3], carry);
402
403        let (r2, carry) = mac(r2, self.0[2], rhs.0[0], 0);
404        let (r3, carry) = mac(r3, self.0[2], rhs.0[1], carry);
405        let (r4, carry) = mac(r4, self.0[2], rhs.0[2], carry);
406        let (r5, r6) = mac(r5, self.0[2], rhs.0[3], carry);
407
408        let (r3, carry) = mac(r3, self.0[3], rhs.0[0], 0);
409        let (r4, carry) = mac(r4, self.0[3], rhs.0[1], carry);
410        let (r5, carry) = mac(r5, self.0[3], rhs.0[2], carry);
411        let (r6, r7) = mac(r6, self.0[3], rhs.0[3], carry);
412
413        Fp::montgomery_reduce(r0, r1, r2, r3, r4, r5, r6, r7)
414    }
415
416    /// Subtracts `rhs` from `self`, returning the result.
417    #[cfg_attr(not(feature = "uninline-portable"), inline)]
418    pub const fn sub(&self, rhs: &Self) -> Self {
419        let (d0, borrow) = sbb(self.0[0], rhs.0[0], 0);
420        let (d1, borrow) = sbb(self.0[1], rhs.0[1], borrow);
421        let (d2, borrow) = sbb(self.0[2], rhs.0[2], borrow);
422        let (d3, borrow) = sbb(self.0[3], rhs.0[3], borrow);
423
424        // If underflow occurred on the final limb, borrow = 0xfff...fff, otherwise
425        // borrow = 0x000...000. Thus, we use it as a mask to conditionally add the modulus.
426        let (d0, carry) = adc(d0, MODULUS.0[0] & borrow, 0);
427        let (d1, carry) = adc(d1, MODULUS.0[1] & borrow, carry);
428        let (d2, carry) = adc(d2, MODULUS.0[2] & borrow, carry);
429        let (d3, _) = adc(d3, MODULUS.0[3] & borrow, carry);
430
431        Fp([d0, d1, d2, d3])
432    }
433
434    /// Adds `rhs` to `self`, returning the result.
435    #[cfg_attr(not(feature = "uninline-portable"), inline)]
436    pub const fn add(&self, rhs: &Self) -> Self {
437        let (d0, carry) = adc(self.0[0], rhs.0[0], 0);
438        let (d1, carry) = adc(self.0[1], rhs.0[1], carry);
439        let (d2, carry) = adc(self.0[2], rhs.0[2], carry);
440        let (d3, _) = adc(self.0[3], rhs.0[3], carry);
441
442        // Attempt to subtract the modulus, to ensure the value
443        // is smaller than the modulus.
444        (&Fp([d0, d1, d2, d3])).sub(&MODULUS)
445    }
446
447    /// Negates `self`.
448    #[cfg_attr(not(feature = "uninline-portable"), inline)]
449    pub const fn neg(&self) -> Self {
450        // Subtract `self` from `MODULUS` to negate. Ignore the final
451        // borrow because it cannot underflow; self is guaranteed to
452        // be in the field.
453        let (d0, borrow) = sbb(MODULUS.0[0], self.0[0], 0);
454        let (d1, borrow) = sbb(MODULUS.0[1], self.0[1], borrow);
455        let (d2, borrow) = sbb(MODULUS.0[2], self.0[2], borrow);
456        let (d3, _) = sbb(MODULUS.0[3], self.0[3], borrow);
457
458        // `tmp` could be `MODULUS` if `self` was zero. Create a mask that is
459        // zero if `self` was zero, and `u64::max_value()` if self was nonzero.
460        let mask = (((self.0[0] | self.0[1] | self.0[2] | self.0[3]) == 0) as u64).wrapping_sub(1);
461
462        Fp([d0 & mask, d1 & mask, d2 & mask, d3 & mask])
463    }
464}
465
466impl From<Fp> for [u8; 32] {
467    fn from(value: Fp) -> [u8; 32] {
468        value.to_repr()
469    }
470}
471
472impl<'a> From<&'a Fp> for [u8; 32] {
473    fn from(value: &'a Fp) -> [u8; 32] {
474        value.to_repr()
475    }
476}
477
478impl ff::Field for Fp {
479    const ZERO: Self = Self::zero();
480    const ONE: Self = Self::one();
481
482    fn random(mut rng: impl RngCore) -> Self {
483        Self::from_u512([
484            rng.next_u64(),
485            rng.next_u64(),
486            rng.next_u64(),
487            rng.next_u64(),
488            rng.next_u64(),
489            rng.next_u64(),
490            rng.next_u64(),
491            rng.next_u64(),
492        ])
493    }
494
495    fn double(&self) -> Self {
496        self.double()
497    }
498
499    #[inline(always)]
500    fn square(&self) -> Self {
501        self.square()
502    }
503
504    fn sqrt_ratio(num: &Self, div: &Self) -> (Choice, Self) {
505        #[cfg(feature = "sqrt-table")]
506        {
507            FP_TABLES.sqrt_ratio(num, div)
508        }
509
510        #[cfg(not(feature = "sqrt-table"))]
511        ff::helpers::sqrt_ratio_generic(num, div)
512    }
513
514    #[cfg(feature = "sqrt-table")]
515    fn sqrt_alt(&self) -> (Choice, Self) {
516        FP_TABLES.sqrt_alt(self)
517    }
518
519    /// Computes the square root of this element, if it exists.
520    fn sqrt(&self) -> CtOption<Self> {
521        #[cfg(feature = "sqrt-table")]
522        {
523            let (is_square, res) = FP_TABLES.sqrt_alt(self);
524            CtOption::new(res, is_square)
525        }
526
527        #[cfg(not(feature = "sqrt-table"))]
528        ff::helpers::sqrt_tonelli_shanks(self, &T_MINUS1_OVER2)
529    }
530
531    /// Computes the multiplicative inverse of this element,
532    /// failing if the element is zero.
533    fn invert(&self) -> CtOption<Self> {
534        let tmp = self.pow_vartime(&[
535            0x992d30ecffffffff,
536            0x224698fc094cf91b,
537            0x0,
538            0x4000000000000000,
539        ]);
540
541        CtOption::new(tmp, !self.ct_eq(&Self::zero()))
542    }
543
544    fn pow_vartime<S: AsRef<[u64]>>(&self, exp: S) -> Self {
545        let mut res = Self::one();
546        let mut found_one = false;
547        for e in exp.as_ref().iter().rev() {
548            for i in (0..64).rev() {
549                if found_one {
550                    res = res.square();
551                }
552
553                if ((*e >> i) & 1) == 1 {
554                    found_one = true;
555                    res *= self;
556                }
557            }
558        }
559        res
560    }
561}
562
563impl ff::PrimeField for Fp {
564    type Repr = [u8; 32];
565
566    const MODULUS: &'static str =
567        "0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001";
568    const TWO_INV: Self = Fp::from_raw([
569        0xcc96987680000001,
570        0x11234c7e04a67c8d,
571        0x0000000000000000,
572        0x2000000000000000,
573    ]);
574    const NUM_BITS: u32 = 255;
575    const CAPACITY: u32 = 254;
576    const MULTIPLICATIVE_GENERATOR: Self = GENERATOR;
577    const S: u32 = S;
578    const ROOT_OF_UNITY: Self = ROOT_OF_UNITY;
579    const ROOT_OF_UNITY_INV: Self = Fp::from_raw([
580        0xf0b87c7db2ce91f6,
581        0x84a0a1d8859f066f,
582        0xb4ed8e647196dad1,
583        0x2cd5282c53116b5c,
584    ]);
585    const DELTA: Self = DELTA;
586
587    fn from_u128(v: u128) -> Self {
588        Fp::from_raw([v as u64, (v >> 64) as u64, 0, 0])
589    }
590
591    fn from_repr(repr: Self::Repr) -> CtOption<Self> {
592        let mut tmp = Fp([0, 0, 0, 0]);
593
594        tmp.0[0] = u64::from_le_bytes(repr[0..8].try_into().unwrap());
595        tmp.0[1] = u64::from_le_bytes(repr[8..16].try_into().unwrap());
596        tmp.0[2] = u64::from_le_bytes(repr[16..24].try_into().unwrap());
597        tmp.0[3] = u64::from_le_bytes(repr[24..32].try_into().unwrap());
598
599        // Try to subtract the modulus
600        let (_, borrow) = sbb(tmp.0[0], MODULUS.0[0], 0);
601        let (_, borrow) = sbb(tmp.0[1], MODULUS.0[1], borrow);
602        let (_, borrow) = sbb(tmp.0[2], MODULUS.0[2], borrow);
603        let (_, borrow) = sbb(tmp.0[3], MODULUS.0[3], borrow);
604
605        // If the element is smaller than MODULUS then the
606        // subtraction will underflow, producing a borrow value
607        // of 0xffff...ffff. Otherwise, it'll be zero.
608        let is_some = (borrow as u8) & 1;
609
610        // Convert to Montgomery form by computing
611        // (a.R^0 * R^2) / R = a.R
612        tmp *= &R2;
613
614        CtOption::new(tmp, Choice::from(is_some))
615    }
616
617    fn to_repr(&self) -> Self::Repr {
618        // Turn into canonical form by computing
619        // (a.R) / R = a
620        let tmp = Fp::montgomery_reduce(self.0[0], self.0[1], self.0[2], self.0[3], 0, 0, 0, 0);
621
622        let mut res = [0; 32];
623        res[0..8].copy_from_slice(&tmp.0[0].to_le_bytes());
624        res[8..16].copy_from_slice(&tmp.0[1].to_le_bytes());
625        res[16..24].copy_from_slice(&tmp.0[2].to_le_bytes());
626        res[24..32].copy_from_slice(&tmp.0[3].to_le_bytes());
627
628        res
629    }
630
631    fn is_odd(&self) -> Choice {
632        Choice::from(self.to_repr()[0] & 1)
633    }
634}
635
636#[cfg(all(feature = "bits", not(target_pointer_width = "64")))]
637type ReprBits = [u32; 8];
638
639#[cfg(all(feature = "bits", target_pointer_width = "64"))]
640type ReprBits = [u64; 4];
641
642#[cfg(feature = "bits")]
643#[cfg_attr(docsrs, doc(cfg(feature = "bits")))]
644impl PrimeFieldBits for Fp {
645    type ReprBits = ReprBits;
646
647    fn to_le_bits(&self) -> FieldBits<Self::ReprBits> {
648        let bytes = self.to_repr();
649
650        #[cfg(not(target_pointer_width = "64"))]
651        let limbs = [
652            u32::from_le_bytes(bytes[0..4].try_into().unwrap()),
653            u32::from_le_bytes(bytes[4..8].try_into().unwrap()),
654            u32::from_le_bytes(bytes[8..12].try_into().unwrap()),
655            u32::from_le_bytes(bytes[12..16].try_into().unwrap()),
656            u32::from_le_bytes(bytes[16..20].try_into().unwrap()),
657            u32::from_le_bytes(bytes[20..24].try_into().unwrap()),
658            u32::from_le_bytes(bytes[24..28].try_into().unwrap()),
659            u32::from_le_bytes(bytes[28..32].try_into().unwrap()),
660        ];
661
662        #[cfg(target_pointer_width = "64")]
663        let limbs = [
664            u64::from_le_bytes(bytes[0..8].try_into().unwrap()),
665            u64::from_le_bytes(bytes[8..16].try_into().unwrap()),
666            u64::from_le_bytes(bytes[16..24].try_into().unwrap()),
667            u64::from_le_bytes(bytes[24..32].try_into().unwrap()),
668        ];
669
670        FieldBits::new(limbs)
671    }
672
673    fn char_le_bits() -> FieldBits<Self::ReprBits> {
674        #[cfg(not(target_pointer_width = "64"))]
675        {
676            FieldBits::new(MODULUS_LIMBS_32)
677        }
678
679        #[cfg(target_pointer_width = "64")]
680        FieldBits::new(MODULUS.0)
681    }
682}
683
684#[cfg(feature = "sqrt-table")]
685lazy_static! {
686    // The perfect hash parameters are found by `squareroottab.sage` in zcash/pasta.
687    #[cfg_attr(docsrs, doc(cfg(feature = "sqrt-table")))]
688    static ref FP_TABLES: SqrtTables<Fp> = SqrtTables::new(0x11BE, 1098);
689}
690
691impl SqrtTableHelpers for Fp {
692    fn pow_by_t_minus1_over2(&self) -> Self {
693        let sqr = |x: Fp, i: u32| (0..i).fold(x, |x, _| x.square());
694
695        let r10 = self.square();
696        let r11 = r10 * self;
697        let r110 = r11.square();
698        let r111 = r110 * self;
699        let r1001 = r111 * r10;
700        let r1101 = r111 * r110;
701        let ra = sqr(*self, 129) * self;
702        let rb = sqr(ra, 7) * r1001;
703        let rc = sqr(rb, 7) * r1101;
704        let rd = sqr(rc, 4) * r11;
705        let re = sqr(rd, 6) * r111;
706        let rf = sqr(re, 3) * r111;
707        let rg = sqr(rf, 10) * r1001;
708        let rh = sqr(rg, 5) * r1001;
709        let ri = sqr(rh, 4) * r1001;
710        let rj = sqr(ri, 3) * r111;
711        let rk = sqr(rj, 4) * r1001;
712        let rl = sqr(rk, 5) * r11;
713        let rm = sqr(rl, 4) * r111;
714        let rn = sqr(rm, 4) * r11;
715        let ro = sqr(rn, 6) * r1001;
716        let rp = sqr(ro, 5) * r1101;
717        let rq = sqr(rp, 4) * r11;
718        let rr = sqr(rq, 7) * r111;
719        let rs = sqr(rr, 3) * r11;
720        rs.square() // rt
721    }
722
723    fn get_lower_32(&self) -> u32 {
724        // TODO: don't reduce, just hash the Montgomery form. (Requires rebuilding perfect hash table.)
725        let tmp = Fp::montgomery_reduce(self.0[0], self.0[1], self.0[2], self.0[3], 0, 0, 0, 0);
726
727        tmp.0[0] as u32
728    }
729}
730
731impl WithSmallOrderMulGroup<3> for Fp {
732    const ZETA: Self = Fp::from_raw([
733        0x1dad5ebdfdfe4ab9,
734        0x1d1f8bd237ad3149,
735        0x2caad5dc57aab1b0,
736        0x12ccca834acdba71,
737    ]);
738}
739
740impl FromUniformBytes<64> for Fp {
741    /// Converts a 512-bit little endian integer into
742    /// a `Fp` by reducing by the modulus.
743    fn from_uniform_bytes(bytes: &[u8; 64]) -> Fp {
744        Fp::from_u512([
745            u64::from_le_bytes(bytes[0..8].try_into().unwrap()),
746            u64::from_le_bytes(bytes[8..16].try_into().unwrap()),
747            u64::from_le_bytes(bytes[16..24].try_into().unwrap()),
748            u64::from_le_bytes(bytes[24..32].try_into().unwrap()),
749            u64::from_le_bytes(bytes[32..40].try_into().unwrap()),
750            u64::from_le_bytes(bytes[40..48].try_into().unwrap()),
751            u64::from_le_bytes(bytes[48..56].try_into().unwrap()),
752            u64::from_le_bytes(bytes[56..64].try_into().unwrap()),
753        ])
754    }
755}
756
757#[cfg(feature = "gpu")]
758impl ec_gpu::GpuName for Fp {
759    fn name() -> alloc::string::String {
760        ec_gpu::name!()
761    }
762}
763
764#[cfg(feature = "gpu")]
765impl ec_gpu::GpuField for Fp {
766    fn one() -> alloc::vec::Vec<u32> {
767        crate::fields::u64_to_u32(&R.0[..])
768    }
769
770    fn r2() -> alloc::vec::Vec<u32> {
771        crate::fields::u64_to_u32(&R2.0[..])
772    }
773
774    fn modulus() -> alloc::vec::Vec<u32> {
775        crate::fields::u64_to_u32(&MODULUS.0[..])
776    }
777}
778
779#[test]
780fn test_inv() {
781    // Compute -(r^{-1} mod 2^64) mod 2^64 by exponentiating
782    // by totient(2**64) - 1
783
784    let mut inv = 1u64;
785    for _ in 0..63 {
786        inv = inv.wrapping_mul(inv);
787        inv = inv.wrapping_mul(MODULUS.0[0]);
788    }
789    inv = inv.wrapping_neg();
790
791    assert_eq!(inv, INV);
792}
793
794#[test]
795fn test_sqrt() {
796    // NB: TWO_INV is standing in as a "random" field element
797    let v = (Fp::TWO_INV).square().sqrt().unwrap();
798    assert!(v == Fp::TWO_INV || (-v) == Fp::TWO_INV);
799}
800
801#[test]
802fn test_sqrt_32bit_overflow() {
803    assert!((Fp::from(5)).sqrt().is_none().unwrap_u8() == 1);
804}
805
806#[test]
807fn test_pow_by_t_minus1_over2() {
808    // NB: TWO_INV is standing in as a "random" field element
809    let v = (Fp::TWO_INV).pow_by_t_minus1_over2();
810    assert!(v == ff::Field::pow_vartime(&Fp::TWO_INV, &T_MINUS1_OVER2));
811}
812
813#[test]
814fn test_sqrt_ratio_and_alt() {
815    // (true, sqrt(num/div)), if num and div are nonzero and num/div is a square in the field
816    let num = (Fp::TWO_INV).square();
817    let div = Fp::from(25);
818    let div_inverse = div.invert().unwrap();
819    let expected = Fp::TWO_INV * Fp::from(5).invert().unwrap();
820    let (is_square, v) = Fp::sqrt_ratio(&num, &div);
821    assert!(bool::from(is_square));
822    assert!(v == expected || (-v) == expected);
823
824    let (is_square_alt, v_alt) = Fp::sqrt_alt(&(num * div_inverse));
825    assert!(bool::from(is_square_alt));
826    assert!(v_alt == v);
827
828    // (false, sqrt(ROOT_OF_UNITY * num/div)), if num and div are nonzero and num/div is a nonsquare in the field
829    let num = num * Fp::ROOT_OF_UNITY;
830    let expected = Fp::TWO_INV * Fp::ROOT_OF_UNITY * Fp::from(5).invert().unwrap();
831    let (is_square, v) = Fp::sqrt_ratio(&num, &div);
832    assert!(!bool::from(is_square));
833    assert!(v == expected || (-v) == expected);
834
835    let (is_square_alt, v_alt) = Fp::sqrt_alt(&(num * div_inverse));
836    assert!(!bool::from(is_square_alt));
837    assert!(v_alt == v);
838
839    // (true, 0), if num is zero
840    let num = Fp::zero();
841    let expected = Fp::zero();
842    let (is_square, v) = Fp::sqrt_ratio(&num, &div);
843    assert!(bool::from(is_square));
844    assert!(v == expected);
845
846    let (is_square_alt, v_alt) = Fp::sqrt_alt(&(num * div_inverse));
847    assert!(bool::from(is_square_alt));
848    assert!(v_alt == v);
849
850    // (false, 0), if num is nonzero and div is zero
851    let num = (Fp::TWO_INV).square();
852    let div = Fp::zero();
853    let expected = Fp::zero();
854    let (is_square, v) = Fp::sqrt_ratio(&num, &div);
855    assert!(!bool::from(is_square));
856    assert!(v == expected);
857}
858
859#[test]
860fn test_zeta() {
861    assert_eq!(
862        format!("{:?}", Fp::ZETA),
863        "0x12ccca834acdba712caad5dc57aab1b01d1f8bd237ad31491dad5ebdfdfe4ab9"
864    );
865
866    let a = Fp::ZETA;
867    assert!(a != Fp::one());
868    let b = a * a;
869    assert!(b != Fp::one());
870    let c = b * a;
871    assert!(c == Fp::one());
872}
873
874#[test]
875fn test_root_of_unity() {
876    assert_eq!(
877        Fp::ROOT_OF_UNITY.pow_vartime(&[1 << Fp::S, 0, 0, 0]),
878        Fp::one()
879    );
880}
881
882#[test]
883fn test_inv_root_of_unity() {
884    assert_eq!(Fp::ROOT_OF_UNITY_INV, Fp::ROOT_OF_UNITY.invert().unwrap());
885}
886
887#[test]
888fn test_inv_2() {
889    assert_eq!(Fp::TWO_INV, Fp::from(2).invert().unwrap());
890}
891
892#[test]
893fn test_delta() {
894    assert_eq!(Fp::DELTA, GENERATOR.pow(&[1u64 << Fp::S, 0, 0, 0]));
895    assert_eq!(
896        Fp::DELTA,
897        Fp::MULTIPLICATIVE_GENERATOR.pow(&[1u64 << Fp::S, 0, 0, 0])
898    );
899}
900
901#[cfg(not(target_pointer_width = "64"))]
902#[test]
903fn consistent_modulus_limbs() {
904    for (a, &b) in MODULUS
905        .0
906        .iter()
907        .flat_map(|&limb| {
908            Some(limb as u32)
909                .into_iter()
910                .chain(Some((limb >> 32) as u32))
911        })
912        .zip(MODULUS_LIMBS_32.iter())
913    {
914        assert_eq!(a, b);
915    }
916}
917
918#[test]
919fn test_from_u512() {
920    assert_eq!(
921        Fp::from_raw([
922            0x3daec14d565241d9,
923            0x0b7af45b6073944b,
924            0xea5b8bd611a5bd4c,
925            0x150160330625db3d
926        ]),
927        Fp::from_u512([
928            0xee155641297678a1,
929            0xd83e156bdbfdbe65,
930            0xd9ccd834c68ba0b5,
931            0xf508ede312272758,
932            0x038df7cbf8228e89,
933            0x3505a1e4a3c74b41,
934            0xbfa46f775eb82db3,
935            0x26ebe27e262f471d
936        ])
937    );
938}