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