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