1#![allow(clippy::needless_borrow)]
6use core::cmp::Ordering;
7use core::fmt;
8use core::ops::{Add, Mul, Neg, Sub};
9use ff::{Field, PrimeField, WithSmallOrderMulGroup};
10use rand_core::RngCore;
11use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
12
13use crate::arithmetic::{adc, mac, sbb};
14use crate::{
15 impl_add_binop_specify_output, impl_binops_additive, impl_binops_additive_specify_output,
16 impl_binops_multiplicative, impl_binops_multiplicative_mixed, impl_sub_binop_specify_output,
17};
18#[derive(Copy, Clone, PartialEq, Eq, Hash)]
24pub struct Fp(pub(crate) [u64; 6]);
25
26impl fmt::Debug for Fp {
27 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
28 let tmp = self.to_bytes();
29 write!(f, "0x")?;
30 for &b in tmp.iter().rev() {
31 write!(f, "{b:02x}")?;
32 }
33 Ok(())
34 }
35}
36
37impl Default for Fp {
38 fn default() -> Self {
39 Fp::zero()
40 }
41}
42
43#[cfg(feature = "zeroize")]
44impl zeroize::DefaultIsZeroes for Fp {}
45
46impl ConstantTimeEq for Fp {
47 fn ct_eq(&self, other: &Self) -> Choice {
48 self.0[0].ct_eq(&other.0[0])
49 & self.0[1].ct_eq(&other.0[1])
50 & self.0[2].ct_eq(&other.0[2])
51 & self.0[3].ct_eq(&other.0[3])
52 & self.0[4].ct_eq(&other.0[4])
53 & self.0[5].ct_eq(&other.0[5])
54 }
55}
56
57impl Ord for Fp {
66 fn cmp(&self, other: &Self) -> Ordering {
67 let left = self.to_repr().0;
68 let right = other.to_repr().0;
69 left.iter()
70 .zip(right.iter())
71 .rev()
72 .find_map(|(left_byte, right_byte)| match left_byte.cmp(right_byte) {
73 Ordering::Equal => None,
74 res => Some(res),
75 })
76 .unwrap_or(Ordering::Equal)
77 }
78}
79
80impl PartialOrd for Fp {
81 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
82 Some(self.cmp(other))
83 }
84}
85
86impl ConditionallySelectable for Fp {
87 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
88 Fp([
89 u64::conditional_select(&a.0[0], &b.0[0], choice),
90 u64::conditional_select(&a.0[1], &b.0[1], choice),
91 u64::conditional_select(&a.0[2], &b.0[2], choice),
92 u64::conditional_select(&a.0[3], &b.0[3], choice),
93 u64::conditional_select(&a.0[4], &b.0[4], choice),
94 u64::conditional_select(&a.0[5], &b.0[5], choice),
95 ])
96 }
97}
98
99impl From<u64> for Fp {
100 fn from(value: u64) -> Self {
101 Self([value, 0, 0, 0, 0, 0]) * R2
102 }
103}
104
105const MODULUS: [u64; 6] = [
107 0xb9fe_ffff_ffff_aaab,
108 0x1eab_fffe_b153_ffff,
109 0x6730_d2a0_f6b0_f624,
110 0x6477_4b84_f385_12bf,
111 0x4b1b_a7b6_434b_acd7,
112 0x1a01_11ea_397f_e69a,
113];
114
115const INV: u64 = 0x89f3_fffc_fffc_fffd;
117
118const R: Fp = Fp([
120 0x7609_0000_0002_fffd,
121 0xebf4_000b_c40c_0002,
122 0x5f48_9857_53c7_58ba,
123 0x77ce_5853_7052_5745,
124 0x5c07_1a97_a256_ec6d,
125 0x15f6_5ec3_fa80_e493,
126]);
127
128const R2: Fp = Fp([
130 0xf4df_1f34_1c34_1746,
131 0x0a76_e6a6_09d1_04f1,
132 0x8de5_476c_4c95_b6d5,
133 0x67eb_88a9_939d_83c0,
134 0x9a79_3e85_b519_952d,
135 0x1198_8fe5_92ca_e3aa,
136]);
137
138const R3: Fp = Fp([
140 0xed48_ac6b_d94c_a1e0,
141 0x315f_831e_03a7_adf8,
142 0x9a53_352a_615e_29dd,
143 0x34c0_4e5e_921e_1761,
144 0x2512_d435_6572_4728,
145 0x0aa6_3460_9175_5d4d,
146]);
147
148const TWO_INV: Fp = Fp([
153 0x1804000000015554,
154 0x855000053ab00001,
155 0x633cb57c253c276f,
156 0x6e22d1ec31ebb502,
157 0xd3916126f2d14ca2,
158 0x17fbb8571a006596,
159]);
160
161const GENERATOR: Fp = Fp([
166 0x321300000006554f,
167 0xb93c0018d6c40005,
168 0x57605e0db0ddbb51,
169 0x8b256521ed1f9bcb,
170 0x6cf28d7901622c03,
171 0x11ebab9dbb81e28c,
172]);
173
174const ROOT_OF_UNITY: Fp = Fp([
179 0x43f5fffffffcaaae,
180 0x32b7fff2ed47fffd,
181 0x07e83a49a2e99d69,
182 0xeca8f3318332bb7a,
183 0xef148d1ea0f4c069,
184 0x40ab3263eff0206,
185]);
186
187const ROOT_OF_UNITY_INV: Fp = Fp([
192 0x43f5fffffffcaaae,
193 0x32b7fff2ed47fffd,
194 0x07e83a49a2e99d69,
195 0xeca8f3318332bb7a,
196 0xef148d1ea0f4c069,
197 0x40ab3263eff0206,
198]);
199
200const DELTA: Fp = Fp([
206 0xaa270000000cfff3,
207 0x53cc0032fc34000a,
208 0x478fe97a6b0a807f,
209 0xb1d37ebee6ba24d7,
210 0x8ec9733bbf78ab2f,
211 0x9d645513d83de7e,
212]);
213
214const ZETA: Fp = Fp([
219 0xcd03c9e48671f071,
220 0x5dab22461fcda5d2,
221 0x587042afd3851b95,
222 0x8eb60ebe01bacb9e,
223 0x03f97d6e83d050d2,
224 0x18f0206554638741,
225]);
226
227impl<'a> Neg for &'a Fp {
228 type Output = Fp;
229
230 #[inline]
231 fn neg(self) -> Fp {
232 self.neg()
233 }
234}
235
236impl Neg for Fp {
237 type Output = Fp;
238
239 #[inline]
240 fn neg(self) -> Fp {
241 -&self
242 }
243}
244
245impl<'a, 'b> Sub<&'b Fp> for &'a Fp {
246 type Output = Fp;
247
248 #[inline]
249 fn sub(self, rhs: &'b Fp) -> Fp {
250 self.sub(rhs)
251 }
252}
253
254impl<'a, 'b> Add<&'b Fp> for &'a Fp {
255 type Output = Fp;
256
257 #[inline]
258 fn add(self, rhs: &'b Fp) -> Fp {
259 self.add(rhs)
260 }
261}
262
263impl<'a, 'b> Mul<&'b Fp> for &'a Fp {
264 type Output = Fp;
265
266 #[inline]
267 fn mul(self, rhs: &'b Fp) -> Fp {
268 self.mul(rhs)
269 }
270}
271
272impl_binops_additive!(Fp, Fp);
273impl_binops_multiplicative!(Fp, Fp);
274
275impl<T> core::iter::Sum<T> for Fp
276where
277 T: core::borrow::Borrow<Fp>,
278{
279 fn sum<I>(iter: I) -> Self
280 where
281 I: Iterator<Item = T>,
282 {
283 iter.fold(Self::zero(), |acc, item| acc + item.borrow())
284 }
285}
286
287impl<T> core::iter::Product<T> for Fp
288where
289 T: core::borrow::Borrow<Fp>,
290{
291 fn product<I>(iter: I) -> Self
292 where
293 I: Iterator<Item = T>,
294 {
295 iter.fold(Self::one(), |acc, item| acc * item.borrow())
296 }
297}
298
299impl Field for Fp {
300 const ZERO: Self = Fp::zero();
301 const ONE: Self = Fp::one();
302
303 fn random(rng: impl RngCore) -> Self {
304 Self::random(rng)
305 }
306
307 fn square(&self) -> Self {
308 self.square()
309 }
310
311 fn double(&self) -> Self {
312 self.add(self)
313 }
314
315 fn invert(&self) -> CtOption<Self> {
316 self.invert()
317 }
318
319 fn sqrt_ratio(num: &Self, div: &Self) -> (Choice, Self) {
320 ff::helpers::sqrt_ratio_generic(num, div)
321 }
322
323 fn sqrt(&self) -> CtOption<Self> {
324 self.sqrt()
325 }
326}
327
328#[derive(Debug, Clone, Copy)]
331pub struct ReprFp(pub(crate) [u8; 48]);
332
333impl AsMut<[u8]> for ReprFp {
334 fn as_mut(&mut self) -> &mut [u8] {
335 &mut self.0[..]
336 }
337}
338
339impl AsRef<[u8]> for ReprFp {
340 fn as_ref(&self) -> &[u8] {
341 &self.0[..]
342 }
343}
344
345impl AsRef<[u8; 48]> for ReprFp {
346 fn as_ref(&self) -> &[u8; 48] {
347 &self.0
348 }
349}
350
351impl From<[u8; 48]> for ReprFp {
352 fn from(value: [u8; 48]) -> Self {
353 Self(value)
356 }
357}
358
359impl Default for ReprFp {
360 fn default() -> Self {
361 Self([0u8; 48])
362 }
363}
364
365impl PrimeField for Fp {
366 type Repr = ReprFp;
367
368 fn from_repr(r: Self::Repr) -> CtOption<Self> {
369 Self::from_bytes(&r.0)
372 }
373
374 fn to_repr(&self) -> Self::Repr {
375 ReprFp(self.to_bytes())
376 }
377
378 fn is_odd(&self) -> Choice {
379 Choice::from(self.to_bytes()[0] & 1)
380 }
381
382 const MODULUS: &'static str = "0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab";
383 const NUM_BITS: u32 = 381;
384 const CAPACITY: u32 = Self::NUM_BITS - 1;
385 const TWO_INV: Self = TWO_INV;
386 const MULTIPLICATIVE_GENERATOR: Self = GENERATOR;
387 const S: u32 = 1;
388 const ROOT_OF_UNITY: Self = ROOT_OF_UNITY;
389 const ROOT_OF_UNITY_INV: Self = ROOT_OF_UNITY_INV;
390 const DELTA: Self = DELTA;
391}
392
393impl WithSmallOrderMulGroup<3> for Fp {
394 const ZETA: Self = ZETA;
395}
396
397impl Fp {
398 #[inline]
400 pub const fn zero() -> Fp {
401 Fp([0, 0, 0, 0, 0, 0])
402 }
403
404 #[inline]
406 pub const fn one() -> Fp {
407 R
408 }
409
410 pub fn from_bytes(bytes: &[u8; 48]) -> CtOption<Fp> {
413 let mut tmp = Fp([0, 0, 0, 0, 0, 0]);
414
415 tmp.0[0] = u64::from_le_bytes(<[u8; 8]>::try_from(&bytes[0..8]).unwrap());
416 tmp.0[1] = u64::from_le_bytes(<[u8; 8]>::try_from(&bytes[8..16]).unwrap());
417 tmp.0[2] = u64::from_le_bytes(<[u8; 8]>::try_from(&bytes[16..24]).unwrap());
418 tmp.0[3] = u64::from_le_bytes(<[u8; 8]>::try_from(&bytes[24..32]).unwrap());
419 tmp.0[4] = u64::from_le_bytes(<[u8; 8]>::try_from(&bytes[32..40]).unwrap());
420 tmp.0[5] = u64::from_le_bytes(<[u8; 8]>::try_from(&bytes[40..48]).unwrap());
421
422 let (_, borrow) = sbb(tmp.0[0], MODULUS[0], 0);
424 let (_, borrow) = sbb(tmp.0[1], MODULUS[1], borrow);
425 let (_, borrow) = sbb(tmp.0[2], MODULUS[2], borrow);
426 let (_, borrow) = sbb(tmp.0[3], MODULUS[3], borrow);
427 let (_, borrow) = sbb(tmp.0[4], MODULUS[4], borrow);
428 let (_, borrow) = sbb(tmp.0[5], MODULUS[5], borrow);
429
430 let is_some = (borrow as u8) & 1;
434
435 tmp *= &R2;
438
439 CtOption::new(tmp, Choice::from(is_some))
440 }
441
442 pub fn from_bytes_be(bytes: &[u8; 48]) -> CtOption<Fp> {
445 let mut tmp = Fp([0, 0, 0, 0, 0, 0]);
446
447 tmp.0[5] = u64::from_be_bytes(<[u8; 8]>::try_from(&bytes[0..8]).unwrap());
448 tmp.0[4] = u64::from_be_bytes(<[u8; 8]>::try_from(&bytes[8..16]).unwrap());
449 tmp.0[3] = u64::from_be_bytes(<[u8; 8]>::try_from(&bytes[16..24]).unwrap());
450 tmp.0[2] = u64::from_be_bytes(<[u8; 8]>::try_from(&bytes[24..32]).unwrap());
451 tmp.0[1] = u64::from_be_bytes(<[u8; 8]>::try_from(&bytes[32..40]).unwrap());
452 tmp.0[0] = u64::from_be_bytes(<[u8; 8]>::try_from(&bytes[40..48]).unwrap());
453
454 let (_, borrow) = sbb(tmp.0[0], MODULUS[0], 0);
456 let (_, borrow) = sbb(tmp.0[1], MODULUS[1], borrow);
457 let (_, borrow) = sbb(tmp.0[2], MODULUS[2], borrow);
458 let (_, borrow) = sbb(tmp.0[3], MODULUS[3], borrow);
459 let (_, borrow) = sbb(tmp.0[4], MODULUS[4], borrow);
460 let (_, borrow) = sbb(tmp.0[5], MODULUS[5], borrow);
461
462 let is_some = (borrow as u8) & 1;
466
467 tmp *= &R2;
470
471 CtOption::new(tmp, Choice::from(is_some))
472 }
473
474 pub fn to_bytes_be(self) -> [u8; 48] {
477 let tmp = Fp::montgomery_reduce(
480 self.0[0], self.0[1], self.0[2], self.0[3], self.0[4], self.0[5], 0, 0, 0, 0, 0, 0,
481 );
482
483 let mut res = [0; 48];
484 res[0..8].copy_from_slice(&tmp.0[5].to_be_bytes());
485 res[8..16].copy_from_slice(&tmp.0[4].to_be_bytes());
486 res[16..24].copy_from_slice(&tmp.0[3].to_be_bytes());
487 res[24..32].copy_from_slice(&tmp.0[2].to_be_bytes());
488 res[32..40].copy_from_slice(&tmp.0[1].to_be_bytes());
489 res[40..48].copy_from_slice(&tmp.0[0].to_be_bytes());
490
491 res
492 }
493
494 pub fn to_bytes(self) -> [u8; 48] {
497 let tmp = Fp::montgomery_reduce(
500 self.0[0], self.0[1], self.0[2], self.0[3], self.0[4], self.0[5], 0, 0, 0, 0, 0, 0,
501 );
502
503 let mut res = [0; 48];
504 res[0..8].copy_from_slice(&tmp.0[0].to_le_bytes());
505 res[8..16].copy_from_slice(&tmp.0[1].to_le_bytes());
506 res[16..24].copy_from_slice(&tmp.0[2].to_le_bytes());
507 res[24..32].copy_from_slice(&tmp.0[3].to_le_bytes());
508 res[32..40].copy_from_slice(&tmp.0[4].to_le_bytes());
509 res[40..48].copy_from_slice(&tmp.0[5].to_le_bytes());
510
511 res
512 }
513
514 pub fn random(mut rng: impl RngCore) -> Fp {
516 let mut bytes = [0u8; 96];
517 rng.fill_bytes(&mut bytes);
518
519 Fp::from_u768([
521 u64::from_be_bytes(<[u8; 8]>::try_from(&bytes[0..8]).unwrap()),
522 u64::from_be_bytes(<[u8; 8]>::try_from(&bytes[8..16]).unwrap()),
523 u64::from_be_bytes(<[u8; 8]>::try_from(&bytes[16..24]).unwrap()),
524 u64::from_be_bytes(<[u8; 8]>::try_from(&bytes[24..32]).unwrap()),
525 u64::from_be_bytes(<[u8; 8]>::try_from(&bytes[32..40]).unwrap()),
526 u64::from_be_bytes(<[u8; 8]>::try_from(&bytes[40..48]).unwrap()),
527 u64::from_be_bytes(<[u8; 8]>::try_from(&bytes[48..56]).unwrap()),
528 u64::from_be_bytes(<[u8; 8]>::try_from(&bytes[56..64]).unwrap()),
529 u64::from_be_bytes(<[u8; 8]>::try_from(&bytes[64..72]).unwrap()),
530 u64::from_be_bytes(<[u8; 8]>::try_from(&bytes[72..80]).unwrap()),
531 u64::from_be_bytes(<[u8; 8]>::try_from(&bytes[80..88]).unwrap()),
532 u64::from_be_bytes(<[u8; 8]>::try_from(&bytes[88..96]).unwrap()),
533 ])
534 }
535
536 fn from_u768(limbs: [u64; 12]) -> Fp {
538 let d1 = Fp([limbs[11], limbs[10], limbs[9], limbs[8], limbs[7], limbs[6]]);
552 let d0 = Fp([limbs[5], limbs[4], limbs[3], limbs[2], limbs[1], limbs[0]]);
553 d0 * R2 + d1 * R3
555 }
556
557 pub fn lexicographically_largest(&self) -> Choice {
560 let tmp = Fp::montgomery_reduce(
567 self.0[0], self.0[1], self.0[2], self.0[3], self.0[4], self.0[5], 0, 0, 0, 0, 0, 0,
568 );
569
570 let (_, borrow) = sbb(tmp.0[0], 0xdcff_7fff_ffff_d556, 0);
571 let (_, borrow) = sbb(tmp.0[1], 0x0f55_ffff_58a9_ffff, borrow);
572 let (_, borrow) = sbb(tmp.0[2], 0xb398_6950_7b58_7b12, borrow);
573 let (_, borrow) = sbb(tmp.0[3], 0xb23b_a5c2_79c2_895f, borrow);
574 let (_, borrow) = sbb(tmp.0[4], 0x258d_d3db_21a5_d66b, borrow);
575 let (_, borrow) = sbb(tmp.0[5], 0x0d00_88f5_1cbf_f34d, borrow);
576
577 !Choice::from((borrow as u8) & 1)
584 }
585
586 pub const fn from_raw_unchecked(v: [u64; 6]) -> Fp {
589 Fp(v)
590 }
591
592 pub fn pow_vartime(&self, by: &[u64; 6]) -> Self {
596 let mut res = Self::one();
597 for e in by.iter().rev() {
598 for i in (0..64).rev() {
599 res = res.square();
600
601 if ((*e >> i) & 1) == 1 {
602 res *= self;
603 }
604 }
605 }
606 res
607 }
608
609 #[inline]
610 pub fn sqrt(&self) -> CtOption<Self> {
618 let sqrt = self.pow_vartime(&[
619 0xee7f_bfff_ffff_eaab,
620 0x07aa_ffff_ac54_ffff,
621 0xd9cc_34a8_3dac_3d89,
622 0xd91d_d2e1_3ce1_44af,
623 0x92c6_e9ed_90d2_eb35,
624 0x0680_447a_8e5f_f9a6,
625 ]);
626
627 CtOption::new(sqrt, sqrt.square().ct_eq(self))
628 }
629
630 #[inline]
631 pub fn invert(&self) -> CtOption<Self> {
635 let t = self.pow_vartime(&[
637 0xb9fe_ffff_ffff_aaa9,
638 0x1eab_fffe_b153_ffff,
639 0x6730_d2a0_f6b0_f624,
640 0x6477_4b84_f385_12bf,
641 0x4b1b_a7b6_434b_acd7,
642 0x1a01_11ea_397f_e69a,
643 ]);
644
645 CtOption::new(t, !self.is_zero())
646 }
647
648 #[inline]
649 const fn subtract_p(&self) -> Fp {
650 let (r0, borrow) = sbb(self.0[0], MODULUS[0], 0);
651 let (r1, borrow) = sbb(self.0[1], MODULUS[1], borrow);
652 let (r2, borrow) = sbb(self.0[2], MODULUS[2], borrow);
653 let (r3, borrow) = sbb(self.0[3], MODULUS[3], borrow);
654 let (r4, borrow) = sbb(self.0[4], MODULUS[4], borrow);
655 let (r5, borrow) = sbb(self.0[5], MODULUS[5], borrow);
656
657 let r0 = (self.0[0] & borrow) | (r0 & !borrow);
660 let r1 = (self.0[1] & borrow) | (r1 & !borrow);
661 let r2 = (self.0[2] & borrow) | (r2 & !borrow);
662 let r3 = (self.0[3] & borrow) | (r3 & !borrow);
663 let r4 = (self.0[4] & borrow) | (r4 & !borrow);
664 let r5 = (self.0[5] & borrow) | (r5 & !borrow);
665
666 Fp([r0, r1, r2, r3, r4, r5])
667 }
668
669 #[inline]
670 pub const fn add(&self, rhs: &Fp) -> Fp {
672 let (d0, carry) = adc(self.0[0], rhs.0[0], 0);
673 let (d1, carry) = adc(self.0[1], rhs.0[1], carry);
674 let (d2, carry) = adc(self.0[2], rhs.0[2], carry);
675 let (d3, carry) = adc(self.0[3], rhs.0[3], carry);
676 let (d4, carry) = adc(self.0[4], rhs.0[4], carry);
677 let (d5, _) = adc(self.0[5], rhs.0[5], carry);
678
679 (Fp([d0, d1, d2, d3, d4, d5])).subtract_p()
682 }
683
684 #[inline]
685 pub const fn neg(&self) -> Fp {
687 let (d0, borrow) = sbb(MODULUS[0], self.0[0], 0);
688 let (d1, borrow) = sbb(MODULUS[1], self.0[1], borrow);
689 let (d2, borrow) = sbb(MODULUS[2], self.0[2], borrow);
690 let (d3, borrow) = sbb(MODULUS[3], self.0[3], borrow);
691 let (d4, borrow) = sbb(MODULUS[4], self.0[4], borrow);
692 let (d5, _) = sbb(MODULUS[5], self.0[5], borrow);
693
694 let mask = (((self.0[0] | self.0[1] | self.0[2] | self.0[3] | self.0[4] | self.0[5]) == 0)
697 as u64)
698 .wrapping_sub(1);
699
700 Fp([
701 d0 & mask,
702 d1 & mask,
703 d2 & mask,
704 d3 & mask,
705 d4 & mask,
706 d5 & mask,
707 ])
708 }
709
710 #[inline]
711 pub const fn sub(&self, rhs: &Fp) -> Fp {
713 (&rhs.neg()).add(self)
714 }
715
716 #[inline]
721 pub(crate) fn sum_of_products<const T: usize>(a: [Fp; T], b: [Fp; T]) -> Fp {
722 let (u0, u1, u2, u3, u4, u5) =
739 (0..6).fold((0, 0, 0, 0, 0, 0), |(u0, u1, u2, u3, u4, u5), j| {
740 let (t0, t1, t2, t3, t4, t5, t6) = (0..T).fold(
743 (u0, u1, u2, u3, u4, u5, 0),
744 |(t0, t1, t2, t3, t4, t5, t6), i| {
745 let (t0, carry) = mac(t0, a[i].0[j], b[i].0[0], 0);
747 let (t1, carry) = mac(t1, a[i].0[j], b[i].0[1], carry);
748 let (t2, carry) = mac(t2, a[i].0[j], b[i].0[2], carry);
749 let (t3, carry) = mac(t3, a[i].0[j], b[i].0[3], carry);
750 let (t4, carry) = mac(t4, a[i].0[j], b[i].0[4], carry);
751 let (t5, carry) = mac(t5, a[i].0[j], b[i].0[5], carry);
752 let (t6, _) = adc(t6, 0, carry);
753
754 (t0, t1, t2, t3, t4, t5, t6)
755 },
756 );
757
758 let k = t0.wrapping_mul(INV);
761 let (_, carry) = mac(t0, k, MODULUS[0], 0);
762 let (r1, carry) = mac(t1, k, MODULUS[1], carry);
763 let (r2, carry) = mac(t2, k, MODULUS[2], carry);
764 let (r3, carry) = mac(t3, k, MODULUS[3], carry);
765 let (r4, carry) = mac(t4, k, MODULUS[4], carry);
766 let (r5, carry) = mac(t5, k, MODULUS[5], carry);
767 let (r6, _) = adc(t6, 0, carry);
768
769 (r1, r2, r3, r4, r5, r6)
770 });
771
772 (&Fp([u0, u1, u2, u3, u4, u5])).subtract_p()
775 }
776
777 #[inline(always)]
778 pub(crate) const fn montgomery_reduce(
779 t0: u64,
780 t1: u64,
781 t2: u64,
782 t3: u64,
783 t4: u64,
784 t5: u64,
785 t6: u64,
786 t7: u64,
787 t8: u64,
788 t9: u64,
789 t10: u64,
790 t11: u64,
791 ) -> Self {
792 let k = t0.wrapping_mul(INV);
797 let (_, carry) = mac(t0, k, MODULUS[0], 0);
798 let (r1, carry) = mac(t1, k, MODULUS[1], carry);
799 let (r2, carry) = mac(t2, k, MODULUS[2], carry);
800 let (r3, carry) = mac(t3, k, MODULUS[3], carry);
801 let (r4, carry) = mac(t4, k, MODULUS[4], carry);
802 let (r5, carry) = mac(t5, k, MODULUS[5], carry);
803 let (r6, r7) = adc(t6, 0, carry);
804
805 let k = r1.wrapping_mul(INV);
806 let (_, carry) = mac(r1, k, MODULUS[0], 0);
807 let (r2, carry) = mac(r2, k, MODULUS[1], carry);
808 let (r3, carry) = mac(r3, k, MODULUS[2], carry);
809 let (r4, carry) = mac(r4, k, MODULUS[3], carry);
810 let (r5, carry) = mac(r5, k, MODULUS[4], carry);
811 let (r6, carry) = mac(r6, k, MODULUS[5], carry);
812 let (r7, r8) = adc(t7, r7, carry);
813
814 let k = r2.wrapping_mul(INV);
815 let (_, carry) = mac(r2, k, MODULUS[0], 0);
816 let (r3, carry) = mac(r3, k, MODULUS[1], carry);
817 let (r4, carry) = mac(r4, k, MODULUS[2], carry);
818 let (r5, carry) = mac(r5, k, MODULUS[3], carry);
819 let (r6, carry) = mac(r6, k, MODULUS[4], carry);
820 let (r7, carry) = mac(r7, k, MODULUS[5], carry);
821 let (r8, r9) = adc(t8, r8, carry);
822
823 let k = r3.wrapping_mul(INV);
824 let (_, carry) = mac(r3, k, MODULUS[0], 0);
825 let (r4, carry) = mac(r4, k, MODULUS[1], carry);
826 let (r5, carry) = mac(r5, k, MODULUS[2], carry);
827 let (r6, carry) = mac(r6, k, MODULUS[3], carry);
828 let (r7, carry) = mac(r7, k, MODULUS[4], carry);
829 let (r8, carry) = mac(r8, k, MODULUS[5], carry);
830 let (r9, r10) = adc(t9, r9, carry);
831
832 let k = r4.wrapping_mul(INV);
833 let (_, carry) = mac(r4, k, MODULUS[0], 0);
834 let (r5, carry) = mac(r5, k, MODULUS[1], carry);
835 let (r6, carry) = mac(r6, k, MODULUS[2], carry);
836 let (r7, carry) = mac(r7, k, MODULUS[3], carry);
837 let (r8, carry) = mac(r8, k, MODULUS[4], carry);
838 let (r9, carry) = mac(r9, k, MODULUS[5], carry);
839 let (r10, r11) = adc(t10, r10, carry);
840
841 let k = r5.wrapping_mul(INV);
842 let (_, carry) = mac(r5, k, MODULUS[0], 0);
843 let (r6, carry) = mac(r6, k, MODULUS[1], carry);
844 let (r7, carry) = mac(r7, k, MODULUS[2], carry);
845 let (r8, carry) = mac(r8, k, MODULUS[3], carry);
846 let (r9, carry) = mac(r9, k, MODULUS[4], carry);
847 let (r10, carry) = mac(r10, k, MODULUS[5], carry);
848 let (r11, _) = adc(t11, r11, carry);
849
850 (&Fp([r6, r7, r8, r9, r10, r11])).subtract_p()
853 }
854
855 #[inline]
856 pub const fn mul(&self, rhs: &Fp) -> Fp {
858 let (t0, carry) = mac(0, self.0[0], rhs.0[0], 0);
859 let (t1, carry) = mac(0, self.0[0], rhs.0[1], carry);
860 let (t2, carry) = mac(0, self.0[0], rhs.0[2], carry);
861 let (t3, carry) = mac(0, self.0[0], rhs.0[3], carry);
862 let (t4, carry) = mac(0, self.0[0], rhs.0[4], carry);
863 let (t5, t6) = mac(0, self.0[0], rhs.0[5], carry);
864
865 let (t1, carry) = mac(t1, self.0[1], rhs.0[0], 0);
866 let (t2, carry) = mac(t2, self.0[1], rhs.0[1], carry);
867 let (t3, carry) = mac(t3, self.0[1], rhs.0[2], carry);
868 let (t4, carry) = mac(t4, self.0[1], rhs.0[3], carry);
869 let (t5, carry) = mac(t5, self.0[1], rhs.0[4], carry);
870 let (t6, t7) = mac(t6, self.0[1], rhs.0[5], carry);
871
872 let (t2, carry) = mac(t2, self.0[2], rhs.0[0], 0);
873 let (t3, carry) = mac(t3, self.0[2], rhs.0[1], carry);
874 let (t4, carry) = mac(t4, self.0[2], rhs.0[2], carry);
875 let (t5, carry) = mac(t5, self.0[2], rhs.0[3], carry);
876 let (t6, carry) = mac(t6, self.0[2], rhs.0[4], carry);
877 let (t7, t8) = mac(t7, self.0[2], rhs.0[5], carry);
878
879 let (t3, carry) = mac(t3, self.0[3], rhs.0[0], 0);
880 let (t4, carry) = mac(t4, self.0[3], rhs.0[1], carry);
881 let (t5, carry) = mac(t5, self.0[3], rhs.0[2], carry);
882 let (t6, carry) = mac(t6, self.0[3], rhs.0[3], carry);
883 let (t7, carry) = mac(t7, self.0[3], rhs.0[4], carry);
884 let (t8, t9) = mac(t8, self.0[3], rhs.0[5], carry);
885
886 let (t4, carry) = mac(t4, self.0[4], rhs.0[0], 0);
887 let (t5, carry) = mac(t5, self.0[4], rhs.0[1], carry);
888 let (t6, carry) = mac(t6, self.0[4], rhs.0[2], carry);
889 let (t7, carry) = mac(t7, self.0[4], rhs.0[3], carry);
890 let (t8, carry) = mac(t8, self.0[4], rhs.0[4], carry);
891 let (t9, t10) = mac(t9, self.0[4], rhs.0[5], carry);
892
893 let (t5, carry) = mac(t5, self.0[5], rhs.0[0], 0);
894 let (t6, carry) = mac(t6, self.0[5], rhs.0[1], carry);
895 let (t7, carry) = mac(t7, self.0[5], rhs.0[2], carry);
896 let (t8, carry) = mac(t8, self.0[5], rhs.0[3], carry);
897 let (t9, carry) = mac(t9, self.0[5], rhs.0[4], carry);
898 let (t10, t11) = mac(t10, self.0[5], rhs.0[5], carry);
899
900 Self::montgomery_reduce(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11)
901 }
902
903 #[inline]
905 pub const fn square(&self) -> Self {
906 let (t1, carry) = mac(0, self.0[0], self.0[1], 0);
907 let (t2, carry) = mac(0, self.0[0], self.0[2], carry);
908 let (t3, carry) = mac(0, self.0[0], self.0[3], carry);
909 let (t4, carry) = mac(0, self.0[0], self.0[4], carry);
910 let (t5, t6) = mac(0, self.0[0], self.0[5], carry);
911
912 let (t3, carry) = mac(t3, self.0[1], self.0[2], 0);
913 let (t4, carry) = mac(t4, self.0[1], self.0[3], carry);
914 let (t5, carry) = mac(t5, self.0[1], self.0[4], carry);
915 let (t6, t7) = mac(t6, self.0[1], self.0[5], carry);
916
917 let (t5, carry) = mac(t5, self.0[2], self.0[3], 0);
918 let (t6, carry) = mac(t6, self.0[2], self.0[4], carry);
919 let (t7, t8) = mac(t7, self.0[2], self.0[5], carry);
920
921 let (t7, carry) = mac(t7, self.0[3], self.0[4], 0);
922 let (t8, t9) = mac(t8, self.0[3], self.0[5], carry);
923
924 let (t9, t10) = mac(t9, self.0[4], self.0[5], 0);
925
926 let t11 = t10 >> 63;
927 let t10 = (t10 << 1) | (t9 >> 63);
928 let t9 = (t9 << 1) | (t8 >> 63);
929 let t8 = (t8 << 1) | (t7 >> 63);
930 let t7 = (t7 << 1) | (t6 >> 63);
931 let t6 = (t6 << 1) | (t5 >> 63);
932 let t5 = (t5 << 1) | (t4 >> 63);
933 let t4 = (t4 << 1) | (t3 >> 63);
934 let t3 = (t3 << 1) | (t2 >> 63);
935 let t2 = (t2 << 1) | (t1 >> 63);
936 let t1 = t1 << 1;
937
938 let (t0, carry) = mac(0, self.0[0], self.0[0], 0);
939 let (t1, carry) = adc(t1, 0, carry);
940 let (t2, carry) = mac(t2, self.0[1], self.0[1], carry);
941 let (t3, carry) = adc(t3, 0, carry);
942 let (t4, carry) = mac(t4, self.0[2], self.0[2], carry);
943 let (t5, carry) = adc(t5, 0, carry);
944 let (t6, carry) = mac(t6, self.0[3], self.0[3], carry);
945 let (t7, carry) = adc(t7, 0, carry);
946 let (t8, carry) = mac(t8, self.0[4], self.0[4], carry);
947 let (t9, carry) = adc(t9, 0, carry);
948 let (t10, carry) = mac(t10, self.0[5], self.0[5], carry);
949 let (t11, _) = adc(t11, 0, carry);
950
951 Self::montgomery_reduce(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11)
952 }
953}
954
955impl ff::FromUniformBytes<64> for Fp {
956 fn from_uniform_bytes(bytes: &[u8; 64]) -> Self {
959 Self::from_u512([
960 u64::from_le_bytes(bytes[0..8].try_into().unwrap()),
961 u64::from_le_bytes(bytes[8..16].try_into().unwrap()),
962 u64::from_le_bytes(bytes[16..24].try_into().unwrap()),
963 u64::from_le_bytes(bytes[24..32].try_into().unwrap()),
964 u64::from_le_bytes(bytes[32..40].try_into().unwrap()),
965 u64::from_le_bytes(bytes[40..48].try_into().unwrap()),
966 u64::from_le_bytes(bytes[48..56].try_into().unwrap()),
967 u64::from_le_bytes(bytes[56..64].try_into().unwrap()),
968 ])
969 }
970}
971
972impl Fp {
973 fn from_u512(limbs: [u64; 8]) -> Fp {
974 let d0 = Fp([limbs[0], limbs[1], limbs[2], limbs[3], limbs[4], limbs[5]]);
975 let d1 = Fp([limbs[6], limbs[7], 0, 0, 0, 0]);
976 d0 * R2 + d1 * R3
978 }
979}
980
981impl From<bool> for Fp {
982 fn from(bit: bool) -> Fp {
983 if bit {
984 Fp::one()
985 } else {
986 Fp::zero()
987 }
988 }
989}
990
991impl From<[u64; 6]> for Fp {
992 fn from(digits: [u64; 6]) -> Self {
993 Self::from_raw_unchecked(digits)
994 }
995}
996
997#[test]
998fn test_constants() {
999 assert_eq!(Fp::ONE.double(), GENERATOR);
1000 assert_eq!(Fp::ONE, Fp::ONE.double() * TWO_INV);
1001 assert_eq!(Fp::ONE, ROOT_OF_UNITY.pow([1 << Fp::S]));
1002 assert_eq!(Fp::ONE, ROOT_OF_UNITY * ROOT_OF_UNITY_INV);
1003 let t = [
1007 0xdcff7fffffffd555,
1008 0x0f55ffff58a9ffff,
1009 0xb39869507b587b12,
1010 0xb23ba5c279c2895f,
1011 0x258dd3db21a5d66b,
1012 0xd0088f51cbff34d,
1013 ];
1014 assert_eq!(Fp::ONE, DELTA.pow(t));
1015 assert_eq!(Fp::ONE, ZETA.pow([3]));
1016}
1017
1018#[test]
1019fn test_conditional_selection() {
1020 let a = Fp([1, 2, 3, 4, 5, 6]);
1021 let b = Fp([7, 8, 9, 10, 11, 12]);
1022
1023 assert_eq!(
1024 ConditionallySelectable::conditional_select(&a, &b, Choice::from(0u8)),
1025 a
1026 );
1027 assert_eq!(
1028 ConditionallySelectable::conditional_select(&a, &b, Choice::from(1u8)),
1029 b
1030 );
1031}
1032
1033#[test]
1034fn test_equality() {
1035 fn is_equal(a: &Fp, b: &Fp) -> bool {
1036 let eq = a == b;
1037 let ct_eq = a.ct_eq(b);
1038
1039 assert_eq!(eq, bool::from(ct_eq));
1040
1041 eq
1042 }
1043
1044 assert!(is_equal(&Fp([1, 2, 3, 4, 5, 6]), &Fp([1, 2, 3, 4, 5, 6])));
1045
1046 assert!(!is_equal(&Fp([7, 2, 3, 4, 5, 6]), &Fp([1, 2, 3, 4, 5, 6])));
1047 assert!(!is_equal(&Fp([1, 7, 3, 4, 5, 6]), &Fp([1, 2, 3, 4, 5, 6])));
1048 assert!(!is_equal(&Fp([1, 2, 7, 4, 5, 6]), &Fp([1, 2, 3, 4, 5, 6])));
1049 assert!(!is_equal(&Fp([1, 2, 3, 7, 5, 6]), &Fp([1, 2, 3, 4, 5, 6])));
1050 assert!(!is_equal(&Fp([1, 2, 3, 4, 7, 6]), &Fp([1, 2, 3, 4, 5, 6])));
1051 assert!(!is_equal(&Fp([1, 2, 3, 4, 5, 7]), &Fp([1, 2, 3, 4, 5, 6])));
1052}
1053
1054#[test]
1055fn test_squaring() {
1056 let a = Fp([
1057 0xd215_d276_8e83_191b,
1058 0x5085_d80f_8fb2_8261,
1059 0xce9a_032d_df39_3a56,
1060 0x3e9c_4fff_2ca0_c4bb,
1061 0x6436_b6f7_f4d9_5dfb,
1062 0x1060_6628_ad4a_4d90,
1063 ]);
1064 let b = Fp([
1065 0x33d9_c42a_3cb3_e235,
1066 0xdad1_1a09_4c4c_d455,
1067 0xa2f1_44bd_729a_aeba,
1068 0xd415_0932_be9f_feac,
1069 0xe27b_c7c4_7d44_ee50,
1070 0x14b6_a78d_3ec7_a560,
1071 ]);
1072
1073 assert_eq!(a.square(), b);
1074}
1075
1076#[test]
1077fn test_multiplication() {
1078 let a = Fp([
1079 0x0397_a383_2017_0cd4,
1080 0x734c_1b2c_9e76_1d30,
1081 0x5ed2_55ad_9a48_beb5,
1082 0x095a_3c6b_22a7_fcfc,
1083 0x2294_ce75_d4e2_6a27,
1084 0x1333_8bd8_7001_1ebb,
1085 ]);
1086 let b = Fp([
1087 0xb9c3_c7c5_b119_6af7,
1088 0x2580_e208_6ce3_35c1,
1089 0xf49a_ed3d_8a57_ef42,
1090 0x41f2_81e4_9846_e878,
1091 0xe076_2346_c384_52ce,
1092 0x0652_e893_26e5_7dc0,
1093 ]);
1094 let c = Fp([
1095 0xf96e_f3d7_11ab_5355,
1096 0xe8d4_59ea_00f1_48dd,
1097 0x53f7_354a_5f00_fa78,
1098 0x9e34_a4f3_125c_5f83,
1099 0x3fbe_0c47_ca74_c19e,
1100 0x01b0_6a8b_bd4a_dfe4,
1101 ]);
1102
1103 assert_eq!(a * b, c);
1104}
1105
1106#[test]
1107fn test_addition() {
1108 let a = Fp([
1109 0x5360_bb59_7867_8032,
1110 0x7dd2_75ae_799e_128e,
1111 0x5c5b_5071_ce4f_4dcf,
1112 0xcdb2_1f93_078d_bb3e,
1113 0xc323_65c5_e73f_474a,
1114 0x115a_2a54_89ba_be5b,
1115 ]);
1116 let b = Fp([
1117 0x9fd2_8773_3d23_dda0,
1118 0xb16b_f2af_738b_3554,
1119 0x3e57_a75b_d3cc_6d1d,
1120 0x900b_c0bd_627f_d6d6,
1121 0xd319_a080_efb2_45fe,
1122 0x15fd_caa4_e4bb_2091,
1123 ]);
1124 let c = Fp([
1125 0x3934_42cc_b58b_b327,
1126 0x1092_685f_3bd5_47e3,
1127 0x3382_252c_ab6a_c4c9,
1128 0xf946_94cb_7688_7f55,
1129 0x4b21_5e90_93a5_e071,
1130 0x0d56_e30f_34f5_f853,
1131 ]);
1132
1133 assert_eq!(a + b, c);
1134}
1135
1136#[test]
1137fn test_subtraction() {
1138 let a = Fp([
1139 0x5360_bb59_7867_8032,
1140 0x7dd2_75ae_799e_128e,
1141 0x5c5b_5071_ce4f_4dcf,
1142 0xcdb2_1f93_078d_bb3e,
1143 0xc323_65c5_e73f_474a,
1144 0x115a_2a54_89ba_be5b,
1145 ]);
1146 let b = Fp([
1147 0x9fd2_8773_3d23_dda0,
1148 0xb16b_f2af_738b_3554,
1149 0x3e57_a75b_d3cc_6d1d,
1150 0x900b_c0bd_627f_d6d6,
1151 0xd319_a080_efb2_45fe,
1152 0x15fd_caa4_e4bb_2091,
1153 ]);
1154 let c = Fp([
1155 0x6d8d_33e6_3b43_4d3d,
1156 0xeb12_82fd_b766_dd39,
1157 0x8534_7bb6_f133_d6d5,
1158 0xa21d_aa5a_9892_f727,
1159 0x3b25_6cfb_3ad8_ae23,
1160 0x155d_7199_de7f_8464,
1161 ]);
1162
1163 assert_eq!(a - b, c);
1164}
1165
1166#[test]
1167fn test_negation() {
1168 let a = Fp([
1169 0x5360_bb59_7867_8032,
1170 0x7dd2_75ae_799e_128e,
1171 0x5c5b_5071_ce4f_4dcf,
1172 0xcdb2_1f93_078d_bb3e,
1173 0xc323_65c5_e73f_474a,
1174 0x115a_2a54_89ba_be5b,
1175 ]);
1176 let b = Fp([
1177 0x669e_44a6_8798_2a79,
1178 0xa0d9_8a50_37b5_ed71,
1179 0x0ad5_822f_2861_a854,
1180 0x96c5_2bf1_ebf7_5781,
1181 0x87f8_41f0_5c0c_658c,
1182 0x08a6_e795_afc5_283e,
1183 ]);
1184
1185 assert_eq!(-a, b);
1186}
1187
1188#[test]
1189fn test_from_bytes() {
1190 let mut a = Fp([
1191 0xdc90_6d9b_e3f9_5dc8,
1192 0x8755_caf7_4596_91a1,
1193 0xcff1_a7f4_e958_3ab3,
1194 0x9b43_821f_849e_2284,
1195 0xf575_54f3_a297_4f3f,
1196 0x085d_bea8_4ed4_7f79,
1197 ]);
1198
1199 for _ in 0..100 {
1200 a = a.square();
1201 let tmp = a.to_bytes_be();
1202 let b = Fp::from_bytes_be(&tmp).unwrap();
1203
1204 assert_eq!(a, b);
1205 }
1206
1207 assert_eq!(
1208 -Fp::one(),
1209 Fp::from_bytes_be(&[
1210 26, 1, 17, 234, 57, 127, 230, 154, 75, 27, 167, 182, 67, 75, 172, 215, 100, 119, 75,
1211 132, 243, 133, 18, 191, 103, 48, 210, 160, 246, 176, 246, 36, 30, 171, 255, 254, 177,
1212 83, 255, 255, 185, 254, 255, 255, 255, 255, 170, 170
1213 ])
1214 .unwrap()
1215 );
1216
1217 assert!(bool::from(
1218 Fp::from_bytes_be(&[
1219 27, 1, 17, 234, 57, 127, 230, 154, 75, 27, 167, 182, 67, 75, 172, 215, 100, 119, 75,
1220 132, 243, 133, 18, 191, 103, 48, 210, 160, 246, 176, 246, 36, 30, 171, 255, 254, 177,
1221 83, 255, 255, 185, 254, 255, 255, 255, 255, 170, 170
1222 ])
1223 .is_none()
1224 ));
1225
1226 assert!(bool::from(Fp::from_bytes_be(&[0xff; 48]).is_none()));
1227}
1228
1229#[test]
1230fn test_sqrt() {
1231 let a = Fp::from_raw_unchecked([
1233 0xaa27_0000_000c_fff3,
1234 0x53cc_0032_fc34_000a,
1235 0x478f_e97a_6b0a_807f,
1236 0xb1d3_7ebe_e6ba_24d7,
1237 0x8ec9_733b_bf78_ab2f,
1238 0x09d6_4551_3d83_de7e,
1239 ]);
1240
1241 assert_eq!(
1242 -a.sqrt().unwrap(),
1244 Fp::from_raw_unchecked([
1246 0x3213_0000_0006_554f,
1247 0xb93c_0018_d6c4_0005,
1248 0x5760_5e0d_b0dd_bb51,
1249 0x8b25_6521_ed1f_9bcb,
1250 0x6cf2_8d79_0162_2c03,
1251 0x11eb_ab9d_bb81_e28c,
1252 ])
1253 );
1254}
1255
1256#[test]
1257fn test_inversion() {
1258 let a = Fp([
1259 0x43b4_3a50_78ac_2076,
1260 0x1ce0_7630_46f8_962b,
1261 0x724a_5276_486d_735c,
1262 0x6f05_c2a6_282d_48fd,
1263 0x2095_bd5b_b4ca_9331,
1264 0x03b3_5b38_94b0_f7da,
1265 ]);
1266 let b = Fp([
1267 0x69ec_d704_0952_148f,
1268 0x985c_cc20_2219_0f55,
1269 0xe19b_ba36_a9ad_2f41,
1270 0x19bb_16c9_5219_dbd8,
1271 0x14dc_acfd_fb47_8693,
1272 0x115f_f58a_fff9_a8e1,
1273 ]);
1274
1275 assert_eq!(a.invert().unwrap(), b);
1276 assert!(bool::from(Fp::zero().invert().is_none()));
1277}
1278
1279#[test]
1280fn test_lexicographic_largest() {
1281 assert!(!bool::from(Fp::zero().lexicographically_largest()));
1282 assert!(!bool::from(Fp::one().lexicographically_largest()));
1283 assert!(!bool::from(
1284 Fp::from_raw_unchecked([
1285 0xa1fa_ffff_fffe_5557,
1286 0x995b_fff9_76a3_fffe,
1287 0x03f4_1d24_d174_ceb4,
1288 0xf654_7998_c199_5dbd,
1289 0x778a_468f_507a_6034,
1290 0x0205_5993_1f7f_8103
1291 ])
1292 .lexicographically_largest()
1293 ));
1294 assert!(bool::from(
1295 Fp::from_raw_unchecked([
1296 0x1804_0000_0001_5554,
1297 0x8550_0005_3ab0_0001,
1298 0x633c_b57c_253c_276f,
1299 0x6e22_d1ec_31eb_b502,
1300 0xd391_6126_f2d1_4ca2,
1301 0x17fb_b857_1a00_6596,
1302 ])
1303 .lexicographically_largest()
1304 ));
1305 assert!(bool::from(
1306 Fp::from_raw_unchecked([
1307 0x43f5_ffff_fffc_aaae,
1308 0x32b7_fff2_ed47_fffd,
1309 0x07e8_3a49_a2e9_9d69,
1310 0xeca8_f331_8332_bb7a,
1311 0xef14_8d1e_a0f4_c069,
1312 0x040a_b326_3eff_0206,
1313 ])
1314 .lexicographically_largest()
1315 ));
1316}
1317
1318#[cfg(feature = "zeroize")]
1319#[test]
1320fn test_zeroize() {
1321 use zeroize::Zeroize;
1322
1323 let mut a = Fp::one();
1324 a.zeroize();
1325 assert!(bool::from(a.is_zero()));
1326}
1327
1328#[test]
1329fn test_from_bytes_debug() {
1330 assert!(bool::from(
1337 Fp::from_bytes(&[
1338 220u8, 214, 26, 93, 113, 152, 62, 165, 185, 230, 195, 24, 61, 41, 116, 148, 248, 59,
1339 10, 81, 185, 242, 151, 83, 182, 242, 42, 201, 239, 33, 70, 221, 221, 179, 240, 87, 84,
1340 220, 123, 92, 72, 180, 248, 99, 100, 200, 6, 9
1341 ])
1342 .is_some()
1343 ));
1344}