#![doc(include = "../../doc/references.md")]
use crate::numeric::*;
use crate::semigroup::*;
pub trait MulMonoid: MulSemigroup {
fn one() -> Self;
fn is_one(&self) -> bool {
*self == Self::one()
}
}
pub trait MulMonoidLaws: MulMonoid {
fn left_identity(&self) -> bool {
Self::one().mul(self) == *self
}
fn right_identity(&self) -> bool {
self.mul(&Self::one()) == *self
}
fn identity(&self) -> bool {
self.left_identity() && self.right_identity()
}
}
impl<M: MulMonoid> MulMonoidLaws for M {}
pub trait NumMulMonoidLaws: NumEq + MulMonoid {
fn num_left_identity(&self, eps: &Self::Eps) -> bool {
Self::one().mul(self).num_eq(&self, eps)
}
fn num_right_identity(&self, eps: &Self::Eps) -> bool {
self.mul(&Self::one()).num_eq(&self, eps)
}
fn num_identity(&self, eps: &Self::Eps) -> bool {
self.num_left_identity(eps) && self.num_right_identity(eps)
}
}
impl<M: NumEq + MulMonoid> NumMulMonoidLaws for M {}
macro_rules! numeric_mul_monoid {
($type:ty) => {
impl MulMonoid for $type {
fn one() -> Self {
1 as Self
}
}
};
($type:ty, $($others:ty),+) => {
numeric_mul_monoid! {$type}
numeric_mul_monoid! {$($others),+}
};
}
numeric_mul_monoid! {
u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize, f32, f64
}
impl MulMonoid for () {
fn one() -> Self {}
}
impl<T: MulMonoid> MulMonoid for (T,) {
fn one() -> Self {
(T::one(), )
}
}
impl<A: MulMonoid, B: MulMonoid> MulMonoid for (A, B) {
fn one() -> Self {
(A::one(), B::one())
}
}
impl<A: MulMonoid, B: MulMonoid, C: MulMonoid> MulMonoid for (A, B, C) {
fn one() -> Self {
(A::one(), B::one(), C::one())
}
}
macro_rules! array_mul_monoid {
($size:expr) => {
impl<T: Copy + MulMonoid> MulMonoid for [T; $size] {
fn one() -> Self {
[T::one(); $size]
}
}
};
($size:expr, $($others:expr),+) => {
array_mul_monoid! {$size}
array_mul_monoid! {$($others),+}
};
}
array_mul_monoid! {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
}
#[cfg(test)]
mod tests;