1use alloc::format;
4use core::{
5 array, fmt,
6 hash::{Hash, Hasher},
7 iter::{Product, Sum},
8 ops::{Add, AddAssign, Deref, DerefMut, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign},
9};
10
11use miden_serde_utils::{
12 ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable,
13};
14use num_bigint::BigUint;
15use p3_challenger::UniformSamplingField;
16use p3_field::{
17 Field, InjectiveMonomial, Packable, PermutationMonomial, PrimeCharacteristicRing, PrimeField,
18 PrimeField64, RawDataSerializable, TwoAdicField,
19 extension::{BinomiallyExtendable, BinomiallyExtendableAlgebra, HasTwoAdicBinomialExtension},
20 impl_raw_serializable_primefield64,
21 integers::QuotientMap,
22 quotient_map_large_iint, quotient_map_large_uint, quotient_map_small_int,
23};
24use p3_goldilocks::Goldilocks;
25use rand::{
26 Rng,
27 distr::{Distribution, StandardUniform},
28};
29
30#[cfg(test)]
31mod tests;
32
33#[derive(Copy, Clone, Default, serde::Serialize, serde::Deserialize)]
38#[repr(transparent)]
39pub struct Felt(Goldilocks);
40
41impl Felt {
42 pub const ORDER: u64 = <Goldilocks as PrimeField64>::ORDER_U64;
44
45 pub const ZERO: Self = Self(Goldilocks::ZERO);
46 pub const ONE: Self = Self(Goldilocks::ONE);
47
48 pub const NUM_BYTES: usize = Goldilocks::NUM_BYTES;
50
51 #[inline]
56 pub const fn new(value: u64) -> Self {
57 Self(Goldilocks::new(value))
58 }
59
60 #[inline]
61 pub fn from_u8(value: u8) -> Self {
62 <Self as PrimeCharacteristicRing>::from_u8(value)
63 }
64
65 #[inline]
66 pub fn from_u16(value: u16) -> Self {
67 <Self as PrimeCharacteristicRing>::from_u16(value)
68 }
69
70 #[inline]
71 pub fn from_u32(value: u32) -> Self {
72 <Self as PrimeCharacteristicRing>::from_u32(value)
73 }
74
75 #[inline]
77 pub fn double(&self) -> Self {
78 <Self as PrimeCharacteristicRing>::double(self)
79 }
80
81 #[inline]
83 pub fn square(&self) -> Self {
84 <Self as PrimeCharacteristicRing>::square(self)
85 }
86
87 #[inline]
89 pub fn exp_u64(&self, power: u64) -> Self {
90 <Self as PrimeCharacteristicRing>::exp_u64(self, power)
91 }
92
93 #[inline]
95 pub fn exp_const_u64<const POWER: u64>(&self) -> Self {
96 <Self as PrimeCharacteristicRing>::exp_const_u64::<POWER>(self)
97 }
98
99 #[inline]
102 pub fn as_canonical_u64(&self) -> u64 {
103 <Self as PrimeField64>::as_canonical_u64(self)
104 }
105}
106
107impl fmt::Display for Felt {
108 #[inline]
109 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
110 fmt::Display::fmt(&self.0, f)
111 }
112}
113
114impl fmt::Debug for Felt {
115 #[inline]
116 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
117 fmt::Debug::fmt(&self.0, f)
118 }
119}
120
121impl Hash for Felt {
122 #[inline]
123 fn hash<H: Hasher>(&self, state: &mut H) {
124 state.write_u64(self.as_canonical_u64());
125 }
126}
127
128impl Field for Felt {
132 type Packing = Self;
133
134 const GENERATOR: Self = Self(Goldilocks::GENERATOR);
135
136 #[inline]
137 fn is_zero(&self) -> bool {
138 self.0.is_zero()
139 }
140
141 #[inline]
142 fn try_inverse(&self) -> Option<Self> {
143 self.0.try_inverse().map(Self)
144 }
145
146 #[inline]
147 fn order() -> BigUint {
148 <Goldilocks as Field>::order()
149 }
150}
151
152impl Packable for Felt {}
153
154impl PrimeCharacteristicRing for Felt {
155 type PrimeSubfield = Goldilocks;
156
157 const ZERO: Self = Self(Goldilocks::ZERO);
158 const ONE: Self = Self(Goldilocks::ONE);
159 const TWO: Self = Self(Goldilocks::TWO);
160 const NEG_ONE: Self = Self(Goldilocks::NEG_ONE);
161
162 #[inline]
163 fn from_prime_subfield(f: Self::PrimeSubfield) -> Self {
164 Self(f)
165 }
166
167 #[inline]
168 fn from_bool(value: bool) -> Self {
169 Self::new(value.into())
170 }
171
172 #[inline]
173 fn halve(&self) -> Self {
174 Self(self.0.halve())
175 }
176
177 #[inline]
178 fn mul_2exp_u64(&self, exp: u64) -> Self {
179 Self(self.0.mul_2exp_u64(exp))
180 }
181
182 #[inline]
183 fn div_2exp_u64(&self, exp: u64) -> Self {
184 Self(self.0.div_2exp_u64(exp))
185 }
186
187 #[inline]
188 fn exp_u64(&self, power: u64) -> Self {
189 self.0.exp_u64(power).into()
190 }
191}
192
193quotient_map_small_int!(Felt, u64, [u8, u16, u32]);
194quotient_map_small_int!(Felt, i64, [i8, i16, i32]);
195
196quotient_map_large_uint!(
197 Felt,
198 u64,
199 Felt::ORDER_U64,
200 "`[0, 2^64 - 2^32]`",
201 "`[0, 2^64 - 1]`",
202 [u128]
203);
204quotient_map_large_iint!(
205 Felt,
206 i64,
207 "`[-(2^63 - 2^31), 2^63 - 2^31]`",
208 "`[1 + 2^32 - 2^64, 2^64 - 1]`",
209 [(i128, u128)]
210);
211
212impl QuotientMap<u64> for Felt {
213 #[inline]
214 fn from_int(int: u64) -> Self {
215 Goldilocks::from_int(int).into()
216 }
217
218 #[inline]
219 fn from_canonical_checked(int: u64) -> Option<Self> {
220 Goldilocks::from_canonical_checked(int).map(From::from)
221 }
222
223 #[inline(always)]
224 unsafe fn from_canonical_unchecked(int: u64) -> Self {
225 Goldilocks::new(int).into()
226 }
227}
228
229impl QuotientMap<i64> for Felt {
230 #[inline]
231 fn from_int(int: i64) -> Self {
232 Goldilocks::from_int(int).into()
233 }
234
235 #[inline]
236 fn from_canonical_checked(int: i64) -> Option<Self> {
237 Goldilocks::from_canonical_checked(int).map(From::from)
238 }
239
240 #[inline(always)]
241 unsafe fn from_canonical_unchecked(int: i64) -> Self {
242 unsafe { Goldilocks::from_canonical_unchecked(int).into() }
243 }
244}
245
246impl PrimeField for Felt {
247 #[inline]
248 fn as_canonical_biguint(&self) -> BigUint {
249 <Goldilocks as PrimeField>::as_canonical_biguint(&self.0)
250 }
251}
252
253impl PrimeField64 for Felt {
254 const ORDER_U64: u64 = <Goldilocks as PrimeField64>::ORDER_U64;
255
256 #[inline]
257 fn as_canonical_u64(&self) -> u64 {
258 self.0.as_canonical_u64()
259 }
260}
261
262impl TwoAdicField for Felt {
263 const TWO_ADICITY: usize = <Goldilocks as TwoAdicField>::TWO_ADICITY;
264
265 #[inline]
266 fn two_adic_generator(bits: usize) -> Self {
267 Self(<Goldilocks as TwoAdicField>::two_adic_generator(bits))
268 }
269}
270
271impl BinomiallyExtendableAlgebra<Self, 2> for Felt {}
275
276impl BinomiallyExtendable<2> for Felt {
277 const W: Self = Self(<Goldilocks as BinomiallyExtendable<2>>::W);
278
279 const DTH_ROOT: Self = Self(<Goldilocks as BinomiallyExtendable<2>>::DTH_ROOT);
280
281 const EXT_GENERATOR: [Self; 2] = [
282 Self(<Goldilocks as BinomiallyExtendable<2>>::EXT_GENERATOR[0]),
283 Self(<Goldilocks as BinomiallyExtendable<2>>::EXT_GENERATOR[1]),
284 ];
285}
286
287impl HasTwoAdicBinomialExtension<2> for Felt {
288 const EXT_TWO_ADICITY: usize = <Goldilocks as HasTwoAdicBinomialExtension<2>>::EXT_TWO_ADICITY;
289
290 #[inline]
291 fn ext_two_adic_generator(bits: usize) -> [Self; 2] {
292 let [a, b] = <Goldilocks as HasTwoAdicBinomialExtension<2>>::ext_two_adic_generator(bits);
293 [Self(a), Self(b)]
294 }
295}
296
297impl BinomiallyExtendableAlgebra<Self, 5> for Felt {}
298
299impl BinomiallyExtendable<5> for Felt {
300 const W: Self = Self(<Goldilocks as BinomiallyExtendable<5>>::W);
301
302 const DTH_ROOT: Self = Self(<Goldilocks as BinomiallyExtendable<5>>::DTH_ROOT);
303
304 const EXT_GENERATOR: [Self; 5] = [
305 Self(<Goldilocks as BinomiallyExtendable<5>>::EXT_GENERATOR[0]),
306 Self(<Goldilocks as BinomiallyExtendable<5>>::EXT_GENERATOR[1]),
307 Self(<Goldilocks as BinomiallyExtendable<5>>::EXT_GENERATOR[2]),
308 Self(<Goldilocks as BinomiallyExtendable<5>>::EXT_GENERATOR[3]),
309 Self(<Goldilocks as BinomiallyExtendable<5>>::EXT_GENERATOR[4]),
310 ];
311}
312
313impl HasTwoAdicBinomialExtension<5> for Felt {
314 const EXT_TWO_ADICITY: usize = <Goldilocks as HasTwoAdicBinomialExtension<5>>::EXT_TWO_ADICITY;
315
316 #[inline]
317 fn ext_two_adic_generator(bits: usize) -> [Self; 5] {
318 let ext_generator =
319 <Goldilocks as HasTwoAdicBinomialExtension<5>>::ext_two_adic_generator(bits);
320 [
321 Self(ext_generator[0]),
322 Self(ext_generator[1]),
323 Self(ext_generator[2]),
324 Self(ext_generator[3]),
325 Self(ext_generator[4]),
326 ]
327 }
328}
329
330impl RawDataSerializable for Felt {
331 impl_raw_serializable_primefield64!();
332}
333
334impl Distribution<Felt> for StandardUniform {
335 #[inline]
336 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Felt {
337 let inner = <StandardUniform as Distribution<Goldilocks>>::sample(self, rng);
338 Felt(inner)
339 }
340}
341
342impl UniformSamplingField for Felt {
343 const MAX_SINGLE_SAMPLE_BITS: usize =
344 <Goldilocks as UniformSamplingField>::MAX_SINGLE_SAMPLE_BITS;
345 const SAMPLING_BITS_M: [u64; 64] = <Goldilocks as UniformSamplingField>::SAMPLING_BITS_M;
346}
347
348impl InjectiveMonomial<7> for Felt {}
349
350impl PermutationMonomial<7> for Felt {
351 #[inline]
352 fn injective_exp_root_n(&self) -> Self {
353 Self(self.0.injective_exp_root_n())
354 }
355}
356
357impl From<u8> for Felt {
361 fn from(int: u8) -> Self {
362 Self::from_u8(int)
363 }
364}
365
366impl From<u16> for Felt {
367 fn from(int: u16) -> Self {
368 Self::from_u16(int)
369 }
370}
371
372impl From<u32> for Felt {
373 fn from(int: u32) -> Self {
374 Self::from_u32(int)
375 }
376}
377
378impl TryFrom<u64> for Felt {
379 type Error = FeltFromIntError;
380
381 fn try_from(int: u64) -> Result<Felt, Self::Error> {
382 Felt::from_canonical_checked(int).ok_or(FeltFromIntError(int))
383 }
384}
385
386#[derive(Debug, thiserror::Error)]
387#[error("integer {0} is equal to or exceeds the felt modulus {modulus}", modulus = Felt::ORDER)]
388pub struct FeltFromIntError(u64);
389
390impl FeltFromIntError {
391 pub fn as_u64(&self) -> u64 {
393 self.0
394 }
395}
396
397impl Deref for Felt {
398 type Target = Goldilocks;
399
400 #[inline]
401 fn deref(&self) -> &Self::Target {
402 &self.0
403 }
404}
405
406impl DerefMut for Felt {
407 #[inline]
408 fn deref_mut(&mut self) -> &mut Self::Target {
409 &mut self.0
410 }
411}
412
413impl From<Goldilocks> for Felt {
414 #[inline]
415 fn from(value: Goldilocks) -> Self {
416 Self(value)
417 }
418}
419
420impl From<Felt> for Goldilocks {
421 #[inline]
422 fn from(value: Felt) -> Self {
423 value.0
424 }
425}
426
427impl Add for Felt {
431 type Output = Self;
432
433 #[inline]
434 fn add(self, other: Self) -> Self {
435 Self(self.0 + other.0)
436 }
437}
438
439impl AddAssign for Felt {
440 #[inline]
441 fn add_assign(&mut self, other: Self) {
442 *self = *self + other;
443 }
444}
445
446impl Sub for Felt {
447 type Output = Self;
448
449 #[inline]
450 fn sub(self, other: Self) -> Self {
451 Self(self.0 - other.0)
452 }
453}
454
455impl SubAssign for Felt {
456 #[inline]
457 fn sub_assign(&mut self, other: Self) {
458 *self = *self - other;
459 }
460}
461
462impl Mul for Felt {
463 type Output = Self;
464
465 #[inline]
466 fn mul(self, other: Self) -> Self {
467 Self(self.0 * other.0)
468 }
469}
470
471impl MulAssign for Felt {
472 #[inline]
473 fn mul_assign(&mut self, other: Self) {
474 *self = *self * other;
475 }
476}
477
478impl Div for Felt {
479 type Output = Self;
480
481 #[inline]
482 fn div(self, other: Self) -> Self {
483 Self(self.0 / other.0)
484 }
485}
486
487impl DivAssign for Felt {
488 #[inline]
489 fn div_assign(&mut self, other: Self) {
490 *self = *self / other;
491 }
492}
493
494impl Neg for Felt {
495 type Output = Self;
496
497 #[inline]
498 fn neg(self) -> Self {
499 Self(-self.0)
500 }
501}
502
503impl Sum for Felt {
504 #[inline]
505 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
506 Self(iter.map(|x| x.0).sum())
507 }
508}
509
510impl<'a> Sum<&'a Felt> for Felt {
511 #[inline]
512 fn sum<I: Iterator<Item = &'a Felt>>(iter: I) -> Self {
513 Self(iter.map(|x| x.0).sum())
514 }
515}
516
517impl Product for Felt {
518 #[inline]
519 fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
520 Self(iter.map(|x| x.0).product())
521 }
522}
523
524impl<'a> Product<&'a Felt> for Felt {
525 #[inline]
526 fn product<I: Iterator<Item = &'a Felt>>(iter: I) -> Self {
527 Self(iter.map(|x| x.0).product())
528 }
529}
530
531impl PartialEq for Felt {
535 #[inline]
536 fn eq(&self, other: &Self) -> bool {
537 self.0 == other.0
538 }
539}
540
541impl PartialEq<Goldilocks> for Felt {
542 #[inline]
543 fn eq(&self, other: &Goldilocks) -> bool {
544 self.0 == *other
545 }
546}
547
548impl Eq for Felt {}
549
550impl PartialOrd for Felt {
551 #[inline]
552 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
553 Some(self.cmp(other))
554 }
555}
556
557impl Ord for Felt {
558 #[inline]
559 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
560 self.0.cmp(&other.0)
561 }
562}
563
564impl Serializable for Felt {
568 fn write_into<W: ByteWriter>(&self, target: &mut W) {
569 target.write_u64(self.as_canonical_u64());
570 }
571
572 fn get_size_hint(&self) -> usize {
573 core::mem::size_of::<u64>()
574 }
575}
576
577impl Deserializable for Felt {
578 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
579 let value = source.read_u64()?;
580 Self::from_canonical_checked(value).ok_or_else(|| {
581 DeserializationError::InvalidValue(format!("value {value} is not a valid felt"))
582 })
583 }
584}
585
586#[cfg(all(any(test, feature = "testing"), not(all(target_family = "wasm", miden))))]
590mod arbitrary {
591 use proptest::prelude::*;
592
593 use super::Felt;
594
595 impl Arbitrary for Felt {
596 type Parameters = ();
597 type Strategy = BoxedStrategy<Self>;
598
599 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
600 let canonical = (0u64..Felt::ORDER).prop_map(Felt::new).boxed();
601 let non_canonical = (Felt::ORDER..=u64::MAX).prop_map(Felt::new).boxed();
605 prop_oneof![4 => canonical, 1 => non_canonical].no_shrink().boxed()
606 }
607 }
608}