1use crate::traits::Borsh;
2use crate::Uint;
3use crate::{BitIterBE, BitIteratorBE};
4
5pub trait PrimeFieldParams {
6 type Inner: Uint;
7 const MODULUS: Self::Inner;
8 const MODULUS_BITS: u32;
9 const REPR_SHAVE_BITS: u32;
10 const R: Self::Inner;
11 const R2: Self::Inner;
12 const INV: u64;
13 const GENERATOR: Self::Inner;
14 const S: u32;
15 const ROOT_OF_UNITY: Self::Inner;
16}
17
18#[derive(Debug, PartialEq)]
19pub enum LegendreSymbol {
20 Zero = 0,
21 QuadraticResidue = 1,
22 QuadraticNonResidue = -1,
23}
24
25pub trait Field:
26 Sized
27 + Clone
28 + Copy
29 + Default
30 + core::cmp::PartialEq
31 + core::cmp::Eq
32 + core::fmt::Debug
33 + core::fmt::Display
34{
35 const ZERO: Self;
36 const ONE: Self;
37
38 #[cfg(feature = "rand_support")]
39 fn random<R: rand::Rng + ?Sized>(rng: &mut R) -> Self;
40 fn is_zero(&self) -> bool;
41
42 fn wrapping_add(self, other: Self) -> Self;
43 fn wrapping_sub(self, other: Self) -> Self;
44 fn wrapping_mul(self, other: Self) -> Self;
45 fn wrapping_div(self, other: Self) -> Self {
46 self.wrapping_mul(other.checked_inv().expect("Division by zero"))
47 }
48 fn wrapping_neg(self) -> Self;
49 fn square(self) -> Self;
50 fn double(self) -> Self;
51 fn checked_inv(self) -> Option<Self>;
52
53 fn frobenius_map(self, power: usize) -> Self;
54
55 fn pow<S: BitIterBE>(self, exp: S) -> Self {
56 let mut res = Self::ONE;
57 let mut found_one = false;
58 for i in exp.bit_iter_be() {
59 if found_one {
60 res = res.square();
61 } else {
62 found_one = i;
63 }
64 if i {
65 res = res.wrapping_mul(self);
66 }
67 }
68 res
69 }
70}
71
72pub trait SqrtField: Field {
73 fn legendre(&self) -> LegendreSymbol;
74 fn sqrt(&self) -> Option<Self>;
75}
76
77pub trait PrimeField:
78 PrimeFieldParams + SqrtField + core::str::FromStr + From<&'static str> + Borsh
79{
80 fn from_uint(v: Self::Inner) -> Option<Self>;
81 fn from_mont_uint(v: Self::Inner) -> Option<Self>;
82 fn from_uint_unchecked(v: Self::Inner) -> Self;
83 fn from_mont_uint_unchecked(v: Self::Inner) -> Self;
84
85 fn to_uint(&self) -> Self::Inner;
86 fn to_mont_uint(&self) -> Self::Inner;
87 fn as_mont_uint(&self) -> &Self::Inner;
88 fn as_mont_uint_mut(&mut self) -> &mut Self::Inner;
89
90 fn to_other<Fq: PrimeField>(&self) -> Option<Fq> {
91 let u = self.to_uint().to_other()?;
92
93 if u >= Fq::MODULUS {
94 None
95 } else {
96 Some(Fq::from_uint_unchecked(u))
97 }
98 }
99
100 fn to_other_reduced<Fq: PrimeField>(&self) -> Fq {
101 match self.to_uint().to_other::<Fq::Inner>() {
102 Some(u) => Fq::from_uint_unchecked(u.wrapping_rem(Fq::MODULUS)),
103 None => {
104 let u = self
105 .to_uint()
106 .wrapping_rem(<Fq as PrimeFieldParams>::MODULUS.to_other().unwrap());
107 Fq::from_uint_unchecked(u.to_other().unwrap())
108 }
109 }
110 }
111}