trident/field/
goldilocks.rs1use super::PrimeField;
9
10pub const MODULUS: u64 = 0xFFFF_FFFF_0000_0001;
12
13#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
15pub struct Goldilocks(pub u64);
16
17impl Goldilocks {
18 #[inline]
20 fn reduce128(x: u128) -> Self {
21 let lo = x as u64;
22 let hi = (x >> 64) as u64;
23 let hi_shifted = (hi as u128) * ((1u128 << 32) - 1);
24 let sum = lo as u128 + hi_shifted;
25 let lo2 = sum as u64;
26 let hi2 = (sum >> 64) as u64;
27 if hi2 == 0 {
28 Self(if lo2 >= MODULUS { lo2 - MODULUS } else { lo2 })
29 } else {
30 let r = lo2 as u128 + (hi2 as u128) * ((1u128 << 32) - 1);
31 let lo3 = r as u64;
32 let hi3 = (r >> 64) as u64;
33 if hi3 == 0 {
34 Self(if lo3 >= MODULUS { lo3 - MODULUS } else { lo3 })
35 } else {
36 let v = lo3.wrapping_add(hi3.wrapping_mul(u32::MAX as u64));
37 Self(if v >= MODULUS { v - MODULUS } else { v })
38 }
39 }
40 }
41
42 #[inline]
44 pub fn sbox(self) -> Self {
45 let x2 = self.mul(self);
46 let x3 = x2.mul(self);
47 let x6 = x3.mul(x3);
48 x6.mul(self)
49 }
50}
51
52impl PrimeField for Goldilocks {
53 const MODULUS: u128 = MODULUS as u128;
54 const BITS: u32 = 64;
55 const ZERO: Self = Self(0);
56 const ONE: Self = Self(1);
57
58 #[inline]
59 fn from_u64(v: u64) -> Self {
60 Self(v % MODULUS)
61 }
62
63 #[inline]
64 fn to_u64(self) -> u64 {
65 self.0
66 }
67
68 #[inline]
69 fn add(self, rhs: Self) -> Self {
70 let (sum, carry) = self.0.overflowing_add(rhs.0);
71 if carry {
72 let r = sum + (u32::MAX as u64);
73 Self(if r >= MODULUS { r - MODULUS } else { r })
74 } else {
75 Self(if sum >= MODULUS { sum - MODULUS } else { sum })
76 }
77 }
78
79 #[inline]
80 fn sub(self, rhs: Self) -> Self {
81 if self.0 >= rhs.0 {
82 Self(self.0 - rhs.0)
83 } else {
84 Self(MODULUS - rhs.0 + self.0)
85 }
86 }
87
88 #[inline]
89 fn mul(self, rhs: Self) -> Self {
90 Self::reduce128((self.0 as u128) * (rhs.0 as u128))
91 }
92
93 #[inline]
94 fn neg(self) -> Self {
95 if self.0 == 0 {
96 Self(0)
97 } else {
98 Self(MODULUS - self.0)
99 }
100 }
101}