mod element;
mod poly;
mod prime;
mod tables;
pub use element::{DynamicGf, GfElement};
pub use poly::{
IRREDUCIBLE_POLYS, IrreduciblePoly, available_field_orders, get_irreducible_poly,
has_irreducible_poly,
};
pub use prime::{GF2, GF3, GF5, GF7, GF11, GF13, GfPrime};
pub use tables::GfTables;
use std::fmt::Debug;
use std::hash::Hash;
pub trait GaloisField:
Copy + Clone + Eq + PartialEq + Hash + Debug + Default + Send + Sync
{
fn order(&self) -> u32;
fn characteristic(&self) -> u32;
fn degree(&self) -> u32;
fn zero(&self) -> Self;
fn one(&self) -> Self;
fn from_u32(&self, val: u32) -> Self;
fn to_u32(&self) -> u32;
fn is_zero(&self) -> bool;
fn is_one(&self) -> bool;
fn neg(&self) -> Self;
fn inv(&self) -> Self;
fn checked_inv(&self) -> Option<Self>;
fn add(&self, rhs: Self) -> Self;
fn sub(&self, rhs: Self) -> Self;
fn mul(&self, rhs: Self) -> Self;
fn div(&self, rhs: Self) -> Self;
fn checked_div(&self, rhs: Self) -> Option<Self>;
fn pow(&self, exp: u32) -> Self;
}
pub trait QuadraticCharacter: GaloisField {
fn chi(&self) -> i8;
fn is_quadratic_residue(&self) -> bool {
self.chi() == 1
}
fn is_quadratic_nonresidue(&self) -> bool {
self.chi() == -1
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_gf_prime_basic() {
let gf7 = DynamicGf::new(7).unwrap();
let zero = gf7.zero();
let one = gf7.one();
assert!(zero.is_zero());
assert!(one.is_one());
assert_eq!(zero.to_u32(), 0);
assert_eq!(one.to_u32(), 1);
let a = gf7.element(3);
let b = gf7.element(5);
assert_eq!(a.add(b.clone()).to_u32(), 1);
assert_eq!(a.mul(b.clone()).to_u32(), 1);
assert_eq!(a.mul(a.inv()).to_u32(), 1);
assert_eq!(b.mul(b.inv()).to_u32(), 1);
}
#[test]
fn test_field_axioms() {
let gf5 = DynamicGf::new(5).unwrap();
for i in 0..5 {
for j in 0..5 {
let a = gf5.element(i);
let b = gf5.element(j);
assert_eq!(a.add(b.clone()).to_u32(), b.add(a.clone()).to_u32());
assert_eq!(a.mul(b.clone()).to_u32(), b.mul(a.clone()).to_u32());
assert_eq!(a.add(gf5.zero()).to_u32(), a.to_u32());
assert_eq!(a.mul(gf5.one()).to_u32(), a.to_u32());
assert_eq!(a.add(a.neg()).to_u32(), 0);
if !a.is_zero() {
assert_eq!(a.mul(a.inv()).to_u32(), 1);
}
}
}
}
}