use core::fmt;
use core::ops::{Add, Sub, Mul};
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct Field {
pub v: u64,
}
impl fmt::Debug for Field {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Field({})", self.v)
}
}
impl Field {
pub const MOD: u64 = 65537;
pub fn new(x: u128) -> Self {
let m = Self::MOD as u128;
Field { v: (x % m) as u64 }
}
pub fn zero() -> Self {
Field { v: 0 }
}
pub fn one() -> Self {
Field { v: 1 % Self::MOD }
}
pub fn pow(self, mut exp: u128) -> Self {
let mut base = self;
let mut acc = Field::one();
while exp > 0 {
if exp & 1 != 0 {
acc = acc * base;
}
base = base * base;
exp >>= 1;
}
acc
}
pub fn inv(self) -> Option<Self> {
let (g, x, _y) = Self::egcd(self.v as i128, Self::MOD as i128);
if g != 1 && g != -1 {
return None;
}
let mut inv = x % (Self::MOD as i128);
if inv < 0 {
inv += Self::MOD as i128;
}
Some(Field { v: inv as u64 })
}
fn egcd(a: i128, b: i128) -> (i128, i128, i128) {
if b == 0 {
return (a.abs(), a.signum(), 0);
}
let (g, x1, y1) = Self::egcd(b, a % b);
(g, y1, x1 - (a / b) * y1)
}
}
impl Add for Field {
type Output = Self;
fn add(self, other: Self) -> Self {
let s = (self.v as u128 + other.v as u128) % (Self::MOD as u128);
Field::new(s)
}
}
impl Sub for Field {
type Output = Self;
fn sub(self, other: Self) -> Self {
let m = Self::MOD as u128;
let a = self.v as u128;
let b = other.v as u128;
Field::new((a + m - (b % m)) % m)
}
}
impl Mul for Field {
type Output = Self;
fn mul(self, other: Self) -> Self {
Field::new((self.v as u128) * (other.v as u128))
}
}