#![forbid(unsafe_code)]
use fgf::field::{FieldElem, PrimeIdentity};
use fgf::poly::{AES, RS};
use fgf::{
Binary, Elem, Field, FieldBuffer, Goldilocks, HasGenerator, Mersenne31, Polynomial,
QuadMersenne31,
};
type Gf1 = fgf::Binary<1, fgf::Polynomial<3>>;
type Gf16 = fgf::Binary<16, fgf::Tower<fgf::Rijndael16>>;
type Gf32 = fgf::Binary<32, fgf::Tower<fgf::Rijndael32>>;
type Gf64 = fgf::Binary<64, fgf::Tower<fgf::Rijndael64>>;
type FanPaar8Field = fgf::Binary<8, fgf::Tower<fgf::FanPaar8>>;
type FanPaar16Field = fgf::Binary<16, fgf::Tower<fgf::FanPaar16>>;
type FanPaar32Field = fgf::Binary<32, fgf::Tower<fgf::FanPaar32>>;
type FanPaar64Field = fgf::Binary<64, fgf::Tower<fgf::FanPaar64>>;
const SCALE: Elem<Gf16> = Elem::<Gf16>::from_raw(0x0108);
const PRODUCT: Elem<Gf16> = Elem::<Gf16>::from_raw(0x1234).mul(SCALE);
fn main() {
assert_eq!(PRODUCT.div(SCALE), Elem::<Gf16>::from_raw(0x1234));
let aes = Elem::<Binary<8, Polynomial<AES>>>::from_raw(0x80)
* Elem::<Binary<8, Polynomial<AES>>>::from_raw(2);
let rs = Elem::<Binary<8, Polynomial<RS>>>::from_raw(0x80)
* Elem::<Binary<8, Polynomial<RS>>>::from_raw(2);
assert_eq!(aes.to_raw(), 0x1b);
assert_eq!(rs.to_raw(), 0x1d);
println!("0x80 * 2: AES basis = {aes}, Reed–Solomon basis = {rs}");
assert_eq!(Elem::<Gf1>::ONE + Elem::<Gf1>::ONE, Elem::<Gf1>::ZERO);
assert_eq!(Elem::<Gf1>::ONE * Elem::<Gf1>::ONE, Elem::<Gf1>::ONE);
println!("{}: 1 + 1 = 0, 1 * 1 = 1; vectors use fgf::bits", Gf1::NAME);
describe::<Binary<8, Polynomial<AES>>>();
describe::<Binary<8, Polynomial<RS>>>();
describe::<Gf16>();
describe::<Gf32>();
describe::<Gf64>();
describe::<FanPaar8Field>();
describe::<FanPaar16Field>();
describe::<FanPaar32Field>();
describe::<FanPaar64Field>();
describe::<Mersenne31>();
describe::<Goldilocks>();
describe::<QuadMersenne31>();
}
fn describe<F: FieldBuffer + HasGenerator>() {
let a = Elem::<F>::GENERATOR;
let b = a.square();
let product = a.mul(b);
assert_eq!(product.div(b), a);
assert_eq!(a.add(b).sub(b), a);
assert!(!b.is_zero());
assert_eq!(Elem::<F>::ZERO.inv(), Elem::<F>::ZERO);
assert_eq!(a.div(Elem::<F>::ZERO), Elem::<F>::ZERO);
let mut storage = [0u8; 8];
let bytes = &mut storage[..F::BYTES];
F::encode(bytes, product);
assert_eq!(F::decode(bytes), product);
println!(
"{}: characteristic={}, order={}, width={} bytes, product={product:?}, encoding={bytes:02x?}",
F::NAME,
<<F as Field>::Characteristic as PrimeIdentity>::CHARACTERISTIC,
F::ORDER,
F::BYTES,
);
}