1use crate::ByteOrder;
5use bigint::{
6 ArrayEncoding, ByteArray, Invert, Reduce, Uint, Word, ctutils,
7 hybrid_array::{Array, ArraySize, typenum::Unsigned},
8 modular::{
9 ConstMontyForm as MontyForm, ConstMontyParams, ConstPrimeMontyParams, FixedMontyParams,
10 Retrieve,
11 },
12};
13use common::Generate;
14use core::{
15 cmp::Ordering,
16 fmt,
17 iter::{Product, Sum},
18 ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
19};
20use ff::{Field, PrimeField};
21use rand_core::TryCryptoRng;
22use subtle::{
23 Choice, ConditionallySelectable, ConstantTimeEq, ConstantTimeGreater, ConstantTimeLess,
24 CtOption,
25};
26
27pub trait MontyFieldParams<const LIMBS: usize>: ConstPrimeMontyParams<LIMBS> {
30 type ByteSize: ArraySize;
32
33 const BYTE_ORDER: ByteOrder;
35
36 const MODULUS_HEX: &'static str;
38
39 const T: Uint<LIMBS>;
41}
42
43pub type MontyFieldBytes<MOD, const LIMBS: usize> =
45 Array<u8, <MOD as MontyFieldParams<LIMBS>>::ByteSize>;
46
47#[derive(Clone, Copy)]
49pub struct MontyFieldElement<MOD, const LIMBS: usize>
50where
51 MOD: MontyFieldParams<LIMBS>,
52{
53 inner: MontyForm<MOD, LIMBS>,
54}
55
56impl<MOD, const LIMBS: usize> MontyFieldElement<MOD, LIMBS>
57where
58 MOD: MontyFieldParams<LIMBS>,
59{
60 pub const ZERO: Self = Self {
62 inner: MontyForm::ZERO,
63 };
64
65 pub const ONE: Self = Self {
67 inner: MontyForm::ONE,
68 };
69
70 pub const LIMBS: usize = LIMBS;
72
73 #[inline]
75 pub fn from_bytes(repr: &MontyFieldBytes<MOD, LIMBS>) -> CtOption<Self>
76 where
77 Uint<LIMBS>: ArrayEncoding,
78 {
79 let mut byte_array = ByteArray::<Uint<LIMBS>>::default();
80 debug_assert!(repr.len() <= byte_array.len());
81
82 let offset = byte_array.len().saturating_sub(repr.len());
83 let uint = match MOD::BYTE_ORDER {
84 ByteOrder::BigEndian => {
85 byte_array[offset..].copy_from_slice(repr);
86 Uint::from_be_byte_array(byte_array)
87 }
88 ByteOrder::LittleEndian => {
89 byte_array[..repr.len()].copy_from_slice(repr);
95 Uint::from_le_byte_array(byte_array)
96 }
97 };
98
99 Self::from_uint(&uint)
100 }
101
102 #[inline]
106 #[must_use]
107 pub fn from_slice(slice: &[u8]) -> Option<Self>
108 where
109 Uint<LIMBS>: ArrayEncoding,
110 {
111 let array = Array::try_from(slice).ok()?;
112 Self::from_bytes(&array).into()
113 }
114
115 #[must_use]
125 pub const fn from_hex_vartime(hex: &str) -> Self {
126 let uint = match MOD::BYTE_ORDER {
127 ByteOrder::BigEndian => Uint::from_be_hex(hex),
128 ByteOrder::LittleEndian => Uint::from_le_hex(hex),
129 };
130
131 assert!(
132 uint.cmp_vartime(MOD::PARAMS.modulus().as_ref()).is_lt(),
133 "hex encoded field element overflows modulus"
134 );
135
136 Self::from_uint_reduced(&uint)
137 }
138
139 #[inline]
147 #[must_use]
148 pub const fn from_uint_reduced(uint: &Uint<LIMBS>) -> Self {
149 Self {
150 inner: MontyForm::new(uint),
151 }
152 }
153
154 #[inline]
164 #[must_use]
165 pub fn from_uint(uint: &Uint<LIMBS>) -> CtOption<Self> {
166 let is_some = ctutils::CtLt::ct_lt(uint, MOD::PARAMS.modulus());
167
168 CtOption::new(Self::from_uint_reduced(uint), is_some.into())
170 }
171
172 #[inline]
178 #[must_use]
179 pub const fn from_u32(w: u32) -> Self {
180 assert!(
181 MOD::PARAMS.modulus().as_ref().bits() > 32,
182 "modulus is too small to ensure all u32s are in range"
183 );
184
185 Self::from_uint_reduced(&Uint::from_u32(w))
186 }
187
188 #[inline]
194 #[must_use]
195 pub const fn from_u64(w: u64) -> Self {
196 assert!(
197 MOD::PARAMS.modulus().as_ref().bits() > 64,
198 "modulus is too small to ensure all u64s are in range"
199 );
200
201 Self::from_uint_reduced(&Uint::from_u64(w))
202 }
203
204 #[inline]
211 #[must_use]
212 pub const fn from_montgomery(uint: Uint<LIMBS>) -> Self {
213 Self {
214 inner: MontyForm::from_montgomery(uint),
215 }
216 }
217
218 #[inline]
222 #[must_use]
223 pub const fn from_montgomery_words(words: [Word; LIMBS]) -> Self {
224 Self::from_montgomery(Uint::from_words(words))
225 }
226
227 #[must_use]
235 pub const fn as_montgomery(&self) -> &Uint<LIMBS> {
236 self.inner.as_montgomery()
237 }
238
239 #[must_use]
242 pub const fn to_montgomery_words(&self) -> [Word; LIMBS] {
243 self.as_montgomery().to_words()
244 }
245
246 #[inline]
248 #[must_use]
249 pub fn to_bytes(self) -> MontyFieldBytes<MOD, LIMBS>
250 where
251 MOD: MontyFieldParams<LIMBS>,
252 Uint<LIMBS>: ArrayEncoding,
253 {
254 let mut repr = MontyFieldBytes::<MOD, LIMBS>::default();
255 debug_assert!(repr.len() <= <Uint::<LIMBS> as ArrayEncoding>::ByteSize::USIZE);
256
257 let offset = <Uint<LIMBS> as ArrayEncoding>::ByteSize::USIZE.saturating_sub(repr.len());
258
259 match MOD::BYTE_ORDER {
260 ByteOrder::BigEndian => {
261 let padded = self.inner.retrieve().to_be_byte_array();
262 repr.copy_from_slice(&padded[offset..]);
263 }
264 ByteOrder::LittleEndian => {
265 let padded = self.inner.retrieve().to_le_byte_array();
266 let len = repr.len();
269 repr.copy_from_slice(&padded[..len]);
270 }
271 }
272
273 repr
274 }
275
276 #[inline]
282 #[must_use]
283 pub fn is_odd(&self) -> Choice {
284 self.inner.retrieve().is_odd().into()
285 }
286
287 #[inline]
293 #[must_use]
294 pub fn is_even(&self) -> Choice {
295 !self.is_odd()
296 }
297
298 #[inline]
304 #[must_use]
305 pub fn is_zero(&self) -> Choice {
306 self.ct_eq(&Self::ZERO)
307 }
308
309 #[inline]
311 #[must_use]
312 pub const fn to_canonical(self) -> Uint<LIMBS> {
313 self.inner.retrieve()
314 }
315
316 #[inline]
318 #[must_use]
319 pub const fn add(&self, rhs: &Self) -> Self {
320 Self {
321 inner: MontyForm::add(&self.inner, &rhs.inner),
322 }
323 }
324
325 #[inline]
327 #[must_use]
328 pub const fn double(&self) -> Self {
329 Self {
330 inner: MontyForm::double(&self.inner),
331 }
332 }
333
334 #[inline]
336 #[must_use]
337 pub const fn sub(&self, rhs: &Self) -> Self {
338 Self {
339 inner: MontyForm::sub(&self.inner, &rhs.inner),
340 }
341 }
342
343 #[inline]
345 #[must_use]
346 pub const fn multiply(&self, rhs: &Self) -> Self {
347 Self {
348 inner: MontyForm::mul(&self.inner, &rhs.inner),
349 }
350 }
351
352 #[inline]
354 #[must_use]
355 pub const fn neg(&self) -> Self {
356 Self {
357 inner: MontyForm::neg(&self.inner),
358 }
359 }
360
361 #[inline]
363 #[must_use]
364 pub const fn square(&self) -> Self {
365 Self {
366 inner: MontyForm::square(&self.inner),
367 }
368 }
369
370 #[inline]
372 #[must_use]
373 pub fn invert(&self) -> CtOption<Self> {
374 CtOption::from(self.inner.invert()).map(|inner| Self { inner })
375 }
376
377 #[inline]
379 #[must_use]
380 pub fn invert_vartime(&self) -> CtOption<Self> {
381 CtOption::from(self.inner.invert_vartime()).map(|inner| Self { inner })
382 }
383
384 #[must_use]
388 pub const fn const_invert(&self) -> Self {
389 Self {
390 inner: self
391 .inner
392 .invert()
393 .expect_copied("input to invert should be non-zero"),
394 }
395 }
396
397 #[must_use]
404 pub const fn pow_vartime<const RHS_LIMBS: usize>(&self, exp: &Uint<RHS_LIMBS>) -> Self {
405 Self {
406 inner: self.inner.pow_vartime(exp),
407 }
408 }
409
410 #[must_use]
416 pub const fn sqn_vartime(&self, n: usize) -> Self {
417 let mut x = *self;
418 let mut i = 0;
419 while i < n {
420 x = x.square();
421 i += 1;
422 }
423 x
424 }
425}
426
427impl<MOD, const LIMBS: usize> Field for MontyFieldElement<MOD, LIMBS>
432where
433 MOD: MontyFieldParams<LIMBS>,
434 MontyFieldBytes<MOD, LIMBS>: Copy,
435 Uint<LIMBS>: ArrayEncoding,
436{
437 const ZERO: Self = Self::ZERO;
438 const ONE: Self = Self::ONE;
439
440 fn try_random<R: rand_core::TryRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
441 let mut bytes = MontyFieldBytes::<MOD, LIMBS>::default();
442
443 loop {
444 rng.try_fill_bytes(&mut bytes)?;
445 if let Some(fe) = Self::from_bytes(&bytes).into() {
446 return Ok(fe);
447 }
448 }
449 }
450
451 fn is_zero(&self) -> Choice {
452 Self::ZERO.ct_eq(self)
453 }
454
455 fn square(&self) -> Self {
456 self.square()
457 }
458
459 fn double(&self) -> Self {
460 self.double()
461 }
462
463 fn invert(&self) -> CtOption<Self> {
464 self.invert()
465 }
466
467 fn sqrt(&self) -> CtOption<Self> {
468 self.inner.sqrt().map(|inner| Self { inner }).into()
469 }
470
471 fn sqrt_ratio(num: &Self, div: &Self) -> (Choice, Self) {
472 ff::helpers::sqrt_ratio_generic(num, div)
473 }
474}
475
476impl<MOD, const LIMBS: usize> PrimeField for MontyFieldElement<MOD, LIMBS>
477where
478 MOD: MontyFieldParams<LIMBS>,
479 MontyFieldBytes<MOD, LIMBS>: Copy,
480 Uint<LIMBS>: ArrayEncoding,
481{
482 type Repr = MontyFieldBytes<MOD, LIMBS>;
483
484 const MODULUS: &'static str = MOD::MODULUS_HEX;
485 const NUM_BITS: u32 = MOD::PARAMS.modulus().as_ref().bits_vartime();
486 const CAPACITY: u32 = Self::NUM_BITS - 1;
487 const TWO_INV: Self = Self::from_u64(2).const_invert();
488 const MULTIPLICATIVE_GENERATOR: Self = Self::from_u32(MOD::PRIME_PARAMS.generator().get());
489 const S: u32 = MOD::PRIME_PARAMS.s().get();
490 const ROOT_OF_UNITY: Self = Self::MULTIPLICATIVE_GENERATOR.pow_vartime(&MOD::T);
491 const ROOT_OF_UNITY_INV: Self = Self::ROOT_OF_UNITY.const_invert();
492 const DELTA: Self = Self::MULTIPLICATIVE_GENERATOR.sqn_vartime(Self::S as usize);
493
494 fn from_repr(bytes: Self::Repr) -> CtOption<Self> {
495 Self::from_bytes(&bytes)
496 }
497
498 fn to_repr(&self) -> Self::Repr {
499 self.to_bytes()
500 }
501
502 fn is_odd(&self) -> Choice {
503 self.is_odd()
504 }
505}
506
507macro_rules! monty_field_op {
513 ($op:tt, $func:ident, $inner_func:ident) => {
514 impl<MOD, const LIMBS: usize> $op for MontyFieldElement<MOD, LIMBS>
515 where
516 MOD: MontyFieldParams<LIMBS>,
517 {
518 type Output = MontyFieldElement<MOD, LIMBS>;
519
520 #[inline]
521 fn $func(self, rhs: MontyFieldElement<MOD, LIMBS>) -> MontyFieldElement<MOD, LIMBS> {
522 <MontyFieldElement<MOD, LIMBS>>::$inner_func(&self, &rhs)
523 }
524 }
525
526 impl<MOD, const LIMBS: usize> $op<&Self> for MontyFieldElement<MOD, LIMBS>
527 where
528 MOD: MontyFieldParams<LIMBS>,
529 {
530 type Output = MontyFieldElement<MOD, LIMBS>;
531
532 #[inline]
533 fn $func(self, rhs: &MontyFieldElement<MOD, LIMBS>) -> MontyFieldElement<MOD, LIMBS> {
534 <MontyFieldElement<MOD, LIMBS>>::$inner_func(&self, rhs)
535 }
536 }
537
538 impl<MOD, const LIMBS: usize> $op<Self> for &MontyFieldElement<MOD, LIMBS>
539 where
540 MOD: MontyFieldParams<LIMBS>,
541 {
542 type Output = MontyFieldElement<MOD, LIMBS>;
543
544 #[inline]
545 fn $func(self, rhs: &MontyFieldElement<MOD, LIMBS>) -> MontyFieldElement<MOD, LIMBS> {
546 <MontyFieldElement<MOD, LIMBS>>::$inner_func(self, rhs)
547 }
548 }
549 };
550}
551
552monty_field_op!(Add, add, add);
553monty_field_op!(Sub, sub, sub);
554monty_field_op!(Mul, mul, multiply);
555
556impl<MOD, const LIMBS: usize> AddAssign<Self> for MontyFieldElement<MOD, LIMBS>
557where
558 MOD: MontyFieldParams<LIMBS>,
559{
560 #[inline]
561 fn add_assign(&mut self, other: MontyFieldElement<MOD, LIMBS>) {
562 *self = *self + other;
563 }
564}
565
566impl<MOD, const LIMBS: usize> AddAssign<&Self> for MontyFieldElement<MOD, LIMBS>
567where
568 MOD: MontyFieldParams<LIMBS>,
569{
570 #[inline]
571 fn add_assign(&mut self, other: &MontyFieldElement<MOD, LIMBS>) {
572 *self = *self + other;
573 }
574}
575
576impl<MOD, const LIMBS: usize> SubAssign<Self> for MontyFieldElement<MOD, LIMBS>
577where
578 MOD: MontyFieldParams<LIMBS>,
579{
580 #[inline]
581 fn sub_assign(&mut self, other: MontyFieldElement<MOD, LIMBS>) {
582 *self = *self - other;
583 }
584}
585
586impl<MOD, const LIMBS: usize> SubAssign<&Self> for MontyFieldElement<MOD, LIMBS>
587where
588 MOD: MontyFieldParams<LIMBS>,
589{
590 #[inline]
591 fn sub_assign(&mut self, other: &MontyFieldElement<MOD, LIMBS>) {
592 *self = *self - other;
593 }
594}
595
596impl<MOD, const LIMBS: usize> MulAssign<&Self> for MontyFieldElement<MOD, LIMBS>
597where
598 MOD: MontyFieldParams<LIMBS>,
599{
600 #[inline]
601 fn mul_assign(&mut self, other: &MontyFieldElement<MOD, LIMBS>) {
602 *self = *self * other;
603 }
604}
605
606impl<MOD, const LIMBS: usize> MulAssign for MontyFieldElement<MOD, LIMBS>
607where
608 MOD: MontyFieldParams<LIMBS>,
609{
610 #[inline]
611 fn mul_assign(&mut self, other: MontyFieldElement<MOD, LIMBS>) {
612 *self = *self * other;
613 }
614}
615
616impl<MOD, const LIMBS: usize> Neg for MontyFieldElement<MOD, LIMBS>
617where
618 MOD: MontyFieldParams<LIMBS>,
619{
620 type Output = MontyFieldElement<MOD, LIMBS>;
621
622 #[inline]
623 fn neg(self) -> MontyFieldElement<MOD, LIMBS> {
624 <MontyFieldElement<MOD, LIMBS>>::neg(&self)
625 }
626}
627
628impl<MOD, const LIMBS: usize> Neg for &MontyFieldElement<MOD, LIMBS>
629where
630 MOD: MontyFieldParams<LIMBS>,
631{
632 type Output = MontyFieldElement<MOD, LIMBS>;
633
634 #[inline]
635 fn neg(self) -> MontyFieldElement<MOD, LIMBS> {
636 <MontyFieldElement<MOD, LIMBS>>::neg(self)
637 }
638}
639
640impl<MOD, const LIMBS: usize> Sum for MontyFieldElement<MOD, LIMBS>
641where
642 MOD: MontyFieldParams<LIMBS>,
643{
644 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
645 iter.reduce(Add::add).unwrap_or(Self::ZERO)
646 }
647}
648
649impl<'a, MOD, const LIMBS: usize> Sum<&'a Self> for MontyFieldElement<MOD, LIMBS>
650where
651 MOD: MontyFieldParams<LIMBS>,
652{
653 fn sum<I: Iterator<Item = &'a MontyFieldElement<MOD, LIMBS>>>(iter: I) -> Self {
654 iter.copied().sum()
655 }
656}
657
658impl<MOD, const LIMBS: usize> Product for MontyFieldElement<MOD, LIMBS>
659where
660 MOD: MontyFieldParams<LIMBS>,
661{
662 fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
663 iter.reduce(Mul::mul).unwrap_or(Self::ONE)
664 }
665}
666
667impl<'a, MOD: MontyFieldParams<LIMBS>, const LIMBS: usize>
668 Product<&'a MontyFieldElement<MOD, LIMBS>> for MontyFieldElement<MOD, LIMBS>
669{
670 fn product<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
671 iter.copied().product()
672 }
673}
674
675impl<MOD, const LIMBS: usize> Invert for MontyFieldElement<MOD, LIMBS>
676where
677 MOD: MontyFieldParams<LIMBS>,
678 MontyForm<MOD, LIMBS>: Invert<Output = CtOption<MontyForm<MOD, LIMBS>>>,
679{
680 type Output = CtOption<Self>;
681
682 fn invert(&self) -> CtOption<Self> {
683 Self::invert(self)
684 }
685
686 fn invert_vartime(&self) -> CtOption<Self> {
687 Self::invert_vartime(self)
688 }
689}
690
691impl<MOD, const LIMBS: usize> Reduce<Uint<LIMBS>> for MontyFieldElement<MOD, LIMBS>
692where
693 MOD: MontyFieldParams<LIMBS>,
694{
695 #[inline]
696 fn reduce(w: &Uint<LIMBS>) -> Self {
697 Self::from_uint_reduced(w)
698 }
699}
700
701impl<MOD, const LIMBS: usize> Reduce<MontyFieldBytes<MOD, LIMBS>> for MontyFieldElement<MOD, LIMBS>
702where
703 MOD: MontyFieldParams<LIMBS>,
704 Uint<LIMBS>: ArrayEncoding<ByteSize = MOD::ByteSize>,
705{
706 #[inline]
707 fn reduce(bytes: &MontyFieldBytes<MOD, LIMBS>) -> Self {
708 let uint = match MOD::BYTE_ORDER {
709 ByteOrder::BigEndian => Uint::<LIMBS>::from_be_byte_array(bytes.clone()),
710 ByteOrder::LittleEndian => Uint::<LIMBS>::from_le_byte_array(bytes.clone()),
711 };
712
713 Self::reduce(&uint)
714 }
715}
716
717impl<MOD, const LIMBS: usize> ConditionallySelectable for MontyFieldElement<MOD, LIMBS>
722where
723 MOD: MontyFieldParams<LIMBS>,
724{
725 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
726 Self {
727 inner: MontyForm::conditional_select(&a.inner, &b.inner, choice),
728 }
729 }
730}
731
732impl<MOD, const LIMBS: usize> ConstantTimeEq for MontyFieldElement<MOD, LIMBS>
733where
734 MOD: MontyFieldParams<LIMBS>,
735{
736 fn ct_eq(&self, other: &Self) -> Choice {
737 self.inner.ct_eq(&other.inner)
738 }
739}
740
741impl<MOD, const LIMBS: usize> ConstantTimeGreater for MontyFieldElement<MOD, LIMBS>
742where
743 MOD: MontyFieldParams<LIMBS>,
744{
745 fn ct_gt(&self, other: &Self) -> Choice {
746 self.inner.retrieve().ct_gt(&other.inner.retrieve())
748 }
749}
750
751impl<MOD, const LIMBS: usize> ConstantTimeLess for MontyFieldElement<MOD, LIMBS>
752where
753 MOD: MontyFieldParams<LIMBS>,
754{
755 fn ct_lt(&self, other: &Self) -> Choice {
756 ctutils::CtLt::ct_lt(&self.inner.retrieve(), &other.inner.retrieve()).into()
758 }
759}
760
761impl<MOD, const LIMBS: usize> ctutils::CtEq for MontyFieldElement<MOD, LIMBS>
766where
767 MOD: MontyFieldParams<LIMBS>,
768{
769 fn ct_eq(&self, other: &Self) -> ctutils::Choice {
770 ConstantTimeEq::ct_eq(self, other).into()
771 }
772}
773
774impl<MOD, const LIMBS: usize> ctutils::CtSelect for MontyFieldElement<MOD, LIMBS>
775where
776 MOD: MontyFieldParams<LIMBS>,
777{
778 fn ct_select(&self, other: &Self, choice: ctutils::Choice) -> Self {
779 ConditionallySelectable::conditional_select(self, other, choice.into())
780 }
781}
782
783impl<MOD, const LIMBS: usize> ctutils::CtGt for MontyFieldElement<MOD, LIMBS>
784where
785 MOD: MontyFieldParams<LIMBS>,
786{
787 fn ct_gt(&self, other: &Self) -> ctutils::Choice {
788 ctutils::CtGt::ct_gt(&self.inner.retrieve(), &other.inner.retrieve())
790 }
791}
792
793impl<MOD, const LIMBS: usize> ctutils::CtLt for MontyFieldElement<MOD, LIMBS>
794where
795 MOD: MontyFieldParams<LIMBS>,
796{
797 fn ct_lt(&self, other: &Self) -> ctutils::Choice {
798 ctutils::CtLt::ct_lt(&self.inner.retrieve(), &other.inner.retrieve())
800 }
801}
802
803impl<MOD, const LIMBS: usize> fmt::Debug for MontyFieldElement<MOD, LIMBS>
808where
809 MOD: MontyFieldParams<LIMBS>,
810{
811 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
812 let canonical = self.to_canonical();
813 write!(
814 f,
815 "MontyFieldElement<p={}>(0x{:X})",
816 MOD::MODULUS_HEX,
817 canonical
818 )
819 }
820}
821
822impl<MOD, const LIMBS: usize> fmt::Display for MontyFieldElement<MOD, LIMBS>
823where
824 MOD: MontyFieldParams<LIMBS>,
825{
826 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
827 fmt::UpperHex::fmt(self, f)
828 }
829}
830
831impl<MOD, const LIMBS: usize> fmt::Binary for MontyFieldElement<MOD, LIMBS>
832where
833 MOD: MontyFieldParams<LIMBS>,
834{
835 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
836 fmt::Binary::fmt(&self.to_canonical(), f)
837 }
838}
839
840impl<MOD, const LIMBS: usize> fmt::LowerHex for MontyFieldElement<MOD, LIMBS>
841where
842 MOD: MontyFieldParams<LIMBS>,
843{
844 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
845 fmt::LowerHex::fmt(&self.to_canonical(), f)
846 }
847}
848
849impl<MOD, const LIMBS: usize> fmt::UpperHex for MontyFieldElement<MOD, LIMBS>
850where
851 MOD: MontyFieldParams<LIMBS>,
852{
853 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
854 fmt::UpperHex::fmt(&self.to_canonical(), f)
855 }
856}
857
858impl<MOD, const LIMBS: usize> ConstMontyParams<LIMBS> for MontyFieldElement<MOD, LIMBS>
863where
864 MOD: MontyFieldParams<LIMBS>,
865{
866 const LIMBS: usize = LIMBS;
867 const PARAMS: FixedMontyParams<LIMBS> = MOD::PARAMS;
868}
869
870impl<MOD, const LIMBS: usize> Default for MontyFieldElement<MOD, LIMBS>
871where
872 MOD: MontyFieldParams<LIMBS>,
873{
874 fn default() -> Self {
875 Self::ZERO
876 }
877}
878
879impl<MOD: MontyFieldParams<LIMBS>, const LIMBS: usize> Eq for MontyFieldElement<MOD, LIMBS> {}
880impl<MOD: MontyFieldParams<LIMBS>, const LIMBS: usize> PartialEq for MontyFieldElement<MOD, LIMBS> {
881 fn eq(&self, rhs: &Self) -> bool {
882 self.inner.ct_eq(&(rhs.inner)).into()
883 }
884}
885
886impl<MOD, const LIMBS: usize> From<u32> for MontyFieldElement<MOD, LIMBS>
887where
888 MOD: MontyFieldParams<LIMBS>,
889{
890 #[inline]
891 fn from(n: u32) -> MontyFieldElement<MOD, LIMBS> {
892 Self::from_uint_reduced(&Uint::from(n))
893 }
894}
895
896impl<MOD, const LIMBS: usize> From<u64> for MontyFieldElement<MOD, LIMBS>
897where
898 MOD: MontyFieldParams<LIMBS>,
899{
900 #[inline]
901 fn from(n: u64) -> MontyFieldElement<MOD, LIMBS> {
902 Self::from_u64(n)
903 }
904}
905
906impl<MOD, const LIMBS: usize> From<u128> for MontyFieldElement<MOD, LIMBS>
907where
908 MOD: MontyFieldParams<LIMBS>,
909{
910 fn from(n: u128) -> MontyFieldElement<MOD, LIMBS> {
911 Self::from_uint_reduced(&Uint::from(n))
912 }
913}
914
915impl<MOD, const LIMBS: usize> From<MontyFieldElement<MOD, LIMBS>> for MontyFieldBytes<MOD, LIMBS>
916where
917 MOD: MontyFieldParams<LIMBS>,
918 Uint<LIMBS>: ArrayEncoding,
919{
920 fn from(fe: MontyFieldElement<MOD, LIMBS>) -> Self {
921 MontyFieldBytes::<MOD, LIMBS>::from(&fe)
922 }
923}
924
925impl<MOD, const LIMBS: usize> From<&MontyFieldElement<MOD, LIMBS>> for MontyFieldBytes<MOD, LIMBS>
926where
927 MOD: MontyFieldParams<LIMBS>,
928 Uint<LIMBS>: ArrayEncoding,
929{
930 fn from(fe: &MontyFieldElement<MOD, LIMBS>) -> Self {
931 fe.to_bytes()
932 }
933}
934
935impl<MOD, const LIMBS: usize> From<MontyFieldElement<MOD, LIMBS>> for Uint<LIMBS>
936where
937 MOD: MontyFieldParams<LIMBS>,
938{
939 fn from(fe: MontyFieldElement<MOD, LIMBS>) -> Uint<LIMBS> {
940 Uint::from(&fe)
941 }
942}
943
944impl<MOD, const LIMBS: usize> From<&MontyFieldElement<MOD, LIMBS>> for Uint<LIMBS>
945where
946 MOD: MontyFieldParams<LIMBS>,
947{
948 fn from(fe: &MontyFieldElement<MOD, LIMBS>) -> Uint<LIMBS> {
949 fe.to_canonical()
950 }
951}
952
953impl<MOD, const LIMBS: usize> Generate for MontyFieldElement<MOD, LIMBS>
954where
955 MOD: MontyFieldParams<LIMBS>,
956 MontyFieldBytes<MOD, LIMBS>: Copy,
957 Uint<LIMBS>: ArrayEncoding,
958{
959 fn try_generate_from_rng<R: TryCryptoRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
960 Self::try_random(rng)
961 }
962}
963
964impl<MOD, const LIMBS: usize> Ord for MontyFieldElement<MOD, LIMBS>
965where
966 MOD: MontyFieldParams<LIMBS>,
967{
968 fn cmp(&self, other: &Self) -> Ordering {
969 self.to_canonical().cmp(&other.to_canonical())
970 }
971}
972impl<MOD, const LIMBS: usize> PartialOrd for MontyFieldElement<MOD, LIMBS>
973where
974 MOD: MontyFieldParams<LIMBS>,
975{
976 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
977 Some(self.cmp(other))
978 }
979}
980
981impl<MOD, const LIMBS: usize> Retrieve for MontyFieldElement<MOD, LIMBS>
982where
983 MOD: MontyFieldParams<LIMBS>,
984{
985 type Output = Uint<LIMBS>;
986
987 fn retrieve(&self) -> Uint<LIMBS> {
988 self.to_canonical()
989 }
990}
991
992#[must_use]
994pub const fn compute_t<const LIMBS: usize>(modulus: &Uint<LIMBS>) -> Uint<LIMBS> {
995 let s = modulus.wrapping_sub(&Uint::ONE).trailing_zeros();
996 modulus.wrapping_sub(&Uint::ONE).unbounded_shr(s)
997}
998
999#[cfg(test)]
1000mod tests {
1001 use super::MontyFieldElement;
1002 use crate::{ByteOrder, monty_field_params, test_primefield};
1003 use bigint::U256;
1004
1005 monty_field_params!(
1008 name: P256Params,
1009 modulus: "ffffffff00000001000000000000000000000000ffffffffffffffffffffffff",
1010 uint: U256,
1011 byte_order: ByteOrder::BigEndian,
1012 multiplicative_generator: 6,
1013 doc: "P-256 field modulus"
1014 );
1015
1016 type FieldElement = MontyFieldElement<P256Params, { U256::LIMBS }>;
1017
1018 test_primefield!(FieldElement, U256);
1019
1020 #[test]
1021 fn modulus_bits_constant() {
1022 assert_eq!(FieldElement::NUM_BITS, 256);
1023 }
1024
1025 #[test]
1026 fn s_constant() {
1027 assert_eq!(FieldElement::S, 1);
1028 }
1029
1030 #[test]
1031 fn computed_delta_constant() {
1032 assert_eq!(FieldElement::DELTA, FieldElement::from_u64(36));
1033 }
1034
1035 mod little_endian {
1038 use super::*;
1039
1040 monty_field_params!(
1043 name: BignParams,
1044 modulus: "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF43",
1045 uint: U256,
1046 byte_order: ByteOrder::LittleEndian,
1047 multiplicative_generator: 2,
1048 doc: "BIGNP-256 field modulus"
1049 );
1050
1051 type BignP256Element = MontyFieldElement<BignParams, { U256::LIMBS }>;
1052
1053 test_primefield!(BignP256Element, U256);
1054
1055 #[test]
1056 fn byte_order() {
1057 let value = BignP256Element::from_u64(0x0123456789ABCDEF);
1059 let bytes = value.to_bytes();
1060
1061 assert_eq!(bytes[0], 0xEF); assert_eq!(bytes[1], 0xCD);
1063 assert_eq!(bytes[2], 0xAB);
1064 assert_eq!(bytes[3], 0x89);
1065 }
1066
1067 #[test]
1068 fn roundtrip() {
1069 let value = BignP256Element::from_u64(0x0123456789ABCDEF);
1070 let bytes = value.to_bytes();
1071 let recovered = BignP256Element::from_bytes(&bytes).unwrap();
1072 assert_eq!(value, recovered);
1073 }
1074
1075 #[test]
1076 fn modulus_bits_constant() {
1077 assert_eq!(BignP256Element::NUM_BITS, 256);
1078 }
1079
1080 #[test]
1081 fn s_constant() {
1082 assert_eq!(BignP256Element::S, 1);
1083 }
1084
1085 #[test]
1086 fn computed_delta_constant() {
1087 assert_eq!(BignP256Element::DELTA, BignP256Element::from_u64(4));
1088 }
1089 }
1090}