#![doc(include = "../../doc/references.md")]
use crate::magma::*;
use crate::numeric::*;
pub trait MulSemigroup: MulMagma {}
pub trait MulSemigroupLaws: MulSemigroup {
fn associativity(&self, x: &Self, y: &Self) -> bool {
self.mul(&x.mul(y)) == self.mul(x).mul(y)
}
}
impl<S: MulSemigroup> MulSemigroupLaws for S {}
pub trait NumMulSemigroupLaws: NumEq + MulSemigroup {
fn num_associativity(&self, x: &Self, y: &Self, eps: &Self::Eps) -> bool {
self.mul(&x.mul(y)).num_eq(&self.mul(x).mul(y), eps)
}
}
impl<S: NumEq + MulSemigroup> NumMulSemigroupLaws for S {}
macro_rules! numeric_mul_semigroup {
($type:ty) => {
impl MulSemigroup for $type {}
};
($type:ty, $($others:ty),+) => {
numeric_mul_semigroup! {$type}
numeric_mul_semigroup! {$($others),+}
};
}
numeric_mul_semigroup! {
u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize, f32, f64
}
impl MulSemigroup for () {}
impl<A: MulSemigroup> MulSemigroup for (A,) {}
impl<A: MulSemigroup, B: MulSemigroup> MulSemigroup for (A, B) {}
impl<A: MulSemigroup, B: MulSemigroup, C: MulSemigroup> MulSemigroup for (A, B, C) {}
macro_rules! array_mul_semigroup {
($size:expr) => {
impl<T: Copy + MulSemigroup> MulSemigroup for [T; $size] {}
};
($size:expr, $($others:expr),+) => {
array_mul_semigroup! {$size}
array_mul_semigroup! {$($others),+}
};
}
array_mul_semigroup! {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
}
#[cfg(test)]
mod tests;