primitives/algebra/field/
field_element.rs1use 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#[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
35unsafe impl<F: FieldExtension> bytemuck::TransparentWrapper<F> for FieldElement<F> {}
37
38unsafe 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 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 #[inline]
71 pub fn new(inner: F) -> Self {
72 FieldElement(inner)
73 }
74
75 #[inline]
77 pub fn inner(&self) -> F {
78 self.0
79 }
80
81 #[inline]
83 pub fn pow(&self, exp: u64) -> Self {
84 FieldElement::new(self.0.pow([exp]))
85 }
86
87 #[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 #[inline]
105 pub fn to_le_bytes(&self) -> Array<u8, ByteSize<F>> {
106 self.0.to_le_bytes()
107 }
108
109 #[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#[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#[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#[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#[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#[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
247impl<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
264impl<F: FieldExtension> AdditiveShares for FieldElement<F> {}
267
268impl<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
321impl<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
370impl<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
401impl<'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
413impl<'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
425impl<'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
437impl<F: FieldExtension> Zero for FieldElement<F> {
442 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 fn one() -> Self {
455 FieldElement(F::ONE)
456 }
457}
458
459impl<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}