pub mod fp;
pub mod fpn;
pub mod nimber;
pub mod wittvec;
pub use fp::*;
pub use fpn::*;
pub use nimber::*;
pub use wittvec::*;
use crate::scalar::Scalar;
pub trait FiniteField: Scalar + Copy {
fn frobenius(&self) -> Self;
fn pow(&self, e: u128) -> Self {
Scalar::pow(self, e)
}
fn ext_degree() -> usize;
fn group_order() -> u128;
fn group_order_factors() -> Vec<u128>;
fn frobenius_iter(&self, k: usize) -> Self {
let mut x = *self;
for _ in 0..k {
x = x.frobenius();
}
x
}
fn degree(&self) -> usize {
for d in divisors(Self::ext_degree()) {
if self.frobenius_iter(d) == *self {
return d;
}
}
Self::ext_degree()
}
fn conjugates(&self) -> Vec<Self> {
let d = self.degree();
let mut out = Vec::with_capacity(d);
let mut c = *self;
for _ in 0..d {
out.push(c);
c = c.frobenius();
}
out
}
fn min_poly_monic(&self) -> Vec<Self> {
let mut poly = vec![Self::one()]; for c in self.conjugates() {
let neg_c = c.neg(); let mut next = vec![Self::zero(); poly.len() + 1];
for (i, a) in poly.iter().enumerate() {
next[i + 1] = next[i + 1].add(a); next[i] = next[i].add(&neg_c.mul(a)); }
poly = next;
}
poly
}
fn relative_trace_over(&self, m: usize, e: usize) -> Self {
assert!(e > 0 && m.is_multiple_of(e), "relative trace needs e | m");
let mut acc = Self::zero();
let mut t = *self;
for _ in 0..(m / e) {
acc = acc.add(&t);
t = t.frobenius_iter(e);
}
acc
}
fn relative_norm_over(&self, m: usize, e: usize) -> Self {
assert!(e > 0 && m.is_multiple_of(e), "relative norm needs e | m");
let mut acc = Self::one();
let mut t = *self;
for _ in 0..(m / e) {
acc = acc.mul(&t);
t = t.frobenius_iter(e);
}
acc
}
fn relative_trace(&self, e: usize) -> Self {
self.relative_trace_over(Self::ext_degree(), e)
}
fn relative_norm(&self, e: usize) -> Self {
self.relative_norm_over(Self::ext_degree(), e)
}
fn multiplicative_order(&self) -> Option<u128> {
if self.is_zero() {
return None;
}
let mut ord = Self::group_order();
for p in Self::group_order_factors() {
while ord % p == 0 && FiniteField::pow(self, ord / p) == Self::one() {
ord /= p;
}
}
Some(ord)
}
fn is_primitive(&self) -> bool {
self.multiplicative_order() == Some(Self::group_order())
}
fn discrete_log(&self, x: Self) -> Option<u128> {
if self.is_zero() {
return None;
}
let n = self.multiplicative_order()?;
let mut cur = Self::one();
for e in 0..n {
if cur == x {
return Some(e);
}
cur = cur.mul(self);
}
None
}
}
fn divisors(n: usize) -> Vec<usize> {
(1..=n).filter(|d| n.is_multiple_of(*d)).collect()
}