p3_field/field.rs
1use alloc::vec;
2use alloc::vec::Vec;
3use core::fmt::{Debug, Display};
4use core::hash::Hash;
5use core::iter::{Product, Sum};
6use core::ops::{Add, AddAssign, Div, Mul, MulAssign, Neg, Sub, SubAssign};
7use core::slice;
8
9use itertools::Itertools;
10use num_bigint::BigUint;
11use num_traits::One;
12use nums::{Factorizer, FactorizerFromSplitter, MillerRabin, PollardRho};
13use serde::de::DeserializeOwned;
14use serde::Serialize;
15
16use crate::exponentiation::exp_u64_by_squaring;
17use crate::packed::{PackedField, PackedValue};
18use crate::Packable;
19
20/// A commutative algebra over a finite field.
21///
22/// This permits elements like:
23/// - an actual field element
24/// - a symbolic expression which would evaluate to a field element
25/// - an array of field elements
26///
27/// Mathematically speaking, this is an algebraic structure with addition,
28/// multiplication and scalar multiplication. The addition and multiplication
29/// maps must be both commutative and associative, and there must
30/// exist identity elements for both (named `ZERO` and `ONE`
31/// respectively). Furthermore, multiplication must distribute over
32/// addition. Finally, the scalar multiplication must be realized by
33/// a ring homomorphism from the field to the algebra.
34pub trait FieldAlgebra:
35 Sized
36 + Default
37 + Clone
38 + Add<Output = Self>
39 + AddAssign
40 + Sub<Output = Self>
41 + SubAssign
42 + Neg<Output = Self>
43 + Mul<Output = Self>
44 + MulAssign
45 + Sum
46 + Product
47 + Debug
48{
49 type F: Field;
50
51 /// The additive identity of the algebra.
52 ///
53 /// For every element `a` in the algebra we require the following properties:
54 ///
55 /// `a + ZERO = ZERO + a = a,`
56 ///
57 /// `a + (-a) = (-a) + a = ZERO.`
58 const ZERO: Self;
59
60 /// The multiplicative identity of the Algebra
61 ///
62 /// For every element `a` in the algebra we require the following property:
63 ///
64 /// `a*ONE = ONE*a = a.`
65 const ONE: Self;
66
67 /// The element in the algebra given by `ONE + ONE`.
68 ///
69 /// This is provided as a convenience as `TWO` occurs regularly in
70 /// the proving system. This also is slightly faster than computing
71 /// it via addition. Note that multiplication by `TWO` is discouraged.
72 /// Instead of `a * TWO` use `a.double()` which will be faster.
73 ///
74 /// If the field has characteristic 2 this is equal to ZERO.
75 const TWO: Self;
76
77 /// The element in the algebra given by `-ONE`.
78 ///
79 /// This is provided as a convenience as `NEG_ONE` occurs regularly in
80 /// the proving system. This also is slightly faster than computing
81 /// it via negation. Note that where possible `NEG_ONE` should be absorbed
82 /// into mathematical operations. For example `a - b` will be faster
83 /// than `a + NEG_ONE * b` and similarly `(-b)` is faster than `NEG_ONE * b`.
84 ///
85 /// If the field has characteristic 2 this is equal to ONE.
86 const NEG_ONE: Self;
87
88 /// Interpret a field element as a commutative algebra element.
89 ///
90 /// Mathematically speaking, this map is a ring homomorphism from the base field
91 /// to the commutative algebra. The existence of this map makes this structure
92 /// an algebra and not simply a commutative ring.
93 fn from_f(f: Self::F) -> Self;
94
95 /// Convert from a `bool`.
96 fn from_bool(b: bool) -> Self {
97 if b {
98 Self::ONE
99 } else {
100 Self::ZERO
101 }
102 }
103
104 /// Convert from a canonical `u8`.
105 ///
106 /// If the input is not canonical, i.e. if it exceeds the field's characteristic, then the
107 /// behavior is undefined.
108 fn from_canonical_u8(n: u8) -> Self;
109
110 /// Convert from a canonical `u16`.
111 ///
112 /// If the input is not canonical, i.e. if it exceeds the field's characteristic, then the
113 /// behavior is undefined.
114 fn from_canonical_u16(n: u16) -> Self;
115
116 /// Convert from a canonical `u32`.
117 ///
118 /// If the input is not canonical, i.e. if it exceeds the field's characteristic, then the
119 /// behavior is undefined.
120 fn from_canonical_u32(n: u32) -> Self;
121
122 /// Convert from a canonical `u64`.
123 ///
124 /// If the input is not canonical, i.e. if it exceeds the field's characteristic, then the
125 /// behavior is undefined.
126 fn from_canonical_u64(n: u64) -> Self;
127
128 /// Convert from a canonical `usize`.
129 ///
130 /// If the input is not canonical, i.e. if it exceeds the field's characteristic, then the
131 /// behavior is undefined.
132 fn from_canonical_usize(n: usize) -> Self;
133
134 fn from_wrapped_u32(n: u32) -> Self;
135 fn from_wrapped_u64(n: u64) -> Self;
136
137 /// The elementary function `double(a) = 2*a`.
138 ///
139 /// This function should be preferred over calling `a + a` or `TWO * a` as a faster implementation may be available for some algebras.
140 /// If the field has characteristic 2 then this returns 0.
141 #[must_use]
142 fn double(&self) -> Self {
143 self.clone() + self.clone()
144 }
145
146 /// The elementary function `square(a) = a^2`.
147 ///
148 /// This function should be preferred over calling `a * a`, as a faster implementation may be available for some algebras.
149 #[must_use]
150 fn square(&self) -> Self {
151 self.clone() * self.clone()
152 }
153
154 /// The elementary function `cube(a) = a^3`.
155 ///
156 /// This function should be preferred over calling `a * a * a`, as a faster implementation may be available for some algebras.
157 #[must_use]
158 fn cube(&self) -> Self {
159 self.square() * self.clone()
160 }
161
162 /// Exponentiation by a `u64` power.
163 ///
164 /// The default implementation calls `exp_u64_generic`, which by default performs exponentiation
165 /// by squaring. Rather than override this method, it is generally recommended to have the
166 /// concrete field type override `exp_u64_generic`, so that any optimizations will apply to all
167 /// abstract fields.
168 #[must_use]
169 #[inline]
170 fn exp_u64(&self, power: u64) -> Self {
171 Self::F::exp_u64_generic(self.clone(), power)
172 }
173
174 /// Exponentiation by a constant power.
175 ///
176 /// For a collection of small values we implement custom multiplication chain circuits which can be faster than the
177 /// simpler square and multiply approach.
178 #[must_use]
179 #[inline(always)]
180 fn exp_const_u64<const POWER: u64>(&self) -> Self {
181 match POWER {
182 0 => Self::ONE,
183 1 => self.clone(),
184 2 => self.square(),
185 3 => self.cube(),
186 4 => self.square().square(),
187 5 => self.square().square() * self.clone(),
188 6 => self.square().cube(),
189 7 => {
190 let x2 = self.square();
191 let x3 = x2.clone() * self.clone();
192 let x4 = x2.square();
193 x3 * x4
194 }
195 _ => self.exp_u64(POWER),
196 }
197 }
198
199 /// Compute self^{2^power_log} by repeated squaring.
200 #[must_use]
201 fn exp_power_of_2(&self, power_log: usize) -> Self {
202 let mut res = self.clone();
203 for _ in 0..power_log {
204 res = res.square();
205 }
206 res
207 }
208
209 /// self * 2^exp
210 #[must_use]
211 #[inline]
212 fn mul_2exp_u64(&self, exp: u64) -> Self {
213 self.clone() * Self::TWO.exp_u64(exp)
214 }
215
216 /// Construct an iterator which returns powers of `self: self^0, self^1, self^2, ...`.
217 #[must_use]
218 fn powers(&self) -> Powers<Self> {
219 self.shifted_powers(Self::ONE)
220 }
221
222 /// Construct an iterator which returns powers of `self` shifted by `start: start, start*self^1, start*self^2, ...`.
223 fn shifted_powers(&self, start: Self) -> Powers<Self> {
224 Powers {
225 base: self.clone(),
226 current: start,
227 }
228 }
229
230 /// Construct an iterator which returns powers of `self` packed into `PackedField` elements.
231 ///
232 /// E.g. if `PACKING::WIDTH = 4` this returns the elements:
233 /// `[self^0, self^1, self^2, self^3], [self^4, self^5, self^6, self^7], ...`.
234 fn powers_packed<P: PackedField<Scalar = Self>>(&self) -> Powers<P> {
235 self.shifted_powers_packed(Self::ONE)
236 }
237
238 /// Construct an iterator which returns powers of `self` shifted by start
239 /// and packed into `PackedField` elements.
240 ///
241 /// E.g. if `PACKING::WIDTH = 4` this returns the elements:
242 /// `[start, start*self, start*self^2, start*self^3], [start*self^4, start*self^5, start*self^6, start*self^7], ...`.
243 fn shifted_powers_packed<P: PackedField<Scalar = Self>>(&self, start: Self) -> Powers<P> {
244 let mut current = P::from_f(start);
245 let slice = current.as_slice_mut();
246 for i in 1..P::WIDTH {
247 slice[i] = slice[i - 1].clone() * self.clone();
248 }
249
250 Powers {
251 base: P::from_f(self.clone()).exp_u64(P::WIDTH as u64),
252 current,
253 }
254 }
255
256 /// Compute the dot product of two vectors.
257 fn dot_product<const N: usize>(u: &[Self; N], v: &[Self; N]) -> Self {
258 u.iter().zip(v).map(|(x, y)| x.clone() * y.clone()).sum()
259 }
260
261 /// Allocates a vector of zero elements of length `len`. Many operating systems zero pages
262 /// before assigning them to a userspace process. In that case, our process should not need to
263 /// write zeros, which would be redundant. However, the compiler may not always recognize this.
264 ///
265 /// In particular, `vec![Self::ZERO; len]` appears to result in redundant userspace zeroing.
266 /// This is the default implementation, but implementors may wish to provide their own
267 /// implementation which transmutes something like `vec![0u32; len]`.
268 #[inline]
269 fn zero_vec(len: usize) -> Vec<Self> {
270 vec![Self::ZERO; len]
271 }
272}
273
274/// An element of a finite field.
275pub trait Field:
276 FieldAlgebra<F = Self>
277 + Packable
278 + 'static
279 + Copy
280 + Div<Self, Output = Self>
281 + Eq
282 + Hash
283 + Send
284 + Sync
285 + Display
286 + Serialize
287 + DeserializeOwned
288{
289 type Packing: PackedField<Scalar = Self>;
290
291 /// A generator of this field's entire multiplicative group.
292 const GENERATOR: Self;
293
294 fn is_zero(&self) -> bool {
295 *self == Self::ZERO
296 }
297
298 fn is_one(&self) -> bool {
299 *self == Self::ONE
300 }
301
302 /// self / 2^exp
303 #[must_use]
304 #[inline]
305 fn div_2exp_u64(&self, exp: u64) -> Self {
306 *self / Self::TWO.exp_u64(exp)
307 }
308
309 /// Exponentiation by a `u64` power. This is similar to `exp_u64`, but more general in that it
310 /// can be used with `FieldAlgebra`s, not just this concrete field.
311 ///
312 /// The default implementation uses naive square and multiply. Implementations may want to
313 /// override this and handle certain powers with more optimal addition chains.
314 #[must_use]
315 #[inline]
316 fn exp_u64_generic<FA: FieldAlgebra<F = Self>>(val: FA, power: u64) -> FA {
317 exp_u64_by_squaring(val, power)
318 }
319
320 /// The multiplicative inverse of this field element, if it exists.
321 ///
322 /// NOTE: The inverse of `0` is undefined and will return `None`.
323 #[must_use]
324 fn try_inverse(&self) -> Option<Self>;
325
326 #[must_use]
327 fn inverse(&self) -> Self {
328 self.try_inverse().expect("Tried to invert zero")
329 }
330
331 /// Computes input/2.
332 /// Should be overwritten by most field implementations to use bitshifts.
333 /// Will error if the field characteristic is 2.
334 #[must_use]
335 fn halve(&self) -> Self {
336 let half = Self::TWO
337 .try_inverse()
338 .expect("Cannot divide by 2 in fields with characteristic 2");
339 *self * half
340 }
341
342 fn order() -> BigUint;
343
344 /// A list of (factor, exponent) pairs.
345 fn multiplicative_group_factors() -> Vec<(BigUint, usize)> {
346 let primality_test = MillerRabin { error_bits: 128 };
347 let composite_splitter = PollardRho;
348 let factorizer = FactorizerFromSplitter {
349 primality_test,
350 composite_splitter,
351 };
352 let n = Self::order() - BigUint::one();
353 factorizer.factor_counts(&n)
354 }
355
356 #[inline]
357 fn bits() -> usize {
358 Self::order().bits() as usize
359 }
360}
361
362pub trait PrimeField: Field + Ord {
363 fn as_canonical_biguint(&self) -> BigUint;
364}
365
366/// A prime field of order less than `2^64`.
367pub trait PrimeField64: PrimeField {
368 const ORDER_U64: u64;
369
370 /// Return the representative of `value` that is less than `ORDER_U64`.
371 fn as_canonical_u64(&self) -> u64;
372
373 /// Convert a field element to a `u64` such that any two field elements
374 /// are converted to the same `u64` if and only if they represent the same value.
375 ///
376 /// This will be the fastest way to convert a field element to a `u64` and
377 /// is intended for use in hashing. It will also be consistent across different targets.
378 fn to_unique_u64(&self) -> u64 {
379 // A simple default which is optimal for some fields.
380 self.as_canonical_u64()
381 }
382}
383
384/// A prime field of order less than `2^32`.
385pub trait PrimeField32: PrimeField64 {
386 const ORDER_U32: u32;
387
388 /// Return the representative of `value` that is less than `ORDER_U32`.
389 fn as_canonical_u32(&self) -> u32;
390
391 /// Convert a field element to a `u32` such that any two field elements
392 /// are converted to the same `u32` if and only if they represent the same value.
393 ///
394 /// This will be the fastest way to convert a field element to a `u32` and
395 /// is intended for use in hashing. It will also be consistent across different targets.
396 fn to_unique_u32(&self) -> u32 {
397 // A simple default which is optimal for some fields.
398 self.as_canonical_u32()
399 }
400}
401
402/// A commutative algebra over an extension field.
403///
404/// Mathematically, this trait captures a slightly more interesting structure than the above one liner.
405/// As implemented here, A FieldExtensionAlgebra `FEA` over and extension field `EF` is
406/// really the result of applying extension of scalars to a FieldAlgebra `FA` to lift `FA`
407/// from an algebra over `F` to an algebra over `EF` and so `FEA = EF ⊗ FA` where the tensor
408/// product is over `F`.
409pub trait FieldExtensionAlgebra<Base: FieldAlgebra>:
410 FieldAlgebra
411 + From<Base>
412 + Add<Base, Output = Self>
413 + AddAssign<Base>
414 + Sub<Base, Output = Self>
415 + SubAssign<Base>
416 + Mul<Base, Output = Self>
417 + MulAssign<Base>
418{
419 const D: usize;
420
421 fn from_base(b: Base) -> Self;
422
423 /// Suppose this field extension is represented by the quotient
424 /// ring B[X]/(f(X)) where B is `Base` and f is an irreducible
425 /// polynomial of degree `D`. This function takes a slice `bs` of
426 /// length at exactly D, and constructs the field element
427 /// \sum_i bs[i] * X^i.
428 ///
429 /// NB: The value produced by this function fundamentally depends
430 /// on the choice of irreducible polynomial f. Care must be taken
431 /// to ensure portability if these values might ever be passed to
432 /// (or rederived within) another compilation environment where a
433 /// different f might have been used.
434 fn from_base_slice(bs: &[Base]) -> Self;
435
436 /// Similar to `core:array::from_fn`, with the same caveats as
437 /// `from_base_slice`.
438 fn from_base_fn<F: FnMut(usize) -> Base>(f: F) -> Self;
439 fn from_base_iter<I: Iterator<Item = Base>>(iter: I) -> Self;
440
441 /// Suppose this field extension is represented by the quotient
442 /// ring B[X]/(f(X)) where B is `Base` and f is an irreducible
443 /// polynomial of degree `D`. This function takes a field element
444 /// \sum_i bs[i] * X^i and returns the coefficients as a slice
445 /// `bs` of length at most D containing, from lowest degree to
446 /// highest.
447 ///
448 /// NB: The value produced by this function fundamentally depends
449 /// on the choice of irreducible polynomial f. Care must be taken
450 /// to ensure portability if these values might ever be passed to
451 /// (or rederived within) another compilation environment where a
452 /// different f might have been used.
453 fn as_base_slice(&self) -> &[Base];
454
455 /// Suppose this field extension is represented by the quotient
456 /// ring B[X]/(f(X)) where B is `Base` and f is an irreducible
457 /// polynomial of degree `D`. This function returns the field
458 /// element `X^exponent` if `exponent < D` and panics otherwise.
459 /// (The fact that f is not known at the point that this function
460 /// is defined prevents implementing exponentiation of higher
461 /// powers since the reduction cannot be performed.)
462 ///
463 /// NB: The value produced by this function fundamentally depends
464 /// on the choice of irreducible polynomial f. Care must be taken
465 /// to ensure portability if these values might ever be passed to
466 /// (or rederived within) another compilation environment where a
467 /// different f might have been used.
468 fn monomial(exponent: usize) -> Self {
469 assert!(exponent < Self::D, "requested monomial of too high degree");
470 let mut vec = vec![Base::ZERO; Self::D];
471 vec[exponent] = Base::ONE;
472 Self::from_base_slice(&vec)
473 }
474}
475
476pub trait ExtensionField<Base: Field>: Field + FieldExtensionAlgebra<Base> {
477 type ExtensionPacking: FieldExtensionAlgebra<Base::Packing, F = Self>
478 + 'static
479 + Copy
480 + Send
481 + Sync;
482
483 #[inline(always)]
484 fn is_in_basefield(&self) -> bool {
485 self.as_base_slice()[1..].iter().all(Field::is_zero)
486 }
487
488 fn as_base(&self) -> Option<Base> {
489 if self.is_in_basefield() {
490 Some(self.as_base_slice()[0])
491 } else {
492 None
493 }
494 }
495
496 /// Construct an iterator which returns powers of `self` packed into `ExtensionPacking` elements.
497 ///
498 /// E.g. if `PACKING::WIDTH = 4` this returns the elements:
499 /// `[self^0, self^1, self^2, self^3], [self^4, self^5, self^6, self^7], ...`.
500 fn ext_powers_packed(&self) -> Powers<Self::ExtensionPacking> {
501 let powers = self.powers().take(Base::Packing::WIDTH + 1).collect_vec();
502 // Transpose first WIDTH powers
503 let current = Self::ExtensionPacking::from_base_fn(|i| {
504 Base::Packing::from_fn(|j| powers[j].as_base_slice()[i])
505 });
506 // Broadcast self^WIDTH
507 let multiplier = Self::ExtensionPacking::from_base_fn(|i| {
508 Base::Packing::from(powers[Base::Packing::WIDTH].as_base_slice()[i])
509 });
510
511 Powers {
512 base: multiplier,
513 current,
514 }
515 }
516}
517
518impl<F: Field> ExtensionField<F> for F {
519 type ExtensionPacking = F::Packing;
520}
521
522impl<FA: FieldAlgebra> FieldExtensionAlgebra<FA> for FA {
523 const D: usize = 1;
524
525 fn from_base(b: FA) -> Self {
526 b
527 }
528
529 fn from_base_slice(bs: &[FA]) -> Self {
530 assert_eq!(bs.len(), 1);
531 bs[0].clone()
532 }
533
534 fn from_base_iter<I: Iterator<Item = FA>>(mut iter: I) -> Self {
535 iter.next().unwrap()
536 }
537
538 fn from_base_fn<F: FnMut(usize) -> FA>(mut f: F) -> Self {
539 f(0)
540 }
541
542 #[inline(always)]
543 fn as_base_slice(&self) -> &[FA] {
544 slice::from_ref(self)
545 }
546}
547
548/// A field which supplies information like the two-adicity of its multiplicative group, and methods
549/// for obtaining two-adic generators.
550pub trait TwoAdicField: Field {
551 /// The number of factors of two in this field's multiplicative group.
552 const TWO_ADICITY: usize;
553
554 /// Returns a generator of the multiplicative group of order `2^bits`.
555 /// Assumes `bits <= TWO_ADICITY`, otherwise the result is undefined.
556 #[must_use]
557 fn two_adic_generator(bits: usize) -> Self;
558}
559
560/// An iterator which returns the powers of a base element `b` shifted by current `c`: `c, c * b, c * b^2, ...`.
561#[derive(Clone, Debug)]
562pub struct Powers<F> {
563 pub base: F,
564 pub current: F,
565}
566
567impl<FA: FieldAlgebra> Iterator for Powers<FA> {
568 type Item = FA;
569
570 fn next(&mut self) -> Option<FA> {
571 let result = self.current.clone();
572 self.current *= self.base.clone();
573 Some(result)
574 }
575}