Skip to main content

p3_goldilocks/
goldilocks.rs

1use alloc::vec;
2use alloc::vec::Vec;
3use core::fmt::{Debug, Display, Formatter};
4use core::hash::{Hash, Hasher};
5use core::hint::assert_unchecked;
6use core::iter::{Product, Sum};
7use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
8use core::{array, fmt};
9
10use num_bigint::BigUint;
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, UniformSamplingField,
19    impl_raw_serializable_primefield64, quotient_map_large_iint, quotient_map_small_int,
20};
21use p3_util::{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
27/// The Goldilocks prime
28pub(crate) const P: u64 = 0xFFFF_FFFF_0000_0001;
29
30/// The prime field known as Goldilocks, defined as `F_p` where `p = 2^64 - 2^32 + 1`.
31///
32/// The serde encoding is canonical: every field element has exactly one valid byte representation.
33#[derive(Copy, Clone, Default)]
34#[repr(transparent)] // Important for reasoning about memory layout
35#[must_use]
36pub struct Goldilocks {
37    /// Not necessarily canonical.
38    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        // Emit the canonical representative so every field element has one encoding.
44        let val = self.as_canonical_u64();
45        // Binary (non human-readable) formats get a fixed 8-byte encoding instead of
46        // the serializer's default varint, since every value here is a near-uniform
47        // 64-bit integer and varint saves nothing on average.
48        if serializer.is_human_readable() {
49            serializer.serialize_u64(val)
50        } else {
51            val.to_le_bytes().serialize(serializer)
52        }
53    }
54}
55
56impl<'de> Deserialize<'de> for Goldilocks {
57    fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
58        let human_readable = d.is_human_readable();
59        let val = if human_readable {
60            u64::deserialize(d)?
61        } else {
62            u64::from_le_bytes(<[u8; 8]>::deserialize(d)?)
63        };
64        // Reject non-canonical encodings so a proof cannot be re-encoded without the witness.
65        if val < P {
66            Ok(Self::new(val))
67        } else {
68            Err(D::Error::custom("Goldilocks value is out of range"))
69        }
70    }
71}
72
73impl Goldilocks {
74    /// Create a new field element from any `u64`.
75    ///
76    /// Any `u64` value is accepted. No reduction is performed since
77    /// Goldilocks uses a non-canonical internal representation.
78    #[inline]
79    pub const fn new(value: u64) -> Self {
80        Self { value }
81    }
82
83    /// Convert a `[u64; N]` array to an array of field elements.
84    ///
85    /// Const version of `input.map(Goldilocks::new)`.
86    #[inline]
87    pub const fn new_array<const N: usize>(input: [u64; N]) -> [Self; N] {
88        let mut output = [Self::ZERO; N];
89        let mut i = 0;
90        while i < N {
91            output[i].value = input[i];
92            i += 1;
93        }
94        output
95    }
96
97    /// Convert a `[[u64; N]; M]` array to a 2D array of field elements.
98    ///
99    /// Const version of `input.map(Goldilocks::new_array)`.
100    #[inline]
101    pub const fn new_2d_array<const N: usize, const M: usize>(
102        input: [[u64; N]; M],
103    ) -> [[Self; N]; M] {
104        let mut output = [[Self::ZERO; N]; M];
105        let mut i = 0;
106        while i < M {
107            output[i] = Self::new_array(input[i]);
108            i += 1;
109        }
110        output
111    }
112
113    /// Two's complement of `ORDER`, i.e. `2^64 - ORDER = 2^32 - 1`.
114    const NEG_ORDER: u64 = Self::ORDER_U64.wrapping_neg();
115
116    /// A list of generators for the two-adic subgroups of the goldilocks field.
117    ///
118    /// These satisfy the properties that `TWO_ADIC_GENERATORS[0] = 1` and `TWO_ADIC_GENERATORS[i+1]^2 = TWO_ADIC_GENERATORS[i]`.
119    pub const TWO_ADIC_GENERATORS: [Self; 33] = Self::new_array([
120        0x0000000000000001,
121        0xffffffff00000000,
122        0x0001000000000000,
123        0xfffffffeff000001,
124        0xefffffff00000001,
125        0x00003fffffffc000,
126        0x0000008000000000,
127        0xf80007ff08000001,
128        0xbf79143ce60ca966,
129        0x1905d02a5c411f4e,
130        0x9d8f2ad78bfed972,
131        0x0653b4801da1c8cf,
132        0xf2c35199959dfcb6,
133        0x1544ef2335d17997,
134        0xe0ee099310bba1e2,
135        0xf6b2cffe2306baac,
136        0x54df9630bf79450e,
137        0xabd0a6e8aa3d8a0e,
138        0x81281a7b05f9beac,
139        0xfbd41c6b8caa3302,
140        0x30ba2ecd5e93e76d,
141        0xf502aef532322654,
142        0x4b2a18ade67246b5,
143        0xea9d5a1336fbc98b,
144        0x86cdcc31c307e171,
145        0x4bbaf5976ecfefd8,
146        0xed41d05b78d6e286,
147        0x10d78dd8915a171d,
148        0x59049500004a4485,
149        0xdfa8c93ba46d2666,
150        0x7e9bd009b86a0845,
151        0x400a7f755588e659,
152        0x185629dcda58878c,
153    ]);
154
155    /// A list of powers of two from 0 to 95.
156    ///
157    /// Note that 2^{96} = -1 mod P so all powers of two can be simply
158    /// derived from this list.
159    const POWERS_OF_TWO: [Self; 96] = {
160        let mut powers_of_two = [Self::ONE; 96];
161
162        let mut i = 1;
163        while i < 64 {
164            powers_of_two[i] = Self::new(1 << i);
165            i += 1;
166        }
167        let mut var = Self::new(1 << 63);
168        while i < 96 {
169            var = const_add(var, var);
170            powers_of_two[i] = var;
171            i += 1;
172        }
173        powers_of_two
174    };
175
176    /// Returns the canonical coefficient 2^exp mod P for packed multiplication.
177    #[cfg(any(
178        test,
179        all(target_arch = "aarch64", target_feature = "neon"),
180        all(
181            target_arch = "x86_64",
182            any(target_feature = "avx2", target_feature = "avx512f")
183        ),
184        all(target_arch = "wasm32", target_feature = "simd128")
185    ))]
186    #[inline]
187    pub(crate) const fn power_of_two(exp: u64) -> Self {
188        // 2^96 = -1 mod P, so powers repeat with period 192.
189        let exp = (exp % 192) as usize;
190        if exp < 96 {
191            Self::POWERS_OF_TWO[exp]
192        } else {
193            // Every table entry is nonzero and canonical, so this cannot underflow.
194            Self::new(Self::ORDER_U64 - Self::POWERS_OF_TWO[exp - 96].value)
195        }
196    }
197}
198
199impl PartialEq for Goldilocks {
200    fn eq(&self, other: &Self) -> bool {
201        self.as_canonical_u64() == other.as_canonical_u64()
202    }
203}
204
205impl Eq for Goldilocks {}
206
207impl Packable for Goldilocks {}
208
209impl Hash for Goldilocks {
210    fn hash<H: Hasher>(&self, state: &mut H) {
211        state.write_u64(self.as_canonical_u64());
212    }
213}
214
215impl Ord for Goldilocks {
216    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
217        self.as_canonical_u64().cmp(&other.as_canonical_u64())
218    }
219}
220
221impl PartialOrd for Goldilocks {
222    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
223        Some(self.cmp(other))
224    }
225}
226
227impl Display for Goldilocks {
228    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
229        Display::fmt(&self.as_canonical_u64(), f)
230    }
231}
232
233impl Debug for Goldilocks {
234    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
235        Debug::fmt(&self.as_canonical_u64(), f)
236    }
237}
238
239impl Distribution<Goldilocks> for StandardUniform {
240    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Goldilocks {
241        loop {
242            let next_u64 = rng.next_u64();
243            let is_canonical = next_u64 < Goldilocks::ORDER_U64;
244            if is_canonical {
245                return Goldilocks::new(next_u64);
246            }
247        }
248    }
249}
250
251impl UniformSamplingField for Goldilocks {
252    const MAX_SINGLE_SAMPLE_BITS: usize = 32;
253    const SAMPLING_BITS_M: [u64; 64] = {
254        let prime: u64 = P;
255        let mut a = [0u64; 64];
256        let mut k = 0;
257        while k < 64 {
258            if k == 0 {
259                a[k] = prime; // This value is irrelevant in practice. `bits = 0` returns 0 always.
260            } else {
261                // Create a mask to zero out the last k bits
262                let mask = !((1u64 << k) - 1);
263                a[k] = prime & mask;
264            }
265            k += 1;
266        }
267        a
268    };
269}
270
271impl PrimeCharacteristicRing for Goldilocks {
272    type PrimeSubfield = Self;
273
274    const ZERO: Self = Self::new(0);
275    const ONE: Self = Self::new(1);
276    const TWO: Self = Self::new(2);
277    const NEG_ONE: Self = Self::new(Self::ORDER_U64 - 1);
278
279    #[inline]
280    fn from_prime_subfield(f: Self::PrimeSubfield) -> Self {
281        f
282    }
283
284    #[inline]
285    fn from_bool(b: bool) -> Self {
286        Self::new(b.into())
287    }
288
289    #[inline]
290    fn halve(&self) -> Self {
291        // Branchless halving: x/2 = (x >> 1) + ((x & 1) * (p+1)/2).
292        // When x is odd, add (p+1)/2 to compensate for the lost bit.
293        // Uses mask arithmetic to avoid the 50/50 unpredictable branch.
294        const HALF_P_PLUS_1: u64 = (P + 1) >> 1; // 0x7FFFFFFF80000001
295        let lo_bit = self.value & 1;
296        let half = self.value >> 1;
297        let mask = 0u64.wrapping_sub(lo_bit); // all-ones when odd, zero when even
298        Self::new(half.wrapping_add(mask & HALF_P_PLUS_1))
299    }
300
301    #[cfg(target_arch = "wasm32")]
302    #[inline]
303    fn square(&self) -> Self {
304        reduce128(square_wide(self.value))
305    }
306
307    #[inline]
308    fn mul_2exp_u64(&self, exp: u64) -> Self {
309        // In the Goldilocks field, 2^96 = -1 mod P and 2^192 = 1 mod P.
310        match exp {
311            0 => *self,
312            1 => *self + *self,
313            _ => {
314                if exp < 96 {
315                    *self * Self::POWERS_OF_TWO[exp as usize]
316                } else if exp < 192 {
317                    -*self * Self::POWERS_OF_TWO[(exp - 96) as usize]
318                } else {
319                    self.mul_2exp_u64(exp % 192)
320                }
321            }
322        }
323    }
324
325    #[inline]
326    fn div_2exp_u64(&self, mut exp: u64) -> Self {
327        // In the goldilocks field, 2^192 = 1 mod P.
328        // Thus 2^{-n} = 2^{192 - n} mod P.
329        exp %= 192;
330        match exp {
331            0 => *self,
332            1 => self.halve(),
333            2..=32 => {
334                let lo = self.value & ((1u64 << exp) - 1);
335                let hi = self.value >> exp;
336
337                // Multiplying the expression below by 2^exp gives self.value modulo P,
338                // since 2^64 - 2^32 + 1 = P. Moreover, a < 2^64 and -P < a - b < P,
339                // so correcting a wrapping subtraction once produces a canonical result.
340                let a = hi + (lo << (32 - exp));
341                let b = lo << (64 - exp);
342                let (result, borrow) = a.overflowing_sub(b);
343                Self::new(result.wrapping_sub(Self::NEG_ORDER * u64::from(borrow)))
344            }
345            _ => self.mul_2exp_u64(192 - exp),
346        }
347    }
348
349    #[inline]
350    fn sum_array<const N: usize>(input: &[Self]) -> Self {
351        assert_eq!(N, input.len());
352        // Benchmarking shows that for N <= 3 it's faster to sum the elements directly
353        // but for N > 3 it's faster to use the .sum() methods which passes through u128's
354        // allowing for delayed reductions.
355        match N {
356            0 => Self::ZERO,
357            1 => input[0],
358            2 => input[0] + input[1],
359            3 => input[0] + input[1] + input[2],
360            _ => input.iter().copied().sum(),
361        }
362    }
363
364    #[inline]
365    fn dot_product<const N: usize>(lhs: &[Self; N], rhs: &[Self; N]) -> Self {
366        // The constant OFFSET has 2 important properties:
367        // 1. It is a multiple of P.
368        // 2. It is greater than the maximum possible product of two u64s.
369        const OFFSET: u128 = ((P as u128) << 64) - (P as u128) + ((P as u128) << 32);
370        const {
371            assert!((N as u32) <= (1 << 31));
372        }
373        match N {
374            0 => Self::ZERO,
375            1 => lhs[0] * rhs[0],
376            2 => {
377                // We unroll the N = 2 case as it is slightly faster and this is an important case
378                // as a major use is in extension field arithmetic and Goldilocks has a degree 2 extension.
379                let long_prod_0 = mul_wide(lhs[0].value, rhs[0].value);
380                let long_prod_1 = mul_wide(lhs[1].value, rhs[1].value);
381
382                // We know that long_prod_0, long_prod_1 < OFFSET.
383                // Thus if long_prod_0 + long_prod_1 overflows, we can just subtract OFFSET.
384                let (sum, over) = long_prod_0.overflowing_add(long_prod_1);
385                // Compiler really likes defining sum_corr here instead of in the if/else.
386                let sum_corr = sum.wrapping_sub(OFFSET);
387                if over {
388                    reduce128(sum_corr)
389                } else {
390                    reduce128(sum)
391                }
392            }
393            _ => {
394                let (lo_plus_hi, hi) = lhs
395                    .iter()
396                    .zip(rhs)
397                    .map(|(x, y)| mul_wide(x.value, y.value))
398                    .fold((0_u128, 0_u64), |(acc_lo, acc_hi), val| {
399                        // Split val into (hi, lo) where hi is the upper 32 bits and lo is the lower 96 bits.
400                        let val_hi = (val >> 96) as u64;
401                        // acc_hi accumulates hi, acc_lo accumulates lo + 2^{96}hi.
402                        // As N <= 2^32, acc_hi cannot overflow.
403                        unsafe { (acc_lo.wrapping_add(val), acc_hi.unchecked_add(val_hi)) }
404                    });
405                // First, remove the hi part from lo_plus_hi.
406                let lo = lo_plus_hi.wrapping_sub((hi as u128) << 96);
407                // As 2^{96} = -1 mod P, we simply need to reduce lo - hi.
408                // As N <= 2^31, lo < 2^127 and hi < 2^63 < P. Hence the equation below will not over or underflow.
409                let sum = unsafe { lo.unchecked_add(P.unchecked_sub(hi) as u128) };
410                reduce128(sum)
411            }
412        }
413    }
414
415    #[inline]
416    fn zero_vec(len: usize) -> Vec<Self> {
417        // SAFETY:
418        // Due to `#[repr(transparent)]`, Goldilocks and u64 have the same size, alignment
419        // and memory layout making `flatten_to_base` safe. This will create
420        // a vector of Goldilocks elements with value set to 0.
421        unsafe { flatten_to_base(vec![0u64; len]) }
422    }
423}
424
425/// Degree of the smallest permutation polynomial for Goldilocks.
426///
427/// As p - 1 = 2^32 * 3 * 5 * 17 * ... the smallest choice for a degree D satisfying gcd(p - 1, D) = 1 is 7.
428impl InjectiveMonomial<7> for Goldilocks {}
429
430impl PermutationMonomial<7> for Goldilocks {
431    /// In the field `Goldilocks`, `a^{1/7}` is equal to a^{10540996611094048183}.
432    ///
433    /// This follows from the calculation `7*10540996611094048183 = 4*(2^64 - 2**32) + 1 = 1 mod (p - 1)`.
434    fn injective_exp_root_n(&self) -> Self {
435        exp_10540996611094048183(*self)
436    }
437}
438
439impl RawDataSerializable for Goldilocks {
440    impl_raw_serializable_primefield64!();
441}
442
443/// Compute `x^(2^31 - 1)` using a fixed addition chain.
444#[inline(always)]
445fn exp_2_31_minus_1(x: Goldilocks) -> Goldilocks {
446    let x3 = x.square() * x;
447    let x7 = x3.square() * x;
448    let x63 = x7.exp_power_of_2(3) * x7;
449    let x4095 = x63.exp_power_of_2(6) * x63;
450    let x24 = x4095.exp_power_of_2(12) * x4095;
451    let x30 = x24.exp_power_of_2(6) * x63;
452    x30.square() * x
453}
454
455impl Field for Goldilocks {
456    #[cfg(all(
457        target_arch = "x86_64",
458        target_feature = "avx2",
459        not(target_feature = "avx512f")
460    ))]
461    type Packing = crate::PackedGoldilocksAVX2;
462
463    #[cfg(all(target_arch = "x86_64", target_feature = "avx512f"))]
464    type Packing = crate::PackedGoldilocksAVX512;
465
466    #[cfg(all(target_arch = "aarch64", target_feature = "neon"))]
467    type Packing = crate::PackedGoldilocksNeon;
468
469    #[cfg(all(target_arch = "wasm32", target_feature = "simd128"))]
470    type Packing = crate::PackedGoldilocksWasmSimd128;
471
472    #[cfg(not(any(
473        all(
474            target_arch = "x86_64",
475            target_feature = "avx2",
476            not(target_feature = "avx512f")
477        ),
478        all(target_arch = "x86_64", target_feature = "avx512f"),
479        all(target_arch = "aarch64", target_feature = "neon"),
480        all(target_arch = "wasm32", target_feature = "simd128"),
481    )))]
482    type Packing = Self;
483
484    // Sage: GF(2^64 - 2^32 + 1).multiplicative_generator()
485    const GENERATOR: Self = Self::new(7);
486
487    // Measured -11% on quotient evaluation (twoadic PCS, Keccak AIR, aarch64+neon).
488    const BENEFITS_FROM_LOCKSTEP_EVALUATION: bool = true;
489
490    fn is_zero(&self) -> bool {
491        self.value == 0 || self.value == Self::ORDER_U64
492    }
493
494    fn try_inverse(&self) -> Option<Self> {
495        if self.is_zero() {
496            return None;
497        }
498
499        Some(gcd_inversion(*self))
500    }
501
502    #[inline]
503    fn order() -> BigUint {
504        P.into()
505    }
506
507    #[inline]
508    fn try_sqrt(&self) -> Option<Self> {
509        // Zero is its own square root and would otherwise break Tonelli-Shanks.
510        if self.is_zero() {
511            return Some(Self::ZERO);
512        }
513
514        // Goldilocks has `p - 1 = (2^32 - 1) * 2^32`, so the initial
515        // Tonelli-Shanks exponent is `(2^32 - 2) / 2 = 2^31 - 1`.
516        let u = exp_2_31_minus_1(*self);
517        let mut r = u * *self;
518        let mut t = r * u;
519        let mut m = 32;
520
521        while t != Self::ONE {
522            // Find the least i with t^(2^i) = 1. If no such i is below m,
523            // t has order 2^m and the input is a quadratic non-residue.
524            let mut i = 0;
525            let mut t2i = t;
526            while t2i != Self::ONE {
527                t2i = t2i.square();
528                i += 1;
529                if i == m {
530                    return None;
531                }
532            }
533
534            // The current correction is the (i + 1)-th two-adic generator:
535            // G_m^(2^(m-i-1)) = G_(i+1), and its square is G_i. Since
536            // i < m <= 32, both table indices are always in range.
537            r *= Self::TWO_ADIC_GENERATORS[i + 1];
538            t *= Self::TWO_ADIC_GENERATORS[i];
539            m = i;
540        }
541
542        Some(r)
543    }
544}
545
546// We use macros to implement QuotientMap<Int> for all integer types except u64, i64, and u128.
547quotient_map_small_int!(Goldilocks, u64, [u8, u16, u32]);
548quotient_map_small_int!(Goldilocks, i64, [i8, i16, i32]);
549quotient_map_large_iint!(
550    Goldilocks,
551    i64,
552    "`[-(2^63 - 2^31), 2^63 - 2^31]`",
553    "`[1 + 2^32 - 2^64, 2^64 - 1]`",
554    [(i128, u128)]
555);
556
557impl QuotientMap<u128> for Goldilocks {
558    /// Convert a given `u128` integer into an element of the `Goldilocks` field.
559    ///
560    /// Uses the specialized Goldilocks reduction and returns a canonical representation.
561    #[inline]
562    fn from_int(int: u128) -> Self {
563        Self::new(reduce128(int).as_canonical_u64())
564    }
565
566    /// Convert a given `u128` integer into an element of the `Goldilocks` field.
567    ///
568    /// Returns `None` if the input does not lie in the range `[0, 2^64 - 2^32]`.
569    #[inline]
570    fn from_canonical_checked(int: u128) -> Option<Self> {
571        (int < Self::ORDER_U64 as u128).then(|| Self::new(int as u64))
572    }
573
574    /// Convert a given `u128` integer into an element of the `Goldilocks` field.
575    ///
576    /// # Safety
577    /// The input must lie in the range `[0, 2^64 - 1]`.
578    #[inline]
579    unsafe fn from_canonical_unchecked(int: u128) -> Self {
580        Self::new(int as u64)
581    }
582}
583
584impl QuotientMap<u64> for Goldilocks {
585    /// Convert a given `u64` integer into an element of the `Goldilocks` field.
586    ///
587    /// No reduction is needed as the internal value is allowed
588    /// to be any u64.
589    #[inline]
590    fn from_int(int: u64) -> Self {
591        Self::new(int)
592    }
593
594    /// Convert a given `u64` integer into an element of the `Goldilocks` field.
595    ///
596    /// Return `None` if the given integer is greater than `p = 2^64 - 2^32 + 1`.
597    #[inline]
598    fn from_canonical_checked(int: u64) -> Option<Self> {
599        (int < Self::ORDER_U64).then(|| Self::new(int))
600    }
601
602    /// Convert a given `u64` integer into an element of the `Goldilocks` field.
603    ///
604    /// # Safety
605    /// In this case this function is actually always safe as the internal
606    /// value is allowed to be any u64.
607    #[inline(always)]
608    unsafe fn from_canonical_unchecked(int: u64) -> Self {
609        Self::new(int)
610    }
611}
612
613impl QuotientMap<i64> for Goldilocks {
614    /// Convert a given `i64` integer into an element of the `Goldilocks` field.
615    ///
616    /// We simply need to deal with the sign.
617    #[inline]
618    fn from_int(int: i64) -> Self {
619        if int >= 0 {
620            Self::new(int as u64)
621        } else {
622            Self::new(Self::ORDER_U64.wrapping_add_signed(int))
623        }
624    }
625
626    /// Convert a given `i64` integer into an element of the `Goldilocks` field.
627    ///
628    /// Returns none if the input does not lie in the range `(-(2^63 - 2^31), 2^63 - 2^31)`.
629    #[inline]
630    fn from_canonical_checked(int: i64) -> Option<Self> {
631        const POS_BOUND: i64 = (P >> 1) as i64;
632        const NEG_BOUND: i64 = -POS_BOUND;
633        match int {
634            0..=POS_BOUND => Some(Self::new(int as u64)),
635            NEG_BOUND..0 => Some(Self::new(Self::ORDER_U64.wrapping_add_signed(int))),
636            _ => None,
637        }
638    }
639
640    /// Convert a given `i64` integer into an element of the `Goldilocks` field.
641    ///
642    /// # Safety
643    /// In this case this function is actually always safe as the internal
644    /// value is allowed to be any u64.
645    #[inline(always)]
646    unsafe fn from_canonical_unchecked(int: i64) -> Self {
647        Self::from_int(int)
648    }
649}
650
651impl PrimeField for Goldilocks {
652    fn as_canonical_biguint(&self) -> BigUint {
653        self.as_canonical_u64().into()
654    }
655}
656
657impl PrimeField64 for Goldilocks {
658    const ORDER_U64: u64 = P;
659
660    #[inline]
661    fn as_canonical_u64(&self) -> u64 {
662        let mut c = self.value;
663        // We only need one condition subtraction, since 2 * ORDER would not fit in a u64.
664        if c >= Self::ORDER_U64 {
665            c -= Self::ORDER_U64;
666        }
667        c
668    }
669}
670
671impl TwoAdicField for Goldilocks {
672    const TWO_ADICITY: usize = 32;
673
674    fn two_adic_generator(bits: usize) -> Self {
675        assert!(bits <= Self::TWO_ADICITY);
676        Self::TWO_ADIC_GENERATORS[bits]
677    }
678}
679
680/// A const version of the addition function.
681///
682/// Useful for constructing constants values in const contexts. Outside of
683/// const contexts, Add should be used instead.
684#[inline]
685const fn const_add(lhs: Goldilocks, rhs: Goldilocks) -> Goldilocks {
686    let (sum, over) = lhs.value.overflowing_add(rhs.value);
687    let (mut sum, over) = sum.overflowing_add((over as u64) * Goldilocks::NEG_ORDER);
688    if over {
689        sum += Goldilocks::NEG_ORDER;
690    }
691    Goldilocks::new(sum)
692}
693
694impl Add for Goldilocks {
695    type Output = Self;
696
697    #[inline]
698    fn add(self, rhs: Self) -> Self {
699        let (sum, over) = self.value.overflowing_add(rhs.value);
700        let (mut sum, over) = sum.overflowing_add(u64::from(over) * Self::NEG_ORDER);
701        if over {
702            // NB: self.value > Self::ORDER && rhs.value > Self::ORDER is necessary but not
703            // sufficient for double-overflow.
704            // This hint does two things:
705            //  1. If compiler knows that either self.value or rhs.value <= ORDER, then it can skip
706            //     this check.
707            //  2. Hints to the compiler how rare this double-overflow is (thus handled better with
708            //     a branch).
709            unsafe {
710                assert_unchecked(self.value > Self::ORDER_U64 && rhs.value > Self::ORDER_U64);
711            }
712            branch_hint();
713            sum += Self::NEG_ORDER; // Cannot overflow.
714        }
715        Self::new(sum)
716    }
717}
718
719impl Sub for Goldilocks {
720    type Output = Self;
721
722    #[inline]
723    fn sub(self, rhs: Self) -> Self {
724        let (diff, under) = self.value.overflowing_sub(rhs.value);
725        let (mut diff, under) = diff.overflowing_sub(u64::from(under) * Self::NEG_ORDER);
726        if under {
727            // NB: self.value < NEG_ORDER - 1 && rhs.value > ORDER is necessary but not
728            // sufficient for double-underflow.
729            // This hint does two things:
730            //  1. If compiler knows that either self.value >= NEG_ORDER - 1 or rhs.value <= ORDER,
731            //     then it can skip this check.
732            //  2. Hints to the compiler how rare this double-underflow is (thus handled better
733            //     with a branch).
734            unsafe {
735                assert_unchecked(self.value < Self::NEG_ORDER - 1 && rhs.value > Self::ORDER_U64);
736            }
737            branch_hint();
738            diff -= Self::NEG_ORDER; // Cannot underflow.
739        }
740        Self::new(diff)
741    }
742}
743
744impl Neg for Goldilocks {
745    type Output = Self;
746
747    #[inline]
748    fn neg(self) -> Self::Output {
749        Self::new(Self::ORDER_U64 - self.as_canonical_u64())
750    }
751}
752
753impl Mul for Goldilocks {
754    type Output = Self;
755
756    #[inline]
757    fn mul(self, rhs: Self) -> Self {
758        reduce128(mul_wide(self.value, rhs.value))
759    }
760}
761
762/// Full-width product. Explicit 32-bit limbs avoid the out-of-line `__multi3`
763/// lowering of a `u128` multiplication on wasm, which has native `i64.mul`.
764#[inline]
765fn mul_wide(x: u64, y: u64) -> u128 {
766    #[cfg(not(target_arch = "wasm32"))]
767    {
768        u128::from(x) * u128::from(y)
769    }
770    #[cfg(target_arch = "wasm32")]
771    {
772        let x_lo = x & Goldilocks::NEG_ORDER;
773        let x_hi = x >> 32;
774        let y_lo = y & Goldilocks::NEG_ORDER;
775        let y_hi = y >> 32;
776        let ll = x_lo * y_lo;
777        let lh = x_lo * y_hi;
778        let hl = x_hi * y_lo;
779        let hh = x_hi * y_hi;
780
781        // Each partial product is at most (2^32 - 1)^2. Adding one
782        // 32-bit carry therefore fits in u64, without wrapping.
783        let t0 = hl + (ll >> 32);
784        let t1 = lh + (t0 & Goldilocks::NEG_ORDER);
785        let hi = hh + (t0 >> 32) + (t1 >> 32);
786        let lo = (ll & Goldilocks::NEG_ORDER) | (t1 << 32);
787        (u128::from(hi) << 64) | u128::from(lo)
788    }
789}
790
791/// Squaring shares its two cross products, requiring only three `i64.mul`s.
792#[cfg(target_arch = "wasm32")]
793#[inline]
794fn square_wide(x: u64) -> u128 {
795    let lo = x & Goldilocks::NEG_ORDER;
796    let hi = x >> 32;
797    let ll = lo * lo;
798    let lh = lo * hi;
799    let hh = hi * hi;
800    // x^2 = ll + lh*2^33 + hh*2^64. Adding ll>>33 to lh cannot
801    // overflow: lh <= (2^32 - 1)^2 and ll>>33 < 2^31.
802    let middle = lh + (ll >> 33);
803    let product_hi = hh + (middle >> 31);
804    let product_lo = ll.wrapping_add(lh << 33);
805    (u128::from(product_hi) << 64) | u128::from(product_lo)
806}
807
808impl_add_assign!(Goldilocks);
809impl_sub_assign!(Goldilocks);
810impl_mul_methods!(Goldilocks);
811impl_div_methods!(Goldilocks, Goldilocks);
812
813impl Sum for Goldilocks {
814    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
815        // This is faster than iter.reduce(|x, y| x + y).unwrap_or(Self::ZERO) for iterators of length > 2.
816
817        // This sum will not overflow so long as iter.len() < 2^64.
818        let sum = iter.map(|x| x.value as u128).sum::<u128>();
819        reduce128(sum)
820    }
821}
822
823/// Reduces to a 64-bit value. The result might not be in canonical form; it could be in between the
824/// field order and `2^64`.
825#[inline]
826pub(crate) fn reduce128(x: u128) -> Goldilocks {
827    let (x_lo, x_hi) = split(x); // This is a no-op
828    let x_hi_hi = x_hi >> 32;
829    let x_hi_lo = x_hi & Goldilocks::NEG_ORDER;
830
831    let (mut t0, borrow) = x_lo.overflowing_sub(x_hi_hi);
832    if borrow {
833        branch_hint(); // A borrow is exceedingly rare. It is faster to branch.
834        t0 -= Goldilocks::NEG_ORDER; // Cannot underflow.
835    }
836    let t1 = x_hi_lo * Goldilocks::NEG_ORDER;
837    let t2 = unsafe { add_no_canonicalize_trashing_input(t0, t1) };
838    Goldilocks::new(t2)
839}
840
841#[inline]
842#[allow(clippy::cast_possible_truncation)]
843const fn split(x: u128) -> (u64, u64) {
844    (x as u64, (x >> 64) as u64)
845}
846
847/// Fast addition modulo ORDER for x86-64.
848/// This function is marked unsafe for the following reasons:
849///   - It is only correct if x + y < 2**64 + ORDER = 0x1ffffffff00000001.
850///   - It is only faster in some circumstances. In particular, on x86 it overwrites both inputs in
851///     the registers, so its use is not recommended when either input will be used again.
852#[inline(always)]
853#[cfg(target_arch = "x86_64")]
854unsafe fn add_no_canonicalize_trashing_input(x: u64, y: u64) -> u64 {
855    unsafe {
856        let res_wrapped: u64;
857        let adjustment: u64;
858        core::arch::asm!(
859            "add {0}, {1}",
860            // Trick. The carry flag is set iff the addition overflowed.
861            // sbb x, y does x := x - y - CF. In our case, x and y are both {1:e}, so it simply does
862            // {1:e} := 0xffffffff on overflow and {1:e} := 0 otherwise. {1:e} is the low 32 bits of
863            // {1}; the high 32-bits are zeroed on write. In the end, we end up with 0xffffffff in {1}
864            // on overflow; this happens be NEG_ORDER.
865            // Note that the CPU does not realize that the result of sbb x, x does not actually depend
866            // on x. We must write the result to a register that we know to be ready. We have a
867            // dependency on {1} anyway, so let's use it.
868            "sbb {1:e}, {1:e}",
869            inlateout(reg) x => res_wrapped,
870            inlateout(reg) y => adjustment,
871            options(pure, nomem, nostack),
872        );
873        assert_unchecked(x != 0 || (res_wrapped == y && adjustment == 0));
874        assert_unchecked(y != 0 || (res_wrapped == x && adjustment == 0));
875        // Add NEG_ORDER == subtract ORDER.
876        // Cannot overflow unless the assumption if x + y < 2**64 + ORDER is incorrect.
877        res_wrapped + adjustment
878    }
879}
880
881#[inline(always)]
882#[cfg(not(target_arch = "x86_64"))]
883unsafe fn add_no_canonicalize_trashing_input(x: u64, y: u64) -> u64 {
884    let (res_wrapped, carry) = x.overflowing_add(y);
885    // Below cannot overflow unless the assumption if x + y < 2**64 + ORDER is incorrect.
886    res_wrapped + Goldilocks::NEG_ORDER * u64::from(carry)
887}
888
889/// Compute the inverse of a Goldilocks element `a` using the binary GCD algorithm.
890///
891/// Instead of applying the standard algorithm this uses a variant inspired by <https://eprint.iacr.org/2020/972.pdf>.
892/// The key idea is to compute update factors which are incorrect by a known power of 2 which
893/// can be corrected at the end. These update factors can then be used to construct the inverse
894/// via a simple linear combination.
895///
896/// This is much faster than the standard algorithm as we avoid most of the (more expensive) field arithmetic.
897fn gcd_inversion(input: Goldilocks) -> Goldilocks {
898    // Initialise our values to the value we want to invert and the prime.
899    let (mut a, mut b) = (input.value, P);
900
901    // As the goldilocks prime is 64 bit, initially `len(a) + len(b) ≤ 2 * 64 = 128`.
902    // This means we will need `126` iterations of the inner loop ensure `len(a) + len(b) ≤ 2`.
903    // We split the iterations into 2 rounds of length 63.
904    const ROUND_SIZE: usize = 63;
905
906    // In theory we could make this slightly faster by replacing the first `gcd_inner` by a copy-pasted
907    // version which doesn't do any computations involving g. But either the compiler works this out
908    // for itself or the speed up is negligible as I couldn't notice any difference in benchmarks.
909    let (f00, _, f10, _) = gcd_inner::<ROUND_SIZE>(&mut a, &mut b);
910    let (_, _, f11, g11) = gcd_inner::<ROUND_SIZE>(&mut a, &mut b);
911
912    // The update factors are i64's except we need to interpret -2^63 as 2^63.
913    // This is because the outputs of `gcd_inner` are always in the range `(-2^ROUND_SIZE, 2^ROUND_SIZE]`.
914    let u = from_unusual_int(f00);
915    let v = from_unusual_int(f10);
916    let u_fac11 = from_unusual_int(f11);
917    let v_fac11 = from_unusual_int(g11);
918
919    // Each iteration introduced a factor of 2 and so we need to divide by 2^{126}.
920    // But 2^{192} = 1 mod P, so we can instead multiply by 2^{66} as 192 - 126 = 66.
921    (u * u_fac11 + v * v_fac11).mul_2exp_u64(66)
922}
923
924/// Convert from an i64 to a Goldilocks element but interpret -2^63 as 2^63.
925const fn from_unusual_int(int: i64) -> Goldilocks {
926    if (int >= 0) || (int == i64::MIN) {
927        Goldilocks::new(int as u64)
928    } else {
929        Goldilocks::new(Goldilocks::ORDER_U64.wrapping_add_signed(int))
930    }
931}
932
933#[cfg(test)]
934mod tests {
935    use p3_field::extension::BinomialExtensionField;
936    use p3_field::{PackedValue, tonelli_shanks_two_adic};
937    use p3_field_testing::{
938        test_field, test_field_dft, test_prime_field, test_prime_field_64, test_two_adic_field,
939    };
940    use rand::rngs::SmallRng;
941    use rand::{RngExt, SeedableRng};
942
943    use super::*;
944
945    type F = Goldilocks;
946    type EF = BinomialExtensionField<F, 5>;
947
948    /// Check both product limbs, not just the residue: a lost carry could otherwise
949    /// be hidden by the field reduction. Includes noncanonical field representatives.
950    #[cfg(target_arch = "wasm32")]
951    #[test]
952    fn wasm_wide_products_match_u128_oracle() {
953        const EDGES: [u64; 12] = [
954            0,
955            1,
956            (1 << 32) - 2,
957            (1 << 32) - 1,
958            1 << 32,
959            (1 << 32) + 1,
960            (1 << 63) - 1,
961            1 << 63,
962            P - 1,
963            P,
964            P + 1,
965            u64::MAX,
966        ];
967        let check = |a: u64, b: u64| {
968            let product = u128::from(a) * u128::from(b);
969            let square = u128::from(a) * u128::from(a);
970            assert_eq!(mul_wide(a, b), product, "a={a}, b={b}");
971            assert_eq!(square_wide(a), square, "a={a}");
972            assert_eq!(
973                (F::new(a) * F::new(b)).as_canonical_u64(),
974                (product % u128::from(P)) as u64
975            );
976            assert_eq!(
977                F::new(a).square().as_canonical_u64(),
978                (square % u128::from(P)) as u64
979            );
980        };
981        for a in EDGES {
982            for b in EDGES {
983                check(a, b);
984            }
985        }
986        let mut rng = SmallRng::seed_from_u64(0x64_32_CA77);
987        for _ in 0..10_000 {
988            check(rng.random(), rng.random());
989        }
990    }
991
992    /// Compare every packed lane with an independent full-u64 sum modulo the field order.
993    /// This avoids using the scalar Goldilocks sum as the oracle because it also delays reduction.
994    #[test]
995    fn packed_sum_array_matches_full_u64_oracle() {
996        type PF = <F as Field>::Packing;
997
998        const RAW_EDGES: [u64; 10] = [
999            0,
1000            1,
1001            (1 << 32) - 1,
1002            1 << 32,
1003            1 << 63,
1004            P - 1,
1005            P,
1006            P + 1,
1007            u64::MAX - 1,
1008            u64::MAX,
1009        ];
1010
1011        fn check<const N: usize>(values: &[u64]) {
1012            type PF = <F as Field>::Packing;
1013
1014            assert_eq!(values.len(), PF::WIDTH * N);
1015            let input: [PF; N] =
1016                core::array::from_fn(|term| PF::from_fn(|lane| F::new(values[lane * N + term])));
1017            let actual = PF::sum_array::<N>(&input);
1018
1019            for lane in 0..PF::WIDTH {
1020                let expected = (values[lane * N..(lane + 1) * N]
1021                    .iter()
1022                    .map(|&value| u128::from(value))
1023                    .sum::<u128>()
1024                    % u128::from(P)) as u64;
1025                assert_eq!(
1026                    actual.as_slice()[lane].as_canonical_u64(),
1027                    expected,
1028                    "N={N}, lane={lane}"
1029                );
1030            }
1031        }
1032
1033        macro_rules! check_length {
1034            ($rng:ident, $n:literal, $random_cases:literal) => {{
1035                let edge_values = (0..PF::WIDTH * $n)
1036                    .map(|index| RAW_EDGES[index % RAW_EDGES.len()])
1037                    .collect::<Vec<_>>();
1038                check::<$n>(&edge_values);
1039                check::<$n>(&[u64::MAX; PF::WIDTH * $n]);
1040
1041                for _ in 0..$random_cases {
1042                    let values = (0..PF::WIDTH * $n)
1043                        .map(|_| $rng.random::<u64>())
1044                        .collect::<Vec<_>>();
1045                    check::<$n>(&values);
1046                }
1047            }};
1048        }
1049
1050        let mut rng = SmallRng::seed_from_u64(0x5A_0B17_5EED);
1051        check_length!(rng, 0, 16);
1052        check_length!(rng, 1, 16);
1053        check_length!(rng, 2, 16);
1054        check_length!(rng, 3, 16);
1055        check_length!(rng, 4, 16);
1056        check_length!(rng, 5, 16);
1057        check_length!(rng, 6, 16);
1058        check_length!(rng, 7, 16);
1059        check_length!(rng, 8, 16);
1060        check_length!(rng, 12, 16);
1061        check_length!(rng, 16, 16);
1062        check_length!(rng, 32, 16);
1063        check_length!(rng, 63, 8);
1064        check_length!(rng, 64, 8);
1065        check_length!(rng, 129, 4);
1066    }
1067
1068    /// Reduce each full-u64 product separately in the oracle, so repeated max * max
1069    /// also checks sums exceeding u128 without overflowing the expected-value calculation.
1070    #[test]
1071    fn packed_dot_products_match_full_u64_oracle() {
1072        use p3_field::Algebra;
1073
1074        type PF = <F as Field>::Packing;
1075
1076        const RAW_EDGES: [u64; 10] = [
1077            0,
1078            1,
1079            (1 << 32) - 2,
1080            (1 << 32) - 1,
1081            1 << 32,
1082            1 << 63,
1083            P - 1,
1084            P,
1085            P + 1,
1086            u64::MAX,
1087        ];
1088
1089        fn check<const N: usize>(lhs: &[PF; N], rhs: &[PF; N], coeffs: &[F; N]) {
1090            let ordinary = PF::dot_product(lhs, rhs);
1091            let mixed = PF::mixed_dot_product(lhs, coeffs);
1092            let broadcast = PF::dot_product(lhs, &coeffs.map(PF::from));
1093            assert_eq!(mixed, broadcast, "mixed/broadcast, N={N}");
1094
1095            for lane in 0..PF::WIDTH {
1096                let mut ordinary_expected = 0u128;
1097                let mut mixed_expected = 0u128;
1098                for term in 0..N {
1099                    let a = u128::from(lhs[term].as_slice()[lane].value);
1100                    let b = u128::from(rhs[term].as_slice()[lane].value);
1101                    ordinary_expected += (a * b) % u128::from(P);
1102                    mixed_expected += (a * u128::from(coeffs[term].value)) % u128::from(P);
1103                }
1104                assert_eq!(
1105                    ordinary.as_slice()[lane].as_canonical_u64(),
1106                    (ordinary_expected % u128::from(P)) as u64,
1107                    "ordinary, N={N}, lane={lane}"
1108                );
1109                assert_eq!(
1110                    mixed.as_slice()[lane].as_canonical_u64(),
1111                    (mixed_expected % u128::from(P)) as u64,
1112                    "mixed, N={N}, lane={lane}"
1113                );
1114            }
1115        }
1116
1117        fn check_length<const N: usize>(rng: &mut SmallRng) {
1118            // Repeated edge pairs exercise carries above bit 128, zero representatives,
1119            // and the largest possible high limbs in every lane.
1120            for a in RAW_EDGES {
1121                for b in RAW_EDGES {
1122                    check::<N>(
1123                        &[PF::from(F::new(a)); N],
1124                        &[PF::from(F::new(b)); N],
1125                        &[F::new(b); N],
1126                    );
1127                }
1128            }
1129            for offset in 0..RAW_EDGES.len() {
1130                let lhs = core::array::from_fn(|term| {
1131                    PF::from_fn(|lane| F::new(RAW_EDGES[(offset + term + lane) % RAW_EDGES.len()]))
1132                });
1133                let rhs = core::array::from_fn(|term| {
1134                    PF::from_fn(|lane| {
1135                        F::new(RAW_EDGES[(offset + 3 * term + 7 * lane) % RAW_EDGES.len()])
1136                    })
1137                });
1138                let coeffs = core::array::from_fn(|term| {
1139                    F::new(RAW_EDGES[(offset + term) % RAW_EDGES.len()])
1140                });
1141                check::<N>(&lhs, &rhs, &coeffs);
1142            }
1143            for _ in 0..128 {
1144                let lhs = core::array::from_fn(|_| PF::from_fn(|_| F::new(rng.random())));
1145                let rhs = core::array::from_fn(|_| PF::from_fn(|_| F::new(rng.random())));
1146                let coeffs = core::array::from_fn(|_| F::new(rng.random()));
1147                check::<N>(&lhs, &rhs, &coeffs);
1148            }
1149        }
1150
1151        let mut rng = SmallRng::seed_from_u64(0xD07_F011_5EED);
1152        check_length::<0>(&mut rng);
1153        check_length::<1>(&mut rng);
1154        check_length::<2>(&mut rng);
1155        check_length::<3>(&mut rng);
1156        check_length::<4>(&mut rng);
1157        check_length::<5>(&mut rng);
1158        check_length::<6>(&mut rng);
1159        check_length::<7>(&mut rng);
1160        check_length::<8>(&mut rng);
1161        check_length::<12>(&mut rng);
1162        check_length::<16>(&mut rng);
1163        check_length::<31>(&mut rng);
1164        check_length::<32>(&mut rng);
1165        check_length::<33>(&mut rng);
1166        check_length::<64>(&mut rng);
1167        check_length::<65>(&mut rng);
1168        check_length::<129>(&mut rng);
1169    }
1170
1171    #[test]
1172    fn power_of_two_coefficient_matches_generic_exponentiation() {
1173        for exp in (0..384).chain([1 << 32, 1 << 63, u64::MAX - 1, u64::MAX]) {
1174            let coefficient = F::power_of_two(exp);
1175            assert_eq!(coefficient, F::TWO.exp_u64(exp), "exp = {exp}");
1176            assert!(
1177                coefficient.value < P,
1178                "noncanonical coefficient: exp = {exp}"
1179            );
1180            assert_eq!(
1181                coefficient * F::power_of_two(192 - exp % 192),
1182                F::ONE,
1183                "inverse coefficient: exp = {exp}"
1184            );
1185        }
1186    }
1187
1188    #[test]
1189    fn packed_powers_of_two_match_scalar_oracle_for_arbitrary_representatives() {
1190        type PF = <F as Field>::Packing;
1191
1192        const EXPONENTS: [u64; 17] = [
1193            0,
1194            1,
1195            2,
1196            3,
1197            5,
1198            31,
1199            32,
1200            33,
1201            63,
1202            95,
1203            96,
1204            191,
1205            192,
1206            194,
1207            224,
1208            225,
1209            u64::MAX,
1210        ];
1211        const RAW_EDGES: [u64; 10] = [
1212            0,
1213            1,
1214            (1 << 32) - 2,
1215            (1 << 32) - 1,
1216            1 << 32,
1217            1 << 63,
1218            P - 1,
1219            P,
1220            P + 1,
1221            u64::MAX,
1222        ];
1223
1224        let check = |raw: &[u64]| {
1225            assert_eq!(raw.len(), PF::WIDTH);
1226            let input = PF::from_fn(|lane| F::new(raw[lane]));
1227
1228            for exp in EXPONENTS {
1229                let power = F::TWO.exp_u64(exp);
1230                let product = input.mul_2exp_u64(exp);
1231                let quotient = input.div_2exp_u64(exp);
1232
1233                for (lane, &raw) in raw.iter().enumerate() {
1234                    let scalar = F::new(raw);
1235                    assert_eq!(
1236                        product.as_slice()[lane],
1237                        scalar * power,
1238                        "mul: raw = {raw:#018x}, exp = {exp}, lane = {lane}"
1239                    );
1240                    assert_eq!(
1241                        quotient.as_slice()[lane],
1242                        scalar / power,
1243                        "div: raw = {raw:#018x}, exp = {exp}, lane = {lane}"
1244                    );
1245                }
1246            }
1247        };
1248
1249        for offset in 0..RAW_EDGES.len() {
1250            let raw = (0..PF::WIDTH)
1251                .map(|lane| RAW_EDGES[(offset + lane) % RAW_EDGES.len()])
1252                .collect::<Vec<_>>();
1253            check(&raw);
1254        }
1255
1256        let mut rng = SmallRng::seed_from_u64(0x2E80_2E80_5EED);
1257        for _ in 0..256 {
1258            let raw = (0..PF::WIDTH)
1259                .map(|_| rng.random::<u64>())
1260                .collect::<Vec<_>>();
1261            check(&raw);
1262        }
1263    }
1264
1265    #[test]
1266    fn deserialize_rejects_non_canonical_encodings() {
1267        // p, p + i, and u64::MAX are all field-equal to canonical values.
1268        // Only the canonical encoding may deserialize.
1269        // This blocks re-encoding a proof as p + i without the witness.
1270        for non_canonical in [P, P + 5, u64::MAX] {
1271            let json = serde_json::to_string(&non_canonical).unwrap();
1272            assert!(serde_json::from_str::<F>(&json).is_err());
1273        }
1274
1275        // The largest canonical value, p - 1, still deserializes.
1276        let max_canonical_json = serde_json::to_string(&(P - 1)).unwrap();
1277        let max_canonical: F = serde_json::from_str(&max_canonical_json).unwrap();
1278        assert_eq!(max_canonical.as_canonical_u64(), P - 1);
1279    }
1280
1281    #[test]
1282    fn serialize_is_canonical() {
1283        // A non-canonical in-memory value serializes to its canonical representative.
1284        //     in memory : p + 5
1285        //     canonical : 5
1286        let non_canonical = F::new(P + 5);
1287        let json = serde_json::to_string(&non_canonical).unwrap();
1288        assert_eq!(json, "5");
1289
1290        // The canonical encoding round-trips back to the same field element.
1291        let roundtrip: F = serde_json::from_str(&json).unwrap();
1292        assert_eq!(roundtrip, non_canonical);
1293    }
1294
1295    #[test]
1296    fn test_goldilocks() {
1297        let f = F::new(100);
1298        assert_eq!(f.as_canonical_u64(), 100);
1299
1300        // Over the Goldilocks field, the following set of equations hold
1301        // p               = 0
1302        // 2^64 - 2^32 + 1 = 0
1303        // 2^64            = 2^32 - 1
1304        let f = F::new(u64::MAX);
1305        assert_eq!(f.as_canonical_u64(), u32::MAX as u64 - 1);
1306
1307        let f = F::from_u64(u64::MAX);
1308        assert_eq!(f.as_canonical_u64(), u32::MAX as u64 - 1);
1309
1310        // Generator check
1311        let expected_multiplicative_group_generator = F::new(7);
1312        assert_eq!(F::GENERATOR, expected_multiplicative_group_generator);
1313        assert_eq!(F::GENERATOR.as_canonical_u64(), 7_u64);
1314
1315        // Check on `reduce_u128`
1316        let x = u128::MAX;
1317        let y = reduce128(x);
1318        // The following equality sequence holds, modulo p = 2^64 - 2^32 + 1
1319        // 2^128 - 1 = (2^64 - 1) * (2^64 + 1)
1320        //           = (2^32 - 1 - 1) * (2^32 - 1 + 1)
1321        //           = (2^32 - 2) * (2^32)
1322        //           = 2^64 - 2 * 2^32
1323        //           = 2^64 - 2^33
1324        //           = 2^32 - 1 - 2^33
1325        //           = - 2^32 - 1
1326        let expected_result = -F::TWO.exp_power_of_2(5) - F::ONE;
1327        assert_eq!(y, expected_result);
1328
1329        let f = F::new(100);
1330        assert_eq!(f.injective_exp_n().injective_exp_root_n(), f);
1331        assert_eq!(y.injective_exp_n().injective_exp_root_n(), y);
1332        assert_eq!(F::TWO.injective_exp_n().injective_exp_root_n(), F::TWO);
1333    }
1334
1335    #[test]
1336    fn u128_conversion_matches_modulo_oracle() {
1337        const EDGES: [u128; 12] = [
1338            0,
1339            1,
1340            P as u128 - 1,
1341            P as u128,
1342            P as u128 + 1,
1343            u64::MAX as u128,
1344            1 << 64,
1345            (1 << 64) + P as u128,
1346            1 << 96,
1347            1 << 127,
1348            u128::MAX - 1,
1349            u128::MAX,
1350        ];
1351
1352        let check = |input: u128| {
1353            let expected = (input % P as u128) as u64;
1354            let actual = F::from_int(input);
1355            assert_eq!(actual.value, expected, "input = {input:#034x}");
1356        };
1357
1358        for input in EDGES {
1359            check(input);
1360        }
1361
1362        let mut rng = SmallRng::seed_from_u64(0x128_C0DE);
1363        for _ in 0..10_000 {
1364            check(rng.random());
1365        }
1366    }
1367
1368    #[test]
1369    fn i128_conversion_matches_modulo_oracle() {
1370        const P_I128: i128 = P as i128;
1371        const EDGES: [i128; 14] = [
1372            i128::MIN,
1373            i128::MIN + 1,
1374            -(1 << 96),
1375            -P_I128 - 1,
1376            -P_I128,
1377            -P_I128 + 1,
1378            -1,
1379            0,
1380            1,
1381            P_I128 - 1,
1382            P_I128,
1383            P_I128 + 1,
1384            i128::MAX - 1,
1385            i128::MAX,
1386        ];
1387
1388        let check = |input: i128| {
1389            let magnitude_mod_p = (input.unsigned_abs() % P as u128) as u64;
1390            let expected_raw = if input < 0 {
1391                P - magnitude_mod_p
1392            } else {
1393                magnitude_mod_p
1394            };
1395            let actual = F::from_int(input);
1396            assert_eq!(actual.value, expected_raw, "input = {input}");
1397        };
1398
1399        for input in EDGES {
1400            check(input);
1401        }
1402
1403        let mut rng = SmallRng::seed_from_u64(0x128_51C0);
1404        for _ in 0..10_000 {
1405            check(rng.random());
1406        }
1407    }
1408
1409    #[test]
1410    fn sqrt_matches_generic_tonelli_shanks_for_arbitrary_representatives() {
1411        const RAW_EDGES: [u64; 10] = [
1412            0,
1413            1,
1414            (1 << 32) - 1,
1415            1 << 32,
1416            1 << 63,
1417            P - 1,
1418            P,
1419            P + 1,
1420            u64::MAX - 1,
1421            u64::MAX,
1422        ];
1423
1424        let check = |raw: u64| {
1425            let input = F::new(raw);
1426            let expected = tonelli_shanks_two_adic(input);
1427            let actual = input.try_sqrt();
1428            assert_eq!(actual.is_some(), expected.is_some(), "raw = {raw:#018x}");
1429            if let Some(root) = actual {
1430                assert_eq!(root.square(), input, "raw = {raw:#018x}");
1431            }
1432        };
1433
1434        for raw in RAW_EDGES {
1435            check(raw);
1436        }
1437
1438        let mut rng = SmallRng::seed_from_u64(0x5A7_C0DE);
1439        for _ in 0..10_000 {
1440            check(rng.random());
1441        }
1442    }
1443
1444    #[test]
1445    fn large_integer_checked_conversion_preserves_bounds_and_raw_values() {
1446        let unsigned_cases = [
1447            (0, Some(0)),
1448            (P as u128 - 1, Some(P - 1)),
1449            (P as u128, None),
1450            (P as u128 + 1, None),
1451            (u128::MAX, None),
1452        ];
1453        for (input, expected_raw) in unsigned_cases {
1454            assert_eq!(
1455                F::from_canonical_checked(input).map(|value| value.value),
1456                expected_raw,
1457                "input = {input}"
1458            );
1459        }
1460
1461        const BOUND: i128 = (P >> 1) as i128;
1462        let signed_cases = [
1463            (-BOUND - 1, None),
1464            (-BOUND, Some(P - BOUND as u64)),
1465            (-1, Some(P - 1)),
1466            (0, Some(0)),
1467            (BOUND, Some(BOUND as u64)),
1468            (BOUND + 1, None),
1469            (i128::MIN, None),
1470            (i128::MAX, None),
1471        ];
1472        for (input, expected_raw) in signed_cases {
1473            assert_eq!(
1474                F::from_canonical_checked(input).map(|value| value.value),
1475                expected_raw,
1476                "input = {input}"
1477            );
1478        }
1479    }
1480
1481    #[test]
1482    fn large_integer_unchecked_conversion_preserves_cast_behavior() {
1483        let unsigned_cases = [
1484            (0, 0),
1485            (P as u128 - 1, P - 1),
1486            (P as u128, P),
1487            (u64::MAX as u128, u64::MAX),
1488        ];
1489        for (input, expected_raw) in unsigned_cases {
1490            let actual = unsafe { F::from_canonical_unchecked(input) };
1491            assert_eq!(actual.value, expected_raw, "input = {input}");
1492        }
1493
1494        const MIN_UNCHECKED: i128 = 1 + (1_i128 << 32) - (1_i128 << 64);
1495        let signed_inputs = [
1496            MIN_UNCHECKED,
1497            i64::MIN as i128 - 1,
1498            i64::MIN as i128,
1499            -1,
1500            0,
1501            i64::MAX as i128,
1502            i64::MAX as i128 + 1,
1503            u64::MAX as i128,
1504        ];
1505        for input in signed_inputs {
1506            let narrowed = input as i64;
1507            let expected_raw = if narrowed >= 0 {
1508                narrowed as u64
1509            } else {
1510                P.wrapping_add_signed(narrowed)
1511            };
1512            let actual = unsafe { F::from_canonical_unchecked(input) };
1513            assert_eq!(actual.value, expected_raw, "input = {input}");
1514        }
1515    }
1516
1517    #[test]
1518    fn div_2exp_matches_field_division_for_all_representatives() {
1519        const EPSILON: u64 = (1 << 32) - 1;
1520        const RAW_EDGES: [u64; 10] = [
1521            0,
1522            1,
1523            EPSILON - 1,
1524            EPSILON,
1525            1 << 32,
1526            1 << 63,
1527            P - 1,
1528            P,
1529            P + 1,
1530            u64::MAX,
1531        ];
1532        const LARGE_EXPONENTS: [u64; 5] = [193, 384, 1 << 32, 1 << 63, u64::MAX];
1533
1534        let check = |raw: u64, exp: u64| {
1535            let x = F::new(raw);
1536            let divisor = F::TWO.exp_u64(exp % 192);
1537            assert_eq!(
1538                x.div_2exp_u64(exp),
1539                x / divisor,
1540                "raw = {raw:#018x}, exp = {exp}"
1541            );
1542        };
1543
1544        for raw in RAW_EDGES {
1545            for exp in 0..=192 {
1546                check(raw, exp);
1547            }
1548            for exp in LARGE_EXPONENTS {
1549                check(raw, exp);
1550            }
1551        }
1552
1553        let mut rng = SmallRng::seed_from_u64(0xD12_2E98);
1554        for _ in 0..10_000 {
1555            check(rng.random(), rng.random());
1556        }
1557    }
1558
1559    // Goldilocks has a redundant representation for both 0 and 1.
1560    const ZEROS: [Goldilocks; 2] = [Goldilocks::ZERO, Goldilocks::new(P)];
1561    const ONES: [Goldilocks; 2] = [Goldilocks::ONE, Goldilocks::new(P + 1)];
1562
1563    // Get the prime factorization of the order of the multiplicative group.
1564    // i.e. the prime factorization of P - 1.
1565    fn multiplicative_group_prime_factorization() -> [(BigUint, u32); 6] {
1566        [
1567            (BigUint::from(2u8), 32),
1568            (BigUint::from(3u8), 1),
1569            (BigUint::from(5u8), 1),
1570            (BigUint::from(17u8), 1),
1571            (BigUint::from(257u16), 1),
1572            (BigUint::from(65537u32), 1),
1573        ]
1574    }
1575
1576    test_field!(
1577        crate::Goldilocks,
1578        &super::ZEROS,
1579        &super::ONES,
1580        &super::multiplicative_group_prime_factorization()
1581    );
1582    test_prime_field!(crate::Goldilocks);
1583    test_prime_field_64!(crate::Goldilocks, &super::ZEROS, &super::ONES);
1584    test_two_adic_field!(crate::Goldilocks);
1585
1586    test_field_dft!(
1587        radix2dit,
1588        crate::Goldilocks,
1589        super::EF,
1590        p3_dft::Radix2Dit<_>
1591    );
1592    test_field_dft!(bowers, crate::Goldilocks, super::EF, p3_dft::Radix2Bowers);
1593    test_field_dft!(
1594        parallel,
1595        crate::Goldilocks,
1596        super::EF,
1597        p3_dft::Radix2DitParallel<crate::Goldilocks>
1598    );
1599}