#![doc(include = "../../doc/references.md")]
use crate::monoid::*;
use crate::helpers::*;
use crate::numeric::*;
use crate::com_group::*;
pub trait Ring: AddComGroup + MulMonoid {}
pub trait RingLaws: Ring {
fn left_distributivity(&self, x: &Self, y: &Self) -> bool {
self.mul(&x.add(y)) == self.mul(x).add(&self.mul(y))
}
fn right_distributivity(&self, x: &Self, y: &Self) -> bool {
x.add(y).mul(self) == x.mul(self).add(&y.mul(self))
}
fn distributivity(&self, x: &Self, y: &Self) -> bool {
self.left_distributivity(x, y) && self.right_distributivity(x, y)
}
fn left_absorption(&self) -> bool {
self.mul(&Self::zero()) == Self::zero()
}
fn right_absorption(&self) -> bool {
Self::zero().mul(self) == Self::zero()
}
fn absorption(&self) -> bool {
self.left_absorption() && self.right_absorption()
}
fn left_negation(&self, x: &Self) -> bool {
self.negate().mul(x) == self.mul(x).negate()
}
fn right_negation(&self, x: &Self) -> bool {
self.mul(&x.negate()) == self.mul(x).negate()
}
fn negation(&self, x: &Self) -> bool {
self.left_negation(x) && self.right_negation(x)
}
fn left_zero_divisors(&self, x: &Self) -> bool {
imply(self.mul(x).is_zero(), self.is_zero() || x.is_zero())
}
fn right_zero_divisors(&self, x: &Self) -> bool {
imply(x.mul(self).is_zero(), self.is_zero() || x.is_zero())
}
fn zero_divisors(&self, x: &Self) -> bool {
self.left_zero_divisors(x) && self.right_zero_divisors(x)
}
}
impl<R: Ring> RingLaws for R {}
pub trait NumRingLaws: NumEq + Ring {
fn num_left_distributivity(&self, x: &Self, y: &Self, eps: &Self::Eps) -> bool {
self.mul(&x.add(y)).num_eq(&self.mul(x).add(&self.mul(y)), eps)
}
fn num_right_distributivity(&self, x: &Self, y: &Self, eps: &Self::Eps) -> bool {
x.add(y).mul(self).num_eq(&x.mul(self).add(&y.mul(self)), eps)
}
fn num_distributivity(&self, x: &Self, y: &Self, eps: &Self::Eps) -> bool {
self.num_left_distributivity(x, y, eps) && self.num_right_distributivity(x, y, eps)
}
fn num_left_absorption(&self, eps: &Self::Eps) -> bool {
self.mul(&Self::zero()).num_eq(&Self::zero(), eps)
}
fn num_right_absorption(&self, eps: &Self::Eps) -> bool {
Self::zero().mul(self).num_eq(&Self::zero(), eps)
}
fn num_absorption(&self, eps: &Self::Eps) -> bool {
self.num_left_absorption(eps) && self.num_right_absorption(eps)
}
fn num_left_negation(&self, x: &Self, eps: &Self::Eps) -> bool {
self.negate().mul(x).num_eq(&self.mul(x).negate(), eps)
}
fn num_right_negation(&self, x: &Self, eps: &Self::Eps) -> bool {
self.mul(&x.negate()).num_eq(&self.mul(x).negate(), eps)
}
fn num_negation(&self, x: &Self, eps: &Self::Eps) -> bool {
self.num_left_negation(x, eps) && self.num_right_negation(x, eps)
}
fn num_left_zero_divisors(&self, x: &Self, _: &Self::Eps) -> bool {
imply(self.mul(x).is_zero(), self.is_zero() || x.is_zero())
}
fn num_right_zero_divisors(&self, x: &Self, _: &Self::Eps) -> bool {
imply(x.mul(self).is_zero(), self.is_zero() || x.is_zero())
}
fn num_zero_divisors(&self, x: &Self, eps: &Self::Eps) -> bool {
self.num_left_zero_divisors(x, eps) && self.num_right_zero_divisors(x, eps)
}
}
impl<R: NumEq + Ring> NumRingLaws for R {}
macro_rules! numeric_ring {
($type:ty) => {
impl Ring for $type {}
};
($type:ty, $($others:ty),+) => {
numeric_ring! {$type}
numeric_ring! {$($others),+}
};
}
numeric_ring! {
i8, i16, i32, i64, i128, isize, f32, f64
}
impl Ring for () {}
impl<A: Ring> Ring for (A,) {}
impl<A: Ring, B: Ring> Ring for (A, B) {}
impl<A: Ring, B: Ring, C: Ring> Ring for (A, B, C) {}
macro_rules! array_ring {
($size:expr) => {
impl<T: Copy + Ring> Ring for [T; $size] {}
};
($size:expr, $($others:expr),+) => {
array_ring! {$size}
array_ring! {$($others),+}
};
}
array_ring! {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
}
#[cfg(test)]
mod tests;