1use ff::PrimeField;
4use internment::Intern;
5use num_bigint::BigUint;
6use std::ops::{Add, AddAssign, Deref, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign};
7
8#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
10pub struct Prime(Intern<BigUint>);
11
12impl Prime {
13 pub fn new<F: PrimeField>() -> Self {
15 let f = -F::ONE;
16 Self(Intern::new(
17 BigUint::from_bytes_le(f.to_repr().as_ref()) + 1usize,
18 ))
19 }
20
21 fn value(&self) -> &BigUint {
22 self.0.as_ref()
23 }
24
25 fn minus_one(&self) -> Felt {
26 Felt::from_parts(self.value() - 1usize, *self)
27 }
28}
29
30#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
35pub struct Felt {
36 value: Intern<BigUint>,
37 prime: Prime,
38}
39
40impl Felt {
41 pub fn new<F: PrimeField>(f: F) -> Self {
43 Self {
44 value: Intern::new(BigUint::from_bytes_le(f.to_repr().as_ref())),
45 prime: Prime::new::<F>(),
46 }
47 }
48
49 pub fn from_parts(value: BigUint, prime: Prime) -> Self {
51 Self {
52 value: Intern::new(value),
53 prime,
54 }
55 }
56
57 pub fn prime(&self) -> Prime {
59 self.prime
60 }
61
62 #[cfg(test)]
66 pub fn new_from<F: PrimeField>(i: impl Into<BigUint>) -> Self {
67 Self {
68 value: Intern::new(i.into()),
69 prime: Prime::new::<F>(),
70 }
71 }
72
73 fn replace(self, value: BigUint) -> Self {
74 Self {
75 value: Intern::new(value % self.prime.value()),
76 prime: self.prime,
77 }
78 }
79
80 pub fn is_minus_one(&self) -> bool {
82 *self == self.prime().minus_one()
83 }
84}
85
86impl<F: PrimeField> From<F> for Felt {
87 fn from(value: F) -> Self {
88 Self::new(value)
89 }
90}
91
92impl std::fmt::Debug for Felt {
93 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
94 write!(f, "{:?}", self.as_ref())
95 }
96}
97
98impl<T> PartialEq<T> for Felt
99where
100 T: Into<BigUint> + Copy,
101{
102 fn eq(&self, other: &T) -> bool {
103 let other: BigUint = (*other).into() % self.prime.value();
104 self.as_ref().eq(&other)
105 }
106}
107
108impl AsRef<BigUint> for Felt {
109 fn as_ref(&self) -> &BigUint {
110 self.value.as_ref()
111 }
112}
113
114impl Deref for Felt {
115 type Target = BigUint;
116
117 fn deref(&self) -> &Self::Target {
118 self.as_ref()
119 }
120}
121
122impl Rem for Felt {
123 type Output = Self;
124
125 fn rem(self, rhs: Self) -> Self::Output {
129 assert_eq!(self.prime, rhs.prime);
130 if self < rhs {
131 return self;
132 }
133 self.replace(self.as_ref() % rhs.as_ref())
134 }
135}
136
137impl Rem<Prime> for Felt {
138 type Output = Self;
139
140 fn rem(self, prime: Prime) -> Self::Output {
141 if self.prime() == prime {
142 return self;
143 }
144 if self.prime() > prime {
145 return Self::from_parts(self.value.as_ref().clone(), prime);
146 }
147 Self::from_parts(self.as_ref() % prime.value(), prime)
148 }
149}
150
151impl RemAssign for Felt {
152 fn rem_assign(&mut self, rhs: Self) {
156 *self = *self % rhs;
157 }
158}
159
160impl RemAssign<Prime> for Felt {
161 fn rem_assign(&mut self, rhs: Prime) {
162 *self = *self % rhs;
163 }
164}
165
166impl Sub for Felt {
167 type Output = Self;
168
169 fn sub(self, rhs: Self) -> Self::Output {
173 assert_eq!(self.prime, rhs.prime);
174 if self < rhs {
175 let diff = rhs.as_ref() - self.as_ref();
176 return self.replace(self.prime.value() - diff);
177 }
178
179 self.replace(self.as_ref() - rhs.as_ref())
180 }
181}
182
183impl SubAssign for Felt {
184 fn sub_assign(&mut self, rhs: Self) {
188 *self = *self - rhs;
189 }
190}
191
192impl Add for Felt {
193 type Output = Felt;
194
195 fn add(self, rhs: Self) -> Self::Output {
199 assert_eq!(self.prime, rhs.prime);
200 self.replace(self.as_ref() + rhs.as_ref())
201 }
202}
203
204impl AddAssign for Felt {
205 fn add_assign(&mut self, rhs: Self) {
209 *self = *self + rhs;
210 }
211}
212
213impl Mul for Felt {
214 type Output = Felt;
215
216 fn mul(self, rhs: Self) -> Self::Output {
220 assert_eq!(self.prime, rhs.prime);
221 self.replace(self.as_ref() * rhs.as_ref())
222 }
223}
224
225impl MulAssign for Felt {
226 fn mul_assign(&mut self, rhs: Self) {
230 *self = *self * rhs;
231 }
232}
233
234impl Neg for Felt {
235 type Output = Self;
236
237 fn neg(self) -> Self::Output {
238 self.replace(self.prime().value() - self.as_ref())
239 }
240}
241
242impl std::fmt::Display for Felt {
243 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
244 write!(f, "{}", self.as_ref())
245 }
246}
247
248#[allow(missing_docs)]
249#[cfg(test)]
250pub mod tests {
251
252 use super::*;
253 use ff::PrimeField;
254 use halo2curves::bn256::Fq;
255 use num_bigint::BigInt;
256 use quickcheck_macros::quickcheck;
257
258 #[derive(PrimeField)]
260 #[PrimeFieldModulus = "2013265921"]
261 #[PrimeFieldGenerator = "31"]
262 #[PrimeFieldReprEndianness = "little"]
263 pub struct BabyBear([u64; 1]);
264 const BABYBEAR: u32 = 2013265921;
265
266 #[quickcheck]
267 fn partial_eq_for_other_types(x: u32) {
268 let v: u32 = x % BABYBEAR;
269 let v_f = Felt::new(BabyBear::from(x as u64));
270 if x < BABYBEAR {
271 assert_eq!(v, x);
272 } else {
273 assert_ne!(v, x);
274 }
275 assert_eq!(v_f, x);
276 }
277
278 #[quickcheck]
279 fn mul(x: u32, y: u32) {
280 let r = Felt::new(BabyBear::from(x as u64)) * Felt::new(BabyBear::from(y as u64));
281 let e = (BigUint::from(x) * BigUint::from(y)) % BigUint::from(BABYBEAR);
282
283 assert_eq!(r.as_ref(), &e);
284 }
285
286 #[quickcheck]
287 fn sum(x: u32, y: u32) {
288 let r = Felt::new(BabyBear::from(x as u64)) + Felt::new(BabyBear::from(y as u64));
289 let e = (BigUint::from(x) + BigUint::from(y)) % BigUint::from(BABYBEAR);
290
291 assert_eq!(r.as_ref(), &e);
292 }
293
294 #[quickcheck]
295 fn sub(x: u32, y: u32) {
296 let r = Felt::new(BabyBear::from(x as u64)) - Felt::new(BabyBear::from(y as u64));
297 let e = if x >= y {
298 (BigUint::from(x) - BigUint::from(y)) % BigUint::from(BABYBEAR)
299 } else {
300 let b = BigInt::from(BABYBEAR);
301 let mut i = BigInt::from(x) - BigInt::from(y);
302 while i.sign() == num_bigint::Sign::Minus {
303 i += &b;
304 }
305 i.try_into().unwrap()
306 };
307
308 assert_eq!(r.as_ref(), &e);
309 }
310
311 #[quickcheck]
312 fn same_prime_eq(i: u64) {
313 let x = Felt::new(BabyBear::from(i));
314 let y = Felt::new(BabyBear::from(i));
315 assert_eq!(x, y);
316 }
317
318 #[quickcheck]
319 fn different_primes_eq(i: u64) {
320 let x = Felt::new(BabyBear::from(i));
321 let y = Felt::new(Fq::from(i));
322 assert_ne!(x, y);
323 }
324
325 #[quickcheck]
326 #[should_panic]
327 fn different_primes_sum(a: u64, b: u64) {
328 let a = Felt::new(BabyBear::from(a));
329 let b = Felt::new(Fq::from(b));
330 let _ = a + b;
331 }
332
333 #[quickcheck]
334 #[should_panic]
335 fn different_primes_sum_assign(a: u64, b: u64) {
336 let mut a = Felt::new(BabyBear::from(a));
337 let b = Felt::new(Fq::from(b));
338 a += b;
339 }
340
341 #[quickcheck]
342 #[should_panic]
343 fn different_primes_mul(a: u64, b: u64) {
344 let a = Felt::new(BabyBear::from(a));
345 let b = Felt::new(Fq::from(b));
346 let _ = a * b;
347 }
348
349 #[quickcheck]
350 #[should_panic]
351 fn different_primes_mul_assign(a: u64, b: u64) {
352 let mut a = Felt::new(BabyBear::from(a));
353 let b = Felt::new(Fq::from(b));
354 a *= b;
355 }
356
357 #[quickcheck]
358 #[should_panic]
359 fn different_primes_sub(a: u64, b: u64) {
360 let a = Felt::new(BabyBear::from(a));
361 let b = Felt::new(Fq::from(b));
362 let _ = a - b;
363 }
364
365 #[quickcheck]
366 #[should_panic]
367 fn different_primes_sub_assign(a: u64, b: u64) {
368 let mut a = Felt::new(BabyBear::from(a));
369 let b = Felt::new(Fq::from(b));
370 a -= b;
371 }
372
373 #[quickcheck]
374 #[should_panic]
375 fn different_primes_rem(a: u64, b: u64) {
376 let a = Felt::new(BabyBear::from(a));
377 let b = Felt::new(Fq::from(b));
378 let _ = a % b;
379 }
380
381 #[quickcheck]
382 #[should_panic]
383 fn different_primes_rem_assign(a: u64, b: u64) {
384 let mut a = Felt::new(BabyBear::from(a));
385 let b = Felt::new(Fq::from(b));
386 a %= b;
387 }
388}