use crypto_bigint::Uint;
use fp::f2_element::F2Element;
use fp::f2_ext::{BinaryIrreducible, F2Ext};
use fp::field_ops::{FieldOps, FieldRandom};
struct Deg8Poly;
impl BinaryIrreducible<1> for Deg8Poly {
fn modulus() -> Uint<1> {
Uint::<1>::from_u64(0b1_0001_1011) }
fn degree() -> usize {
8usize
}
}
struct F2511Poly;
impl BinaryIrreducible<8> for F2511Poly {
fn modulus() -> Uint<8> {
let one = Uint::<8>::from_u64(1);
(one << 511) | (one << 10) | one
}
fn degree() -> usize {
511
}
}
type GF2_511 = F2Ext<8, F2511Poly>;
#[test]
fn random_elements_test() {
let mut rng = rand::rng();
for _ in 0..6 {
let a = GF2_511::random(&mut rng);
if bool::from(a.is_zero()) {
continue;
}
let a_inv = a.invert().unwrap();
let prod = a_inv * a;
assert!(bool::from(prod.is_one()));
}
}
type F256 = F2Ext<1, Deg8Poly>;
fn elt(binary_str: u64) -> F256 {
F256::from_u64(binary_str)
}
#[test]
fn degree_is_8() {
assert_eq!(F256::degree(), 8usize);
}
#[test]
fn characteristic_equals_() {
assert_eq!(F256::characteristic(), F2Element::characteristic());
assert_eq!(F256::characteristic(), vec![2u64]);
}
#[test]
fn zero_is_zero() {
assert!(bool::from(F256::zero().is_zero()));
}
#[test]
fn one_is_one() {
assert!(bool::from(F256::one().is_one()));
}
#[test]
fn nonzero_is_not_zero() {
assert!(bool::from(!elt(0b000000001).is_zero()));
assert!(bool::from(!elt(0b1000110).is_zero()));
assert!(bool::from(!elt(0b1101111010111101).is_zero()));
}
#[test]
fn inv_zero_is_none() {
assert!(bool::from(F256::zero().invert().is_none()));
}
#[test]
fn add_coefficient_wise() {
let a = elt(0b1_1111); let b = elt(0b101_0111); let c = FieldOps::add(&a, &b); assert_eq!(c, elt(0b100_1000));
let d = elt(0b10_1010); let e = elt(0b1101_0100); let f = FieldOps::add(&d, &e); assert_eq!(f, elt(0b1111_1110));
}
#[test]
fn negate_then_add_is_zero() {
let a = elt(0b1_1111); assert!(bool::from(FieldOps::add(&a, &a.negate()).is_zero()));
}
#[test]
fn add_zero_is_identity() {
let a = elt(0b1_1111); assert_eq!(FieldOps::add(&a, &F256::zero()), a);
}
#[test]
fn double_equals_zero() {
let a = elt(0b1_1111); assert!(bool::from(a.double().is_zero()));
}
#[test]
fn mul_by_one_is_identity() {
let a = elt(0b1_1111); assert_eq!(FieldOps::mul(&a, &F256::one()), a);
}
#[test]
fn reduce_concrete_values() {
let a = elt(0b1_0000_0000); let b = elt(0b100_0010_0000); let c = elt(0b1_1011); let d = elt(0b100_1100); assert_eq!(a, c);
assert_eq!(b, d);
}
#[test]
fn mul_concrete_values() {
let a = elt(0b1_1001); let b = elt(0b101_0011); let c = FieldOps::mul(&a, &b); assert_eq!(c, elt(0b1011_1010));
let d = elt(0b10_1010); let e = elt(0b1101_0100); let f = FieldOps::mul(&d, &e); assert_eq!(f, elt(0b1000_1100));
let g = FieldOps::mul(&b, &d); assert_eq!(g, elt(0b1000_0110));
}
#[test]
fn mul_commutativity() {
let a = elt(0b1_1001); let b = elt(0b101_0011); assert_eq!(FieldOps::mul(&a, &b), FieldOps::mul(&b, &a));
}
#[test]
fn mul_associativity() {
let a = elt(0b1_1001); let b = elt(0b101_0011); let c = FieldOps::mul(&a, &b); assert_eq!(
FieldOps::mul(&FieldOps::mul(&a, &b), &c),
FieldOps::mul(&a, &FieldOps::mul(&b, &c))
);
}
#[test]
fn mul_distributivity() {
let a = elt(0b1_1001); let b = elt(0b101_0011); let c = FieldOps::mul(&a, &b); assert_eq!(
FieldOps::mul(&a, &FieldOps::add(&b, &c)),
FieldOps::add(&FieldOps::mul(&a, &b), &FieldOps::mul(&a, &c))
);
}
#[test]
fn square_equals_mul_self() {
let a = elt(0b1_1001); assert_eq!(a.square(), FieldOps::mul(&a, &a));
}
#[test]
fn invert_concrete_value() {
let a = elt(0b1_1001);
let inv_a = a
.invert()
.expect("(x^4 + x^3 + 1) is invertible in F_{256}");
assert_eq!(inv_a, elt(0b11_1111));
let b = elt(0b101_0011);
let inv_b = b
.invert()
.expect("(x^6 + x^4 + x + 1) is invertible in F_{256}");
assert_eq!(inv_b, elt(0b1100_1010));
let c = FieldOps::mul(&a, &b);
let inv_c = c
.invert()
.expect("(x^7 + x^5 + x^4 + x^3 + x) is invertible in F_{256}");
assert_eq!(inv_c, elt(0b111_0110));
let d = elt(0b10_1010);
let inv_d = d
.invert()
.expect("(x^5 + x^3 + x) is invertible in F_{256}");
assert_eq!(inv_d, elt(0b1001_1000));
}
#[test]
fn invert_zero_is_none() {
assert!(bool::from(F256::zero().invert().is_none()));
}
#[test]
fn frobenius_concrete_values() {
let a = elt(0b1_1001); let a_sq = a.frobenius(); assert_eq!(a_sq, elt(0b101_1010));
assert_eq!(a_sq.frobenius(), elt(0b1111_0100)); }
#[test]
fn norm_concrete_values() {
let a = elt(0b1_1001); assert_eq!(a.norm(), elt(0b1));
let b = elt(0b101_0011); assert_eq!(b.norm(), elt(0b1));
}
#[test]
fn trace_concrete_values() {
let a = elt(0b1_1001); assert_eq!(a.trace(), elt(0b0));
let b = elt(0b101_0011); assert_eq!(b.trace(), elt(0b0));
let e = elt(0b1101_0100); assert_eq!(e.trace(), elt(0b1));
}
#[test]
fn pow_zero_is_one() {
let a = elt(0b1_1001); assert!(bool::from(a.pow(&[0]).is_one()));
}
#[test]
fn pow_one_is_self() {
let a = elt(0b1_1001); assert_eq!(a.pow(&[1]), a);
}
#[test]
fn pow_concrete_values() {
let a = elt(0b1_1001); assert_eq!(a.pow(&[39]), elt(0b110_0010)); let b = elt(0b101_0011); assert_eq!(b.pow(&[73]), elt(0b100_0011)); let e = elt(0b1101_0100); assert_eq!(e.pow(&[111]), elt(0b1000)); }
#[test]
fn pow_group_order() {
let a = elt(0b1_1001); assert_eq!(a.pow(&[255]), elt(0b1));
}
#[test]
fn sqrt_of_zero_is_zero() {
let a = F256::zero(); assert_eq!(a.sqrt().expect("zero is a square!"), F256::zero());
}
#[test]
fn sqrt_of_one_is_one() {
let a = F256::one(); assert_eq!(a.sqrt().expect("one is a square!"), F256::one());
}
#[test]
fn sqrt_concrete_values() {
let a = elt(0b1_1001);
let sqrt_a = a.sqrt().expect("(x^4 + x^3 + 1) is a square in F_{256}");
assert_eq!(sqrt_a, elt(0b1110_1010));
let b = elt(0b101_0011);
let sqrt_b = b
.sqrt()
.expect("(x^6 + x^4 + x + 1) is a square in F_{256}");
assert_eq!(sqrt_b, elt(0b1111_0111));
let d = elt(0b10_1010);
let sqrt_d = d.sqrt().expect("(x^5 + x^3 + x) is a square in F_{256}");
assert_eq!(sqrt_d, elt(0b1101_0000));
let e = elt(0b1101_0100);
let sqrt_e = e
.sqrt()
.expect("(x^7 + x^6 + x^4 + x^2) is a square in F_{256}");
assert_eq!(sqrt_e, elt(0b1001_1111));
}
#[test]
fn sqrt_of_product() {
let a = elt(0b1_1001);
let sqrt_a = a.sqrt().expect("(x^4 + x^3 + 1) is a square in F_{256}");
let b = elt(0b101_0011);
let sqrt_b = b
.sqrt()
.expect("(x^6 + x^4 + x + 1) is a square in F_{256}");
let c = FieldOps::mul(&a, &b);
let sqrt_c = c
.sqrt()
.expect("(x^7 + x^5 + x^4 + x^3 + x) is a square in F_{256}");
assert_eq!(sqrt_c, FieldOps::mul(&sqrt_a, &sqrt_b));
}