use crate::{Integer, Rational};
pub trait Ring: Sized + Clone + PartialEq {
fn zero() -> Self;
fn one() -> Self;
fn from_i64_coeff(v: i64) -> Self;
fn add(&self, other: &Self) -> Self;
fn sub(&self, other: &Self) -> Self;
fn mul(&self, other: &Self) -> Self;
fn neg(&self) -> Self;
fn is_zero(&self) -> bool;
fn is_one(&self) -> bool;
fn pow_u32(&self, e: u32) -> Self {
let mut acc = Self::one();
for _ in 0..e {
acc = acc.mul(self);
}
acc
}
}
pub trait Field: Ring {
fn inv(&self) -> Option<Self>;
}
impl Ring for Integer {
fn zero() -> Self {
Integer::zero()
}
fn one() -> Self {
Integer::one()
}
fn from_i64_coeff(v: i64) -> Self {
Integer::from_i64(v)
}
fn add(&self, other: &Self) -> Self {
Integer::add(self, other)
}
fn sub(&self, other: &Self) -> Self {
Integer::sub(self, other)
}
fn mul(&self, other: &Self) -> Self {
Integer::mul(self, other)
}
fn neg(&self) -> Self {
Integer::neg(self)
}
fn is_zero(&self) -> bool {
Integer::is_zero(self)
}
fn is_one(&self) -> bool {
Integer::is_one(self)
}
fn pow_u32(&self, e: u32) -> Self {
Integer::pow(self, e)
}
}
impl Ring for Rational {
fn zero() -> Self {
Rational::zero()
}
fn one() -> Self {
Rational::one()
}
fn from_i64_coeff(v: i64) -> Self {
Rational::from_integer(&Integer::from_i64(v))
}
fn add(&self, other: &Self) -> Self {
Rational::add(self, other)
}
fn sub(&self, other: &Self) -> Self {
Rational::sub(self, other)
}
fn mul(&self, other: &Self) -> Self {
Rational::mul(self, other)
}
fn neg(&self) -> Self {
Rational::neg(self)
}
fn is_zero(&self) -> bool {
Rational::is_zero(self)
}
fn is_one(&self) -> bool {
Rational::is_one(self)
}
fn pow_u32(&self, e: u32) -> Self {
Rational::pow_reduced(self, e)
}
}
impl Field for Rational {
fn inv(&self) -> Option<Self> {
Rational::inv_reduced(self)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn 整数环() {
let (a, b) = (Integer::from_i64(7), Integer::from_i64(-6));
assert!(a.add(&b).is_one());
let c = Integer::from_i64(7);
assert!(!c.mul(&Integer::from_i64(1)).is_one() || c.is_one());
assert_eq!(a.sub(&a), <Integer as Ring>::zero());
assert_eq!(Integer::from_i64(-3).pow_u32(3), Integer::from_i64(-27));
assert_eq!(<Integer as Ring>::from_i64_coeff(5), Integer::from_i64(5));
}
#[test]
fn 有理数域() {
let r = Rational::from_ints(&Integer::from_i64(3), &Integer::from_i64(4)).unwrap();
let inv = <Rational as Field>::inv(&r).unwrap();
assert!(inv.mul(&r).is_one());
assert!(Rational::zero().inv().is_none());
assert!(r.pow_u32(2).to_string() == "9/16");
}
}