1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
use super::*;

pub use self::free_monoid::*;
pub use self::free_group::*;
pub use self::free_pow::*;

mod free_monoid;
mod free_group;
mod free_pow;

///Multiplication of terms using a type's intrinsic [addition](Add) operation
pub struct AddRule;
///Multiplication of terms using a type's intrinsic [multiplication](Mul) operation
pub struct MulRule;

impl<R,T:Add<Output=T>+AddAssociative> AssociativeAlgebraRule<R,T> for AddRule {}
impl<R,T:Add<Output=T>+AddCommutative> CommutativeAlgebraRule<R,T> for AddRule {}
impl<R,T:Add<Output=T>> AlgebraRule<R,T> for AddRule {
    fn apply(t1:T, t2:T) -> (Option<R>,T) { (None, t1+t2) }
}
impl<R,T:Add<Output=T>+Zero> UnitalAlgebraRule<R,T> for AddRule {
    fn one() -> T { T::zero() }
    fn is_one(t:&T) -> bool { t.is_zero() }
}

impl<R,T:Mul<Output=T>+MulAssociative> AssociativeAlgebraRule<R,T> for MulRule {}
impl<R,T:Mul<Output=T>+MulCommutative> CommutativeAlgebraRule<R,T> for MulRule {}
impl<R,T:Mul<Output=T>> AlgebraRule<R,T> for MulRule {
    fn apply(t1:T, t2:T) -> (Option<R>,T) { (None, t1*t2) }
}
impl<R,T:Mul<Output=T>+One+PartialEq> UnitalAlgebraRule<R,T> for MulRule {
    fn one() -> T { T::one() }
    fn is_one(t:&T) -> bool { t.is_one() }
}

///
///A [FreeModule] over some monoid, but with a multiplication between elements given using the monoid operation
///
///# Examples
///```
///use maths_traits::algebra::*;
///use free_algebra::MonoidRing;
///
///#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
///pub enum SplitComplexUnit { One, J }
///
///impl MulAssociative for SplitComplexUnit {}
///impl MulCommutative for SplitComplexUnit {}
///impl Mul for SplitComplexUnit {
///    type Output = Self;
///    fn mul(self, rhs:Self) -> Self {
///        match self {
///            One => rhs,
///            J => match rhs {
///                One => J,
///                J => One,
///            }
///        }
///    }
///}
///
///impl maths_traits::algebra::One for SplitComplexUnit {
///    fn one() -> Self { One }
///    fn is_one(&self) -> bool { if let One=self { true } else { false } }
///}
///
///use SplitComplexUnit::*;
///type SplitComplex<R> = MonoidRing<R,SplitComplexUnit>;
///
///let x = SplitComplex::one() * 2.5 + SplitComplex::one() * (3.0, J);
///let y = SplitComplex::one() * 4.0 + SplitComplex::one() * (2.0, J);
///
///assert_eq!([x[&One], x[&J]], [2.5, 3.0]);
///assert_eq!([y[&One], y[&J]], [4.0, 2.0]);
///
///let z = x * y;
///assert_eq!([z[&One], z[&J]], [16.0, 17.0]);
///
///```
///
pub type MonoidRing<R,M> = ModuleString<R,M,MulRule>;

///
///A [module](RingModule) over a ring constructed from free addition scalar-multiplication of elements of a set
///
///Concretely, given a set `T` and ring `R`, we construct the free-module of `T` over `R` as
///the set of linear combination over elements in `T` where the scalars are in `R`. In practice,
///though, this construction is effectively just polynomials with variables from `T` but without
///multiplication.
///
///# Examples
///```
///use maths_traits::algebra::Zero;
///use free_algebra::FreeModule;
///
///let p = FreeModule::zero() + (3.5, 'x') + (2.0, 'y') + (1.0, 'x');
///let q = FreeModule::zero() - (1.5, 'x') + (2.0, 'y');
///
///assert_eq!([p[&'x'], p[&'y']], [4.5, 2.0]);
///assert_eq!([q[&'x'], q[&'y']], [-1.5, 2.0]);
///
///let r = &p + &q;
///let s = (p - q) * 0.5;
///
///assert_eq!([r[&'x'], r[&'y']], [3.0, 4.0]);
///assert_eq!([s[&'x'], s.get(&'y')], [3.0, 0.0]);
///
///```
///
pub type FreeModule<R,T> = ModuleString<R,T,!>;

///
///A [module](RingModule) over a ring constructed from free multiplication and addition of elements of a set
///
///Concretely, this is a [MonoidRing] of the [FreeMonoid] over `T` with coeffients in `R`. However,
///effectively, this just makes polynomials with elements of `T` as variables and coefficients in `R`,
///but where multiplication isn't commutative.
///
///# Examples
///```
///use maths_traits::algebra::One;
///use free_algebra::{FreeAlgebra, FreeMonoid};
///
///let one = FreeMonoid::one();
///let x:FreeMonoid<_> = 'x'.into();
///let y:FreeMonoid<_> = 'y'.into();
///
///let p = FreeAlgebra::<f32,_>::one() + &x;
///let q = FreeAlgebra::<f32,_>::one() - &y;
///
///assert_eq!([p[&one], p[&x]], [1.0, 1.0]);
///assert_eq!([q[&one], q[&y]], [1.0, -1.0]);
///
///let r = p * q;
///assert_eq!([r[&one], r[&x], r[&y], r[&(x*y)]], [1.0, 1.0, -1.0, -1.0]);
///
///```
///
pub type FreeAlgebra<R,T> = MonoidRing<R,FreeMonoid<T>>;