Skip to main content

primitives/algebra/field/
field_element.rs

1use std::{
2    iter::{Product, Sum},
3    mem::MaybeUninit,
4    ops::{Add, AddAssign, Div, Mul, MulAssign, Neg, Sub, SubAssign},
5};
6
7use derive_more::derive::{AsMut, AsRef};
8use ff::Field;
9use hybrid_array::Array;
10use num_traits::{One, Zero};
11use rand::RngCore;
12use serde::{Deserialize, Serialize};
13use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
14
15use crate::{
16    algebra::{
17        field::{ByteSize, FieldExtension, PrimeFieldExtension, SubfieldElement},
18        ops::{AccReduce, DefaultDotProduct, IntoWide, MulAccReduce, ReduceWide},
19        uniform_bytes::FromUniformBytes,
20    },
21    errors::PrimitiveError,
22    random::{CryptoRngCore, Random, RandomNonZero},
23    sharing::unauthenticated::AdditiveShares,
24    utils::codec::InPlaceCodec,
25};
26
27/// A field element wrapper.
28#[derive(
29    Copy, Clone, Debug, PartialOrd, PartialEq, Eq, Hash, AsRef, AsMut, Serialize, Deserialize,
30)]
31#[serde(bound = "F: FieldExtension")]
32#[repr(transparent)]
33pub struct FieldElement<F: FieldExtension>(pub F);
34
35// SAFETY: FieldElement<F> is #[repr(transparent)] over F.
36unsafe impl<F: FieldExtension> bytemuck::TransparentWrapper<F> for FieldElement<F> {}
37
38// SAFETY: `FieldElement<F>` is a transparent wrapper over `F`; its encoding is exactly `F`'s
39// `InPlaceCodec` encoding, which is architecture-independent, initializes every byte, and
40// round-trips unbiasedly.
41unsafe impl<F: FieldExtension + InPlaceCodec> InPlaceCodec for FieldElement<F> {
42    const ENCODED_SIZE: usize = F::ENCODED_SIZE;
43
44    fn write_le_bytes(&self, out: &mut [MaybeUninit<u8>]) {
45        self.0.write_le_bytes(out);
46    }
47
48    fn read_le_bytes(bytes: &[u8]) -> Result<Self, PrimitiveError> {
49        F::read_le_bytes(bytes).map(FieldElement)
50    }
51
52    const PACK: usize = F::PACK;
53    const PACK_BYTES: usize = F::PACK_BYTES;
54
55    fn write_pack(items: &[Self], out: &mut [MaybeUninit<u8>]) {
56        let items: &[F] = bytemuck::TransparentWrapper::peel_slice(items);
57        F::write_pack(items, out);
58    }
59
60    fn read_pack(bytes: &[u8], out: &mut [MaybeUninit<Self>]) -> Result<(), PrimitiveError> {
61        // SAFETY: see the impl-level safety comment above.
62        let out: &mut [MaybeUninit<F>] =
63            unsafe { std::slice::from_raw_parts_mut(out.as_mut_ptr().cast(), out.len()) };
64        F::read_pack(bytes, out)
65    }
66}
67
68impl<F: FieldExtension> FieldElement<F> {
69    /// Construct a field element wrapper from an inner field element
70    #[inline]
71    pub fn new(inner: F) -> Self {
72        FieldElement(inner)
73    }
74
75    /// Get the inner value of the field element
76    #[inline]
77    pub fn inner(&self) -> F {
78        self.0
79    }
80
81    /// Compute the exponentiation of the given field element
82    #[inline]
83    pub fn pow(&self, exp: u64) -> Self {
84        FieldElement::new(self.0.pow([exp]))
85    }
86
87    /// Construct a field element from the given bytes
88    #[inline]
89    pub fn from_be_bytes(bytes: &[u8]) -> Result<FieldElement<F>, PrimitiveError> {
90        let mut bytes = bytes.to_vec();
91        bytes.reverse();
92        Ok(FieldElement(F::from_le_bytes(&bytes).ok_or_else(|| {
93            PrimitiveError::DeserializationFailed("Invalid field element encoding".to_string())
94        })?))
95    }
96
97    pub fn from_le_bytes(bytes: &[u8]) -> Result<FieldElement<F>, PrimitiveError> {
98        Ok(FieldElement(F::from_le_bytes(bytes).ok_or_else(|| {
99            PrimitiveError::DeserializationFailed("Invalid field element encoding".to_string())
100        })?))
101    }
102
103    /// Convert the field element to little-endian bytes
104    #[inline]
105    pub fn to_le_bytes(&self) -> Array<u8, ByteSize<F>> {
106        self.0.to_le_bytes()
107    }
108
109    /// Convert the field element to big-endian bytes
110    #[inline]
111    pub fn to_be_bytes(&self) -> Array<u8, ByteSize<F>> {
112        let mut rev = self.0.to_le_bytes();
113        rev.as_mut_slice().reverse();
114        rev
115    }
116
117    pub fn to_biguint(&self) -> num_bigint::BigUint {
118        num_bigint::BigUint::from_bytes_le(self.to_le_bytes().as_ref())
119    }
120}
121
122impl<F: FieldExtension> Random for FieldElement<F> {
123    #[inline]
124    fn random(rng: impl CryptoRngCore) -> Self {
125        FieldElement(Random::random(rng))
126    }
127}
128
129impl<F: FieldExtension> RandomNonZero for FieldElement<F> {
130    fn random_non_zero(mut rng: impl CryptoRngCore) -> Result<Self, PrimitiveError> {
131        Ok(FieldElement(F::random_non_zero(&mut rng)?))
132    }
133}
134
135impl<F: FieldExtension> Default for FieldElement<F> {
136    fn default() -> Self {
137        Self::zero()
138    }
139}
140
141// --------------
142// | Arithmetic |
143// --------------
144
145// === Addition === //
146
147#[macros::op_variants(owned, borrowed, flipped_commutative)]
148impl<F: FieldExtension> Add<&FieldElement<F>> for FieldElement<F> {
149    type Output = FieldElement<F>;
150
151    #[inline]
152    fn add(self, rhs: &FieldElement<F>) -> Self::Output {
153        FieldElement(self.0 + rhs.0)
154    }
155}
156
157#[macros::op_variants(owned)]
158impl<'a, F: FieldExtension> AddAssign<&'a FieldElement<F>> for FieldElement<F> {
159    #[inline]
160    fn add_assign(&mut self, rhs: &'a FieldElement<F>) {
161        *self = *self + rhs;
162    }
163}
164
165// === Subtraction === //
166
167#[macros::op_variants(owned, borrowed, flipped)]
168impl<F: FieldExtension> Sub<&FieldElement<F>> for FieldElement<F> {
169    type Output = FieldElement<F>;
170
171    #[inline]
172    fn sub(self, rhs: &FieldElement<F>) -> Self::Output {
173        FieldElement(self.0 - rhs.0)
174    }
175}
176
177#[macros::op_variants(owned)]
178impl<'a, F: FieldExtension> SubAssign<&'a FieldElement<F>> for FieldElement<F> {
179    #[inline]
180    fn sub_assign(&mut self, rhs: &'a FieldElement<F>) {
181        *self = *self - rhs;
182    }
183}
184
185// === Multiplication === //
186
187#[macros::op_variants(owned, borrowed, flipped_commutative)]
188impl<F: FieldExtension> Mul<&FieldElement<F>> for FieldElement<F> {
189    type Output = FieldElement<F>;
190
191    #[inline]
192    fn mul(self, rhs: &FieldElement<F>) -> Self::Output {
193        FieldElement(self.0 * rhs.0)
194    }
195}
196
197#[macros::op_variants(owned, borrowed, flipped)]
198impl<F: FieldExtension> Mul<&SubfieldElement<F>> for FieldElement<F> {
199    type Output = FieldElement<F>;
200
201    #[inline]
202    fn mul(self, rhs: &SubfieldElement<F>) -> Self::Output {
203        FieldElement(self.0 * rhs.0)
204    }
205}
206
207#[macros::op_variants(owned)]
208impl<'a, F: FieldExtension> MulAssign<&'a FieldElement<F>> for FieldElement<F> {
209    #[inline]
210    fn mul_assign(&mut self, rhs: &'a FieldElement<F>) {
211        *self = *self * rhs;
212    }
213}
214
215#[macros::op_variants(owned)]
216impl<'a, F: FieldExtension> MulAssign<&'a SubfieldElement<F>> for FieldElement<F> {
217    #[inline]
218    fn mul_assign(&mut self, rhs: &'a SubfieldElement<F>) {
219        *self = *self * rhs;
220    }
221}
222
223// === Negation === //
224
225#[macros::op_variants(borrowed)]
226impl<F: FieldExtension> Neg for FieldElement<F> {
227    type Output = FieldElement<F>;
228
229    #[inline]
230    fn neg(self) -> Self::Output {
231        FieldElement(-self.0)
232    }
233}
234
235// === Division === //
236
237#[macros::op_variants(owned, borrowed, flipped)]
238impl<F: FieldExtension> Div<&FieldElement<F>> for FieldElement<F> {
239    type Output = CtOption<FieldElement<F>>;
240
241    #[inline]
242    fn div(self, rhs: &FieldElement<F>) -> Self::Output {
243        rhs.0.invert().map(|inv| FieldElement(self.0 * inv))
244    }
245}
246
247// === Equality === //
248
249impl<F: FieldExtension> ConstantTimeEq for FieldElement<F> {
250    #[inline]
251    fn ct_eq(&self, other: &Self) -> Choice {
252        self.0.ct_eq(&other.0)
253    }
254}
255
256impl<F: FieldExtension> ConditionallySelectable for FieldElement<F> {
257    #[inline]
258    fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
259        let selected = F::conditional_select(&a.0, &b.0, choice);
260        FieldElement(selected)
261    }
262}
263
264// === Other === //
265
266impl<F: FieldExtension> AdditiveShares for FieldElement<F> {}
267
268// ---------------
269// | Conversions |
270// ---------------
271
272impl<F: FieldExtension> From<bool> for FieldElement<F> {
273    #[inline]
274    fn from(value: bool) -> Self {
275        FieldElement(F::from(value as u64))
276    }
277}
278
279impl<F: FieldExtension> From<u8> for FieldElement<F> {
280    #[inline]
281    fn from(value: u8) -> Self {
282        FieldElement(F::from(value as u64))
283    }
284}
285
286impl<F: FieldExtension> From<u16> for FieldElement<F> {
287    #[inline]
288    fn from(value: u16) -> Self {
289        FieldElement(F::from(value as u64))
290    }
291}
292
293impl<F: FieldExtension> From<u32> for FieldElement<F> {
294    #[inline]
295    fn from(value: u32) -> Self {
296        FieldElement(F::from(value as u64))
297    }
298}
299
300impl<F: FieldExtension> From<u64> for FieldElement<F> {
301    #[inline]
302    fn from(value: u64) -> Self {
303        FieldElement(F::from(value))
304    }
305}
306
307impl<F: FieldExtension> From<u128> for FieldElement<F> {
308    #[inline]
309    fn from(value: u128) -> Self {
310        FieldElement(F::from(value))
311    }
312}
313
314impl<F: PrimeFieldExtension> From<SubfieldElement<F>> for FieldElement<F> {
315    #[inline]
316    fn from(value: SubfieldElement<F>) -> Self {
317        FieldElement(value.0)
318    }
319}
320
321// -------------------
322// | Iterator Traits |
323// -------------------
324impl<F: FieldExtension> Sum for FieldElement<F> {
325    #[inline]
326    fn sum<I: Iterator<Item = FieldElement<F>>>(iter: I) -> Self {
327        let tmp = iter.fold(<F as AccReduce>::zero_wide(), |mut acc, x| {
328            F::acc(&mut acc, x.0);
329            acc
330        });
331
332        FieldElement(F::reduce_mod_order(tmp))
333    }
334}
335
336impl<'a, F: FieldExtension> Sum<&'a FieldElement<F>> for FieldElement<F> {
337    #[inline]
338    fn sum<I: Iterator<Item = &'a FieldElement<F>>>(iter: I) -> Self {
339        let tmp = iter.fold(<F as AccReduce>::zero_wide(), |mut acc, x| {
340            F::acc(&mut acc, x.0);
341            acc
342        });
343
344        FieldElement(F::reduce_mod_order(tmp))
345    }
346}
347
348impl<F: FieldExtension> Product for FieldElement<F> {
349    #[inline]
350    fn product<I: Iterator<Item = FieldElement<F>>>(iter: I) -> Self {
351        iter.fold(FieldElement::one(), |acc, x| acc * x)
352    }
353}
354
355impl<'a, F: FieldExtension> Product<&'a FieldElement<F>> for FieldElement<F> {
356    #[inline]
357    fn product<I: Iterator<Item = &'a FieldElement<F>>>(iter: I) -> Self {
358        iter.fold(FieldElement::one(), |acc, x| acc * x)
359    }
360}
361
362impl<F: FieldExtension> FromUniformBytes for FieldElement<F> {
363    type UniformBytes = <F as FromUniformBytes>::UniformBytes;
364
365    fn from_uniform_bytes(bytes: &Array<u8, Self::UniformBytes>) -> Self {
366        Self(F::from_uniform_bytes(bytes))
367    }
368}
369
370// Dot product: FieldElement<F> x FieldElement<F>
371impl<F: FieldExtension> IntoWide<<F as MulAccReduce>::WideType> for FieldElement<F> {
372    #[inline]
373    fn to_wide(&self) -> <F as MulAccReduce>::WideType {
374        <F as MulAccReduce>::to_wide(&self.0)
375    }
376
377    #[inline]
378    fn zero_wide() -> <F as MulAccReduce>::WideType {
379        <F as MulAccReduce>::zero_wide()
380    }
381}
382
383impl<F: FieldExtension> ReduceWide<<F as MulAccReduce>::WideType> for FieldElement<F> {
384    #[inline]
385    fn reduce_mod_order(a: <F as MulAccReduce>::WideType) -> Self {
386        Self(F::reduce_mod_order(a))
387    }
388}
389
390impl<F: FieldExtension> MulAccReduce for FieldElement<F> {
391    type WideType = <F as MulAccReduce>::WideType;
392
393    #[inline]
394    fn mul_acc(acc: &mut Self::WideType, a: Self, b: Self) {
395        F::mul_acc(acc, a.0, b.0);
396    }
397}
398
399impl<F: FieldExtension> DefaultDotProduct for FieldElement<F> {}
400
401// Dot product: &FieldElement<F> x FieldElement<F>
402impl<'a, F: FieldExtension> MulAccReduce<&'a Self, Self> for FieldElement<F> {
403    type WideType = <F as MulAccReduce>::WideType;
404
405    #[inline]
406    fn mul_acc(acc: &mut Self::WideType, a: &'a Self, b: Self) {
407        F::mul_acc(acc, a.0, b.0);
408    }
409}
410
411impl<F: FieldExtension> DefaultDotProduct<&Self, Self> for FieldElement<F> {}
412
413// Dot product: FieldElement<F> x &FieldElement<F>
414impl<'a, F: FieldExtension> MulAccReduce<Self, &'a Self> for FieldElement<F> {
415    type WideType = <F as MulAccReduce>::WideType;
416
417    #[inline]
418    fn mul_acc(acc: &mut Self::WideType, a: Self, b: &'a Self) {
419        F::mul_acc(acc, a.0, b.0);
420    }
421}
422
423impl<F: FieldExtension> DefaultDotProduct<Self, &Self> for FieldElement<F> {}
424
425// Dot product: &FieldElement<F> x &FieldElement<F>
426impl<'a, 'b, F: FieldExtension> MulAccReduce<&'a Self, &'b Self> for FieldElement<F> {
427    type WideType = <F as MulAccReduce>::WideType;
428
429    #[inline]
430    fn mul_acc(acc: &mut Self::WideType, a: &'a Self, b: &'b Self) {
431        F::mul_acc(acc, a.0, b.0);
432    }
433}
434
435impl<F: FieldExtension> DefaultDotProduct<&Self, &Self> for FieldElement<F> {}
436
437// ----------------
438// | Zero and One |
439// ----------------
440
441impl<F: FieldExtension> Zero for FieldElement<F> {
442    /// The field's additive identity.
443    fn zero() -> Self {
444        FieldElement(F::ZERO)
445    }
446
447    fn is_zero(&self) -> bool {
448        self.0.is_zero().into()
449    }
450}
451
452impl<F: FieldExtension> One for FieldElement<F> {
453    /// The field's multiplicative identity.
454    fn one() -> Self {
455        FieldElement(F::ONE)
456    }
457}
458
459// ---------------
460// | Field trait |
461// ---------------
462
463impl<F: FieldExtension> Field for FieldElement<F> {
464    const ZERO: Self = FieldElement(F::ZERO);
465    const ONE: Self = FieldElement(F::ONE);
466
467    fn random(rng: impl RngCore) -> Self {
468        Self(<F as Field>::random(rng))
469    }
470
471    fn square(&self) -> Self {
472        FieldElement(self.0.square())
473    }
474
475    fn double(&self) -> Self {
476        FieldElement(self.0.double())
477    }
478
479    fn invert(&self) -> CtOption<Self> {
480        self.0.invert().map(FieldElement)
481    }
482
483    fn sqrt_ratio(num: &Self, div: &Self) -> (Choice, Self) {
484        let (choice, sqrt) = F::sqrt_ratio(&num.0, &div.0);
485        (choice, FieldElement(sqrt))
486    }
487}
488
489#[cfg(test)]
490mod tests {
491    use super::*;
492    use crate::{algebra::field::mersenne::Mersenne107, utils::codec::bincode_io};
493
494    #[test]
495    fn test_fieldelement_mersenne107_bincode() {
496        let elem = FieldElement::<Mersenne107>::new(Mersenne107::from(42u64));
497        let bytes = bincode_io::serialize(&elem).unwrap();
498
499        let decoded: FieldElement<Mersenne107> = bincode_io::deserialize(&bytes).unwrap();
500
501        assert_eq!(elem, decoded);
502    }
503}