primitives/algebra/field/binary/
gf2_128_field.rs1use std::{
2 iter::{Product, Sum},
3 mem::MaybeUninit,
4 ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
5};
6
7use ff::Field;
8use hybrid_array::Array;
9use rand::RngCore;
10use serde::{Deserialize, Serialize};
11use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
12use typenum::{U1, U128, U16};
13
14use crate::{
15 algebra::{
16 field::{
17 binary::{
18 gf2_ext::{Gf2LimbsWide, MulWide},
19 Gf2_128,
20 },
21 FieldExtension,
22 },
23 ops::{AccReduce, DefaultDotProduct, IntoWide, MulAccReduce, ReduceWide},
24 uniform_bytes::FromUniformBytes,
25 },
26 errors::PrimitiveError,
27 random::{CryptoRngCore, Random},
28 types::{HeapArray, Positive},
29 utils::codec::InPlaceCodec,
30};
31
32#[derive(
42 Copy, Clone, Default, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize,
43)]
44#[serde(transparent)]
45#[repr(transparent)]
46pub struct Gf2_128Field(pub Gf2_128);
47
48unsafe impl InPlaceCodec for Gf2_128Field {
51 const ENCODED_SIZE: usize = Gf2_128::ENCODED_SIZE;
52
53 fn write_le_bytes(&self, out: &mut [MaybeUninit<u8>]) {
54 self.0.write_le_bytes(out);
55 }
56
57 fn read_le_bytes(bytes: &[u8]) -> Result<Self, PrimitiveError> {
58 Gf2_128::read_le_bytes(bytes).map(Gf2_128Field)
59 }
60}
61
62#[macros::op_variants(owned)]
67impl<'a> MulAssign<&'a Gf2_128Field> for Gf2_128Field {
68 #[inline]
69 fn mul_assign(&mut self, rhs: &'a Gf2_128Field) {
70 self.0 *= rhs.0;
71 }
72}
73
74#[macros::op_variants(owned)]
75impl<'a> Mul<&'a Gf2_128Field> for Gf2_128Field {
76 type Output = Self;
77
78 #[inline]
79 fn mul(mut self, rhs: &'a Gf2_128Field) -> Self::Output {
80 self.mul_assign(rhs);
81 self
82 }
83}
84
85#[macros::op_variants(owned)]
86impl<'a> AddAssign<&'a Gf2_128Field> for Gf2_128Field {
87 #[inline]
88 fn add_assign(&mut self, rhs: &'a Gf2_128Field) {
89 self.0 += rhs.0;
90 }
91}
92
93#[macros::op_variants(owned)]
94impl<'a> Add<&'a Gf2_128Field> for Gf2_128Field {
95 type Output = Self;
96
97 #[inline]
98 fn add(mut self, rhs: &'a Gf2_128Field) -> Self::Output {
99 self.add_assign(rhs);
100 self
101 }
102}
103
104#[macros::op_variants(owned)]
105impl<'a> SubAssign<&'a Gf2_128Field> for Gf2_128Field {
106 #[inline]
107 fn sub_assign(&mut self, rhs: &'a Gf2_128Field) {
108 self.0 -= rhs.0;
109 }
110}
111
112#[macros::op_variants(owned)]
113impl<'a> Sub<&'a Gf2_128Field> for Gf2_128Field {
114 type Output = Self;
115
116 #[inline]
117 fn sub(mut self, rhs: &'a Gf2_128Field) -> Self::Output {
118 self.sub_assign(rhs);
119 self
120 }
121}
122
123#[macros::op_variants(borrowed)]
124impl Neg for Gf2_128Field {
125 type Output = Gf2_128Field;
126
127 #[inline]
128 fn neg(self) -> Self::Output {
129 self
130 }
131}
132
133impl Sum for Gf2_128Field {
134 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
135 iter.fold(<Self as Field>::ZERO, |acc, x| acc + x)
136 }
137}
138
139impl<'a> Sum<&'a Self> for Gf2_128Field {
140 fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
141 iter.fold(<Self as Field>::ZERO, |acc, x| acc + x)
142 }
143}
144
145impl Product for Gf2_128Field {
146 fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
147 iter.fold(<Self as Field>::ONE, |acc, x| acc * x)
148 }
149}
150
151impl<'a> Product<&'a Self> for Gf2_128Field {
152 fn product<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
153 iter.fold(<Self as Field>::ONE, |acc, x| acc * x)
154 }
155}
156
157impl ConditionallySelectable for Gf2_128Field {
162 #[inline]
163 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
164 Self(Gf2_128::conditional_select(&a.0, &b.0, choice))
165 }
166}
167
168impl ConstantTimeEq for Gf2_128Field {
169 #[inline]
170 fn ct_eq(&self, other: &Self) -> Choice {
171 self.0.ct_eq(&other.0)
172 }
173}
174
175impl Field for Gf2_128Field {
180 const ZERO: Self = Self(<Gf2_128 as Field>::ZERO);
181 const ONE: Self = Self(<Gf2_128 as Field>::ONE);
182
183 fn random(rng: impl RngCore) -> Self {
184 Self(<Gf2_128 as Field>::random(rng))
185 }
186
187 fn square(&self) -> Self {
188 Self(self.0.square())
189 }
190
191 fn double(&self) -> Self {
192 Self(self.0.double())
193 }
194
195 fn invert(&self) -> CtOption<Self> {
196 self.0.invert().map(Self)
197 }
198
199 fn sqrt_ratio(num: &Self, div: &Self) -> (Choice, Self) {
200 let (is_valid, root) = Gf2_128::sqrt_ratio(&num.0, &div.0);
201 (is_valid, Self(root))
202 }
203
204 fn sqrt(&self) -> CtOption<Self> {
205 self.0.sqrt().map(Self)
206 }
207}
208
209impl FieldExtension for Gf2_128Field {
210 type Subfield = Self;
211 type Degree = U1;
212 type FieldBitSize = U128;
213 type FieldBytesSize = U16;
214
215 fn to_subfield_elements(&self) -> Array<Self::Subfield, Self::Degree> {
216 Array([*self])
217 }
218
219 fn from_subfield_elements(elems: Array<Self::Subfield, Self::Degree>) -> Self {
220 elems[0]
221 }
222
223 fn to_le_bytes(&self) -> Array<u8, Self::FieldBytesSize> {
224 self.0.to_le_bytes()
225 }
226
227 fn from_le_bytes(bytes: &[u8]) -> Option<Self> {
228 Gf2_128::from_le_bytes(bytes).map(Self)
229 }
230
231 fn mul_by_subfield(&self, other: &Self::Subfield) -> Self {
232 *self * other
233 }
234
235 fn generator() -> Self {
236 Self(Gf2_128::generator())
237 }
238
239 fn linear_orthomorphism(&self) -> Self {
242 Self(self.0.linear_orthomorphism())
243 }
244}
245
246impl Random for Gf2_128Field {
247 fn random(rng: impl CryptoRngCore) -> Self {
248 Self(Random::random(rng))
249 }
250
251 fn random_array<M: Positive>(mut rng: impl CryptoRngCore) -> HeapArray<Self, M> {
252 let mut buf = HeapArray::<Self, M>::default().into_box_bytes();
253 rng.fill_bytes(&mut buf);
254 HeapArray::from_box_bytes(buf)
255 }
256}
257
258unsafe impl bytemuck::Zeroable for Gf2_128Field {}
259unsafe impl bytemuck::Pod for Gf2_128Field {}
260
261impl FromUniformBytes for Gf2_128Field {
262 type UniformBytes = U16;
263
264 fn from_uniform_bytes(bytes: &Array<u8, Self::UniformBytes>) -> Self {
265 Self(Gf2_128::from_uniform_bytes(bytes))
266 }
267}
268
269impl From<u64> for Gf2_128Field {
270 fn from(val: u64) -> Self {
271 Self(Gf2_128::from(val))
272 }
273}
274
275impl From<u128> for Gf2_128Field {
276 fn from(val: u128) -> Self {
277 Self(Gf2_128::from(val))
278 }
279}
280
281impl IntoWide<Gf2LimbsWide<2>> for Gf2_128Field {
286 #[inline]
287 fn to_wide(&self) -> Gf2LimbsWide<2> {
288 <Gf2_128 as IntoWide<Gf2LimbsWide<2>>>::to_wide(&self.0)
289 }
290
291 #[inline]
292 fn zero_wide() -> Gf2LimbsWide<2> {
293 <Gf2_128 as IntoWide<Gf2LimbsWide<2>>>::zero_wide()
294 }
295}
296
297impl ReduceWide<Gf2LimbsWide<2>> for Gf2_128Field {
298 #[inline]
299 fn reduce_mod_order(a: Gf2LimbsWide<2>) -> Self {
300 Self(Gf2_128::reduce_mod_order(a))
301 }
302}
303
304impl IntoWide for Gf2_128Field {
305 #[inline]
306 fn to_wide(&self) -> Self {
307 *self
308 }
309
310 #[inline]
311 fn zero_wide() -> Self {
312 <Self as Field>::ZERO
313 }
314}
315
316impl ReduceWide for Gf2_128Field {
317 #[inline]
318 fn reduce_mod_order(a: Self) -> Self {
319 a
320 }
321}
322
323impl MulAccReduce for Gf2_128Field {
324 type WideType = Gf2LimbsWide<2>;
325
326 #[inline]
327 fn mul_acc(acc: &mut Self::WideType, a: Self, b: Self) {
328 *acc += a.0.mul_wide(b.0);
329 }
330}
331
332impl MulAccReduce<Self, &Self> for Gf2_128Field {
333 type WideType = Gf2LimbsWide<2>;
334
335 #[inline]
336 fn mul_acc(acc: &mut Self::WideType, a: Self, b: &Self) {
337 <Self as MulAccReduce>::mul_acc(acc, a, *b);
338 }
339}
340
341impl MulAccReduce<&Self, Self> for Gf2_128Field {
342 type WideType = Gf2LimbsWide<2>;
343
344 #[inline]
345 fn mul_acc(acc: &mut Self::WideType, a: &Self, b: Self) {
346 <Self as MulAccReduce>::mul_acc(acc, *a, b);
347 }
348}
349
350impl MulAccReduce<&Self, &Self> for Gf2_128Field {
351 type WideType = Gf2LimbsWide<2>;
352
353 #[inline]
354 fn mul_acc(acc: &mut Self::WideType, a: &Self, b: &Self) {
355 <Self as MulAccReduce>::mul_acc(acc, *a, *b);
356 }
357}
358
359impl AccReduce for Gf2_128Field {
360 type WideType = Self;
361
362 #[inline]
363 fn acc(acc: &mut Self, a: Self) {
364 *acc += a;
365 }
366}
367
368impl AccReduce<&Self> for Gf2_128Field {
369 type WideType = Self;
370
371 #[inline]
372 fn acc(acc: &mut Self, a: &Self) {
373 *acc += a;
374 }
375}
376
377impl DefaultDotProduct for Gf2_128Field {}
378impl DefaultDotProduct<Self, &Self> for Gf2_128Field {}
379impl DefaultDotProduct<&Self, Self> for Gf2_128Field {}
380impl DefaultDotProduct<&Self, &Self> for Gf2_128Field {}
381
382#[cfg(test)]
383mod test {
384 use ff::Field;
385 use subtle::ConstantTimeEq;
386 use typenum::Unsigned;
387
388 use super::Gf2_128Field;
389 use crate::{
390 algebra::{field::FieldExtension, ops::DotProduct},
391 random::{test_rng, Random},
392 utils::bincode_io,
393 };
394
395 type M = typenum::U100;
396
397 #[test]
398 fn test_field_axioms() {
399 let mut rng = test_rng();
400 for _ in 0..M::to_usize() {
401 let a: Gf2_128Field = Random::random(&mut rng);
402 let b: Gf2_128Field = Random::random(&mut rng);
403
404 assert_eq!(a + a, Gf2_128Field::ZERO);
406 assert_eq!(-a, a);
407 assert_eq!(a - b, a + b);
408
409 assert_eq!(a * (a + b), a * a + a * b);
411
412 let mut cumul = a;
414 for _ in 0..128 {
415 cumul *= cumul;
416 }
417 assert_eq!(a, cumul);
418 }
419 }
420
421 #[test]
422 fn test_invert_and_sqrt() {
423 let mut rng = test_rng();
424
425 assert!(bool::from(Gf2_128Field::ZERO.invert().is_none()));
426
427 for _ in 0..M::to_usize() {
428 let a: Gf2_128Field = Random::random(&mut rng);
429 if bool::from(a.is_zero()) {
430 continue;
431 }
432 assert_eq!(a * a.invert().unwrap(), Gf2_128Field::ONE);
433
434 let root = a.sqrt().unwrap();
435 assert_eq!(root * root, a);
436
437 let (is_valid, ratio_root) = Gf2_128Field::sqrt_ratio_ext(&Gf2_128Field::ONE, &a);
438 assert!(bool::from(is_valid));
439 assert_eq!(ratio_root * ratio_root * a, Gf2_128Field::ONE);
440 }
441 }
442
443 #[test]
444 fn test_linear_orthomorphism() {
445 let mut rng = test_rng();
448 for _ in 0..M::to_usize() {
449 let a: Gf2_128Field = Random::random(&mut rng);
450 if bool::from(a.is_zero()) {
451 continue;
452 }
453 let sigma = a.linear_orthomorphism();
454 assert_ne!(sigma, Gf2_128Field::ZERO);
455 assert_ne!(sigma + a, Gf2_128Field::ZERO);
456 }
457 }
458
459 #[test]
460 fn test_byte_roundtrips() {
461 let mut rng = test_rng();
462 for _ in 0..M::to_usize() {
463 let a: Gf2_128Field = Random::random(&mut rng);
464
465 let bytes = a.to_le_bytes();
466 assert_eq!(Gf2_128Field::from_le_bytes(&bytes), Some(a));
467
468 let serialized = bincode_io::serialize(&a).unwrap();
469 assert_eq!(
470 bincode_io::deserialize::<Gf2_128Field>(&serialized).unwrap(),
471 a
472 );
473 }
474 }
475
476 #[test]
477 fn test_dot_product() {
478 let mut rng = test_rng();
479 let a = Gf2_128Field::random_array::<typenum::U13>(&mut rng);
480 let b = Gf2_128Field::random_array::<typenum::U13>(&mut rng);
481
482 let expected = a
483 .iter()
484 .zip(b.iter())
485 .fold(Gf2_128Field::ZERO, |acc, (x, y)| acc + *x * y);
486 let actual = Gf2_128Field::dot(a, b);
487 assert_eq!(expected, actual);
488
489 assert_eq!(
490 Gf2_128Field::ZERO,
491 Gf2_128Field::dot(
492 std::iter::empty::<Gf2_128Field>(),
493 std::iter::empty::<Gf2_128Field>()
494 )
495 );
496 }
497
498 #[test]
499 fn test_constant_time_eq() {
500 let a = Gf2_128Field::from(42u64);
501 assert!(bool::from(a.ct_eq(&Gf2_128Field::from(42u64))));
502 assert!(!bool::from(a.ct_eq(&Gf2_128Field::from(43u64))));
503 }
504}