use std::ops::{AddAssign, Neg, Mul};
use std::iter::Iterator;
use ::Data;
pub use self::Abelian as Diff;
pub trait Monoid : for<'a> AddAssign<&'a Self> + ::std::marker::Sized + Data + Clone {
#[inline(always)]
fn is_zero(&self) -> bool { self.eq(&Self::zero()) }
fn zero() -> Self;
}
pub trait Abelian : Monoid + Neg<Output=Self> { }
impl<T: Monoid + Neg<Output=Self>> Abelian for T { }
impl Monoid for isize {
#[inline(always)] fn zero() -> Self { 0 }
}
impl Monoid for i64 {
#[inline(always)] fn zero() -> Self { 0 }
}
impl Monoid for i32 {
#[inline(always)] fn zero() -> Self { 0 }
}
#[derive(Abomonation, Copy, Ord, PartialOrd, Eq, PartialEq, Debug, Clone, Serialize, Deserialize)]
pub struct DiffPair<R1, R2> {
pub element1: R1,
pub element2: R2,
}
impl<R1, R2> DiffPair<R1, R2> {
#[inline(always)] pub fn new(elt1: R1, elt2: R2) -> Self {
DiffPair {
element1: elt1,
element2: elt2,
}
}
}
impl<R1: Monoid, R2: Monoid> Monoid for DiffPair<R1, R2> {
#[inline(always)] fn zero() -> Self {
DiffPair {
element1: R1::zero(),
element2: R2::zero(),
}
}
}
impl<'a, R1: AddAssign<&'a R1>, R2: AddAssign<&'a R2>> AddAssign<&'a DiffPair<R1, R2>> for DiffPair<R1, R2> {
#[inline(always)] fn add_assign(&mut self, rhs: &'a Self) {
self.element1 += &rhs.element1;
self.element2 += &rhs.element2;
}
}
impl<R1: Neg, R2: Neg> Neg for DiffPair<R1, R2> {
type Output = DiffPair<<R1 as Neg>::Output, <R2 as Neg>::Output>;
#[inline(always)] fn neg(self) -> Self::Output {
DiffPair {
element1: -self.element1,
element2: -self.element2,
}
}
}
impl<T: Copy, R1: Mul<T>, R2: Mul<T>> Mul<T> for DiffPair<R1,R2> {
type Output = DiffPair<<R1 as Mul<T>>::Output, <R2 as Mul<T>>::Output>;
fn mul(self, other: T) -> Self::Output {
DiffPair::new(
self.element1 * other,
self.element2 * other,
)
}
}
#[derive(Abomonation, Ord, PartialOrd, Eq, PartialEq, Debug, Clone, Serialize, Deserialize)]
pub struct DiffVector<R> {
buffer: Vec<R>,
}
impl<R> DiffVector<R> {
#[inline(always)]
pub fn new(vec: Vec<R>) -> DiffVector<R> {
DiffVector { buffer: vec }
}
}
impl<R> IntoIterator for DiffVector<R> {
type Item = R;
type IntoIter = ::std::vec::IntoIter<R>;
fn into_iter(self) -> Self::IntoIter {
self.buffer.into_iter()
}
}
impl<R: Monoid> Monoid for DiffVector<R> {
#[inline(always)] fn is_zero(&self) -> bool {
self.buffer.iter().all(|x| x.is_zero())
}
#[inline(always)] fn zero() -> Self {
Self { buffer: Vec::new() }
}
}
impl<'a, R: AddAssign<&'a R>+Clone> AddAssign<&'a DiffVector<R>> for DiffVector<R> {
#[inline(always)]
fn add_assign(&mut self, rhs: &'a Self) {
while self.buffer.len() < rhs.buffer.len() {
let element = &rhs.buffer[self.buffer.len()];
self.buffer.push(element.clone());
}
for (index, update) in rhs.buffer.iter().enumerate() {
self.buffer[index] += update;
}
}
}
impl<R: Neg<Output=R>+Clone> Neg for DiffVector<R> {
type Output = DiffVector<<R as Neg>::Output>;
#[inline(always)]
fn neg(mut self) -> Self::Output {
for update in self.buffer.iter_mut() {
*update = -update.clone();
}
self
}
}
impl<T: Copy, R: Mul<T>> Mul<T> for DiffVector<R> {
type Output = DiffVector<<R as Mul<T>>::Output>;
fn mul(self, other: T) -> Self::Output {
let buffer =
self.buffer
.into_iter()
.map(|x| x * other)
.collect();
DiffVector { buffer }
}
}