lambdaworks_math/field/fields/
u64_goldilocks_field.rs1use core::fmt::{self, Display};
2
3use crate::traits::ByteConversion;
4use crate::{
5 errors::CreationError,
6 field::{
7 element::FieldElement,
8 errors::FieldError,
9 extensions::quadratic::{HasQuadraticNonResidue, QuadraticExtensionField},
10 traits::{IsField, IsPrimeField},
11 },
12};
13
14#[derive(Debug, Clone, Copy, Hash, PartialOrd, Ord, PartialEq, Eq)]
16pub struct Goldilocks64Field;
17
18impl Goldilocks64Field {
19 pub const ORDER: u64 = 0xFFFF_FFFF_0000_0001;
20 pub const NEG_ORDER: u64 = Self::ORDER.wrapping_neg();
22}
23
24impl ByteConversion for u64 {
25 #[cfg(feature = "alloc")]
26 fn to_bytes_be(&self) -> alloc::vec::Vec<u8> {
27 unimplemented!()
28 }
29
30 #[cfg(feature = "alloc")]
31 fn to_bytes_le(&self) -> alloc::vec::Vec<u8> {
32 unimplemented!()
33 }
34
35 fn from_bytes_be(_bytes: &[u8]) -> Result<Self, crate::errors::ByteConversionError>
36 where
37 Self: Sized,
38 {
39 unimplemented!()
40 }
41
42 fn from_bytes_le(_bytes: &[u8]) -> Result<Self, crate::errors::ByteConversionError>
43 where
44 Self: Sized,
45 {
46 unimplemented!()
47 }
48}
49
50impl IsField for Goldilocks64Field {
54 type BaseType = u64;
55
56 fn add(a: &u64, b: &u64) -> u64 {
57 let (sum, over) = a.overflowing_add(*b);
58 let (mut sum, over) = sum.overflowing_add(u64::from(over) * Self::NEG_ORDER);
59 if over {
60 sum += Self::NEG_ORDER
61 }
62 Self::representative(&sum)
63 }
64
65 fn mul(a: &u64, b: &u64) -> u64 {
66 Self::representative(&reduce_128(u128::from(*a) * u128::from(*b)))
67 }
68
69 fn sub(a: &u64, b: &u64) -> u64 {
70 let (diff, under) = a.overflowing_sub(*b);
71 let (mut diff, under) = diff.overflowing_sub(u64::from(under) * Self::NEG_ORDER);
72 if under {
73 diff -= Self::NEG_ORDER;
74 }
75 Self::representative(&diff)
76 }
77
78 fn neg(a: &u64) -> u64 {
79 Self::sub(&Self::ORDER, &Self::representative(a))
80 }
81
82 fn inv(a: &u64) -> Result<u64, FieldError> {
84 if *a == Self::zero() || *a == Self::ORDER {
85 return Err(FieldError::InvZeroError);
86 }
87
88 let t2 = Self::mul(&Self::square(a), a);
90
91 let t3 = Self::mul(&Self::square(&t2), a);
93
94 let t6 = exp_acc::<3>(&t3, &t3);
96 let t60 = Self::square(&t6);
97 let t7 = Self::mul(&t60, a);
98
99 let t12 = exp_acc::<5>(&t60, &t6);
102
103 let t24 = exp_acc::<12>(&t12, &t12);
106
107 let t31 = exp_acc::<7>(&t24, &t7);
110
111 let t63 = exp_acc::<32>(&t31, &t31);
114
115 Ok(Self::mul(&Self::square(&t63), a))
116 }
117
118 fn div(a: &u64, b: &u64) -> Result<u64, FieldError> {
120 let b_inv = &Self::inv(b)?;
121 Ok(Self::mul(a, b_inv))
122 }
123
124 fn eq(a: &u64, b: &u64) -> bool {
126 Self::representative(a) == Self::representative(b)
127 }
128
129 fn zero() -> u64 {
131 0u64
132 }
133
134 fn one() -> u64 {
136 1u64
137 }
138
139 fn from_u64(x: u64) -> u64 {
141 Self::representative(&x)
142 }
143
144 fn from_base_type(x: u64) -> u64 {
147 Self::representative(&x)
148 }
149}
150
151impl IsPrimeField for Goldilocks64Field {
152 type RepresentativeType = u64;
153
154 fn representative(x: &u64) -> u64 {
155 let mut u = *x;
156 if u >= Self::ORDER {
157 u -= Self::ORDER;
158 }
159 u
160 }
161
162 fn field_bit_size() -> usize {
163 ((self::Goldilocks64Field::ORDER - 1).ilog2() + 1) as usize
164 }
165
166 fn from_hex(hex_string: &str) -> Result<Self::BaseType, CreationError> {
167 let mut hex_string = hex_string;
168 let mut char_iterator = hex_string.chars();
170 if hex_string.len() > 2
171 && char_iterator.next().unwrap() == '0'
172 && char_iterator.next().unwrap() == 'x'
173 {
174 hex_string = &hex_string[2..];
175 }
176 u64::from_str_radix(hex_string, 16).map_err(|_| CreationError::InvalidHexString)
177 }
178
179 #[cfg(feature = "std")]
180 fn to_hex(x: &u64) -> String {
181 format!("{x:X}")
182 }
183}
184
185#[inline(always)]
186fn reduce_128(x: u128) -> u64 {
187 let (x_lo, x_hi) = (x as u64, (x >> 64) as u64);
189 let x_hi_hi = x_hi >> 32;
190 let x_hi_lo = x_hi & Goldilocks64Field::NEG_ORDER;
191
192 let (mut t0, borrow) = x_lo.overflowing_sub(x_hi_hi);
193 if borrow {
194 t0 -= Goldilocks64Field::NEG_ORDER }
196
197 let t1 = x_hi_lo * Goldilocks64Field::NEG_ORDER;
198 let (res_wrapped, carry) = t0.overflowing_add(t1);
199 res_wrapped + Goldilocks64Field::NEG_ORDER * u64::from(carry)
201}
202
203#[inline(always)]
204fn exp_acc<const N: usize>(base: &u64, tail: &u64) -> u64 {
205 Goldilocks64Field::mul(&exp_power_of_2::<N>(base), tail)
206}
207
208#[must_use]
209fn exp_power_of_2<const POWER_LOG: usize>(base: &u64) -> u64 {
210 let mut res = *base;
211 for _ in 0..POWER_LOG {
212 res = Goldilocks64Field::square(&res);
213 }
214 res
215}
216
217pub type Goldilocks64ExtensionField = QuadraticExtensionField<Goldilocks64Field, Goldilocks64Field>;
218
219impl HasQuadraticNonResidue<Goldilocks64Field> for Goldilocks64Field {
220 fn residue() -> FieldElement<Goldilocks64Field> {
223 FieldElement::from(Goldilocks64Field::from_u64(7u64))
224 }
225}
226
227impl Display for FieldElement<Goldilocks64Field> {
228 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
229 write!(f, "{:x}", self.representative())?;
230 Ok(())
231 }
232}
233
234#[cfg(test)]
235mod tests {
236 use super::*;
237 type F = Goldilocks64Field;
238
239 #[test]
244 fn from_hex_for_b_is_11() {
245 assert_eq!(F::from_hex("B").unwrap(), 11);
246 }
247
248 #[test]
249 fn from_hex_for_0x1_a_is_26() {
250 assert_eq!(F::from_hex("0x1a").unwrap(), 26);
251 }
252
253 #[test]
254 fn bit_size_of_field_is_64() {
255 assert_eq!(
256 <F as crate::field::traits::IsPrimeField>::field_bit_size(),
257 64
258 );
259 }
260
261 #[test]
262 fn one_plus_one_is_two() {
263 let a = F::one();
264 let b = F::one();
265 let c = F::add(&a, &b);
266 assert_eq!(c, 2u64);
267 }
268
269 #[test]
270 fn neg_one_plus_one_is_zero() {
271 let a = F::neg(&F::one());
272 let b = F::one();
273 let c = F::add(&a, &b);
274 assert_eq!(c, F::zero());
275 }
276
277 #[test]
278 fn neg_one_plus_two_is_one() {
279 let a = F::neg(&F::one());
280 let b = F::from_base_type(2u64);
281 let c = F::add(&a, &b);
282 assert_eq!(c, F::one());
283 }
284
285 #[test]
286 fn max_order_plus_one_is_zero() {
287 let a = F::from_base_type(F::ORDER - 1);
288 let b = F::one();
289 let c = F::add(&a, &b);
290 assert_eq!(c, F::zero());
291 }
292
293 #[test]
294 fn comparing_13_and_13_are_equal() {
295 let a = F::from_base_type(13);
296 let b = F::from_base_type(13);
297 assert_eq!(a, b);
298 }
299
300 #[test]
301 fn comparing_13_and_8_they_are_not_equal() {
302 let a = F::from_base_type(13);
303 let b = F::from_base_type(8);
304 assert_ne!(a, b);
305 }
306
307 #[test]
308 fn one_sub_one_is_zero() {
309 let a = F::one();
310 let b = F::one();
311 let c = F::sub(&a, &b);
312 assert_eq!(c, F::zero());
313 }
314
315 #[test]
316 fn zero_sub_one_is_order_minus_1() {
317 let a = F::zero();
318 let b = F::one();
319 let c = F::sub(&a, &b);
320 assert_eq!(c, F::ORDER - 1);
321 }
322
323 #[test]
324 fn neg_one_sub_neg_one_is_zero() {
325 let a = F::neg(&F::one());
326 let b = F::neg(&F::one());
327 let c = F::sub(&a, &b);
328 assert_eq!(c, F::zero());
329 }
330
331 #[test]
332 fn neg_one_sub_one_is_neg_one() {
333 let a = F::neg(&F::one());
334 let b = F::zero();
335 let c = F::sub(&a, &b);
336 assert_eq!(c, F::neg(&F::one()));
337 }
338
339 #[test]
340 fn mul_neutral_element() {
341 let a = F::from_base_type(1);
342 let b = F::from_base_type(2);
343 let c = F::mul(&a, &b);
344 assert_eq!(c, F::from_base_type(2));
345 }
346
347 #[test]
348 fn mul_two_three_is_six() {
349 let a = F::from_base_type(2);
350 let b = F::from_base_type(3);
351 assert_eq!(a * b, F::from_base_type(6));
352 }
353
354 #[test]
355 fn mul_order_neg_one() {
356 let a = F::from_base_type(F::ORDER - 1);
357 let b = F::from_base_type(F::ORDER - 1);
358 let c = F::mul(&a, &b);
359 assert_eq!(c, F::from_base_type(1));
360 }
361
362 #[test]
363 fn pow_p_neg_one() {
364 assert_eq!(F::pow(&F::from_base_type(2), F::ORDER - 1), F::one())
365 }
366
367 #[test]
368 fn inv_zero_error() {
369 let result = F::inv(&F::zero());
370 assert!(matches!(result, Err(FieldError::InvZeroError)));
371 }
372
373 #[test]
374 fn inv_two() {
375 let result = F::inv(&F::from_base_type(2u64)).unwrap();
376 assert_eq!(result, 9223372034707292161);
378 }
379
380 #[test]
381 fn pow_two_three() {
382 assert_eq!(F::pow(&F::from_base_type(2), 3_u64), 8)
383 }
384
385 #[test]
386 fn div_one() {
387 assert_eq!(
388 F::div(&F::from_base_type(2), &F::from_base_type(1)).unwrap(),
389 2
390 )
391 }
392
393 #[test]
394 fn div_4_2() {
395 assert_eq!(
396 F::div(&F::from_base_type(4), &F::from_base_type(2)).unwrap(),
397 2
398 )
399 }
400
401 #[test]
403 fn div_4_3() {
404 assert_eq!(
406 F::div(&F::from_base_type(4), &F::from_base_type(3)).unwrap(),
407 12297829379609722882
408 )
409 }
410
411 #[test]
412 fn two_plus_its_additive_inv_is_0() {
413 let two = F::from_base_type(2);
414
415 assert_eq!(F::add(&two, &F::neg(&two)), F::zero())
416 }
417
418 #[test]
419 fn from_u64_test() {
420 let num = F::from_u64(1u64);
421 assert_eq!(num, F::one());
422 }
423
424 #[test]
425 fn from_u64_zero_test() {
426 let num = F::from_u64(0);
427 assert_eq!(num, F::zero());
428 }
429
430 #[test]
431 fn from_u64_max_test() {
432 let num = F::from_u64(u64::MAX);
433 assert_eq!(num, u32::MAX as u64 - 1);
434 }
435
436 #[test]
437 fn from_u64_order_test() {
438 let num = F::from_u64(F::ORDER);
439 assert_eq!(num, F::zero());
440 }
441
442 #[test]
443 fn creating_a_field_element_from_its_representative_returns_the_same_element_1() {
444 let change = 1;
445 let f1 = F::from_base_type(F::ORDER + change);
446 let f2 = F::from_base_type(F::representative(&f1));
447 assert_eq!(f1, f2);
448 }
449
450 #[test]
451 fn reduct_128() {
452 let x = u128::MAX;
453 let y = reduce_128(x);
454 let expected_result = F::neg(&F::add(&F::from_base_type(2_u64.pow(32)), &F::one()));
463 assert_eq!(y, expected_result);
464 }
465
466 #[test]
467 fn u64_max_as_representative_less_than_u32_max_sub_1() {
468 let f = F::from_base_type(u64::MAX);
469 assert_eq!(F::representative(&f), u32::MAX as u64 - 1)
470 }
471
472 #[test]
473 fn creating_a_field_element_from_its_representative_returns_the_same_element_2() {
474 let change = 8;
475 let f1 = F::from_base_type(F::ORDER + change);
476 let f2 = F::from_base_type(F::representative(&f1));
477 assert_eq!(f1, f2);
478 }
479
480 #[test]
481 fn from_base_type_test() {
482 let b = F::from_base_type(1u64);
483 assert_eq!(b, F::one());
484 }
485
486 #[cfg(feature = "std")]
487 #[test]
488 fn to_hex_test() {
489 let num = F::from_hex("B").unwrap();
490 assert_eq!(F::to_hex(&num), "B");
491 }
492}