1use core::fmt::{self, Debug, Display, Formatter};
2use core::iter::{Product, Sum};
3use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
4
5use num_bigint::BigUint;
6use p3_field::integers::QuotientMap;
7use p3_field::op_assign_macros::{
8 impl_add_assign, impl_div_methods, impl_mul_methods, impl_sub_assign, ring_sum,
9};
10use p3_field::{
11 Field, Packable, PrimeCharacteristicRing, PrimeField, PrimeField32, PrimeField64,
12 RawDataSerializable, quotient_map_large_iint, quotient_map_large_uint,
13};
14use rand::Rng;
15use rand::distr::{Distribution, StandardUniform};
16use serde::de::Error;
17use serde::{Deserialize, Deserializer, Serialize};
18
19macro_rules! characteristic_two_methods {
35 () => {
36 #[inline]
37 fn double(&self) -> Self {
38 Self::ZERO
40 }
41
42 #[inline]
45 fn halve(&self) -> Self {
46 panic!("halve is undefined in characteristic 2")
47 }
48
49 #[inline]
50 fn xor(&self, y: &Self) -> Self {
51 *self + *y
52 }
53
54 #[inline]
55 fn mul_2exp_u64(&self, exp: u64) -> Self {
56 if exp == 0 { *self } else { Self::ZERO }
57 }
58
59 #[inline]
62 fn div_2exp_u64(&self, _exp: u64) -> Self {
63 panic!("div_2exp_u64 is undefined in characteristic 2")
64 }
65 };
66}
67
68pub(crate) use characteristic_two_methods;
69
70#[derive(Copy, Clone, Default, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize)]
78#[serde(transparent)]
79#[repr(transparent)]
80#[must_use]
81pub struct Gf2(u8);
82
83impl Gf2 {
84 #[inline]
88 pub(crate) const fn new(bit: u8) -> Self {
89 Self(bit & 1)
90 }
91
92 #[inline]
94 pub(crate) const fn to_bit(self) -> u8 {
95 self.0
96 }
97
98 #[inline]
102 pub const fn from_le_bytes(bytes: [u8; 1]) -> Self {
103 Self::new(bytes[0])
104 }
105
106 #[doc(hidden)]
112 #[inline]
113 pub fn reference_mul(self, rhs: Self) -> Self {
114 self * rhs
115 }
116}
117
118impl Packable for Gf2 {}
119
120impl<'de> Deserialize<'de> for Gf2 {
121 fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
122 let val = u8::deserialize(d)?;
123 if val < 2 {
126 Ok(Self(val))
127 } else {
128 Err(D::Error::custom("Value is out of range"))
129 }
130 }
131}
132
133impl Display for Gf2 {
134 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
135 Display::fmt(&self.0, f)
136 }
137}
138
139impl Debug for Gf2 {
140 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
141 Debug::fmt(&self.0, f)
142 }
143}
144
145impl Distribution<Gf2> for StandardUniform {
146 #[inline]
147 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Gf2 {
148 Gf2::new((rng.next_u32() & 1) as u8)
149 }
150}
151
152impl PrimeCharacteristicRing for Gf2 {
153 type PrimeSubfield = Self;
154
155 const ZERO: Self = Self(0);
156 const ONE: Self = Self(1);
157 const TWO: Self = Self(0);
159 const NEG_ONE: Self = Self(1);
161
162 #[inline]
163 fn from_prime_subfield(f: Self::PrimeSubfield) -> Self {
164 f
165 }
166
167 #[inline]
168 fn from_bool(b: bool) -> Self {
169 Self(b as u8)
170 }
171
172 characteristic_two_methods!();
173
174 #[inline]
175 fn square(&self) -> Self {
176 *self
178 }
179}
180
181impl Field for Gf2 {
182 type Packing = Self;
187
188 const GENERATOR: Self = Self::ONE;
190
191 #[inline]
192 fn try_inverse(&self) -> Option<Self> {
193 (self.0 == 1).then_some(Self::ONE)
194 }
195
196 #[inline]
197 fn try_sqrt(&self) -> Option<Self> {
198 Some(*self)
200 }
201
202 #[inline]
203 fn order() -> BigUint {
204 BigUint::from(2u8)
205 }
206
207 #[inline]
212 fn bits() -> usize {
213 1
214 }
215
216 #[inline]
224 fn interpolation_node(i: usize) -> Self {
225 assert!(i < 2, "interpolation node index out of range");
226 Self::new(i as u8)
227 }
228}
229
230impl QuotientMap<u8> for Gf2 {
231 #[inline]
233 fn from_int(int: u8) -> Self {
234 Self::new(int)
235 }
236
237 #[inline]
241 fn from_canonical_checked(int: u8) -> Option<Self> {
242 (int < 2).then(|| Self::new(int))
243 }
244
245 #[inline]
250 unsafe fn from_canonical_unchecked(int: u8) -> Self {
251 debug_assert!(int < 2);
254 Self::new(int)
255 }
256}
257
258impl QuotientMap<i8> for Gf2 {
259 #[inline]
261 fn from_int(int: i8) -> Self {
262 Self::new((int & 1) as u8)
264 }
265
266 #[inline]
270 fn from_canonical_checked(int: i8) -> Option<Self> {
271 (0..2).contains(&int).then(|| Self::new(int as u8))
272 }
273
274 #[inline]
279 unsafe fn from_canonical_unchecked(int: i8) -> Self {
280 debug_assert!((0..2).contains(&int));
283 Self::new(int as u8)
284 }
285}
286
287quotient_map_large_uint!(Gf2, u8, 2u8, "`[0, 1]`", "`[0, 1]`", [u16, u32, u64, u128]);
289
290quotient_map_large_iint!(
292 Gf2,
293 i8,
294 "`[0, 1]`",
295 "`[0, 1]`",
296 [(i16, u16), (i32, u32), (i64, u64), (i128, u128)]
297);
298
299impl PrimeField for Gf2 {
300 #[inline]
301 fn as_canonical_biguint(&self) -> BigUint {
302 BigUint::from(self.0)
303 }
304}
305
306impl PrimeField64 for Gf2 {
307 const ORDER_U64: u64 = 2;
308
309 #[inline]
310 fn as_canonical_u64(&self) -> u64 {
311 self.0 as u64
312 }
313}
314
315impl PrimeField32 for Gf2 {
316 const ORDER_U32: u32 = 2;
317
318 #[inline]
319 fn as_canonical_u32(&self) -> u32 {
320 self.0 as u32
321 }
322}
323
324impl RawDataSerializable for Gf2 {
325 const NUM_BYTES: usize = 1;
326
327 #[inline]
328 fn into_bytes(self) -> impl IntoIterator<Item = u8> {
329 [self.0]
330 }
331}
332
333impl Add for Gf2 {
334 type Output = Self;
335
336 #[inline]
337 #[allow(clippy::suspicious_arithmetic_impl)]
338 fn add(self, rhs: Self) -> Self {
339 Self(self.0 ^ rhs.0)
341 }
342}
343
344impl Sub for Gf2 {
345 type Output = Self;
346
347 #[inline]
348 #[allow(clippy::suspicious_arithmetic_impl)]
349 fn sub(self, rhs: Self) -> Self {
350 self + rhs
352 }
353}
354
355impl Neg for Gf2 {
356 type Output = Self;
357
358 #[inline]
359 fn neg(self) -> Self::Output {
360 self
362 }
363}
364
365impl Mul for Gf2 {
366 type Output = Self;
367
368 #[inline]
369 #[allow(clippy::suspicious_arithmetic_impl)]
370 fn mul(self, rhs: Self) -> Self {
371 Self(self.0 & rhs.0)
373 }
374}
375
376impl_add_assign!(Gf2);
377impl_sub_assign!(Gf2);
378impl_mul_methods!(Gf2);
379impl_div_methods!(Gf2, Gf2);
380ring_sum!(Gf2);
381
382#[cfg(test)]
383mod tests {
384 use p3_field::integers::QuotientMap;
385 use p3_field::{
386 Field, PrimeCharacteristicRing, PrimeField, PrimeField32, PrimeField64, RawDataSerializable,
387 };
388
389 use super::Gf2;
390
391 #[test]
392 fn arithmetic_is_boolean() {
393 assert_eq!(Gf2::ONE + Gf2::ONE, Gf2::ZERO);
394 assert_eq!(Gf2::TWO, Gf2::ZERO);
395 assert_eq!(Gf2::NEG_ONE, Gf2::ONE);
396 assert_eq!(Gf2::ONE * Gf2::ONE, Gf2::ONE);
397 assert_eq!(Gf2::ONE.inverse(), Gf2::ONE);
398 assert_eq!(Gf2::ZERO.try_inverse(), None);
399 assert_eq!(Gf2::from_u64(7), Gf2::ONE);
400 assert_eq!(Gf2::from_u64(6), Gf2::ZERO);
401 }
402
403 #[test]
417 fn quotient_map_covers_every_integer_type() {
418 macro_rules! check_unsigned {
419 ($int:ty) => {
420 assert_eq!(<Gf2 as QuotientMap<$int>>::from_int(0), Gf2::ZERO);
421 assert_eq!(<Gf2 as QuotientMap<$int>>::from_int(1), Gf2::ONE);
422 assert_eq!(<Gf2 as QuotientMap<$int>>::from_int(2), Gf2::ZERO);
423 assert_eq!(<Gf2 as QuotientMap<$int>>::from_int(3), Gf2::ONE);
424 assert_eq!(<Gf2 as QuotientMap<$int>>::from_int(<$int>::MAX), Gf2::ONE);
425 assert_eq!(
426 <Gf2 as QuotientMap<$int>>::from_canonical_checked(0),
427 Some(Gf2::ZERO)
428 );
429 assert_eq!(
430 <Gf2 as QuotientMap<$int>>::from_canonical_checked(1),
431 Some(Gf2::ONE)
432 );
433 assert_eq!(<Gf2 as QuotientMap<$int>>::from_canonical_checked(2), None);
434 assert_eq!(
435 <Gf2 as QuotientMap<$int>>::from_canonical_checked(<$int>::MAX),
436 None
437 );
438 unsafe {
439 assert_eq!(
440 <Gf2 as QuotientMap<$int>>::from_canonical_unchecked(0),
441 Gf2::ZERO
442 );
443 assert_eq!(
444 <Gf2 as QuotientMap<$int>>::from_canonical_unchecked(1),
445 Gf2::ONE
446 );
447 }
448 };
449 }
450 macro_rules! check_signed {
451 ($int:ty) => {
452 assert_eq!(<Gf2 as QuotientMap<$int>>::from_int(0), Gf2::ZERO);
453 assert_eq!(<Gf2 as QuotientMap<$int>>::from_int(1), Gf2::ONE);
454 assert_eq!(<Gf2 as QuotientMap<$int>>::from_int(-1), Gf2::ONE);
455 assert_eq!(<Gf2 as QuotientMap<$int>>::from_int(-2), Gf2::ZERO);
456 assert_eq!(<Gf2 as QuotientMap<$int>>::from_int(-3), Gf2::ONE);
457 assert_eq!(<Gf2 as QuotientMap<$int>>::from_int(<$int>::MIN), Gf2::ZERO);
458 assert_eq!(<Gf2 as QuotientMap<$int>>::from_int(<$int>::MAX), Gf2::ONE);
459 assert_eq!(
460 <Gf2 as QuotientMap<$int>>::from_canonical_checked(0),
461 Some(Gf2::ZERO)
462 );
463 assert_eq!(
464 <Gf2 as QuotientMap<$int>>::from_canonical_checked(1),
465 Some(Gf2::ONE)
466 );
467 assert_eq!(<Gf2 as QuotientMap<$int>>::from_canonical_checked(2), None);
468 assert_eq!(<Gf2 as QuotientMap<$int>>::from_canonical_checked(-1), None);
469 assert_eq!(
470 <Gf2 as QuotientMap<$int>>::from_canonical_checked(<$int>::MIN),
471 None
472 );
473 unsafe {
474 assert_eq!(
475 <Gf2 as QuotientMap<$int>>::from_canonical_unchecked(0),
476 Gf2::ZERO
477 );
478 assert_eq!(
479 <Gf2 as QuotientMap<$int>>::from_canonical_unchecked(1),
480 Gf2::ONE
481 );
482 }
483 };
484 }
485
486 check_unsigned!(u8);
487 check_unsigned!(u16);
488 check_unsigned!(u32);
489 check_unsigned!(u64);
490 check_unsigned!(u128);
491 check_unsigned!(usize);
492 check_signed!(i8);
493 check_signed!(i16);
494 check_signed!(i32);
495 check_signed!(i64);
496 check_signed!(i128);
497 check_signed!(isize);
498 }
499
500 #[test]
503 fn quotient_map_large_value_reduction() {
504 assert_eq!(<Gf2 as QuotientMap<u16>>::from_int(60_000), Gf2::ZERO);
505 assert_eq!(<Gf2 as QuotientMap<u16>>::from_int(60_001), Gf2::ONE);
506 assert_eq!(
507 <Gf2 as QuotientMap<u32>>::from_int(4_000_000_000),
508 Gf2::ZERO
509 );
510 assert_eq!(<Gf2 as QuotientMap<u32>>::from_int(4_000_000_001), Gf2::ONE);
511 assert_eq!(
512 <Gf2 as QuotientMap<u64>>::from_int(18_000_000_000_000_000_002),
513 Gf2::ZERO
514 );
515 assert_eq!(
516 <Gf2 as QuotientMap<u128>>::from_int(u128::MAX - 1),
517 Gf2::ZERO
518 );
519 assert_eq!(
520 <Gf2 as QuotientMap<i32>>::from_int(-2_000_000_001),
521 Gf2::ONE
522 );
523 assert_eq!(
524 <Gf2 as QuotientMap<i64>>::from_int(-9_000_000_000_000_000_002),
525 Gf2::ZERO
526 );
527 assert_eq!(
528 <Gf2 as QuotientMap<i128>>::from_int(i128::MIN + 1),
529 Gf2::ONE
530 );
531 }
532
533 #[test]
534 fn as_canonical_and_raw_bytes() {
535 assert_eq!(Gf2::ORDER_U32, 2);
536 assert_eq!(Gf2::ORDER_U64, 2);
537 assert_eq!(Gf2::ZERO.as_canonical_u32(), 0);
538 assert_eq!(Gf2::ONE.as_canonical_u32(), 1);
539 assert_eq!(Gf2::ZERO.as_canonical_u64(), 0);
540 assert_eq!(Gf2::ONE.as_canonical_u64(), 1);
541 assert_eq!(
542 Gf2::ONE.as_canonical_biguint(),
543 num_bigint::BigUint::from(1u8)
544 );
545 assert_eq!(
546 Gf2::ZERO.as_canonical_biguint(),
547 num_bigint::BigUint::from(0u8)
548 );
549
550 assert_eq!(Gf2::NUM_BYTES, 1);
551 let mut ones_bytes = Gf2::ONE.into_bytes().into_iter();
552 assert_eq!(ones_bytes.next(), Some(1u8));
553 assert_eq!(ones_bytes.next(), None);
554 let mut zeros_bytes = Gf2::ZERO.into_bytes().into_iter();
555 assert_eq!(zeros_bytes.next(), Some(0u8));
556 assert_eq!(zeros_bytes.next(), None);
557
558 assert_eq!(Gf2::from_le_bytes([0]), Gf2::ZERO);
559 assert_eq!(Gf2::from_le_bytes([1]), Gf2::ONE);
560 assert_eq!(Gf2::from_le_bytes([2]), Gf2::ZERO);
562 assert_eq!(Gf2::from_le_bytes([255]), Gf2::ONE);
563 }
564
565 #[test]
566 #[should_panic = "halve is undefined in characteristic 2"]
567 fn halve_panics() {
568 let _halved = Gf2::ONE.halve();
569 }
570
571 #[test]
572 #[should_panic = "div_2exp_u64 is undefined in characteristic 2"]
573 fn div_2exp_u64_panics() {
574 let _divided = Gf2::ONE.div_2exp_u64(1);
575 }
576
577 #[test]
578 #[should_panic = "div_2exp_u64 is undefined in characteristic 2"]
579 fn div_2exp_u64_panics_at_exponent_zero() {
580 let _divided = Gf2::ONE.div_2exp_u64(0);
581 }
582
583 #[test]
584 fn field_order_and_interpolation_nodes() {
585 assert_eq!(Gf2::order(), num_bigint::BigUint::from(2u8));
586 assert_eq!(Gf2::bits(), 1);
587 assert_eq!(Gf2::interpolation_node(0), Gf2::ZERO);
588 assert_eq!(Gf2::interpolation_node(1), Gf2::ONE);
589 }
590
591 #[test]
592 #[should_panic = "interpolation node index out of range"]
593 fn interpolation_node_rejects_an_index_beyond_the_field() {
594 let _node = Gf2::interpolation_node(2);
595 }
596
597 #[test]
602 fn serde_round_trip_rejects_non_canonical_encodings() {
603 assert_eq!(serde_json::to_string(&Gf2::ZERO).unwrap(), "0");
604 assert_eq!(serde_json::to_string(&Gf2::ONE).unwrap(), "1");
605
606 let decoded_zero: Gf2 = serde_json::from_str("0").unwrap();
607 let decoded_one: Gf2 = serde_json::from_str("1").unwrap();
608 assert_eq!(decoded_zero, Gf2::ZERO);
609 assert_eq!(decoded_one, Gf2::ONE);
610
611 assert!(serde_json::from_str::<Gf2>("2").is_err());
613 assert!(serde_json::from_str::<Gf2>("255").is_err());
614 }
615}