use super::PrimeField;
pub const MODULUS: u64 = 0x7FFF_FFFF;
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct Mersenne31(pub u64);
impl Mersenne31 {
#[inline]
fn reduce(v: u64) -> Self {
let lo = v & MODULUS;
let hi = v >> 31;
let sum = lo + hi;
Self(if sum >= MODULUS { sum - MODULUS } else { sum })
}
}
impl PrimeField for Mersenne31 {
const MODULUS: u128 = MODULUS as u128;
const BITS: u32 = 31;
const ZERO: Self = Self(0);
const ONE: Self = Self(1);
#[inline]
fn from_u64(v: u64) -> Self {
Self::reduce(v % MODULUS)
}
#[inline]
fn to_u64(self) -> u64 {
self.0
}
#[inline]
fn add(self, rhs: Self) -> Self {
let sum = self.0 + rhs.0;
Self(if sum >= MODULUS { sum - MODULUS } else { sum })
}
#[inline]
fn sub(self, rhs: Self) -> Self {
if self.0 >= rhs.0 {
Self(self.0 - rhs.0)
} else {
Self(MODULUS - rhs.0 + self.0)
}
}
#[inline]
fn mul(self, rhs: Self) -> Self {
let product = self.0 as u128 * rhs.0 as u128;
let lo = (product & MODULUS as u128) as u64;
let hi = (product >> 31) as u64;
Self::reduce(lo + hi)
}
#[inline]
fn neg(self) -> Self {
if self.0 == 0 {
Self(0)
} else {
Self(MODULUS - self.0)
}
}
}