use derive_more::{Add, AddAssign, BitXor, BitXorAssign, Sub, SubAssign};
#[derive(Clone, Copy, Debug, Default, BitXor, BitXorAssign, PartialEq, Eq)] pub struct Additive(pub Elt);
impl Additive {
#[inline(always)]
pub fn to_wide(self) -> Wide {
self.0 as Wide
}
#[inline(always)]
pub fn from_wide(x: Wide) -> Additive {
Additive(x as Elt)
}
pub const ZERO: Additive = Additive(0);
}
#[cfg(table_bootstrap_complete)]
impl Additive {
#[inline(always)]
pub fn to_multiplier(self) -> Multiplier {
Multiplier(LOG_TABLE[self.0 as usize])
}
#[inline(always)]
pub fn mul(self, other: Multiplier) -> Additive {
if self == Self::ZERO {
return Self::ZERO;
}
let log = (LOG_TABLE[self.0 as usize] as Wide) + other.0 as Wide;
let offset = (log & ONEMASK as Wide) + (log >> FIELD_BITS);
Additive(EXP_TABLE[offset as usize])
}
#[inline(always)]
pub fn mul_assign_slice(selfy: &mut [Self], other: Multiplier) {
for s in selfy {
*s = s.mul(other);
}
}
}
#[derive(Clone, Copy, Debug, Add, AddAssign, Sub, SubAssign, PartialEq, Eq)] pub struct Multiplier(pub Elt);
impl Multiplier {
#[inline(always)]
pub fn to_wide(self) -> Wide {
self.0 as Wide
}
#[inline(always)]
pub fn from_wide(x: Wide) -> Multiplier {
Multiplier(x as Elt)
}
}
pub fn walsh(data: &mut [Multiplier], size: usize) {
let mut depart_no = 1_usize;
while depart_no < size {
let mut j = 0;
let depart_no_next = depart_no << 1;
while j < size {
for i in j..(depart_no + j) {
let mask = ONEMASK as Wide;
let tmp2: Wide = data[i].to_wide() + mask - data[i + depart_no].to_wide();
let tmp1: Wide = data[i].to_wide() + data[i + depart_no].to_wide();
data[i] = Multiplier(((tmp1 & mask) + (tmp1 >> FIELD_BITS)) as Elt);
data[i + depart_no] = Multiplier(((tmp2 & mask) + (tmp2 >> FIELD_BITS)) as Elt);
}
j += depart_no_next;
}
depart_no = depart_no_next;
}
}
#[allow(unused)]
fn bitpoly_mul16(a: Wide, b: Wide) -> Wide {
let mut r: Wide =0;
for i in 0..FIELD_BITS {
if (b>>i) & 1 != 0 {
r ^= a<<i;
}
}
r
}
#[allow(unused)]
fn gf_mul_bitpoly_reduced(a: Elt, b: Elt) -> Elt {
use core::convert::TryInto;
let len = FIELD_BITS;
let mut r: Wide = bitpoly_mul16(a as Wide,b as Wide);
let red : Wide = (1 << FIELD_BITS) + (GENERATOR as Wide);
for i in (len..=(len*2-1)).rev() {
if r & (1<<i) != 0 {
r ^= red<<(i-len);
}
}
r.try_into().unwrap()
}
#[test]
fn cantor_basis() {
for w in BASE.windows(2) {
let b = w[1];
let square = gf_mul_bitpoly_reduced(b,b);
let a = w[0];
assert_eq!(a, square ^ b);
}
}