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, halve_u64, 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::{Deserialize, Serialize};
25
26pub(crate) const P: u64 = 0xFFFF_FFFF_0000_0001;
28
29#[derive(Copy, Clone, Default, Serialize, Deserialize)]
33#[repr(transparent)] #[must_use]
35pub struct Goldilocks {
36 pub(crate) value: u64,
38}
39
40impl Goldilocks {
41 pub(crate) const fn new(value: u64) -> Self {
42 Self { value }
43 }
44
45 #[inline]
49 pub(crate) const fn new_array<const N: usize>(input: [u64; N]) -> [Self; N] {
50 let mut output = [Self::ZERO; N];
51 let mut i = 0;
52 while i < N {
53 output[i].value = input[i];
54 i += 1;
55 }
56 output
57 }
58
59 const NEG_ORDER: u64 = Self::ORDER_U64.wrapping_neg();
61
62 pub const TWO_ADIC_GENERATORS: [Self; 33] = Self::new_array([
66 0x0000000000000001,
67 0xffffffff00000000,
68 0x0001000000000000,
69 0xfffffffeff000001,
70 0xefffffff00000001,
71 0x00003fffffffc000,
72 0x0000008000000000,
73 0xf80007ff08000001,
74 0xbf79143ce60ca966,
75 0x1905d02a5c411f4e,
76 0x9d8f2ad78bfed972,
77 0x0653b4801da1c8cf,
78 0xf2c35199959dfcb6,
79 0x1544ef2335d17997,
80 0xe0ee099310bba1e2,
81 0xf6b2cffe2306baac,
82 0x54df9630bf79450e,
83 0xabd0a6e8aa3d8a0e,
84 0x81281a7b05f9beac,
85 0xfbd41c6b8caa3302,
86 0x30ba2ecd5e93e76d,
87 0xf502aef532322654,
88 0x4b2a18ade67246b5,
89 0xea9d5a1336fbc98b,
90 0x86cdcc31c307e171,
91 0x4bbaf5976ecfefd8,
92 0xed41d05b78d6e286,
93 0x10d78dd8915a171d,
94 0x59049500004a4485,
95 0xdfa8c93ba46d2666,
96 0x7e9bd009b86a0845,
97 0x400a7f755588e659,
98 0x185629dcda58878c,
99 ]);
100
101 const POWERS_OF_TWO: [Self; 96] = {
106 let mut powers_of_two = [Self::ONE; 96];
107
108 let mut i = 1;
109 while i < 64 {
110 powers_of_two[i] = Self::new(1 << i);
111 i += 1;
112 }
113 let mut var = Self::new(1 << 63);
114 while i < 96 {
115 var = const_add(var, var);
116 powers_of_two[i] = var;
117 i += 1;
118 }
119 powers_of_two
120 };
121}
122
123impl PartialEq for Goldilocks {
124 fn eq(&self, other: &Self) -> bool {
125 self.as_canonical_u64() == other.as_canonical_u64()
126 }
127}
128
129impl Eq for Goldilocks {}
130
131impl Packable for Goldilocks {}
132
133impl Hash for Goldilocks {
134 fn hash<H: Hasher>(&self, state: &mut H) {
135 state.write_u64(self.as_canonical_u64());
136 }
137}
138
139impl Ord for Goldilocks {
140 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
141 self.as_canonical_u64().cmp(&other.as_canonical_u64())
142 }
143}
144
145impl PartialOrd for Goldilocks {
146 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
147 Some(self.cmp(other))
148 }
149}
150
151impl Display for Goldilocks {
152 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
153 Display::fmt(&self.as_canonical_u64(), f)
154 }
155}
156
157impl Debug for Goldilocks {
158 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
159 Debug::fmt(&self.as_canonical_u64(), f)
160 }
161}
162
163impl Distribution<Goldilocks> for StandardUniform {
164 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Goldilocks {
165 loop {
166 let next_u64 = rng.next_u64();
167 let is_canonical = next_u64 < Goldilocks::ORDER_U64;
168 if is_canonical {
169 return Goldilocks::new(next_u64);
170 }
171 }
172 }
173}
174
175impl UniformSamplingField for Goldilocks {
176 const MAX_SINGLE_SAMPLE_BITS: usize = 24;
177 const SAMPLING_BITS_M: [u64; 64] = {
178 let prime: u64 = P;
179 let mut a = [0u64; 64];
180 let mut k = 0;
181 while k < 64 {
182 if k == 0 {
183 a[k] = prime; } else {
185 let mask = !((1u64 << k) - 1);
187 a[k] = prime & mask;
188 }
189 k += 1;
190 }
191 a
192 };
193}
194
195impl PrimeCharacteristicRing for Goldilocks {
196 type PrimeSubfield = Self;
197
198 const ZERO: Self = Self::new(0);
199 const ONE: Self = Self::new(1);
200 const TWO: Self = Self::new(2);
201 const NEG_ONE: Self = Self::new(Self::ORDER_U64 - 1);
202
203 #[inline]
204 fn from_prime_subfield(f: Self::PrimeSubfield) -> Self {
205 f
206 }
207
208 #[inline]
209 fn from_bool(b: bool) -> Self {
210 Self::new(b.into())
211 }
212
213 #[inline]
214 fn halve(&self) -> Self {
215 Self::new(halve_u64::<P>(self.value))
216 }
217
218 #[inline]
219 fn mul_2exp_u64(&self, exp: u64) -> Self {
220 if exp < 96 {
222 *self * Self::POWERS_OF_TWO[exp as usize]
223 } else if exp < 192 {
224 -*self * Self::POWERS_OF_TWO[(exp - 96) as usize]
225 } else {
226 self.mul_2exp_u64(exp % 192)
227 }
228 }
229
230 #[inline]
231 fn div_2exp_u64(&self, mut exp: u64) -> Self {
232 exp %= 192;
235 self.mul_2exp_u64(192 - exp)
236 }
237
238 #[inline]
239 fn sum_array<const N: usize>(input: &[Self]) -> Self {
240 assert_eq!(N, input.len());
241 match N {
245 0 => Self::ZERO,
246 1 => input[0],
247 2 => input[0] + input[1],
248 3 => input[0] + input[1] + input[2],
249 _ => input.iter().copied().sum(),
250 }
251 }
252
253 #[inline]
254 fn dot_product<const N: usize>(lhs: &[Self; N], rhs: &[Self; N]) -> Self {
255 const OFFSET: u128 = ((P as u128) << 64) - (P as u128) + ((P as u128) << 32);
259 assert!((N as u32) <= (1 << 31));
260 match N {
261 0 => Self::ZERO,
262 1 => lhs[0] * rhs[0],
263 2 => {
264 let long_prod_0 = (lhs[0].value as u128) * (rhs[0].value as u128);
267 let long_prod_1 = (lhs[1].value as u128) * (rhs[1].value as u128);
268
269 let (sum, over) = long_prod_0.overflowing_add(long_prod_1);
272 let sum_corr = sum.wrapping_sub(OFFSET);
274 if over {
275 reduce128(sum_corr)
276 } else {
277 reduce128(sum)
278 }
279 }
280 _ => {
281 let (lo_plus_hi, hi) = lhs
282 .iter()
283 .zip(rhs)
284 .map(|(x, y)| (x.value as u128) * (y.value as u128))
285 .fold((0_u128, 0_u64), |(acc_lo, acc_hi), val| {
286 let val_hi = (val >> 96) as u64;
288 unsafe { (acc_lo.wrapping_add(val), acc_hi.unchecked_add(val_hi)) }
291 });
292 let lo = lo_plus_hi.wrapping_sub((hi as u128) << 96);
294 let sum = unsafe { lo.unchecked_add(P.unchecked_sub(hi) as u128) };
297 reduce128(sum)
298 }
299 }
300 }
301
302 #[inline]
303 fn zero_vec(len: usize) -> Vec<Self> {
304 unsafe { flatten_to_base(vec![0u64; len]) }
309 }
310}
311
312impl InjectiveMonomial<7> for Goldilocks {}
316
317impl PermutationMonomial<7> for Goldilocks {
318 fn injective_exp_root_n(&self) -> Self {
322 exp_10540996611094048183(*self)
323 }
324}
325
326impl RawDataSerializable for Goldilocks {
327 impl_raw_serializable_primefield64!();
328}
329
330impl Field for Goldilocks {
331 #[cfg(all(
334 target_arch = "x86_64",
335 target_feature = "avx2",
336 not(target_feature = "avx512f")
337 ))]
338 type Packing = crate::PackedGoldilocksAVX2;
339
340 #[cfg(all(target_arch = "x86_64", target_feature = "avx512f"))]
341 type Packing = crate::PackedGoldilocksAVX512;
342 #[cfg(not(any(
343 all(
344 target_arch = "x86_64",
345 target_feature = "avx2",
346 not(target_feature = "avx512f")
347 ),
348 all(target_arch = "x86_64", target_feature = "avx512f"),
349 )))]
350 type Packing = Self;
351
352 const GENERATOR: Self = Self::new(7);
354
355 fn is_zero(&self) -> bool {
356 self.value == 0 || self.value == Self::ORDER_U64
357 }
358
359 fn try_inverse(&self) -> Option<Self> {
360 if self.is_zero() {
361 return None;
362 }
363
364 Some(gcd_inversion(*self))
365 }
366
367 #[inline]
368 fn order() -> BigUint {
369 P.into()
370 }
371}
372
373quotient_map_small_int!(Goldilocks, u64, [u8, u16, u32]);
375quotient_map_small_int!(Goldilocks, i64, [i8, i16, i32]);
376quotient_map_large_uint!(
377 Goldilocks,
378 u64,
379 Goldilocks::ORDER_U64,
380 "`[0, 2^64 - 2^32]`",
381 "`[0, 2^64 - 1]`",
382 [u128]
383);
384quotient_map_large_iint!(
385 Goldilocks,
386 i64,
387 "`[-(2^63 - 2^31), 2^63 - 2^31]`",
388 "`[1 + 2^32 - 2^64, 2^64 - 1]`",
389 [(i128, u128)]
390);
391
392impl QuotientMap<u64> for Goldilocks {
393 #[inline]
398 fn from_int(int: u64) -> Self {
399 Self::new(int)
400 }
401
402 #[inline]
406 fn from_canonical_checked(int: u64) -> Option<Self> {
407 (int < Self::ORDER_U64).then(|| Self::new(int))
408 }
409
410 #[inline(always)]
416 unsafe fn from_canonical_unchecked(int: u64) -> Self {
417 Self::new(int)
418 }
419}
420
421impl QuotientMap<i64> for Goldilocks {
422 #[inline]
426 fn from_int(int: i64) -> Self {
427 if int >= 0 {
428 Self::new(int as u64)
429 } else {
430 Self::new(Self::ORDER_U64.wrapping_add_signed(int))
431 }
432 }
433
434 #[inline]
438 fn from_canonical_checked(int: i64) -> Option<Self> {
439 const POS_BOUND: i64 = (P >> 1) as i64;
440 const NEG_BOUND: i64 = -POS_BOUND;
441 match int {
442 0..=POS_BOUND => Some(Self::new(int as u64)),
443 NEG_BOUND..0 => Some(Self::new(Self::ORDER_U64.wrapping_add_signed(int))),
444 _ => None,
445 }
446 }
447
448 #[inline(always)]
454 unsafe fn from_canonical_unchecked(int: i64) -> Self {
455 Self::from_int(int)
456 }
457}
458
459impl PrimeField for Goldilocks {
460 fn as_canonical_biguint(&self) -> BigUint {
461 self.as_canonical_u64().into()
462 }
463}
464
465impl PrimeField64 for Goldilocks {
466 const ORDER_U64: u64 = P;
467
468 #[inline]
469 fn as_canonical_u64(&self) -> u64 {
470 let mut c = self.value;
471 if c >= Self::ORDER_U64 {
473 c -= Self::ORDER_U64;
474 }
475 c
476 }
477}
478
479impl TwoAdicField for Goldilocks {
480 const TWO_ADICITY: usize = 32;
481
482 fn two_adic_generator(bits: usize) -> Self {
483 assert!(bits <= Self::TWO_ADICITY);
484 Self::TWO_ADIC_GENERATORS[bits]
485 }
486}
487
488#[inline]
493const fn const_add(lhs: Goldilocks, rhs: Goldilocks) -> Goldilocks {
494 let (sum, over) = lhs.value.overflowing_add(rhs.value);
495 let (mut sum, over) = sum.overflowing_add((over as u64) * Goldilocks::NEG_ORDER);
496 if over {
497 sum += Goldilocks::NEG_ORDER;
498 }
499 Goldilocks::new(sum)
500}
501
502impl Add for Goldilocks {
503 type Output = Self;
504
505 #[inline]
506 fn add(self, rhs: Self) -> Self {
507 let (sum, over) = self.value.overflowing_add(rhs.value);
508 let (mut sum, over) = sum.overflowing_add(u64::from(over) * Self::NEG_ORDER);
509 if over {
510 unsafe {
518 assume(self.value > Self::ORDER_U64 && rhs.value > Self::ORDER_U64);
519 }
520 branch_hint();
521 sum += Self::NEG_ORDER; }
523 Self::new(sum)
524 }
525}
526
527impl Sub for Goldilocks {
528 type Output = Self;
529
530 #[inline]
531 fn sub(self, rhs: Self) -> Self {
532 let (diff, under) = self.value.overflowing_sub(rhs.value);
533 let (mut diff, under) = diff.overflowing_sub(u64::from(under) * Self::NEG_ORDER);
534 if under {
535 unsafe {
543 assume(self.value < Self::NEG_ORDER - 1 && rhs.value > Self::ORDER_U64);
544 }
545 branch_hint();
546 diff -= Self::NEG_ORDER; }
548 Self::new(diff)
549 }
550}
551
552impl Neg for Goldilocks {
553 type Output = Self;
554
555 #[inline]
556 fn neg(self) -> Self::Output {
557 Self::new(Self::ORDER_U64 - self.as_canonical_u64())
558 }
559}
560
561impl Mul for Goldilocks {
562 type Output = Self;
563
564 #[inline]
565 fn mul(self, rhs: Self) -> Self {
566 reduce128(u128::from(self.value) * u128::from(rhs.value))
567 }
568}
569
570impl_add_assign!(Goldilocks);
571impl_sub_assign!(Goldilocks);
572impl_mul_methods!(Goldilocks);
573impl_div_methods!(Goldilocks, Goldilocks);
574
575impl Sum for Goldilocks {
576 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
577 let sum = iter.map(|x| x.value as u128).sum::<u128>();
581 reduce128(sum)
582 }
583}
584
585#[inline]
588pub(crate) fn reduce128(x: u128) -> Goldilocks {
589 let (x_lo, x_hi) = split(x); let x_hi_hi = x_hi >> 32;
591 let x_hi_lo = x_hi & Goldilocks::NEG_ORDER;
592
593 let (mut t0, borrow) = x_lo.overflowing_sub(x_hi_hi);
594 if borrow {
595 branch_hint(); t0 -= Goldilocks::NEG_ORDER; }
598 let t1 = x_hi_lo * Goldilocks::NEG_ORDER;
599 let t2 = unsafe { add_no_canonicalize_trashing_input(t0, t1) };
600 Goldilocks::new(t2)
601}
602
603#[inline]
604#[allow(clippy::cast_possible_truncation)]
605const fn split(x: u128) -> (u64, u64) {
606 (x as u64, (x >> 64) as u64)
607}
608
609#[inline(always)]
615#[cfg(target_arch = "x86_64")]
616unsafe fn add_no_canonicalize_trashing_input(x: u64, y: u64) -> u64 {
617 unsafe {
618 let res_wrapped: u64;
619 let adjustment: u64;
620 core::arch::asm!(
621 "add {0}, {1}",
622 "sbb {1:e}, {1:e}",
631 inlateout(reg) x => res_wrapped,
632 inlateout(reg) y => adjustment,
633 options(pure, nomem, nostack),
634 );
635 assume(x != 0 || (res_wrapped == y && adjustment == 0));
636 assume(y != 0 || (res_wrapped == x && adjustment == 0));
637 res_wrapped + adjustment
640 }
641}
642
643#[inline(always)]
644#[cfg(not(target_arch = "x86_64"))]
645unsafe fn add_no_canonicalize_trashing_input(x: u64, y: u64) -> u64 {
646 let (res_wrapped, carry) = x.overflowing_add(y);
647 res_wrapped + Goldilocks::NEG_ORDER * u64::from(carry)
649}
650
651fn gcd_inversion(input: Goldilocks) -> Goldilocks {
660 let (mut a, mut b) = (input.value, P);
662
663 const ROUND_SIZE: usize = 63;
667
668 let (f00, _, f10, _) = gcd_inner::<ROUND_SIZE>(&mut a, &mut b);
672 let (_, _, f11, g11) = gcd_inner::<ROUND_SIZE>(&mut a, &mut b);
673
674 let u = from_unusual_int(f00);
677 let v = from_unusual_int(f10);
678 let u_fac11 = from_unusual_int(f11);
679 let v_fac11 = from_unusual_int(g11);
680
681 (u * u_fac11 + v * v_fac11).mul_2exp_u64(66)
684}
685
686const fn from_unusual_int(int: i64) -> Goldilocks {
688 if (int >= 0) || (int == i64::MIN) {
689 Goldilocks::new(int as u64)
690 } else {
691 Goldilocks::new(Goldilocks::ORDER_U64.wrapping_add_signed(int))
692 }
693}
694
695#[cfg(test)]
696mod tests {
697 use p3_field::extension::BinomialExtensionField;
698 use p3_field_testing::{
699 test_field, test_field_dft, test_prime_field, test_prime_field_64, test_two_adic_field,
700 };
701
702 use super::*;
703
704 type F = Goldilocks;
705 type EF = BinomialExtensionField<F, 5>;
706
707 #[test]
708 fn test_goldilocks() {
709 let f = F::new(100);
710 assert_eq!(f.as_canonical_u64(), 100);
711
712 let f = F::new(u64::MAX);
717 assert_eq!(f.as_canonical_u64(), u32::MAX as u64 - 1);
718
719 let f = F::from_u64(u64::MAX);
720 assert_eq!(f.as_canonical_u64(), u32::MAX as u64 - 1);
721
722 let expected_multiplicative_group_generator = F::new(7);
724 assert_eq!(F::GENERATOR, expected_multiplicative_group_generator);
725 assert_eq!(F::GENERATOR.as_canonical_u64(), 7_u64);
726
727 let x = u128::MAX;
729 let y = reduce128(x);
730 let expected_result = -F::TWO.exp_power_of_2(5) - F::ONE;
739 assert_eq!(y, expected_result);
740
741 let f = F::new(100);
742 assert_eq!(f.injective_exp_n().injective_exp_root_n(), f);
743 assert_eq!(y.injective_exp_n().injective_exp_root_n(), y);
744 assert_eq!(F::TWO.injective_exp_n().injective_exp_root_n(), F::TWO);
745 }
746
747 const ZEROS: [Goldilocks; 2] = [Goldilocks::ZERO, Goldilocks::new(P)];
749 const ONES: [Goldilocks; 2] = [Goldilocks::ONE, Goldilocks::new(P + 1)];
750
751 fn multiplicative_group_prime_factorization() -> [(BigUint, u32); 6] {
754 [
755 (BigUint::from(2u8), 32),
756 (BigUint::from(3u8), 1),
757 (BigUint::from(5u8), 1),
758 (BigUint::from(17u8), 1),
759 (BigUint::from(257u16), 1),
760 (BigUint::from(65537u32), 1),
761 ]
762 }
763
764 test_field!(
765 crate::Goldilocks,
766 &super::ZEROS,
767 &super::ONES,
768 &super::multiplicative_group_prime_factorization()
769 );
770 test_prime_field!(crate::Goldilocks);
771 test_prime_field_64!(crate::Goldilocks, &super::ZEROS, &super::ONES);
772 test_two_adic_field!(crate::Goldilocks);
773
774 test_field_dft!(
775 radix2dit,
776 crate::Goldilocks,
777 super::EF,
778 p3_dft::Radix2Dit<_>
779 );
780 test_field_dft!(bowers, crate::Goldilocks, super::EF, p3_dft::Radix2Bowers);
781 test_field_dft!(
782 parallel,
783 crate::Goldilocks,
784 super::EF,
785 p3_dft::Radix2DitParallel<crate::Goldilocks>
786 );
787}