#![doc(include = "../../doc/references.md")]
use crate::numeric::*;
use crate::monoid::*;
use crate::helpers::*;
pub trait AddGroup: AddMonoid {
fn negate(&self) -> Self;
fn sub(&self, other: &Self) -> Self {
self.add(&other.negate())
}
}
pub trait AddGroupLaws: AddGroup {
fn left_inverse(&self) -> bool {
self.negate().add(self) == Self::zero()
}
fn right_inverse(&self) -> bool {
self.add(&self.negate()) == Self::zero()
}
fn inverses(&self) -> bool {
self.left_inverse() && self.right_inverse()
}
}
impl<G: AddGroup> AddGroupLaws for G {}
pub trait NumAddGroupLaws: NumEq + AddGroup {
fn num_left_inverse(&self, eps: &Self::Eps) -> bool {
self.negate().add(self).num_eq(&Self::zero(), eps)
}
fn num_right_inverse(&self, eps: &Self::Eps) -> bool {
self.add(&self.negate()).num_eq(&Self::zero(), eps)
}
fn num_inverses(&self, eps: &Self::Eps) -> bool {
self.num_left_inverse(eps) && self.num_right_inverse(eps)
}
}
impl<G: NumEq + AddGroup> NumAddGroupLaws for G {}
macro_rules! integer_add_group {
($type:ty) => {
impl AddGroup for $type {
fn negate(&self) -> Self {
self.wrapping_neg()
}
}
};
($type:ty, $($others:ty),+) => {
integer_add_group! {$type}
integer_add_group! {$($others),+}
};
}
integer_add_group! {
i8, i16, i32, i64, i128, isize
}
macro_rules! float_add_group {
($type:ty) => {
impl AddGroup for $type {
fn negate(&self) -> Self {
-*self
}
}
};
($type:ty, $($others:ty),+) => {
float_add_group! {$type}
float_add_group! {$($others),+}
};
}
float_add_group! {
f32, f64
}
impl AddGroup for () {
fn negate(&self) -> Self {}
}
impl<A: AddGroup> AddGroup for (A,) {
fn negate(&self) -> Self {
(self.0.negate(), )
}
}
impl<A: AddGroup, B: AddGroup> AddGroup for (A, B) {
fn negate(&self) -> Self {
(self.0.negate(), self.1.negate())
}
}
impl<A: AddGroup, B: AddGroup, C: AddGroup> AddGroup for (A, B, C) {
fn negate(&self) -> Self {
(self.0.negate(), self.1.negate(), self.2.negate())
}
}
macro_rules! array_add_group {
($size:expr) => {
impl<T: Copy + AddGroup> AddGroup for [T; $size] {
fn negate(&self) -> Self {
self.map(&|&x| x.negate())
}
}
};
($size:expr, $($others:expr),+) => {
array_add_group! {$size}
array_add_group! {$($others),+}
};
}
array_add_group! {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
}
#[cfg(test)]
mod tests;