pub trait Domain: Clone + PartialEq + Eq + std::fmt::Debug + Sized {
type Element: Clone + PartialEq + Eq + std::fmt::Debug;
fn zero(&self) -> Self::Element;
fn one(&self) -> Self::Element;
fn add(&self, a: &Self::Element, b: &Self::Element) -> Self::Element;
fn sub(&self, a: &Self::Element, b: &Self::Element) -> Self::Element;
fn neg(&self, a: &Self::Element) -> Self::Element;
fn mul(&self, a: &Self::Element, b: &Self::Element) -> Self::Element;
fn div(&self, a: &Self::Element, b: &Self::Element) -> Option<Self::Element>;
fn inv(&self, a: &Self::Element) -> Option<Self::Element>;
fn is_zero(&self, a: &Self::Element) -> bool {
*a == self.zero()
}
fn is_one(&self, a: &Self::Element) -> bool {
*a == self.one()
}
fn mul_assign(&self, a: &mut Self::Element, b: &Self::Element) {
*a = self.mul(a, b);
}
fn sub_mul_assign(&self, a: &mut Self::Element, b: &Self::Element, c: &Self::Element) {
let bc = self.mul(b, c);
*a = self.sub(a, &bc);
}
fn pow(&self, a: &Self::Element, n: u64) -> Self::Element {
let mut base = a.clone();
let mut result = self.one();
let mut exp = n;
while exp > 0 {
if exp & 1 == 1 {
result = self.mul(&result, &base);
}
base = self.mul(&base, &base);
exp >>= 1;
}
result
}
fn cast_u64(&self, n: u64) -> Self::Element {
let mut result = self.zero();
let one = self.one();
for _ in 0..n {
result = self.add(&result, &one);
}
result
}
}
pub trait EuclideanDomain: Domain {
fn div_rem(
&self,
a: &Self::Element,
b: &Self::Element,
) -> Option<(Self::Element, Self::Element)>;
fn gcd(&self, a: &Self::Element, b: &Self::Element) -> Self::Element {
let mut a = a.clone();
let mut b = b.clone();
while !self.is_zero(&b) {
if let Some((_, r)) = self.div_rem(&a, &b) {
a = b;
b = r;
} else {
break;
}
}
a
}
fn extended_gcd(
&self,
a: &Self::Element,
b: &Self::Element,
) -> (Self::Element, Self::Element, Self::Element) {
let mut old_r = a.clone();
let mut r = b.clone();
let mut old_s = self.one();
let mut s = self.zero();
let mut old_t = self.zero();
let mut t = self.one();
while !self.is_zero(&r) {
if let Some((q, rem)) = self.div_rem(&old_r, &r) {
old_r = r;
r = rem;
let qs = self.mul(&q, &s);
let new_s = self.sub(&old_s, &qs);
old_s = s;
s = new_s;
let qt = self.mul(&q, &t);
let new_t = self.sub(&old_t, &qt);
old_t = t;
t = new_t;
} else {
break;
}
}
(old_r, old_s, old_t)
}
}