#![forbid(unsafe_code)]
use fgf::poly::AES;
use fgf::{
Cantor, Components, Elem, Embedding, EmbeddingError, Extension, ExtensionField, ExtensionSpec,
Field, FieldElem, FiniteField, Isomorphism, Normal, Polynomial, Relation,
};
type Aes = FiniteField<2, 8, Polynomial<AES>>;
type NormalAes = FiniteField<2, 8, Normal<AES, 0x20>>;
type CantorAes = FiniteField<2, 8, Cantor<AES, 0x20>>;
type Gf7 = FiniteField<7, 1>;
struct Gf49Spec;
impl ExtensionSpec<2> for Gf49Spec {
type Base = Gf7;
type Storage = Components;
const NAME: &'static str = "GF(49)";
const RELATION: Relation = Relation::from_coordinates(&[4, 0]);
}
type Gf49 = FiniteField<7, 2, Extension<Gf49Spec, 2>>;
struct Gf49AltSpec;
impl ExtensionSpec<2> for Gf49AltSpec {
type Base = Gf7;
type Storage = Components;
const NAME: &'static str = "GF(49), t^2 + 1";
const RELATION: Relation = Relation::from_coordinates(&[1, 0]);
}
type Gf49Alt = FiniteField<7, 2, Extension<Gf49AltSpec, 2>>;
fn main() {
bases();
binary_maps();
odd_maps();
}
fn bases() {
let one = Elem::<NormalAes>::ONE;
assert_eq!(one.to_raw(), 0xFF);
assert_eq!(one.to_residue(), Some(1));
assert_eq!(one.to_index(), 0xFF);
assert_eq!(Elem::<NormalAes>::from_residue(1).unwrap(), one);
assert_ne!(Elem::<NormalAes>::from_index(1).unwrap(), one);
assert_eq!(Elem::<NormalAes>::from_index(1).unwrap().to_raw(), 1);
let cantor_one = Elem::<CantorAes>::ONE;
assert_eq!(cantor_one.to_raw(), 1);
assert_eq!(cantor_one.to_residue(), Some(1));
assert_eq!(Elem::<CantorAes>::from_residue(1).unwrap(), cantor_one);
println!(
"normal one has word {:#x}, cantor one has word {:#x}, both read residue 1",
one.to_raw(),
cantor_one.to_raw()
);
}
fn binary_maps() {
let iso = Isomorphism::<NormalAes, Aes>::new().unwrap();
let (g, h) = (
Elem::<NormalAes>::GENERATOR,
Elem::<NormalAes>::from_raw(0x96),
);
assert_eq!(iso.apply(g * h), iso.apply(g) * iso.apply(h));
assert_eq!(iso.unapply(iso.apply(h)), h);
assert_eq!(iso.apply(Elem::<NormalAes>::ONE), Elem::<Aes>::ONE);
let back = iso.inverse();
assert_eq!(back.apply(iso.apply(g)), g);
let to_cantor = Isomorphism::<Aes, CantorAes>::new().unwrap();
let composed = iso.then(&to_cantor);
assert_eq!(composed.apply(g), to_cantor.apply(iso.apply(g)));
assert_eq!(composed.inverse().apply(composed.apply(h)), h);
let rebuilt = Isomorphism::<NormalAes, Aes>::from_images(iso.to_images()).unwrap();
assert_eq!(rebuilt.apply(g), iso.apply(g));
let conjugate =
Isomorphism::<NormalAes, Aes>::from_images(&[Elem::<Aes>::from_raw(4)]).unwrap();
assert_eq!(
conjugate.apply(g * h),
conjugate.apply(g) * conjugate.apply(h)
);
assert_eq!(conjugate.unapply(conjugate.apply(g)), g);
println!(
"normal -> AES -> cantor composed; images rebuild the map; the conjugate root gives a second map"
);
}
fn odd_maps() {
assert_eq!(
Isomorphism::<Gf49Alt, Gf49>::new().unwrap_err(),
EmbeddingError::NoCanonicalMap
);
assert_eq!(
Embedding::<Gf49Alt, Gf49>::new().unwrap_err(),
EmbeddingError::NoCanonicalMap
);
let root =
<Gf49 as ExtensionField<2>>::from_components([Elem::<Gf7>::ZERO, Elem::<Gf7>::from_raw(3)]);
let mapped = Isomorphism::<Gf49Alt, Gf49>::from_images(&[root]).unwrap();
let (p, q) = (
<Gf49Alt as ExtensionField<2>>::from_components([
Elem::<Gf7>::from_raw(2),
Elem::<Gf7>::from_raw(5),
]),
<Gf49Alt as ExtensionField<2>>::from_components([
Elem::<Gf7>::from_raw(6),
Elem::<Gf7>::from_raw(1),
]),
);
assert_eq!(mapped.apply(p * q), mapped.apply(p) * mapped.apply(q));
assert_eq!(mapped.unapply(mapped.apply(p)), p);
let t = <Gf49 as ExtensionField<2>>::from_components([Elem::<Gf7>::ZERO, Elem::<Gf7>::ONE]);
assert_eq!(
Isomorphism::<Gf49Alt, Gf49>::from_images(&[t]).unwrap_err(),
EmbeddingError::InvalidImages
);
assert_eq!(
Embedding::<Gf49Alt, Gf49>::from_images(&[]).unwrap_err(),
EmbeddingError::InvalidImages
);
let subfield = Embedding::<Gf7, Gf49>::new().unwrap();
assert_eq!(subfield.restrict(t), None);
assert_eq!(
subfield.restrict(subfield.embed(Elem::<Gf7>::from_raw(5))),
Some(Elem::<Gf7>::from_raw(5))
);
println!(
"{} <- {}: caller image {} validates, the indeterminate and the empty list reject",
Gf49::NAME,
Gf49Alt::NAME,
root
);
}