use crate::{Bit, TowerField};
pub trait BinaryFieldExtras: TowerField {
fn square(&self) -> Self {
*self * *self
}
fn frobenius(&self, k: u32) -> Self {
let reps = (k % Self::BITS as u32) as usize;
let mut acc = *self;
for _ in 0..reps {
acc = acc.square();
}
acc
}
fn trace(&self) -> Bit {
let mut acc = Self::ZERO;
let mut p = *self;
for _ in 0..Self::BITS {
acc += p;
p = p.square();
}
Bit::new((acc == Self::ONE) as u8)
}
fn solve_quadratic(c: Self) -> Option<Self>;
}
macro_rules! impl_binary_field_extras {
($block:ty, $sub:ty, $map_ct:ident, $trace_mask:ident, $solve_basis:ident) => {
impl BinaryFieldExtras for $block {
#[inline(always)]
fn square(&self) -> Self {
let (lo, hi) = self.split();
let hi2 = hi.square();
Self::new(lo.square() + hi2 * <$sub>::EXTENSION_TAU, hi2)
}
#[inline(always)]
fn trace(&self) -> Bit {
Bit::new(((self.0 & constants::$trace_mask).count_ones() & 1) as u8)
}
#[inline(always)]
fn solve_quadratic(c: Self) -> Option<Self> {
if c.trace() != Bit::ZERO {
return None;
}
Some(Self($map_ct(c.0, &constants::$solve_basis)))
}
}
};
}
pub(crate) use impl_binary_field_extras;