1use serde::{Deserialize, Serialize};
2
3use super::{
4 Field,
5 element::{FieldElement, FieldElementContainer},
6 field_internal::FieldInternal,
7};
8pub use crate::prime::fp::*;
10use crate::{constants::BITS_PER_LIMB, limb::Limb, prime::Prime};
11
12#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
14pub struct Fp<P> {
15 p: P,
16}
17
18impl<P: Prime> Fp<P> {
19 pub const fn new(p: P) -> Self {
20 Self { p }
21 }
22
23 pub fn element(&self, value: u32) -> FieldElement<Self> {
24 self.el(value)
25 }
26}
27
28impl<P: Prime> Field for Fp<P> {
29 type Characteristic = P;
30
31 fn characteristic(self) -> Self::Characteristic {
32 self.p
33 }
34
35 fn degree(self) -> u32 {
36 1
37 }
38
39 fn zero(self) -> FieldElement<Self> {
40 self.el(0)
41 }
42
43 fn one(self) -> FieldElement<Self> {
44 self.el(1)
45 }
46
47 #[cfg(feature = "proptest")]
48 fn arb_element(self) -> impl proptest::strategy::Strategy<Value = FieldElement<Self>> {
49 use proptest::prelude::*;
50
51 (0..self.characteristic().as_u32()).prop_map(move |v| self.element(v))
52 }
53}
54
55impl<P: Prime> FieldInternal for Fp<P> {
56 type ElementContainer = u32;
57
58 fn el(self, value: Self::ElementContainer) -> FieldElement<Self> {
59 FieldElement::new(self, value % self.p.as_u32())
60 }
61
62 fn add_assign(self, a: &mut FieldElement<Self>, b: FieldElement<Self>) {
63 a.value = self.p.sum(**a, *b);
64 }
65
66 fn mul_assign(self, a: &mut FieldElement<Self>, b: FieldElement<Self>) {
67 a.value = self.p.product(**a, *b);
68 }
69
70 fn inv(self, a: FieldElement<Self>) -> Option<FieldElement<Self>> {
71 if *a == 0 {
72 None
73 } else {
74 Some(self.el(crate::prime::inverse(self.p, *a)))
75 }
76 }
77
78 fn neg(self, a: FieldElement<Self>) -> FieldElement<Self> {
79 self.el(if *a == 0 { 0 } else { self.p.as_u32() - *a })
80 }
81
82 fn frobenius(self, a: FieldElement<Self>) -> FieldElement<Self> {
83 a
84 }
85
86 fn encode(self, element: FieldElement<Self>) -> Limb {
87 element.value as Limb
88 }
89
90 fn decode(self, element: Limb) -> FieldElement<Self> {
91 let prime_limb = self.p.as_u32() as Limb;
95 self.el((element % prime_limb) as u32)
96 }
97
98 fn bit_length(self) -> usize {
99 let p = self.characteristic().as_u32() as u64;
100 match p {
101 2 => 1,
103 _ => (BITS_PER_LIMB as u32 - (p * (p - 1)).leading_zeros()) as usize,
104 }
105 }
106
107 fn fma_limb(self, limb_a: Limb, limb_b: Limb, coeff: FieldElement<Self>) -> Limb {
108 if self.characteristic() == 2 {
109 limb_a ^ (coeff.value as Limb * limb_b)
110 } else {
111 limb_a + (coeff.value as Limb) * limb_b
112 }
113 }
114
115 fn reduce(self, limb: Limb) -> Limb {
117 match self.characteristic().as_u32() {
118 2 => limb,
119 3 => {
120 const TOP_BIT: Limb = (!0 / 7) << (2 - BITS_PER_LIMB % 3);
122 let mut limb_2 = ((limb & TOP_BIT) >> 2) + (limb & (!TOP_BIT));
123 let mut limb_3s = limb_2 & (limb_2 >> 1);
124 limb_3s |= limb_3s << 1;
125 limb_2 ^= limb_3s;
126 limb_2
127 }
128 5 => {
129 const BOTTOM_BIT: Limb = (!0 / 31) >> (BITS_PER_LIMB % 5);
131 const BOTTOM_TWO_BITS: Limb = BOTTOM_BIT | (BOTTOM_BIT << 1);
132 const BOTTOM_THREE_BITS: Limb = BOTTOM_BIT | (BOTTOM_TWO_BITS << 1);
133 let a = (limb >> 2) & BOTTOM_THREE_BITS;
134 let b = limb & BOTTOM_TWO_BITS;
135 let m = (BOTTOM_BIT << 3) - a + b;
136 let mut c = (m >> 3) & BOTTOM_BIT;
137 c |= c << 1;
138 let d = m & BOTTOM_THREE_BITS;
139 d + c - BOTTOM_TWO_BITS
140 }
141 _ => self.pack(self.unpack(limb)),
143 }
144 }
145}
146
147#[cfg(feature = "proptest")]
148impl<P: Prime> proptest::arbitrary::Arbitrary for Fp<P> {
149 type Parameters = ();
150 type Strategy = proptest::strategy::BoxedStrategy<Self>;
151
152 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
153 use proptest::prelude::*;
154
155 any::<P>().prop_map(Self::new).boxed()
156 }
157}
158
159impl<P: Prime> crate::MaybeArbitrary<()> for Fp<P> {}
160
161impl<P> std::ops::Deref for Fp<P> {
162 type Target = P;
163
164 fn deref(&self) -> &Self::Target {
165 &self.p
166 }
167}
168
169impl<P: Prime> From<P> for Fp<P> {
170 fn from(p: P) -> Self {
171 Self { p }
172 }
173}
174
175impl FieldElementContainer for u32 {}
176
177impl<P: Prime> From<FieldElement<Fp<P>>> for u32 {
178 fn from(element: FieldElement<Fp<P>>) -> Self {
179 element.value
180 }
181}
182
183#[cfg(test)]
184mod tests {
185 use super::Fp;
186 use crate::field::tests::field_tests;
187
188 mod validprime {
189 use super::*;
190 use crate::prime::ValidPrime;
191
192 field_tests!(Fp<ValidPrime>);
193 }
194
195 macro_rules! static_fp_tests {
196 ($p:tt) => {
197 paste::paste! {
198 static_fp_tests!(@ [<$p:lower>], $p, $p);
199 }
200 };
201 (@ $mod_name:ident, $p_ident:ident, $p_ty:ty) => {
202 mod $mod_name {
203 use super::*;
204 use crate::prime::$p_ident;
205
206 field_tests!(Fp<$p_ty>);
207 }
208 };
209 }
210
211 static_fp_tests!(P2);
212 cfg_if::cfg_if! { if #[cfg(feature = "odd-primes")] {
213 static_fp_tests!(P3);
214 static_fp_tests!(P5);
215 static_fp_tests!(P7);
216 }}
217}