use super::*;
use std::collections::hash_map;
#[derive(Derivative)]
#[derivative(Clone(clone_from="true"))]
#[derivative(Default(bound=""))]
#[derivative(PartialEq, Eq, Hash)]
#[derivative(Debug="transparent")]
pub struct ModuleString<R,T:Hash+Eq,A:?Sized> {
#[derivative(Hash(bound="HashMap<T,R>:Hash"))]
#[derivative(Default(value="HashMap::with_capacity(0)"))]
terms: HashMap<T,R>,
#[derivative(PartialEq="ignore", Hash="ignore")]
#[derivative(Debug="ignore")]
rule: PhantomData<Box<A>>
}
impl<R:Display,T:Hash+Eq+Display,A:?Sized> Display for ModuleString<R,T,A> {
fn fmt(&self, f: &mut Formatter) -> ::std::fmt::Result {
if self.len() == 0 {
match R::_zero() {
Some(zero) => write!(f, "{}", zero)?,
None => write!(f, "{}", 0)?,
}
} else {
if self.len() > 1 { write!(f, "(")?; }
trait IsTOne<R,T> { fn _is_t_one(t:&T) -> bool; }
impl<R,T,A:?Sized> IsTOne<R,T> for A { default fn _is_t_one(_:&T) -> bool {false} }
impl<R,T,A:UnitalAlgebraRule<R,T>+?Sized> IsTOne<R,T> for A { fn _is_t_one(t:&T) -> bool {A::is_one(t)} }
trait IsOne { fn _is_one(&self) -> bool; }
impl<R> IsOne for R { default fn _is_one(&self) -> bool {false} }
impl<R:One+PartialEq> IsOne for R { fn _is_one(&self) -> bool { self.is_one() } }
let mut first = true;
for (r,t) in self.iter() {
if !first {
write!(f, " + ")?;
} else {
first = false;
}
if !<A as IsTOne<R,T>>::_is_t_one(t) {
if (*r)._is_one() {
if f.alternate() {
write!(f, "{:#}", t)?;
} else {
write!(f, "{}", t)?;
}
} else {
if f.alternate() {
write!(f, "{:#}{:#}", r, t)?;
} else {
write!(f, "{}*{}", r, t)?;
}
}
} else {
write!(f, "{}", r)?;
}
}
if self.len() > 1 { write!(f, ")")?; }
}
Ok(())
}
}
pub type Iter<'a,R,T> = Map<hash_map::Iter<'a,T,R>, fn((&'a T,&'a R)) -> (&'a R,&'a T)>;
pub type IntoIter<R,T> = Map<hash_map::IntoIter<T,R>, fn((T,R)) -> (R,T)>;
pub struct IterMut<'a, R:AddAssign, T:Hash+Eq, A:?Sized> {
dest_ref: &'a mut ModuleString<R,T,A>,
next: Option<(R,T)>,
iter: IntoIter<R,T>
}
impl<'a,T:Hash+Eq,R:AddAssign,A:?Sized> FusedIterator for IterMut<'a,R,T,A> {}
impl<'a,T:Hash+Eq,R:AddAssign,A:?Sized> ExactSizeIterator for IterMut<'a,R,T,A> {}
impl<'a,T:Hash+Eq,R:AddAssign,A:?Sized> Iterator for IterMut<'a,R,T,A> {
type Item = (&'a mut R, &'a mut T);
fn next(&mut self) -> Option<Self::Item> {
self.next.take().map(|t| *self.dest_ref += t);
self.next = self.iter.next();
self.next.as_mut().map(|t| unsafe {&mut *(t as *mut (R,T))} ).map(|t| (&mut t.0, &mut t.1))
}
fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
}
impl<'a,T:Hash+Eq,R:AddAssign,A:?Sized> Drop for IterMut<'a,R,T,A> {
fn drop(&mut self) {
loop { if let None = self.next() {break;} }
}
}
impl<T:Hash+Eq,R:One,A:?Sized> From<T> for ModuleString<R,T,A> {
#[inline] fn from(t:T) -> Self {(R::one(),t).into()}
}
impl<T:Hash+Eq,R:One,A:?Sized> From<(R, T)> for ModuleString<R,T,A> {
#[inline]
fn from((r,t):(R,T)) -> Self {
let mut m = HashMap::new();
m.insert(t, r);
ModuleString{terms:m, rule:PhantomData}
}
}
impl<T:Hash+Eq,R,A:?Sized,I> Index<I> for ModuleString<R,T,A> where HashMap<T,R>:Index<I> {
type Output = <HashMap<T,R> as Index<I>>::Output;
#[inline] fn index(&self, i:I) -> &Self::Output {&self.terms[i]}
}
impl<T:Hash+Eq,R,A:?Sized> IntoIterator for ModuleString<R,T,A> {
type Item = (R,T);
type IntoIter = IntoIter<R,T>;
#[inline] fn into_iter(self) -> IntoIter<R,T> { self.terms.into_iter().map(|(t,r)| (r,t)) }
}
impl<T:Hash+Eq,R,A:?Sized> ModuleString<R,T,A> {
pub fn len(&self) -> usize {self.terms.len()}
pub fn get_ref<Q:Hash+Eq>(&self, t: &Q) -> Option<&R> where T:Borrow<Q> {
self.terms.get(t)
}
pub fn get<Q:Hash+Eq>(&self, t: &Q) -> R where T:Borrow<Q>, R:Zero+Clone {
self.terms.get(t).map_or_else(|| R::zero(), |r| r.clone())
}
pub fn iter<'a>(&'a self) -> Iter<'a,R,T> { self.terms.iter().map(|(t,r)| (r,t)) }
pub fn iter_mut<'a>(&'a mut self) -> IterMut<'a,R,T,A> where R:AddAssign {
let mut temp = Self { terms: HashMap::with_capacity(self.len()), rule:PhantomData };
::std::mem::swap(self, &mut temp);
IterMut { dest_ref: self, next: None, iter: temp.into_iter() }
}
pub fn commutator(self, rhs:Self) -> Self where Self:MulMagma+Sub<Output=Self> {
self.clone()*rhs.clone() - rhs*self
}
}
impl<T:Hash+Eq,R,A:?Sized> ModuleString<R,T,A> {
fn insert_term<F:Fn(R)->R>(&mut self, rhs:(R,T), f:F) where R:AddAssign{
if !rhs.0._is_zero() {
let (r, t) = (f(rhs.0), rhs.1);
if let Some(r2) = self.terms.get_mut(&t) {
*r2 += r;
if (*r2)._is_zero() { self.terms.remove(&t); }
} else if !r._is_zero() {
self.terms.insert(t, r);
}
}
}
fn insert<I:IntoIterator<Item=(R,T)>, F:Fn(R)->R+Copy>(&mut self, rhs:I, f:F) where R:AddAssign {
rhs.into_iter().for_each(|term| self.insert_term(term, f));
}
fn clean(&mut self) { self.terms.retain(|_,r| !r._is_zero()); }
}
impl<T:Hash+Eq,R:AddAssign,A:?Sized> Extend<(R,T)> for ModuleString<R,T,A> {
fn extend<I:IntoIterator<Item=(R,T)>>(&mut self, iter:I) { self.insert(iter, |r| r) }
}
impl<T:Hash+Eq,R:AddAssign,A:?Sized> FromIterator<(R,T)> for ModuleString<R,T,A> {
fn from_iter<I:IntoIterator<Item=(R,T)>>(iter:I) -> Self {
let mut from = Self::default();
from.extend(iter);
from
}
}
impl<T:Hash+Eq,R:AddAssign+One,A:?Sized> FromIterator<T> for ModuleString<R,T,A> {
fn from_iter<I:IntoIterator<Item=T>>(iter:I) -> Self {
Self::from_iter(iter.into_iter().map(|t| (R::one(), t)))
}
}
impl<T:Hash+Eq,R:AddAssign,A:?Sized> FromIterator<Self> for ModuleString<R,T,A> {
fn from_iter<I:IntoIterator<Item=Self>>(iter:I) -> Self {
Self::from_iter(iter.into_iter().flatten())
}
}
impl<T:Hash+Eq,R:AddAssign,A:?Sized,K> Sum<K> for ModuleString<R,T,A> where Self:FromIterator<K> {
fn sum<I:Iterator<Item=K>>(iter:I) -> Self { Self::from_iter(iter) }
}
impl<T:Hash+Eq,R,A:?Sized,K> Product<K> for ModuleString<R,T,A> where Self:Mul<K,Output=Self>+One {
fn product<I:Iterator<Item=K>>(iter:I) -> Self { iter.into_iter().fold(Self::one(), |m,k| m*k) }
}
pub trait AlgebraRule<R,T> {
fn apply(t1:T, t2:T) -> (Option<R>,T);
}
pub trait AssociativeAlgebraRule<R,T>: AlgebraRule<R,T> {}
pub trait CommutativeAlgebraRule<R,T>: AlgebraRule<R,T> {}
pub trait UnitalAlgebraRule<R,T>: AlgebraRule<R,T> {
fn one() -> T;
fn is_one(t:&T) -> bool;
}
impl<T:Hash+Eq,R:AddAssociative,A:?Sized> AddAssociative for ModuleString<R,T,A> {}
impl<T:Hash+Eq,R:AddCommutative,A:?Sized> AddCommutative for ModuleString<R,T,A> {}
impl<T:Hash+Eq,R:MulAssociative,A:?Sized+AssociativeAlgebraRule<R,T>> MulAssociative for ModuleString<R,T,A> {}
impl<T:Hash+Eq,R:MulCommutative,A:?Sized+CommutativeAlgebraRule<R,T>> MulCommutative for ModuleString<R,T,A> {}
impl<T:Hash+Eq,R:Distributive,A:?Sized> Distributive for ModuleString<R,T,A> {}
impl<T:Hash+Eq,R:AddAssign,A:?Sized> AddAssign for ModuleString<R,T,A> {
fn add_assign(&mut self, rhs:Self) {self.insert(rhs, |r| r)}
}
impl<T:Hash+Eq,R:AddAssign+Neg<Output=R>,A:?Sized> SubAssign for ModuleString<R,T,A> {
fn sub_assign(&mut self, rhs:Self) {self.insert(rhs, |r| -r)}
}
impl<T:Hash+Eq,R:AddAssign,A:?Sized> AddAssign<(R,T)> for ModuleString<R,T,A> {
fn add_assign(&mut self, rhs:(R,T)) {self.insert_term(rhs, |r| r)}
}
impl<T:Hash+Eq,R:AddAssign+Neg<Output=R>,A:?Sized> SubAssign<(R,T)> for ModuleString<R,T,A> {
fn sub_assign(&mut self, rhs:(R,T)) {self.insert_term(rhs, |r| -r)}
}
impl<T:Hash+Eq,R:AddAssign+One,A:?Sized> AddAssign<T> for ModuleString<R,T,A> {
fn add_assign(&mut self, rhs:T) {*self+=(R::one(),rhs)}
}
impl<T:Hash+Eq,R:AddAssign+Neg<Output=R>+One,A:?Sized> SubAssign<T> for ModuleString<R,T,A> {
fn sub_assign(&mut self, rhs:T) {*self-=(R::one(),rhs)}
}
impl<T:Hash+Eq,R:MulAssign+Clone,A:?Sized> MulAssign<R> for ModuleString<R,T,A> {
fn mul_assign(&mut self, rhs:R) {
for r2 in self.terms.values_mut() { *r2 *= rhs.clone() }
self.clean();
}
}
impl<T:Hash+Eq,R:DivAssign+Clone,A:?Sized> DivAssign<R> for ModuleString<R,T,A> {
fn div_assign(&mut self, rhs:R) {
for r2 in self.terms.values_mut() { *r2 /= rhs.clone() }
self.clean();
}
}
impl_arith!(impl<T,R,A> AddAssign<&Self>.add_assign for ModuleString<R,T,A> where T:Hash+Eq,A:?Sized);
impl_arith!(impl<T,R,A> SubAssign<&Self>.sub_assign for ModuleString<R,T,A> where T:Hash+Eq,A:?Sized);
impl_arith!(impl<T,R,A> AddAssign<&T>.add_assign for ModuleString<R,T,A> where T:Hash+Eq,A:?Sized);
impl_arith!(impl<T,R,A> SubAssign<&T>.sub_assign for ModuleString<R,T,A> where T:Hash+Eq,A:?Sized);
impl_arith!(impl<T,R,A> MulAssign<&R>.mul_assign for ModuleString<R,T,A> where T:Hash+Eq,A:?Sized);
impl_arith!(impl<T,R,A> DivAssign<&R>.div_assign for ModuleString<R,T,A> where T:Hash+Eq,A:?Sized);
impl_arith!(impl<T,R,A> Add.add with AddAssign.add_assign for ModuleString<R,T,A> where T:Hash+Eq, A:?Sized);
impl_arith!(impl<T,R,A> Sub.sub with SubAssign.sub_assign for ModuleString<R,T,A> where T:Hash+Eq, A:?Sized);
impl_arith!(impl<T,R,A> Mul.mul with MulAssign.mul_assign for ModuleString<R,T,A> where T:Hash+Eq, A:?Sized);
impl_arith!(impl<T,R,A> Div.div with DivAssign.div_assign for ModuleString<R,T,A> where T:Hash+Eq, A:?Sized);
impl<T:Hash+Eq,R:Neg,A:?Sized> Neg for ModuleString<R,T,A> {
type Output = ModuleString<R::Output,T,A>;
fn neg(self) -> Self::Output {
ModuleString {
terms: self.terms.into_iter().map(|(t,r)| (t,-r)).filter(|(_,r)| r._is_zero()).collect(),
rule: PhantomData
}
}
}
impl<'a,T:Hash+Eq,R:Neg,A:?Sized> Neg for &'a ModuleString<R,T,A> where ModuleString<R,T,A>:Clone {
type Output = ModuleString<R::Output,T,A>;
#[inline] fn neg(self) -> Self::Output {-(*self).clone()}
}
impl<T:Hash+Eq,R:AddAssign,A:?Sized> Zero for ModuleString<R,T,A> {
#[inline] fn zero() -> Self {Default::default()}
#[inline] fn is_zero(&self) -> bool {self.terms.len()==0}
}
impl<T:Clone+Hash+Eq,R:PartialEq+UnitalSemiring,A:UnitalAlgebraRule<R,T>+?Sized> One for ModuleString<R,T,A> {
#[inline] fn one() -> Self { A::one().into() }
#[inline] fn is_one(&self) -> bool {
if self.terms.len()==1 {
let term = self.iter().next().unwrap();
term.0.is_one() && A::is_one(term.1)
} else {
false
}
}
}
impl<T:Hash+Eq+Clone,R:MulMagma+AddMagma,A:?Sized+AlgebraRule<R,T>> MulAssign<(R,T)> for ModuleString<R,T,A> {
fn mul_assign(&mut self, (r1,t1): (R,T)) {
let mut temp = HashMap::with_capacity(0);
::std::mem::swap(&mut self.terms, &mut temp);
*self = temp.into_iter().map(
|(t, r)| {
let (coeff, t2) = A::apply(t, t1.clone());
match coeff {
Some(r2) => ((r*r1.clone())*r2, t2),
None => (r*r1.clone(), t2),
}
}
).sum();
}
}
impl<T:Hash+Eq+Clone,R:Semiring,A:?Sized+AlgebraRule<R,T>> MulAssign for ModuleString<R,T,A> {
fn mul_assign(&mut self, rhs:Self) {
*self = rhs.terms.into_iter().map(|(t, r)| self.clone() * (r,t)).sum();
}
}
impl<Z,R,T,A> Pow<Z> for ModuleString<R,T,A> where
Z:Natural,
T:Hash+Eq+Clone,
R:PartialEq+UnitalSemiring,
A:?Sized+UnitalAlgebraRule<R,T>+AssociativeAlgebraRule<R,T>
{
type Output = Self;
fn pow(self, p:Z) -> Self { repeated_squaring(self, p) }
}