use core::marker::PhantomData;
use super::{PrimeCharacteristic, PrimeIdentity, private};
mod residue;
pub use residue::Residue;
#[allow(clippy::cast_lossless)]
pub(crate) const fn metadata_order(characteristic: u64, degree: u32) -> u128 {
assert!(degree > 0, "field degree must be positive");
assert!(
characteristic != 2 || degree <= 64,
"binary field degree exceeds 64"
);
assert!(degree <= 64, "field degree exceeds 64");
let mut order: u128 = 1;
let mut i = 0;
while i < degree {
order = match order.checked_mul(characteristic as u128) {
Some(value) => value,
None => panic!("field order overflows u128"),
};
i += 1;
}
order
}
pub(crate) const fn checked_order<const P: u64, const N: u32>() -> u128 {
metadata_order(<PrimeCharacteristic<P> as PrimeIdentity>::CHARACTERISTIC, N)
}
pub struct FiniteField<const P: u64, const N: u32, R: FiniteFieldRepr<P, N> = Residue>(
PhantomData<fn() -> R>,
);
impl<const P: u64, const N: u32, R: FiniteFieldRepr<P, N>> Clone for FiniteField<P, N, R> {
fn clone(&self) -> Self {
*self
}
}
impl<const P: u64, const N: u32, R: FiniteFieldRepr<P, N>> Copy for FiniteField<P, N, R> {}
impl<const P: u64, const N: u32, R: FiniteFieldRepr<P, N>> Default for FiniteField<P, N, R> {
fn default() -> Self {
Self(PhantomData)
}
}
impl<const P: u64, const N: u32, R: FiniteFieldRepr<P, N>> PartialEq for FiniteField<P, N, R> {
fn eq(&self, _other: &Self) -> bool {
true
}
}
impl<const P: u64, const N: u32, R: FiniteFieldRepr<P, N>> Eq for FiniteField<P, N, R> {}
impl<const P: u64, const N: u32, R: FiniteFieldRepr<P, N>> core::hash::Hash
for FiniteField<P, N, R>
{
fn hash<H: core::hash::Hasher>(&self, _state: &mut H) {}
}
impl<const P: u64, const N: u32, R: FiniteFieldRepr<P, N>> PartialOrd for FiniteField<P, N, R> {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl<const P: u64, const N: u32, R: FiniteFieldRepr<P, N>> Ord for FiniteField<P, N, R> {
fn cmp(&self, _other: &Self) -> core::cmp::Ordering {
core::cmp::Ordering::Equal
}
}
impl<const P: u64, const N: u32, R: FiniteFieldRepr<P, N>> core::fmt::Debug
for FiniteField<P, N, R>
{
fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(formatter, "FiniteField<{}, {}, {}>", P, N, R::NAME)
}
}
pub trait FiniteFieldRepr<const P: u64, const N: u32>: private::Sealed + 'static {
const NAME: &'static str;
const VALID: ();
}