1use alloc::vec;
2use alloc::vec::Vec;
3use core::fmt::{Debug, Display, Formatter};
4use core::hash::{Hash, Hasher};
5use core::iter::{Product, Sum};
6use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
7use core::{array, fmt};
8
9use num_bigint::BigUint;
10use p3_challenger::UniformSamplingField;
11use p3_field::exponentiation::exp_10540996611094048183;
12use p3_field::integers::QuotientMap;
13use p3_field::op_assign_macros::{
14 impl_add_assign, impl_div_methods, impl_mul_methods, impl_sub_assign,
15};
16use p3_field::{
17 Field, InjectiveMonomial, Packable, PermutationMonomial, PrimeCharacteristicRing, PrimeField,
18 PrimeField64, RawDataSerializable, TwoAdicField, impl_raw_serializable_primefield64,
19 quotient_map_large_iint, quotient_map_large_uint, quotient_map_small_int,
20};
21use p3_util::{assume, branch_hint, flatten_to_base, gcd_inner};
22use rand::Rng;
23use rand::distr::{Distribution, StandardUniform};
24use serde::de::Error;
25use serde::{Deserialize, Deserializer, Serialize};
26
27pub(crate) const P: u64 = 0xFFFF_FFFF_0000_0001;
29
30#[derive(Copy, Clone, Default)]
34#[repr(transparent)] #[must_use]
36pub struct Goldilocks {
37 pub(crate) value: u64,
39}
40
41impl Serialize for Goldilocks {
42 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
43 serializer.serialize_u64(self.as_canonical_u64())
45 }
46}
47
48impl<'de> Deserialize<'de> for Goldilocks {
49 fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
50 let val = u64::deserialize(d)?;
51 if val < P {
53 Ok(Self::new(val))
54 } else {
55 Err(D::Error::custom("Goldilocks value is out of range"))
56 }
57 }
58}
59
60impl Goldilocks {
61 #[inline]
66 pub const fn new(value: u64) -> Self {
67 Self { value }
68 }
69
70 #[inline]
74 pub const fn new_array<const N: usize>(input: [u64; N]) -> [Self; N] {
75 let mut output = [Self::ZERO; N];
76 let mut i = 0;
77 while i < N {
78 output[i].value = input[i];
79 i += 1;
80 }
81 output
82 }
83
84 #[inline]
88 pub const fn new_2d_array<const N: usize, const M: usize>(
89 input: [[u64; N]; M],
90 ) -> [[Self; N]; M] {
91 let mut output = [[Self::ZERO; N]; M];
92 let mut i = 0;
93 while i < M {
94 output[i] = Self::new_array(input[i]);
95 i += 1;
96 }
97 output
98 }
99
100 const NEG_ORDER: u64 = Self::ORDER_U64.wrapping_neg();
102
103 pub const TWO_ADIC_GENERATORS: [Self; 33] = Self::new_array([
107 0x0000000000000001,
108 0xffffffff00000000,
109 0x0001000000000000,
110 0xfffffffeff000001,
111 0xefffffff00000001,
112 0x00003fffffffc000,
113 0x0000008000000000,
114 0xf80007ff08000001,
115 0xbf79143ce60ca966,
116 0x1905d02a5c411f4e,
117 0x9d8f2ad78bfed972,
118 0x0653b4801da1c8cf,
119 0xf2c35199959dfcb6,
120 0x1544ef2335d17997,
121 0xe0ee099310bba1e2,
122 0xf6b2cffe2306baac,
123 0x54df9630bf79450e,
124 0xabd0a6e8aa3d8a0e,
125 0x81281a7b05f9beac,
126 0xfbd41c6b8caa3302,
127 0x30ba2ecd5e93e76d,
128 0xf502aef532322654,
129 0x4b2a18ade67246b5,
130 0xea9d5a1336fbc98b,
131 0x86cdcc31c307e171,
132 0x4bbaf5976ecfefd8,
133 0xed41d05b78d6e286,
134 0x10d78dd8915a171d,
135 0x59049500004a4485,
136 0xdfa8c93ba46d2666,
137 0x7e9bd009b86a0845,
138 0x400a7f755588e659,
139 0x185629dcda58878c,
140 ]);
141
142 const POWERS_OF_TWO: [Self; 96] = {
147 let mut powers_of_two = [Self::ONE; 96];
148
149 let mut i = 1;
150 while i < 64 {
151 powers_of_two[i] = Self::new(1 << i);
152 i += 1;
153 }
154 let mut var = Self::new(1 << 63);
155 while i < 96 {
156 var = const_add(var, var);
157 powers_of_two[i] = var;
158 i += 1;
159 }
160 powers_of_two
161 };
162}
163
164impl PartialEq for Goldilocks {
165 fn eq(&self, other: &Self) -> bool {
166 self.as_canonical_u64() == other.as_canonical_u64()
167 }
168}
169
170impl Eq for Goldilocks {}
171
172impl Packable for Goldilocks {}
173
174impl Hash for Goldilocks {
175 fn hash<H: Hasher>(&self, state: &mut H) {
176 state.write_u64(self.as_canonical_u64());
177 }
178}
179
180impl Ord for Goldilocks {
181 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
182 self.as_canonical_u64().cmp(&other.as_canonical_u64())
183 }
184}
185
186impl PartialOrd for Goldilocks {
187 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
188 Some(self.cmp(other))
189 }
190}
191
192impl Display for Goldilocks {
193 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
194 Display::fmt(&self.as_canonical_u64(), f)
195 }
196}
197
198impl Debug for Goldilocks {
199 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
200 Debug::fmt(&self.as_canonical_u64(), f)
201 }
202}
203
204impl Distribution<Goldilocks> for StandardUniform {
205 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Goldilocks {
206 loop {
207 let next_u64 = rng.next_u64();
208 let is_canonical = next_u64 < Goldilocks::ORDER_U64;
209 if is_canonical {
210 return Goldilocks::new(next_u64);
211 }
212 }
213 }
214}
215
216impl UniformSamplingField for Goldilocks {
217 const MAX_SINGLE_SAMPLE_BITS: usize = 24;
218 const SAMPLING_BITS_M: [u64; 64] = {
219 let prime: u64 = P;
220 let mut a = [0u64; 64];
221 let mut k = 0;
222 while k < 64 {
223 if k == 0 {
224 a[k] = prime; } else {
226 let mask = !((1u64 << k) - 1);
228 a[k] = prime & mask;
229 }
230 k += 1;
231 }
232 a
233 };
234}
235
236impl PrimeCharacteristicRing for Goldilocks {
237 type PrimeSubfield = Self;
238
239 const ZERO: Self = Self::new(0);
240 const ONE: Self = Self::new(1);
241 const TWO: Self = Self::new(2);
242 const NEG_ONE: Self = Self::new(Self::ORDER_U64 - 1);
243
244 #[inline]
245 fn from_prime_subfield(f: Self::PrimeSubfield) -> Self {
246 f
247 }
248
249 #[inline]
250 fn from_bool(b: bool) -> Self {
251 Self::new(b.into())
252 }
253
254 #[inline]
255 fn halve(&self) -> Self {
256 const HALF_P_PLUS_1: u64 = (P + 1) >> 1; let lo_bit = self.value & 1;
261 let half = self.value >> 1;
262 let mask = 0u64.wrapping_sub(lo_bit); Self::new(half.wrapping_add(mask & HALF_P_PLUS_1))
264 }
265
266 #[inline]
267 fn mul_2exp_u64(&self, exp: u64) -> Self {
268 match exp {
270 0 => *self,
271 1 => *self + *self,
272 _ => {
273 if exp < 96 {
274 *self * Self::POWERS_OF_TWO[exp as usize]
275 } else if exp < 192 {
276 -*self * Self::POWERS_OF_TWO[(exp - 96) as usize]
277 } else {
278 self.mul_2exp_u64(exp % 192)
279 }
280 }
281 }
282 }
283
284 #[inline]
285 fn div_2exp_u64(&self, mut exp: u64) -> Self {
286 exp %= 192;
289 match exp {
290 0 => *self,
291 1 => self.halve(),
292 _ => self.mul_2exp_u64(192 - exp),
293 }
294 }
295
296 #[inline]
297 fn sum_array<const N: usize>(input: &[Self]) -> Self {
298 assert_eq!(N, input.len());
299 match N {
303 0 => Self::ZERO,
304 1 => input[0],
305 2 => input[0] + input[1],
306 3 => input[0] + input[1] + input[2],
307 _ => input.iter().copied().sum(),
308 }
309 }
310
311 #[inline]
312 fn dot_product<const N: usize>(lhs: &[Self; N], rhs: &[Self; N]) -> Self {
313 const OFFSET: u128 = ((P as u128) << 64) - (P as u128) + ((P as u128) << 32);
317 const {
318 assert!((N as u32) <= (1 << 31));
319 }
320 match N {
321 0 => Self::ZERO,
322 1 => lhs[0] * rhs[0],
323 2 => {
324 let long_prod_0 = (lhs[0].value as u128) * (rhs[0].value as u128);
327 let long_prod_1 = (lhs[1].value as u128) * (rhs[1].value as u128);
328
329 let (sum, over) = long_prod_0.overflowing_add(long_prod_1);
332 let sum_corr = sum.wrapping_sub(OFFSET);
334 if over {
335 reduce128(sum_corr)
336 } else {
337 reduce128(sum)
338 }
339 }
340 _ => {
341 let (lo_plus_hi, hi) = lhs
342 .iter()
343 .zip(rhs)
344 .map(|(x, y)| (x.value as u128) * (y.value as u128))
345 .fold((0_u128, 0_u64), |(acc_lo, acc_hi), val| {
346 let val_hi = (val >> 96) as u64;
348 unsafe { (acc_lo.wrapping_add(val), acc_hi.unchecked_add(val_hi)) }
351 });
352 let lo = lo_plus_hi.wrapping_sub((hi as u128) << 96);
354 let sum = unsafe { lo.unchecked_add(P.unchecked_sub(hi) as u128) };
357 reduce128(sum)
358 }
359 }
360 }
361
362 #[inline]
363 fn zero_vec(len: usize) -> Vec<Self> {
364 unsafe { flatten_to_base(vec![0u64; len]) }
369 }
370}
371
372impl InjectiveMonomial<7> for Goldilocks {}
376
377impl PermutationMonomial<7> for Goldilocks {
378 fn injective_exp_root_n(&self) -> Self {
382 exp_10540996611094048183(*self)
383 }
384}
385
386impl RawDataSerializable for Goldilocks {
387 impl_raw_serializable_primefield64!();
388}
389
390impl Field for Goldilocks {
391 #[cfg(all(
392 target_arch = "x86_64",
393 target_feature = "avx2",
394 not(target_feature = "avx512f")
395 ))]
396 type Packing = crate::PackedGoldilocksAVX2;
397
398 #[cfg(all(target_arch = "x86_64", target_feature = "avx512f"))]
399 type Packing = crate::PackedGoldilocksAVX512;
400
401 #[cfg(all(target_arch = "aarch64", target_feature = "neon"))]
402 type Packing = crate::PackedGoldilocksNeon;
403
404 #[cfg(all(target_arch = "wasm32", target_feature = "simd128"))]
405 type Packing = crate::PackedGoldilocksWasmSimd128;
406
407 #[cfg(not(any(
408 all(
409 target_arch = "x86_64",
410 target_feature = "avx2",
411 not(target_feature = "avx512f")
412 ),
413 all(target_arch = "x86_64", target_feature = "avx512f"),
414 target_arch = "aarch64",
415 all(target_arch = "wasm32", target_feature = "simd128"),
416 )))]
417 type Packing = Self;
418
419 const GENERATOR: Self = Self::new(7);
421
422 fn is_zero(&self) -> bool {
423 self.value == 0 || self.value == Self::ORDER_U64
424 }
425
426 fn try_inverse(&self) -> Option<Self> {
427 if self.is_zero() {
428 return None;
429 }
430
431 Some(gcd_inversion(*self))
432 }
433
434 #[inline]
435 fn order() -> BigUint {
436 P.into()
437 }
438}
439
440quotient_map_small_int!(Goldilocks, u64, [u8, u16, u32]);
442quotient_map_small_int!(Goldilocks, i64, [i8, i16, i32]);
443quotient_map_large_uint!(
444 Goldilocks,
445 u64,
446 Goldilocks::ORDER_U64,
447 "`[0, 2^64 - 2^32]`",
448 "`[0, 2^64 - 1]`",
449 [u128]
450);
451quotient_map_large_iint!(
452 Goldilocks,
453 i64,
454 "`[-(2^63 - 2^31), 2^63 - 2^31]`",
455 "`[1 + 2^32 - 2^64, 2^64 - 1]`",
456 [(i128, u128)]
457);
458
459impl QuotientMap<u64> for Goldilocks {
460 #[inline]
465 fn from_int(int: u64) -> Self {
466 Self::new(int)
467 }
468
469 #[inline]
473 fn from_canonical_checked(int: u64) -> Option<Self> {
474 (int < Self::ORDER_U64).then(|| Self::new(int))
475 }
476
477 #[inline(always)]
483 unsafe fn from_canonical_unchecked(int: u64) -> Self {
484 Self::new(int)
485 }
486}
487
488impl QuotientMap<i64> for Goldilocks {
489 #[inline]
493 fn from_int(int: i64) -> Self {
494 if int >= 0 {
495 Self::new(int as u64)
496 } else {
497 Self::new(Self::ORDER_U64.wrapping_add_signed(int))
498 }
499 }
500
501 #[inline]
505 fn from_canonical_checked(int: i64) -> Option<Self> {
506 const POS_BOUND: i64 = (P >> 1) as i64;
507 const NEG_BOUND: i64 = -POS_BOUND;
508 match int {
509 0..=POS_BOUND => Some(Self::new(int as u64)),
510 NEG_BOUND..0 => Some(Self::new(Self::ORDER_U64.wrapping_add_signed(int))),
511 _ => None,
512 }
513 }
514
515 #[inline(always)]
521 unsafe fn from_canonical_unchecked(int: i64) -> Self {
522 Self::from_int(int)
523 }
524}
525
526impl PrimeField for Goldilocks {
527 fn as_canonical_biguint(&self) -> BigUint {
528 self.as_canonical_u64().into()
529 }
530}
531
532impl PrimeField64 for Goldilocks {
533 const ORDER_U64: u64 = P;
534
535 #[inline]
536 fn as_canonical_u64(&self) -> u64 {
537 let mut c = self.value;
538 if c >= Self::ORDER_U64 {
540 c -= Self::ORDER_U64;
541 }
542 c
543 }
544}
545
546impl TwoAdicField for Goldilocks {
547 const TWO_ADICITY: usize = 32;
548
549 fn two_adic_generator(bits: usize) -> Self {
550 assert!(bits <= Self::TWO_ADICITY);
551 Self::TWO_ADIC_GENERATORS[bits]
552 }
553}
554
555#[inline]
560const fn const_add(lhs: Goldilocks, rhs: Goldilocks) -> Goldilocks {
561 let (sum, over) = lhs.value.overflowing_add(rhs.value);
562 let (mut sum, over) = sum.overflowing_add((over as u64) * Goldilocks::NEG_ORDER);
563 if over {
564 sum += Goldilocks::NEG_ORDER;
565 }
566 Goldilocks::new(sum)
567}
568
569impl Add for Goldilocks {
570 type Output = Self;
571
572 #[inline]
573 fn add(self, rhs: Self) -> Self {
574 let (sum, over) = self.value.overflowing_add(rhs.value);
575 let (mut sum, over) = sum.overflowing_add(u64::from(over) * Self::NEG_ORDER);
576 if over {
577 unsafe {
585 assume(self.value > Self::ORDER_U64 && rhs.value > Self::ORDER_U64);
586 }
587 branch_hint();
588 sum += Self::NEG_ORDER; }
590 Self::new(sum)
591 }
592}
593
594impl Sub for Goldilocks {
595 type Output = Self;
596
597 #[inline]
598 fn sub(self, rhs: Self) -> Self {
599 let (diff, under) = self.value.overflowing_sub(rhs.value);
600 let (mut diff, under) = diff.overflowing_sub(u64::from(under) * Self::NEG_ORDER);
601 if under {
602 unsafe {
610 assume(self.value < Self::NEG_ORDER - 1 && rhs.value > Self::ORDER_U64);
611 }
612 branch_hint();
613 diff -= Self::NEG_ORDER; }
615 Self::new(diff)
616 }
617}
618
619impl Neg for Goldilocks {
620 type Output = Self;
621
622 #[inline]
623 fn neg(self) -> Self::Output {
624 Self::new(Self::ORDER_U64 - self.as_canonical_u64())
625 }
626}
627
628impl Mul for Goldilocks {
629 type Output = Self;
630
631 #[inline]
632 fn mul(self, rhs: Self) -> Self {
633 reduce128(u128::from(self.value) * u128::from(rhs.value))
634 }
635}
636
637impl_add_assign!(Goldilocks);
638impl_sub_assign!(Goldilocks);
639impl_mul_methods!(Goldilocks);
640impl_div_methods!(Goldilocks, Goldilocks);
641
642impl Sum for Goldilocks {
643 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
644 let sum = iter.map(|x| x.value as u128).sum::<u128>();
648 reduce128(sum)
649 }
650}
651
652#[inline]
655pub(crate) fn reduce128(x: u128) -> Goldilocks {
656 let (x_lo, x_hi) = split(x); let x_hi_hi = x_hi >> 32;
658 let x_hi_lo = x_hi & Goldilocks::NEG_ORDER;
659
660 let (mut t0, borrow) = x_lo.overflowing_sub(x_hi_hi);
661 if borrow {
662 branch_hint(); t0 -= Goldilocks::NEG_ORDER; }
665 let t1 = x_hi_lo * Goldilocks::NEG_ORDER;
666 let t2 = unsafe { add_no_canonicalize_trashing_input(t0, t1) };
667 Goldilocks::new(t2)
668}
669
670#[inline]
671#[allow(clippy::cast_possible_truncation)]
672const fn split(x: u128) -> (u64, u64) {
673 (x as u64, (x >> 64) as u64)
674}
675
676#[inline(always)]
682#[cfg(target_arch = "x86_64")]
683unsafe fn add_no_canonicalize_trashing_input(x: u64, y: u64) -> u64 {
684 unsafe {
685 let res_wrapped: u64;
686 let adjustment: u64;
687 core::arch::asm!(
688 "add {0}, {1}",
689 "sbb {1:e}, {1:e}",
698 inlateout(reg) x => res_wrapped,
699 inlateout(reg) y => adjustment,
700 options(pure, nomem, nostack),
701 );
702 assume(x != 0 || (res_wrapped == y && adjustment == 0));
703 assume(y != 0 || (res_wrapped == x && adjustment == 0));
704 res_wrapped + adjustment
707 }
708}
709
710#[inline(always)]
711#[cfg(not(target_arch = "x86_64"))]
712unsafe fn add_no_canonicalize_trashing_input(x: u64, y: u64) -> u64 {
713 let (res_wrapped, carry) = x.overflowing_add(y);
714 res_wrapped + Goldilocks::NEG_ORDER * u64::from(carry)
716}
717
718fn gcd_inversion(input: Goldilocks) -> Goldilocks {
727 let (mut a, mut b) = (input.value, P);
729
730 const ROUND_SIZE: usize = 63;
734
735 let (f00, _, f10, _) = gcd_inner::<ROUND_SIZE>(&mut a, &mut b);
739 let (_, _, f11, g11) = gcd_inner::<ROUND_SIZE>(&mut a, &mut b);
740
741 let u = from_unusual_int(f00);
744 let v = from_unusual_int(f10);
745 let u_fac11 = from_unusual_int(f11);
746 let v_fac11 = from_unusual_int(g11);
747
748 (u * u_fac11 + v * v_fac11).mul_2exp_u64(66)
751}
752
753const fn from_unusual_int(int: i64) -> Goldilocks {
755 if (int >= 0) || (int == i64::MIN) {
756 Goldilocks::new(int as u64)
757 } else {
758 Goldilocks::new(Goldilocks::ORDER_U64.wrapping_add_signed(int))
759 }
760}
761
762#[cfg(test)]
763mod tests {
764 use p3_field::extension::BinomialExtensionField;
765 use p3_field_testing::{
766 test_field, test_field_dft, test_prime_field, test_prime_field_64, test_two_adic_field,
767 };
768
769 use super::*;
770
771 type F = Goldilocks;
772 type EF = BinomialExtensionField<F, 5>;
773
774 #[test]
775 fn deserialize_rejects_non_canonical_encodings() {
776 for non_canonical in [P, P + 5, u64::MAX] {
780 let json = serde_json::to_string(&non_canonical).unwrap();
781 assert!(serde_json::from_str::<F>(&json).is_err());
782 }
783
784 let max_canonical_json = serde_json::to_string(&(P - 1)).unwrap();
786 let max_canonical: F = serde_json::from_str(&max_canonical_json).unwrap();
787 assert_eq!(max_canonical.as_canonical_u64(), P - 1);
788 }
789
790 #[test]
791 fn serialize_is_canonical() {
792 let non_canonical = F::new(P + 5);
796 let json = serde_json::to_string(&non_canonical).unwrap();
797 assert_eq!(json, "5");
798
799 let roundtrip: F = serde_json::from_str(&json).unwrap();
801 assert_eq!(roundtrip, non_canonical);
802 }
803
804 #[test]
805 fn test_goldilocks() {
806 let f = F::new(100);
807 assert_eq!(f.as_canonical_u64(), 100);
808
809 let f = F::new(u64::MAX);
814 assert_eq!(f.as_canonical_u64(), u32::MAX as u64 - 1);
815
816 let f = F::from_u64(u64::MAX);
817 assert_eq!(f.as_canonical_u64(), u32::MAX as u64 - 1);
818
819 let expected_multiplicative_group_generator = F::new(7);
821 assert_eq!(F::GENERATOR, expected_multiplicative_group_generator);
822 assert_eq!(F::GENERATOR.as_canonical_u64(), 7_u64);
823
824 let x = u128::MAX;
826 let y = reduce128(x);
827 let expected_result = -F::TWO.exp_power_of_2(5) - F::ONE;
836 assert_eq!(y, expected_result);
837
838 let f = F::new(100);
839 assert_eq!(f.injective_exp_n().injective_exp_root_n(), f);
840 assert_eq!(y.injective_exp_n().injective_exp_root_n(), y);
841 assert_eq!(F::TWO.injective_exp_n().injective_exp_root_n(), F::TWO);
842 }
843
844 const ZEROS: [Goldilocks; 2] = [Goldilocks::ZERO, Goldilocks::new(P)];
846 const ONES: [Goldilocks; 2] = [Goldilocks::ONE, Goldilocks::new(P + 1)];
847
848 fn multiplicative_group_prime_factorization() -> [(BigUint, u32); 6] {
851 [
852 (BigUint::from(2u8), 32),
853 (BigUint::from(3u8), 1),
854 (BigUint::from(5u8), 1),
855 (BigUint::from(17u8), 1),
856 (BigUint::from(257u16), 1),
857 (BigUint::from(65537u32), 1),
858 ]
859 }
860
861 test_field!(
862 crate::Goldilocks,
863 &super::ZEROS,
864 &super::ONES,
865 &super::multiplicative_group_prime_factorization()
866 );
867 test_prime_field!(crate::Goldilocks);
868 test_prime_field_64!(crate::Goldilocks, &super::ZEROS, &super::ONES);
869 test_two_adic_field!(crate::Goldilocks);
870
871 test_field_dft!(
872 radix2dit,
873 crate::Goldilocks,
874 super::EF,
875 p3_dft::Radix2Dit<_>
876 );
877 test_field_dft!(bowers, crate::Goldilocks, super::EF, p3_dft::Radix2Bowers);
878 test_field_dft!(
879 parallel,
880 crate::Goldilocks,
881 super::EF,
882 p3_dft::Radix2DitParallel<crate::Goldilocks>
883 );
884}