#![doc(include = "../../doc/references.md")]
use crate::monoid::*;
use crate::helpers::*;
pub trait Group: Monoid {
fn inverse(&self) -> Self;
fn cancel(&self) -> Self {
self.op(&self.inverse())
}
}
pub trait GroupLaws: Group {
fn left_inverse(&self) -> bool {
self.inverse().op(self) == Self::id()
}
fn right_inverse(&self) -> bool {
self.op(&self.inverse()) == Self::id()
}
fn inverses(&self) -> bool {
self.left_inverse() && self.right_inverse()
}
}
impl<S: Group> GroupLaws for S {}
impl Group for () {
fn inverse(&self) -> Self {}
}
impl<A: Group> Group for (A,) {
fn inverse(&self) -> Self {
(self.0.inverse(), )
}
}
impl<A: Group, B: Group> Group for (A, B) {
fn inverse(&self) -> Self {
(self.0.inverse(), self.1.inverse())
}
}
impl<A: Group, B: Group, C: Group> Group for (A, B, C) {
fn inverse(&self) -> Self {
(self.0.inverse(), self.1.inverse(), self.2.inverse())
}
}
macro_rules! array_group {
($size:expr) => {
impl<T: Copy + Group> Group for [T; $size] {
fn inverse(&self) -> Self {
self.map(&|&x| x.inverse())
}
}
};
($size:expr, $($others:expr),+) => {
array_group! {$size}
array_group! {$($others),+}
};
}
array_group! {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
}