use crypto_bigint::{Limb, U128, U256, U512, Uint};
pub trait PrimeField {
const PRIME: Self;
fn field_add(&self, rhs: &Self) -> Self;
fn field_sub(&self, rhs: &Self) -> Self;
fn field_mul(&self, rhs: &Self) -> Self;
fn field_inv(&self) -> Self;
}
trait PrimeValue {
const PRIME_RPOS: u16;
const RPOS_LIMB: Limb = Limb::from_u16(Self::PRIME_RPOS);
}
impl<const LIMBS: usize> PrimeField for Uint<LIMBS>
where
Uint<LIMBS>: PrimeValue
{
const PRIME: Self = Self::MAX.wrapping_sub(&Self::from_u16(Self::PRIME_RPOS - 1));
fn field_add(&self, rhs: &Self) -> Self {
self.add_mod_special(rhs, Self::RPOS_LIMB)
}
fn field_sub(&self, rhs: &Self) -> Self {
self.sub_mod_special(rhs, Self::RPOS_LIMB)
}
fn field_mul(&self, rhs: &Self) -> Self {
self.mul_mod_special(rhs, Self::RPOS_LIMB)
}
fn field_inv(&self) -> Self {
self.inv_odd_mod_bounded(&Self::PRIME, self.bits_vartime(), Uint::<LIMBS>::BITS).0
}
}
impl PrimeValue for U128 {
const PRIME_RPOS: u16 = 159;
}
impl PrimeValue for U256 {
const PRIME_RPOS: u16 = 189;
}
impl PrimeValue for U512 {
const PRIME_RPOS: u16 = 569;
}