use crypto_bigint::{const_prime_monty_params, Uint};
use fp::f2_element::F2Element;
use fp::f2_ext::{BinaryIrreducible, F2Ext};
use fp::field_ops::{FieldOps, FieldRandom};
use fp::fp_element::FpElement;
use fp::fp_ext::{FpExt, IrreduciblePoly, TonelliShanksConstants};
const_prime_monty_params!(Fp19Mod, Uint<1>, "0000000000000013", 2);
type Fp19 = FpElement<Fp19Mod, 1>;
struct Poly19Quad;
impl IrreduciblePoly<Fp19Mod, 1, 2> for Poly19Quad {
fn modulus() -> [FpElement<Fp19Mod, 1>; 2] {
[Fp19::from_u64(1), Fp19::from_u64(0)]
}
}
struct TS19Quad;
impl TonelliShanksConstants<Fp19Mod, 1, 2, 1> for TS19Quad {
const ORDER: Uint<1> = Uint::<1>::from_u64(360);
const HALF_ORDER: Uint<1> = Uint::<1>::from_u64(180);
const S: u64 = 3;
const T: Uint<1> = Uint::<1>::from_u64(45);
const PROJENATOR_EXP: Uint<1> = Uint::<1>::from_u64(22);
const TWOSM1: Uint<1> = Uint::<1>::from_u64(4);
fn root_of_unity() -> [FpElement<Fp19Mod, 1>; 2] {
[Fp19::from_u64(3), Fp19::from_u64(3)]
}
}
type Fp19_2 = FpExt<Fp19Mod, 1, 2, 1, Poly19Quad, TS19Quad>;
const_prime_monty_params!(Fp97283Mod, Uint<1>, "0000000000017C03", 2);
type Fp97283 = FpElement<Fp97283Mod, 1>;
struct Poly97283Quad;
impl IrreduciblePoly<Fp97283Mod, 1, 2> for Poly97283Quad {
fn modulus() -> [FpElement<Fp97283Mod, 1>; 2] {
[Fp97283::from_u64(1), Fp97283::from_u64(0)]
}
}
struct TS97283Quad;
impl TonelliShanksConstants<Fp97283Mod, 1, 2, 1> for TS97283Quad {
const ORDER: Uint<1> = Uint::<1>::from_u64(9_463_982_088);
const HALF_ORDER: Uint<1> = Uint::<1>::from_u64(4_731_991_044);
const S: u64 = 3;
const T: Uint<1> = Uint::<1>::from_u64(1_182_997_761);
const PROJENATOR_EXP: Uint<1> = Uint::<1>::from_u64(591_498_880);
const TWOSM1: Uint<1> = Uint::<1>::from_u64(4);
fn root_of_unity() -> [FpElement<Fp97283Mod, 1>; 2] {
[Fp97283::from_u64(96_901), Fp97283::from_u64(382)]
}
}
type Fp97283_2 = FpExt<Fp97283Mod, 1, 2, 1, Poly97283Quad, TS97283Quad>;
struct Poly97283Cubic;
impl IrreduciblePoly<Fp97283Mod, 1, 3> for Poly97283Cubic {
fn modulus() -> [FpElement<Fp97283Mod, 1>; 3] {
[
Fp97283::from_u64(1),
Fp97283::from_u64(1),
Fp97283::from_u64(0),
]
}
}
struct TS97283Cubic;
impl TonelliShanksConstants<Fp97283Mod, 1, 3, 1> for TS97283Cubic {
const ORDER: Uint<1> = Uint::<1>::from_u64(920_684_569_564_186);
const HALF_ORDER: Uint<1> = Uint::<1>::from_u64(460_342_284_782_093);
const S: u64 = 1;
const T: Uint<1> = Uint::<1>::from_u64(460_342_284_782_093);
const PROJENATOR_EXP: Uint<1> = Uint::<1>::from_u64(230_171_142_391_046);
const TWOSM1: Uint<1> = Uint::<1>::from_u64(1);
fn root_of_unity() -> [FpElement<Fp97283Mod, 1>; 3] {
[
Fp97283::from_u64(1),
Fp97283::from_u64(0),
Fp97283::from_u64(0),
]
}
}
type Fp97283_3 = FpExt<Fp97283Mod, 1, 3, 1, Poly97283Cubic, TS97283Cubic>;
struct Poly97283Quartic;
impl IrreduciblePoly<Fp97283Mod, 1, 4> for Poly97283Quartic {
fn modulus() -> [FpElement<Fp97283Mod, 1>; 4] {
[
Fp97283::from_u64(2),
Fp97283::from_u64(0),
Fp97283::from_u64(2),
Fp97283::from_u64(0),
]
}
}
struct TS97283Quartic;
impl TonelliShanksConstants<Fp97283Mod, 1, 4, 2> for TS97283Quartic {
const ORDER: Uint<2> =
Uint::<2>::from_words([0xdafdc0d3fc005050, 0x0000000000000004]);
const HALF_ORDER: Uint<2> =
Uint::<2>::from_words([0x6d7ee069fe002828, 0x0000000000000002]);
const S: u64 = 4;
const T: Uint<2> =
Uint::<2>::from_words([0x4dafdc0d3fc00505, 0x0000000000000000]);
const PROJENATOR_EXP: Uint<2> =
Uint::<2>::from_words([0x26d7ee069fe00282, 0x0000000000000000]);
const TWOSM1: Uint<2> =
Uint::<2>::from_words([0x0000000000000008, 0x0000000000000000]);
fn root_of_unity() -> [FpElement<Fp97283Mod, 1>; 4] {
[
Fp97283::from_u64(0),
Fp97283::from_u64(0),
Fp97283::from_u64(0),
Fp97283::from_u64(70_178),
]
}
}
type Fp97283_4 = FpExt<Fp97283Mod, 1, 4, 2, Poly97283Quartic, TS97283Quartic>;
struct AesPoly;
impl BinaryIrreducible<1> for AesPoly {
fn modulus() -> Uint<1> {
Uint::<1>::from_u64(0x11B)
}
fn degree() -> usize {
8
}
}
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>;
type GF256 = F2Ext<1, AesPoly>;
fn main() {
let mut rng = rand::rng();
println!("===== F_2 (base binary field) =====");
for i in 0..5 {
let a = F2Element::random(&mut rng);
println!(" sample {i}: {a}");
}
println!("\n===== F_{{2^8}} (AES field, polynomial form) =====");
for i in 0..5 {
let a = GF256::random(&mut rng);
println!(" sample {i}: {a}");
}
let a = GF256::random(&mut rng);
let a_inv = a.invert().unwrap();
let prod = a * a_inv;
println!(" sanity a = {a}");
println!(" sanity 1/a = {a_inv}");
println!(" a * 1/a = {prod} (should be 1)");
println!("\n===== F_{{2^511}} with modulus x^511 + x^10 + 1 =====");
for i in 0..5 {
let a = GF2_511::random(&mut rng);
println!(" sample {i}: {a}");
}
let a = GF2_511::random(&mut rng);
let a_inv = a.invert().unwrap();
let prod = a * a_inv;
println!(" sanity a = {a}");
println!(" sanity 1/a = {a_inv}");
println!(" a * 1/a = {prod} (should be 1)");
println!("\n===== F_19 (prime field) =====");
for i in 0..5 {
let a = Fp19::random(&mut rng);
println!(" sample {i}: {a}");
}
println!("\n===== F_{{19^2}} = F_19[x]/(x^2+1) =====");
for i in 0..5 {
let a = Fp19_2::random(&mut rng);
println!(" sample {i}: {a}");
}
let b = Fp19_2::random(&mut rng);
let b_inv = b.invert().unwrap();
let prod = b * b_inv;
println!(" sanity b = {b}");
println!(" sanity 1/b = {b_inv}");
println!(" b * 1/b = {prod} (should be 1)");
println!("\n===== F_97283 (prime field) =====");
for i in 0..5 {
let a = Fp97283::random(&mut rng);
println!(" sample {i}: {a}");
}
println!("\n===== F_{{97283^2}} = F_97283[x]/(x^2+1) =====");
for i in 0..5 {
let a = Fp97283_2::random(&mut rng);
println!(" sample {i}: {a}");
}
let a2 = Fp97283_2::random(&mut rng);
let a2_inv = a2.invert().unwrap();
println!(" sanity a = {a2}");
println!(" sanity 1/a = {a2_inv}");
println!(" a * 1/a = {} (should be 1)", a2 * a2_inv);
println!("\n===== F_{{97283^3}} = F_97283[x]/(x^3+x+1) =====");
for i in 0..5 {
let a = Fp97283_3::random(&mut rng);
println!(" sample {i}: {a}");
}
let a3 = Fp97283_3::random(&mut rng);
let a3_inv = a3.invert().unwrap();
println!(" sanity a = {a3}");
println!(" sanity 1/a = {a3_inv}");
println!(" a * 1/a = {} (should be 1)", a3 * a3_inv);
println!("\n===== F_{{97283^4}} = F_97283[x]/(x^4+2x^2+2) =====");
for i in 0..5 {
let a = Fp97283_4::random(&mut rng);
println!(" sample {i}: {a}");
}
let a4 = Fp97283_4::random(&mut rng);
let a4_inv = a4.invert().unwrap();
println!(" sanity a = {a4}");
println!(" sanity 1/a = {a4_inv}");
println!(" a * 1/a = {} (should be 1)", a4 * a4_inv);
}