use crate::Data;
#[deprecated]
pub use self::Abelian as Diff;
pub trait Semigroup : ::std::marker::Sized + Data + Clone {
fn plus_equals(&mut self, rhs: &Self);
fn is_zero(&self) -> bool;
}
pub trait Monoid : Semigroup {
fn zero() -> Self;
}
pub trait Abelian : Monoid {
fn negate(self) -> Self;
}
pub trait Multiply<Rhs = Self> {
type Output;
fn multiply(self, rhs: &Rhs) -> Self::Output;
}
macro_rules! builtin_implementation {
($t:ty) => {
impl Semigroup for $t {
#[inline] fn plus_equals(&mut self, rhs: &Self) { *self += rhs; }
#[inline] fn is_zero(&self) -> bool { self == &0 }
}
impl Monoid for $t {
#[inline] fn zero() -> Self { 0 }
}
impl Multiply<Self> for $t {
type Output = Self;
fn multiply(self, rhs: &Self) -> Self { self * rhs}
}
};
}
macro_rules! builtin_abelian_implementation {
($t:ty) => {
impl Abelian for $t {
#[inline] fn negate(self) -> Self { -self }
}
};
}
builtin_implementation!(i8);
builtin_implementation!(i16);
builtin_implementation!(i32);
builtin_implementation!(i64);
builtin_implementation!(i128);
builtin_implementation!(isize);
builtin_implementation!(u8);
builtin_implementation!(u16);
builtin_implementation!(u32);
builtin_implementation!(u64);
builtin_implementation!(u128);
builtin_implementation!(usize);
builtin_abelian_implementation!(i8);
builtin_abelian_implementation!(i16);
builtin_abelian_implementation!(i32);
builtin_abelian_implementation!(i64);
builtin_abelian_implementation!(i128);
builtin_abelian_implementation!(isize);
macro_rules! wrapping_implementation {
($t:ty) => {
impl Semigroup for $t {
#[inline] fn plus_equals(&mut self, rhs: &Self) { *self += rhs; }
#[inline] fn is_zero(&self) -> bool { self == &std::num::Wrapping(0) }
}
impl Monoid for $t {
#[inline] fn zero() -> Self { std::num::Wrapping(0) }
}
impl Abelian for $t {
#[inline] fn negate(self) -> Self { -self }
}
impl Multiply<Self> for $t {
type Output = Self;
fn multiply(self, rhs: &Self) -> Self { self * rhs}
}
};
}
wrapping_implementation!(std::num::Wrapping<i8>);
wrapping_implementation!(std::num::Wrapping<i16>);
wrapping_implementation!(std::num::Wrapping<i32>);
wrapping_implementation!(std::num::Wrapping<i64>);
wrapping_implementation!(std::num::Wrapping<i128>);
wrapping_implementation!(std::num::Wrapping<isize>);
pub use self::present::Present;
mod present {
use abomonation_derive::Abomonation;
use serde::{Deserialize, Serialize};
#[derive(Abomonation, Copy, Ord, PartialOrd, Eq, PartialEq, Debug, Clone, Serialize, Deserialize, Hash)]
pub struct Present;
impl<T: Clone> super::Multiply<T> for Present {
type Output = T;
fn multiply(self, rhs: &T) -> T {
rhs.clone()
}
}
impl super::Semigroup for Present {
fn plus_equals(&mut self, _rhs: &Self) { }
fn is_zero(&self) -> bool { false }
}
}
mod tuples {
use super::{Semigroup, Monoid, Abelian, Multiply};
macro_rules! tuple_implementation {
( ($($name:ident)*), ($($name2:ident)*) ) => (
impl<$($name: Semigroup),*> Semigroup for ($($name,)*) {
#[allow(non_snake_case)]
#[inline] fn plus_equals(&mut self, rhs: &Self) {
let ($(ref mut $name,)*) = *self;
let ($(ref $name2,)*) = *rhs;
$($name.plus_equals($name2);)*
}
#[allow(unused_mut)]
#[allow(non_snake_case)]
#[inline] fn is_zero(&self) -> bool {
let mut zero = true;
let ($(ref $name,)*) = *self;
$( zero &= $name.is_zero(); )*
zero
}
}
impl<$($name: Monoid),*> Monoid for ($($name,)*) {
#[allow(non_snake_case)]
#[inline] fn zero() -> Self {
( $($name::zero(), )* )
}
}
impl<$($name: Abelian),*> Abelian for ($($name,)*) {
#[allow(non_snake_case)]
#[inline] fn negate(self) -> Self {
let ($($name,)*) = self;
( $($name.negate(), )* )
}
}
impl<T, $($name: Multiply<T>),*> Multiply<T> for ($($name,)*) {
type Output = ($(<$name as Multiply<T>>::Output,)*);
#[allow(unused_variables)]
#[allow(non_snake_case)]
#[inline] fn multiply(self, rhs: &T) -> Self::Output {
let ($($name,)*) = self;
( $($name.multiply(rhs), )* )
}
}
)
}
tuple_implementation!((), ());
tuple_implementation!((A1), (A2));
tuple_implementation!((A1 B1), (A2 B2));
tuple_implementation!((A1 B1 C1), (A2 B2 C2));
tuple_implementation!((A1 B1 C1 D1), (A2 B2 C2 D2));
}
mod vector {
use super::{Semigroup, Monoid, Abelian, Multiply};
impl<R: Semigroup> Semigroup for Vec<R> {
fn plus_equals(&mut self, rhs: &Self) {
while self.len() < rhs.len() {
let element = &rhs[self.len()];
self.push(element.clone());
}
for (index, update) in rhs.iter().enumerate() {
self[index].plus_equals(update);
}
}
fn is_zero(&self) -> bool {
self.iter().all(|x| x.is_zero())
}
}
impl<R: Monoid> Monoid for Vec<R> {
fn zero() -> Self {
Self::new()
}
}
impl<R: Abelian> Abelian for Vec<R> {
fn negate(mut self) -> Self {
for update in self.iter_mut() {
*update = update.clone().negate();
}
self
}
}
impl<T, R: Multiply<T>> Multiply<T> for Vec<R> {
type Output = Vec<<R as Multiply<T>>::Output>;
fn multiply(self, rhs: &T) -> Self::Output {
self.into_iter()
.map(|x| x.multiply(rhs))
.collect()
}
}
}