Skip to main content

primitives/algebra/field/
subfield_element.rs

1use 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/// A subfield element wrapper.
43#[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
49// SAFETY: SubfieldElement<F> is #[repr(transparent)] over F::Subfield.
50unsafe impl<F: FieldExtension> bytemuck::TransparentWrapper<F::Subfield> for SubfieldElement<F> {}
51
52// SAFETY: `SubfieldElement<F>` is a transparent wrapper over `F::Subfield`; its encoding is exactly
53// `F::Subfield`'s `InPlaceCodec` encoding, which is architecture-independent, initializes every
54// byte, and round-trips unbiasedly.
55unsafe 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        // SAFETY: see the impl-level safety comment above.
79        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    /// Construct a subfield element from an inner subfield element
87    #[inline]
88    pub fn new(inner: F::Subfield) -> Self {
89        SubfieldElement(inner)
90    }
91
92    /// Get the inner value of the subfield element
93    #[inline]
94    pub fn inner(&self) -> F::Subfield {
95        self.0
96    }
97
98    /// Compute the exponentiation of the given subfield element
99    #[inline]
100    pub fn pow<S: AsRef<[u64]>>(&self, exp: S) -> Self {
101        SubfieldElement::new(self.0.pow(exp))
102    }
103
104    /// Construct a subfield element from the given bytes
105    #[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    /// Convert the subfield element to little-endian bytes
129    #[inline]
130    pub fn to_le_bytes(&self) -> Array<u8, ByteSize<F::Subfield>> {
131        self.0.to_le_bytes()
132    }
133
134    /// Convert the subfield element to big-endian bytes
135    #[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// --------------
180// | Arithmetic |
181// --------------
182
183// === Addition === //
184
185#[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// === Subtraction === //
204
205#[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// === Multiplication === //
224
225#[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// === Negation === //
254
255#[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// === Division === //
266
267#[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
277// === Equality === //
278
279impl<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
294// === Other === //
295
296impl<F: FieldExtension> AdditiveShares for SubfieldElement<F> {}
297
298// ---------------
299// | Conversions |
300// ---------------
301
302impl<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
351// -------------------
352// | Iterator Traits |
353// -------------------
354
355impl<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
399// Dot product: Subfield<F> x Subfield<F>
400impl<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
430// Dot product: &Subfield<F> x Subfield<F>
431impl<'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
442// Dot product: Subfield<F> x &Subfield<F>
443impl<'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
454// Dot product: &Subfield<F> x &Subfield<F>
455impl<'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
466// ----------------
467// | Zero and One |
468// ----------------
469
470impl<F: FieldExtension> Zero for SubfieldElement<F> {
471    /// The subfield's additive identity
472    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    /// The subfield's multiplicative identity
483    fn one() -> Self {
484        SubfieldElement(F::Subfield::ONE)
485    }
486}
487
488// ---------------
489// | Field trait |
490// ---------------
491
492impl<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}