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>>;