#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Field {
p: u64,
}
impl Field {
pub fn new(p: u64) -> Self {
assert!(p >= 3 && p % 2 == 1, "p must be an odd prime >= 3");
Field { p }
}
#[inline]
pub fn modulus(&self) -> u64 {
self.p
}
#[inline]
pub fn add(&self, a: u64, b: u64) -> u64 {
let mut s = (a % self.p) + (b % self.p);
if s >= self.p {
s -= self.p;
}
s
}
#[inline]
pub fn sub(&self, a: u64, b: u64) -> u64 {
let a = a % self.p;
let b = b % self.p;
if a >= b {
a - b
} else {
self.p - (b - a)
}
}
#[inline]
pub fn mul(&self, a: u64, b: u64) -> u64 {
let a = a % self.p;
let b = b % self.p;
((a as u128 * b as u128) % self.p as u128) as u64
}
#[inline]
pub fn inv(&self, a: u64) -> u64 {
let a = a % self.p;
assert!(a != 0, "cannot invert zero");
self.pow(a, self.p - 2)
}
#[inline]
pub fn div(&self, a: u64, b: u64) -> u64 {
self.mul(a, self.inv(b))
}
#[inline]
pub fn pow(&self, mut a: u64, mut e: u64) -> u64 {
a %= self.p;
let mut result = 1u64;
while e > 0 {
if e & 1 == 1 {
result = self.mul(result, a);
}
a = self.mul(a, a);
e >>= 1;
}
result
}
}