1#![no_std]
4
5extern crate alloc;
6
7mod extension;
8mod mds;
9mod poseidon2;
10
11use core::fmt;
12use core::fmt::{Debug, Display, Formatter};
13use core::hash::{Hash, Hasher};
14use core::iter::{Product, Sum};
15use core::ops::{Add, AddAssign, Div, Mul, MulAssign, Neg, Sub, SubAssign};
16
17pub use mds::*;
18use num_bigint::BigUint;
19use p3_field::{
20 exp_10540996611094048183, exp_u64_by_squaring, halve_u64, AbstractField, Field, Packable,
21 PrimeField, PrimeField64, TwoAdicField,
22};
23use p3_util::{assume, branch_hint};
24pub use poseidon2::*;
25use rand::distributions::{Distribution, Standard};
26use rand::Rng;
27use serde::{Deserialize, Serialize};
28
29const P: u64 = 0xFFFF_FFFF_0000_0001;
31
32#[derive(Copy, Clone, Default, Serialize, Deserialize)]
34pub struct Goldilocks {
35 value: u64,
37}
38
39impl Goldilocks {
40 const fn new(value: u64) -> Self {
41 Self { value }
42 }
43
44 const NEG_ORDER: u64 = Self::ORDER_U64.wrapping_neg();
46}
47
48impl PartialEq for Goldilocks {
49 fn eq(&self, other: &Self) -> bool {
50 self.as_canonical_u64() == other.as_canonical_u64()
51 }
52}
53
54impl Eq for Goldilocks {}
55
56impl Packable for Goldilocks {}
57
58impl Hash for Goldilocks {
59 fn hash<H: Hasher>(&self, state: &mut H) {
60 state.write_u64(self.as_canonical_u64());
61 }
62}
63
64impl Ord for Goldilocks {
65 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
66 self.as_canonical_u64().cmp(&other.as_canonical_u64())
67 }
68}
69
70impl PartialOrd for Goldilocks {
71 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
72 Some(self.cmp(other))
73 }
74}
75
76impl Display for Goldilocks {
77 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
78 Display::fmt(&self.value, f)
79 }
80}
81
82impl Debug for Goldilocks {
83 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
84 Debug::fmt(&self.value, f)
85 }
86}
87
88impl Distribution<Goldilocks> for Standard {
89 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Goldilocks {
90 loop {
91 let next_u64 = rng.next_u64();
92 let is_canonical = next_u64 < Goldilocks::ORDER_U64;
93 if is_canonical {
94 return Goldilocks::new(next_u64);
95 }
96 }
97 }
98}
99
100impl AbstractField for Goldilocks {
101 type F = Self;
102
103 fn zero() -> Self {
104 Self::new(0)
105 }
106 fn one() -> Self {
107 Self::new(1)
108 }
109 fn two() -> Self {
110 Self::new(2)
111 }
112 fn neg_one() -> Self {
113 Self::new(Self::ORDER_U64 - 1)
114 }
115
116 #[inline]
117 fn from_f(f: Self::F) -> Self {
118 f
119 }
120
121 fn from_bool(b: bool) -> Self {
122 Self::new(u64::from(b))
123 }
124
125 fn from_canonical_u8(n: u8) -> Self {
126 Self::new(u64::from(n))
127 }
128
129 fn from_canonical_u16(n: u16) -> Self {
130 Self::new(u64::from(n))
131 }
132
133 fn from_canonical_u32(n: u32) -> Self {
134 Self::new(u64::from(n))
135 }
136
137 fn from_canonical_u64(n: u64) -> Self {
138 Self::new(n)
139 }
140
141 fn from_canonical_usize(n: usize) -> Self {
142 Self::new(n as u64)
143 }
144
145 fn from_wrapped_u32(n: u32) -> Self {
146 Self::new(u64::from(n))
149 }
150
151 fn from_wrapped_u64(n: u64) -> Self {
152 Self::new(n)
155 }
156
157 fn generator() -> Self {
159 Self::new(7)
160 }
161}
162
163impl Field for Goldilocks {
164 type Packing = Self;
166
167 fn is_zero(&self) -> bool {
168 self.value == 0 || self.value == Self::ORDER_U64
169 }
170
171 #[inline]
172 fn exp_u64_generic<AF: AbstractField<F = Self>>(val: AF, power: u64) -> AF {
173 match power {
174 10540996611094048183 => exp_10540996611094048183(val), _ => exp_u64_by_squaring(val, power),
176 }
177 }
178
179 fn try_inverse(&self) -> Option<Self> {
180 if self.is_zero() {
181 return None;
182 }
183
184 let t2 = self.square() * *self;
193
194 let t3 = t2.square() * *self;
196
197 let t6 = exp_acc::<3>(t3, t3);
200 let t60 = t6.square();
201 let t7 = t60 * *self;
202
203 let t12 = exp_acc::<5>(t60, t6);
206
207 let t24 = exp_acc::<12>(t12, t12);
210
211 let t31 = exp_acc::<7>(t24, t7);
215
216 let t63 = exp_acc::<32>(t31, t31);
219
220 Some(t63.square() * *self)
222 }
223
224 #[inline]
225 fn halve(&self) -> Self {
226 Goldilocks::new(halve_u64::<P>(self.value))
227 }
228
229 #[inline]
230 fn order() -> BigUint {
231 P.into()
232 }
233}
234
235impl PrimeField for Goldilocks {
236 fn as_canonical_biguint(&self) -> BigUint {
237 <Self as PrimeField64>::as_canonical_u64(self).into()
238 }
239}
240
241impl PrimeField64 for Goldilocks {
242 const ORDER_U64: u64 = P;
243
244 #[inline]
245 fn as_canonical_u64(&self) -> u64 {
246 let mut c = self.value;
247 if c >= Self::ORDER_U64 {
249 c -= Self::ORDER_U64;
250 }
251 c
252 }
253}
254
255impl TwoAdicField for Goldilocks {
256 const TWO_ADICITY: usize = 32;
257
258 fn two_adic_generator(bits: usize) -> Self {
259 assert!(bits <= Self::TWO_ADICITY);
261 let base = Self::new(1_753_635_133_440_165_772); base.exp_power_of_2(Self::TWO_ADICITY - bits)
263 }
264}
265
266impl Add for Goldilocks {
267 type Output = Self;
268
269 fn add(self, rhs: Self) -> Self {
270 let (sum, over) = self.value.overflowing_add(rhs.value);
271 let (mut sum, over) = sum.overflowing_add(u64::from(over) * Self::NEG_ORDER);
272 if over {
273 assume(self.value > Self::ORDER_U64 && rhs.value > Self::ORDER_U64);
281 branch_hint();
282 sum += Self::NEG_ORDER; }
284 Self::new(sum)
285 }
286}
287
288impl AddAssign for Goldilocks {
289 fn add_assign(&mut self, rhs: Self) {
290 *self = *self + rhs;
291 }
292}
293
294impl Sum for Goldilocks {
295 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
296 let sum = iter.map(|x| x.value as u128).sum::<u128>();
300 reduce128(sum)
301 }
302}
303
304impl Sub for Goldilocks {
305 type Output = Self;
306
307 fn sub(self, rhs: Self) -> Self {
308 let (diff, under) = self.value.overflowing_sub(rhs.value);
309 let (mut diff, under) = diff.overflowing_sub(u64::from(under) * Self::NEG_ORDER);
310 if under {
311 assume(self.value < Self::NEG_ORDER - 1 && rhs.value > Self::ORDER_U64);
319 branch_hint();
320 diff -= Self::NEG_ORDER; }
322 Self::new(diff)
323 }
324}
325
326impl SubAssign for Goldilocks {
327 fn sub_assign(&mut self, rhs: Self) {
328 *self = *self - rhs;
329 }
330}
331
332impl Neg for Goldilocks {
333 type Output = Self;
334
335 fn neg(self) -> Self::Output {
336 Self::new(Self::ORDER_U64 - self.as_canonical_u64())
337 }
338}
339
340impl Mul for Goldilocks {
341 type Output = Self;
342
343 fn mul(self, rhs: Self) -> Self {
344 reduce128(u128::from(self.value) * u128::from(rhs.value))
345 }
346}
347
348impl MulAssign for Goldilocks {
349 fn mul_assign(&mut self, rhs: Self) {
350 *self = *self * rhs;
351 }
352}
353
354impl Product for Goldilocks {
355 fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
356 iter.reduce(|x, y| x * y).unwrap_or(Self::one())
357 }
358}
359
360impl Div for Goldilocks {
361 type Output = Self;
362
363 #[allow(clippy::suspicious_arithmetic_impl)]
364 fn div(self, rhs: Self) -> Self {
365 self * rhs.inverse()
366 }
367}
368
369#[inline(always)]
371fn exp_acc<const N: usize>(base: Goldilocks, tail: Goldilocks) -> Goldilocks {
372 base.exp_power_of_2(N) * tail
373}
374
375#[inline]
378pub(crate) fn reduce128(x: u128) -> Goldilocks {
379 let (x_lo, x_hi) = split(x); let x_hi_hi = x_hi >> 32;
381 let x_hi_lo = x_hi & Goldilocks::NEG_ORDER;
382
383 let (mut t0, borrow) = x_lo.overflowing_sub(x_hi_hi);
384 if borrow {
385 branch_hint(); t0 -= Goldilocks::NEG_ORDER; }
388 let t1 = x_hi_lo * Goldilocks::NEG_ORDER;
389 let t2 = unsafe { add_no_canonicalize_trashing_input(t0, t1) };
390 Goldilocks::new(t2)
391}
392
393#[inline]
394#[allow(clippy::cast_possible_truncation)]
395const fn split(x: u128) -> (u64, u64) {
396 (x as u64, (x >> 64) as u64)
397}
398
399#[inline(always)]
405#[cfg(target_arch = "x86_64")]
406unsafe fn add_no_canonicalize_trashing_input(x: u64, y: u64) -> u64 {
407 let res_wrapped: u64;
408 let adjustment: u64;
409 core::arch::asm!(
410 "add {0}, {1}",
411 "sbb {1:e}, {1:e}",
420 inlateout(reg) x => res_wrapped,
421 inlateout(reg) y => adjustment,
422 options(pure, nomem, nostack),
423 );
424 assume(x != 0 || (res_wrapped == y && adjustment == 0));
425 assume(y != 0 || (res_wrapped == x && adjustment == 0));
426 res_wrapped + adjustment
429}
430
431#[inline(always)]
432#[cfg(not(target_arch = "x86_64"))]
433unsafe fn add_no_canonicalize_trashing_input(x: u64, y: u64) -> u64 {
434 let (res_wrapped, carry) = x.overflowing_add(y);
435 res_wrapped + Goldilocks::NEG_ORDER * u64::from(carry)
437}
438
439#[inline]
441#[must_use]
442pub(crate) const fn to_goldilocks_array<const N: usize>(input: [u64; N]) -> [Goldilocks; N] {
443 let mut output = [Goldilocks { value: 0 }; N];
444 let mut i = 0;
445 loop {
446 if i == N {
447 break;
448 }
449 output[i].value = input[i];
450 i += 1;
451 }
452 output
453}
454
455#[cfg(test)]
456mod tests {
457 use p3_field_testing::{test_field, test_two_adic_field};
458
459 use super::*;
460
461 type F = Goldilocks;
462
463 #[test]
464 fn test_goldilocks() {
465 let f = F::new(100);
466 assert_eq!(f.as_canonical_u64(), 100);
467
468 let f = F::new(u64::MAX);
473 assert_eq!(f.as_canonical_u64(), u32::MAX as u64 - 1);
474
475 let f = F::from_canonical_u64(u64::MAX);
476 assert_eq!(f.as_canonical_u64(), u32::MAX as u64 - 1);
477
478 let f = F::from_canonical_u64(0);
479 assert!(f.is_zero());
480
481 let f = F::from_canonical_u64(F::ORDER_U64);
482 assert!(f.is_zero());
483
484 assert_eq!(F::generator().as_canonical_u64(), 7_u64);
485
486 let f_1 = F::new(1);
487 let f_1_copy = F::new(1);
488
489 let expected_result = F::zero();
490 assert_eq!(f_1 - f_1_copy, expected_result);
491
492 let expected_result = F::new(2);
493 assert_eq!(f_1 + f_1_copy, expected_result);
494
495 let f_2 = F::new(2);
496 let expected_result = F::new(3);
497 assert_eq!(f_1 + f_1_copy * f_2, expected_result);
498
499 let expected_result = F::new(5);
500 assert_eq!(f_1 + f_2 * f_2, expected_result);
501
502 let f_p_minus_1 = F::from_canonical_u64(F::ORDER_U64 - 1);
503 let expected_result = F::zero();
504 assert_eq!(f_1 + f_p_minus_1, expected_result);
505
506 let f_p_minus_2 = F::from_canonical_u64(F::ORDER_U64 - 2);
507 let expected_result = F::from_canonical_u64(F::ORDER_U64 - 3);
508 assert_eq!(f_p_minus_1 + f_p_minus_2, expected_result);
509
510 let expected_result = F::new(1);
511 assert_eq!(f_p_minus_1 - f_p_minus_2, expected_result);
512
513 let expected_result = f_p_minus_1;
514 assert_eq!(f_p_minus_2 - f_p_minus_1, expected_result);
515
516 let expected_result = f_p_minus_2;
517 assert_eq!(f_p_minus_1 - f_1, expected_result);
518
519 let expected_result = F::new(3);
520 assert_eq!(f_2 * f_2 - f_1, expected_result);
521
522 let expected_multiplicative_group_generator = F::new(7);
524 assert_eq!(F::generator(), expected_multiplicative_group_generator);
525
526 let x = u128::MAX;
528 let y = reduce128(x);
529 let expected_result = -F::new(2_u64.pow(32)) - F::new(1);
538 assert_eq!(y, expected_result);
539
540 assert_eq!(f.exp_u64(10540996611094048183).exp_const_u64::<7>(), f);
541 assert_eq!(y.exp_u64(10540996611094048183).exp_const_u64::<7>(), y);
542 assert_eq!(f_2.exp_u64(10540996611094048183).exp_const_u64::<7>(), f_2);
543 }
544
545 test_field!(crate::Goldilocks);
546 test_two_adic_field!(crate::Goldilocks);
547}