use core::fmt;
use super::Elem as ElemTrait;
pub const ORDER: u128 = 2;
pub const GENERATOR: Elem = Elem(1);
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
pub struct Gf2;
impl Gf2 {
pub const NAME: &'static str = "GF(2)";
}
#[derive(Clone, Copy, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Elem(pub(crate) u8);
impl Elem {
pub const ZERO: Self = Self(0);
pub const ONE: Self = Self(1);
#[inline]
#[must_use]
pub const fn from_raw(value: u8) -> Self {
Self(value & 1)
}
#[inline]
#[must_use]
pub const fn to_raw(self) -> u8 {
self.0
}
#[inline]
#[must_use]
pub const fn from_bytes(bytes: [u8; 1]) -> Self {
Self(bytes[0] & 1)
}
#[inline]
#[must_use]
pub const fn to_bytes(self) -> [u8; 1] {
[self.0]
}
#[inline]
#[must_use]
pub const fn canonical(self) -> Self {
self
}
#[inline]
#[must_use]
pub const fn add(self, rhs: Self) -> Self {
Self(self.0 ^ rhs.0)
}
#[inline]
#[must_use]
pub const fn sub(self, rhs: Self) -> Self {
self.add(rhs)
}
#[inline]
#[must_use]
pub const fn neg(self) -> Self {
self
}
#[inline]
#[must_use]
pub const fn mul(self, rhs: Self) -> Self {
Self(self.0 & rhs.0)
}
#[inline]
#[must_use]
pub const fn square(self) -> Self {
self
}
#[inline]
#[must_use]
pub const fn inv(self) -> Self {
self
}
#[inline]
#[must_use]
pub const fn div(self, rhs: Self) -> Self {
if rhs.0 == 0 { Self::ZERO } else { self }
}
#[inline]
#[must_use]
pub const fn pow(self, exponent: u64) -> Self {
if exponent == 0 { Self::ONE } else { self }
}
#[inline]
#[must_use]
pub const fn is_zero(self) -> bool {
self.0 == 0
}
#[inline]
#[must_use]
pub const fn is_one(self) -> bool {
self.0 == 1
}
}
impl ElemTrait for Elem {
const ZERO: Self = Self::ZERO;
const ONE: Self = Self::ONE;
#[inline]
fn add(self, rhs: Self) -> Self {
Elem::add(self, rhs)
}
#[inline]
fn sub(self, rhs: Self) -> Self {
Elem::sub(self, rhs)
}
#[inline]
fn neg(self) -> Self {
Elem::neg(self)
}
#[inline]
fn mul(self, rhs: Self) -> Self {
Elem::mul(self, rhs)
}
#[inline]
fn square(self) -> Self {
Elem::square(self)
}
#[inline]
fn inv(self) -> Self {
Elem::inv(self)
}
#[inline]
fn div(self, rhs: Self) -> Self {
Elem::div(self, rhs)
}
#[inline]
fn pow(self, exponent: u64) -> Self {
Elem::pow(self, exponent)
}
#[inline]
fn is_zero(self) -> bool {
Elem::is_zero(self)
}
#[inline]
fn is_one(self) -> bool {
Elem::is_one(self)
}
}
impl fmt::Debug for Elem {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Gf2({})", self.0)
}
}
impl fmt::Display for Elem {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl core::ops::Add for Elem {
type Output = Self;
#[inline]
fn add(self, rhs: Self) -> Self {
Elem::add(self, rhs)
}
}
impl core::ops::Sub for Elem {
type Output = Self;
#[inline]
fn sub(self, rhs: Self) -> Self {
Elem::sub(self, rhs)
}
}
impl core::ops::Neg for Elem {
type Output = Self;
#[inline]
fn neg(self) -> Self {
Elem::neg(self)
}
}
impl core::ops::Mul for Elem {
type Output = Self;
#[inline]
fn mul(self, rhs: Self) -> Self {
Elem::mul(self, rhs)
}
}
impl core::ops::Div for Elem {
type Output = Self;
#[inline]
fn div(self, rhs: Self) -> Self {
Elem::div(self, rhs)
}
}
impl core::ops::AddAssign for Elem {
#[inline]
fn add_assign(&mut self, rhs: Self) {
*self = Elem::add(*self, rhs);
}
}
impl core::ops::SubAssign for Elem {
#[inline]
fn sub_assign(&mut self, rhs: Self) {
*self = Elem::sub(*self, rhs);
}
}
impl core::ops::MulAssign for Elem {
#[inline]
fn mul_assign(&mut self, rhs: Self) {
*self = Elem::mul(*self, rhs);
}
}
impl core::ops::DivAssign for Elem {
#[inline]
fn div_assign(&mut self, rhs: Self) {
*self = Elem::div(*self, rhs);
}
}
impl core::iter::Sum for Elem {
fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
iter.fold(Self::ZERO, Elem::add)
}
}
impl<'a> core::iter::Sum<&'a Elem> for Elem {
fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
iter.fold(Self::ZERO, |acc, &x| Elem::add(acc, x))
}
}
impl core::iter::Product for Elem {
fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
iter.fold(Self::ONE, Elem::mul)
}
}
impl<'a> core::iter::Product<&'a Elem> for Elem {
fn product<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
iter.fold(Self::ONE, |acc, &x| Elem::mul(acc, x))
}
}