binius_field/field.rs
1// Copyright 2024-2025 Irreducible Inc.
2
3use std::{
4 fmt::{Debug, Display},
5 hash::Hash,
6 iter::{Product, Sum},
7 ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
8};
9
10use binius_utils::{DeserializeBytes, SerializeBytes};
11use bytemuck::Zeroable;
12
13use crate::{
14 Random,
15 arithmetic_traits::{InvertOrZero, Square},
16};
17
18/// This trait is based on `ff::Field` with some unused functionality removed.
19pub trait Field:
20 Sized
21 + Eq
22 + Copy
23 + Clone
24 + Default
25 + Send
26 + Sync
27 + Debug
28 + Display
29 + Hash
30 + 'static
31 + FieldOps<Self>
32 + Random
33 + Zeroable
34 + SerializeBytes
35 + DeserializeBytes
36{
37 /// The zero element of the field, the additive identity.
38 const ZERO: Self;
39
40 /// The one element of the field, the multiplicative identity.
41 const ONE: Self;
42
43 /// The characteristic of the field.
44 const CHARACTERISTIC: usize;
45
46 /// Fixed generator of the multiplicative group.
47 const MULTIPLICATIVE_GENERATOR: Self;
48
49 /// Returns true iff this element is zero.
50 fn is_zero(&self) -> bool {
51 *self == Self::ZERO
52 }
53
54 /// Doubles this element.
55 #[must_use]
56 fn double(&self) -> Self;
57
58 /// Computes the multiplicative inverse of this element,
59 /// failing if the element is zero.
60 fn invert(&self) -> Option<Self> {
61 let inv = self.invert_or_zero();
62 (!inv.is_zero()).then_some(inv)
63 }
64
65 /// Exponentiates `self` by `exp`, where `exp` is a little-endian order integer
66 /// exponent.
67 ///
68 /// # Guarantees
69 ///
70 /// This operation is constant time with respect to `self`, for all exponents with the
71 /// same number of digits (`exp.as_ref().len()`). It is variable time with respect to
72 /// the number of digits in the exponent.
73 fn pow<S: AsRef<[u64]>>(&self, exp: S) -> Self {
74 let mut res = Self::ONE;
75 for e in exp.as_ref().iter().rev() {
76 for i in (0..64).rev() {
77 res = res.square();
78 let mut tmp = res;
79 tmp *= self;
80 if ((*e >> i) & 1) != 0 {
81 res = tmp;
82 }
83 }
84 }
85 res
86 }
87
88 /// Exponentiates `self` by `exp`, where `exp` is a little-endian order integer
89 /// exponent.
90 ///
91 /// # Guarantees
92 ///
93 /// **This operation is variable time with respect to `self`, for all exponent.** If
94 /// the exponent is fixed, this operation is effectively constant time. However, for
95 /// stronger constant-time guarantees, [`Field::pow`] should be used.
96 fn pow_vartime<S: AsRef<[u64]>>(&self, exp: S) -> Self {
97 let mut res = Self::ONE;
98 for e in exp.as_ref().iter().rev() {
99 for i in (0..64).rev() {
100 res = res.square();
101
102 if ((*e >> i) & 1) == 1 {
103 res.mul_assign(self);
104 }
105 }
106 }
107
108 res
109 }
110}
111
112/// Operations for types that represent vectors of field elements.
113///
114/// This trait abstracts over:
115/// - [`Field`] types (single field elements, which are trivially vectors of length 1)
116/// - [`PackedField`](crate::PackedField) types (SIMD-accelerated vectors of field elements)
117/// - Symbolic field types (for constraint system representations)
118///
119/// Mathematically, instances of this trait represent vectors of field elements where
120/// arithmetic operations like addition, subtraction, multiplication, squaring, and
121/// inversion are defined element-wise. For a packed field with width N, multiplying
122/// two values performs N independent field multiplications in parallel.
123///
124/// # Type Parameter
125///
126/// The type parameter `F` represents the scalar field type. For a `Field` implementation,
127/// `F` is `Self`. For a `PackedField` implementation, `F` is the scalar type being packed.
128///
129/// # Required Methods
130///
131/// - [`zero()`](Self::zero) - Returns the additive identity (all elements are zero)
132/// - [`one()`](Self::one) - Returns the multiplicative identity (all elements are one)
133pub trait FieldOps<F>:
134 Neg<Output = Self>
135 + Add<Output = Self>
136 + Sub<Output = Self>
137 + Mul<Output = Self>
138 + Sum
139 + Product
140 + for<'a> Add<&'a Self, Output = Self>
141 + for<'a> Sub<&'a Self, Output = Self>
142 + for<'a> Mul<&'a Self, Output = Self>
143 + for<'a> Sum<&'a Self>
144 + for<'a> Product<&'a Self>
145 + AddAssign
146 + SubAssign
147 + MulAssign
148 + for<'a> AddAssign<&'a Self>
149 + for<'a> SubAssign<&'a Self>
150 + for<'a> MulAssign<&'a Self>
151 + Mul<F, Output = Self>
152 + MulAssign<F>
153 + Square
154 + InvertOrZero
155{
156 /// Returns the zero element (additive identity).
157 fn zero() -> Self;
158
159 /// Returns the one element (multiplicative identity).
160 fn one() -> Self;
161}