p3_monty_31/
monty_31.rs
1use alloc::vec;
4use alloc::vec::Vec;
5use core::fmt::{self, Debug, Display, Formatter};
6use core::hash::Hash;
7use core::intrinsics::transmute;
8use core::iter::{Product, Sum};
9use core::marker::PhantomData;
10use core::ops::{Add, AddAssign, Div, Mul, MulAssign, Neg, Sub, SubAssign};
11
12use num_bigint::BigUint;
13use p3_field::{
14 Field, FieldAlgebra, Packable, PrimeField, PrimeField32, PrimeField64, TwoAdicField,
15};
16use rand::distributions::{Distribution, Standard};
17use rand::Rng;
18use serde::de::Error;
19use serde::{Deserialize, Deserializer, Serialize};
20
21use crate::utils::{from_monty, halve_u32, monty_reduce, to_monty, to_monty_64};
22use crate::{FieldParameters, MontyParameters, TwoAdicData};
23
24#[derive(Clone, Copy, Default, Eq, Hash, PartialEq)]
25#[repr(transparent)] pub struct MontyField31<MP: MontyParameters> {
27 pub(crate) value: u32,
32 _phantom: PhantomData<MP>,
33}
34
35impl<MP: MontyParameters> MontyField31<MP> {
36 #[inline(always)]
39 pub const fn new(value: u32) -> Self {
40 Self {
41 value: to_monty::<MP>(value),
42 _phantom: PhantomData,
43 }
44 }
45
46 #[inline(always)]
50 pub(crate) const fn new_monty(value: u32) -> Self {
51 Self {
52 value,
53 _phantom: PhantomData,
54 }
55 }
56
57 #[inline(always)]
59 pub(crate) fn to_u32(elem: &Self) -> u32 {
60 from_monty::<MP>(elem.value)
61 }
62
63 #[inline]
66 pub const fn new_array<const N: usize>(input: [u32; N]) -> [Self; N] {
67 let mut output = [MontyField31::new_monty(0); N];
68 let mut i = 0;
69 loop {
70 if i == N {
71 break;
72 }
73 output[i] = MontyField31::new(input[i]);
74 i += 1;
75 }
76 output
77 }
78
79 #[inline]
82 pub const fn new_2d_array<const N: usize, const M: usize>(
83 input: [[u32; N]; M],
84 ) -> [[Self; N]; M] {
85 let mut output = [[MontyField31::new_monty(0); N]; M];
86 let mut i = 0;
87 loop {
88 if i == M {
89 break;
90 }
91 output[i] = MontyField31::new_array(input[i]);
92 i += 1;
93 }
94 output
95 }
96
97 #[inline]
103 #[must_use]
104 pub const fn mul_2exp_neg_n(&self, n: u32) -> Self {
105 assert!(n < 33);
106 let value_mul_2exp_neg_n = (self.value as u64) << (32 - n);
107 MontyField31::new_monty(monty_reduce::<MP>(value_mul_2exp_neg_n))
108 }
109}
110
111impl<FP: MontyParameters> Ord for MontyField31<FP> {
112 #[inline]
113 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
114 MontyField31::to_u32(self).cmp(&MontyField31::to_u32(other))
115 }
116}
117
118impl<FP: MontyParameters> PartialOrd for MontyField31<FP> {
119 #[inline]
120 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
121 Some(self.cmp(other))
122 }
123}
124
125impl<FP: MontyParameters> Display for MontyField31<FP> {
126 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
127 Display::fmt(&MontyField31::to_u32(self), f)
128 }
129}
130
131impl<FP: MontyParameters> Debug for MontyField31<FP> {
132 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
133 Debug::fmt(&MontyField31::to_u32(self), f)
134 }
135}
136
137impl<FP: MontyParameters> Distribution<MontyField31<FP>> for Standard {
138 #[inline]
139 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> MontyField31<FP> {
140 loop {
141 let next_u31 = rng.next_u32() >> 1;
142 let is_canonical = next_u31 < FP::PRIME;
143 if is_canonical {
144 return MontyField31::new_monty(next_u31);
145 }
146 }
147 }
148}
149
150impl<FP: FieldParameters> Serialize for MontyField31<FP> {
151 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
152 serializer.serialize_u32(self.value)
154 }
155}
156
157impl<'de, FP: FieldParameters> Deserialize<'de> for MontyField31<FP> {
158 fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
159 let val = u32::deserialize(d)?;
160 if val < FP::PRIME {
162 Ok(MontyField31::new_monty(val))
164 } else {
165 Err(D::Error::custom("Value is out of range"))
166 }
167 }
168}
169
170impl<FP: FieldParameters> Packable for MontyField31<FP> {}
171
172impl<FP: FieldParameters> FieldAlgebra for MontyField31<FP> {
173 type F = Self;
174
175 const ZERO: Self = FP::MONTY_ZERO;
176 const ONE: Self = FP::MONTY_ONE;
177 const TWO: Self = FP::MONTY_TWO;
178 const NEG_ONE: Self = FP::MONTY_NEG_ONE;
179
180 #[inline(always)]
181 fn from_f(f: Self::F) -> Self {
182 f
183 }
184
185 #[inline(always)]
186 fn from_canonical_u8(n: u8) -> Self {
187 Self::from_canonical_u32(n as u32)
188 }
189
190 #[inline(always)]
191 fn from_canonical_u16(n: u16) -> Self {
192 Self::from_canonical_u32(n as u32)
193 }
194
195 #[inline(always)]
196 fn from_canonical_u32(n: u32) -> Self {
197 debug_assert!(n < FP::PRIME);
198 Self::from_wrapped_u32(n)
199 }
200
201 #[inline(always)]
202 fn from_canonical_u64(n: u64) -> Self {
203 debug_assert!(n < FP::PRIME as u64);
204 Self::from_canonical_u32(n as u32)
205 }
206
207 #[inline(always)]
208 fn from_canonical_usize(n: usize) -> Self {
209 debug_assert!(n < FP::PRIME as usize);
210 Self::from_canonical_u32(n as u32)
211 }
212
213 #[inline(always)]
214 fn from_wrapped_u32(n: u32) -> Self {
215 Self::new(n)
216 }
217
218 #[inline(always)]
219 fn from_wrapped_u64(n: u64) -> Self {
220 Self::new_monty(to_monty_64::<FP>(n))
221 }
222
223 #[inline]
224 fn mul_2exp_u64(&self, exp: u64) -> Self {
225 let product = (self.value as u64) << exp;
226 let value = (product % (FP::PRIME as u64)) as u32;
227 Self::new_monty(value)
228 }
229
230 #[inline]
231 fn zero_vec(len: usize) -> Vec<Self> {
232 unsafe { transmute(vec![0u32; len]) }
234 }
235}
236
237impl<FP: FieldParameters> Field for MontyField31<FP> {
238 #[cfg(all(target_arch = "aarch64", target_feature = "neon"))]
239 type Packing = crate::PackedMontyField31Neon<FP>;
240 #[cfg(all(
241 target_arch = "x86_64",
242 target_feature = "avx2",
243 not(all(feature = "nightly-features", target_feature = "avx512f"))
244 ))]
245 type Packing = crate::PackedMontyField31AVX2<FP>;
246 #[cfg(all(
247 feature = "nightly-features",
248 target_arch = "x86_64",
249 target_feature = "avx512f"
250 ))]
251 type Packing = crate::PackedMontyField31AVX512<FP>;
252 #[cfg(not(any(
253 all(target_arch = "aarch64", target_feature = "neon"),
254 all(
255 target_arch = "x86_64",
256 target_feature = "avx2",
257 not(all(feature = "nightly-features", target_feature = "avx512f"))
258 ),
259 all(
260 feature = "nightly-features",
261 target_arch = "x86_64",
262 target_feature = "avx512f"
263 ),
264 )))]
265 type Packing = Self;
266
267 const GENERATOR: Self = FP::MONTY_GEN;
268
269 #[inline]
270 fn exp_u64_generic<FA: FieldAlgebra<F = Self>>(val: FA, power: u64) -> FA {
271 FP::exp_u64_generic(val, power)
272 }
273
274 fn try_inverse(&self) -> Option<Self> {
275 FP::try_inverse(*self)
276 }
277
278 #[inline]
279 fn halve(&self) -> Self {
280 Self::new_monty(halve_u32::<FP>(self.value))
281 }
282
283 #[inline]
284 fn order() -> BigUint {
285 FP::PRIME.into()
286 }
287}
288
289impl<FP: FieldParameters> PrimeField for MontyField31<FP> {
290 fn as_canonical_biguint(&self) -> BigUint {
291 <Self as PrimeField32>::as_canonical_u32(self).into()
292 }
293}
294
295impl<FP: FieldParameters> PrimeField64 for MontyField31<FP> {
296 const ORDER_U64: u64 = FP::PRIME as u64;
297
298 #[inline]
299 fn as_canonical_u64(&self) -> u64 {
300 self.as_canonical_u32().into()
301 }
302
303 #[inline]
304 fn to_unique_u64(&self) -> u64 {
305 self.value as u64
308 }
309}
310
311impl<FP: FieldParameters> PrimeField32 for MontyField31<FP> {
312 const ORDER_U32: u32 = FP::PRIME;
313
314 #[inline]
315 fn as_canonical_u32(&self) -> u32 {
316 MontyField31::to_u32(self)
317 }
318
319 #[inline]
320 fn to_unique_u32(&self) -> u32 {
321 self.value
324 }
325}
326
327impl<FP: FieldParameters + TwoAdicData> TwoAdicField for MontyField31<FP> {
328 const TWO_ADICITY: usize = FP::TWO_ADICITY;
329 fn two_adic_generator(bits: usize) -> Self {
330 assert!(bits <= Self::TWO_ADICITY);
331 FP::TWO_ADIC_GENERATORS.as_ref()[bits]
332 }
333}
334
335impl<FP: MontyParameters> Add for MontyField31<FP> {
336 type Output = Self;
337
338 #[inline]
339 fn add(self, rhs: Self) -> Self {
340 let mut sum = self.value + rhs.value;
341 let (corr_sum, over) = sum.overflowing_sub(FP::PRIME);
342 if !over {
343 sum = corr_sum;
344 }
345 Self::new_monty(sum)
346 }
347}
348
349impl<FP: MontyParameters> AddAssign for MontyField31<FP> {
350 #[inline]
351 fn add_assign(&mut self, rhs: Self) {
352 *self = *self + rhs;
353 }
354}
355
356impl<FP: MontyParameters> Sum for MontyField31<FP> {
357 #[inline]
358 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
359 let sum = iter.map(|x| x.value as u64).sum::<u64>();
364 Self::new_monty((sum % FP::PRIME as u64) as u32)
365 }
366}
367
368impl<FP: MontyParameters> Sub for MontyField31<FP> {
369 type Output = Self;
370
371 #[inline]
372 fn sub(self, rhs: Self) -> Self {
373 let (mut diff, over) = self.value.overflowing_sub(rhs.value);
374 let corr = if over { FP::PRIME } else { 0 };
375 diff = diff.wrapping_add(corr);
376 Self::new_monty(diff)
377 }
378}
379
380impl<FP: MontyParameters> SubAssign for MontyField31<FP> {
381 #[inline]
382 fn sub_assign(&mut self, rhs: Self) {
383 *self = *self - rhs;
384 }
385}
386
387impl<FP: FieldParameters> Neg for MontyField31<FP> {
388 type Output = Self;
389
390 #[inline]
391 fn neg(self) -> Self::Output {
392 Self::ZERO - self
393 }
394}
395
396impl<FP: MontyParameters> Mul for MontyField31<FP> {
397 type Output = Self;
398
399 #[inline]
400 fn mul(self, rhs: Self) -> Self {
401 let long_prod = self.value as u64 * rhs.value as u64;
402 Self::new_monty(monty_reduce::<FP>(long_prod))
403 }
404}
405
406impl<FP: MontyParameters> MulAssign for MontyField31<FP> {
407 #[inline]
408 fn mul_assign(&mut self, rhs: Self) {
409 *self = *self * rhs;
410 }
411}
412
413impl<FP: FieldParameters> Product for MontyField31<FP> {
414 #[inline]
415 fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
416 iter.reduce(|x, y| x * y).unwrap_or(Self::ONE)
417 }
418}
419
420impl<FP: FieldParameters> Div for MontyField31<FP> {
421 type Output = Self;
422
423 #[allow(clippy::suspicious_arithmetic_impl)]
424 #[inline]
425 fn div(self, rhs: Self) -> Self {
426 self * rhs.inverse()
427 }
428}