free_algebra/lib.rs
1//!
2//!Types for constructing free algebras over sets.
3//!
4//!# What even is a "Free Algebra"?
5//!
6//!In the context of this crate, the term "Algebra" refers to a range of mathematical
7//!constructions involving arithmetic operations, and the term "Free" refers to the nature of those
8//!operations. In particular, a "free" operation is one that is made with as little restriction
9//!as possible with respect to the desired set of rules.
10//!
11//!So, in general, the procedure for such a "free" construction is to start with some type `T` and
12//!some set of algebraic rules, and then operated on the elements of `T` as if they were a variable
13//!or symbol, applying the rules as necessary.
14//!
15//!As abstract as that sounds, there is actually a prime example of this already in the standard
16//!library, the [`Vec<T>`](Vec)! If we start with some type `T`, assert that multiplication be associative,
17//!and start multiplying elements like variables, the result is exactly the same as if we took
18// and implemented [multiplication](Mul) as concatenation. In fact, this is *precisely*
19//!what the [`FreeMonoid<T>`](FreeMonoid) type in this crate is.
20//!
21//!```
22//!use maths_traits::algebra::One;
23//!use free_algebra::FreeMonoid;
24//!
25//!let x: FreeMonoid<char> = FreeMonoid::one();
26//!let y = FreeMonoid::one() * 'a' * 'b';
27//!let z = FreeMonoid::one() * 'c' * 'd';
28//!
29//!assert_eq!(x, vec![]);
30//!assert_eq!(y, vec!['a', 'b']);
31//!assert_eq!(z, vec!['c', 'd']);
32//!assert_eq!(&y * &z, vec!['a', 'b', 'c', 'd']);
33//!assert_eq!(&z * &y, vec!['c', 'd', 'a', 'b']);
34//!
35//!```
36//!
37//!In addition to this, moreover, a number of other constructions can be achieved by changing
38//!which types are used, which operations are considered, and what rules are followed.
39//!Examples include:
40//! * [`FreeModule<R,T>`](FreeModule): Results from freely adding elements of `T` in an associative
41//! and commutative manner and allowing distributive multiplication by elements from `R`
42//! * [`FreeAlgebra<R,T>`](FreeAlgebra): The same as with [FreeModule], except that we allow for
43//! free multiplication of elements distributively (like with [FreeMonoid])
44//! * Polynomials: A [FreeAlgebra], but where multiplication between `T`'s is commutative and associative
45//! * Clifford algebra: A [FreeAlgebra], but where multiplication is associative and
46//! an element times itself results in a scalars
47//! * Complex numbers: Results from when `T` is either `1` and `i` and multiplies accordingly
48//! * Quaternions: Same as for Complex numbers, but with more imaginary units
49//!
50//!# Use cases
51//!
52//!The primary purposes for this crate fall into two general categories:
53//! * Use as an abstract foundation to create more specific systems like polynomials or Clifford algebras.
54//! * Utilization as a tool for lazily storing costly arithmetic operations for future evaluation.
55//!
56//!# Crate structures
57//!
58//!This crate consists of the following:
59//! * Two main structures for doing the free-arithmetic over some type
60//! * Traits for specifying the rules for arithmetic
61//! * Type aliases for particular combinations of construction and rules
62//!
63//!Specifically:
64//! * [MonoidalString] constructs free-multiplying structures over a type `T` using an order-dependent
65//! internal representation with a [`Vec<T>`](Vec) that determines its multiplication rule using an
66//! implementor of the trait [MonoidRule]. Aliases of this struct include [FreeMonoid] and [FreeGroup].
67//! * [ModuleString] constructs types consisting of terms of type `T` with scalars from
68//! some additive type `R` stored with an order independent [HashMap]. This grants all [ModuleString]'s
69//! an addition operation by adding the coeffients of like terms, and a free-multiplication can
70//! be included using an optional [AlgebraRule] parameter. Aliases of this struct include
71//! [FreeModule] and [FreeAlgebra].
72//!
73//!For more information, see the respective structs
74//!
75//!
76
77#![feature(specialization)]
78#![feature(marker_trait_attr)]
79#![feature(never_type)]
80
81#[macro_use] extern crate derivative;
82extern crate num_traits;
83extern crate maths_traits;
84
85pub use self::monoid::*;
86pub use self::module::*;
87
88use maths_traits::algebra::*;
89
90use num_traits::Pow;
91
92use std::marker::PhantomData;
93use std::borrow::Borrow;
94use std::collections::HashMap;
95use std::hash::Hash;
96use std::fmt::{Display, Formatter};
97
98use std::iter::*;
99
100macro_rules! impl_arith {
101
102 (impl<$($T:ident),*> $Trait:ident.$fun:ident with $TraitAssign:ident.$fun_assign:ident for $ty:ty where $($where:tt)*) => {
103
104 //impl of an op using its assign variant
105 impl<RHS, $($T),*> $Trait<RHS> for $ty where $($where)*, Self:$TraitAssign<RHS> {
106 type Output = Self;
107 #[inline] fn $fun(mut self, rhs:RHS) -> Self {self.$fun_assign(rhs); self}
108 }
109
110 //impl of an op on a reference
111 impl<'a, RHS, $($T),*> $Trait<RHS> for &'a $ty where $($where)*, $ty:Clone+$Trait<RHS> {
112 type Output = <$ty as $Trait<RHS>>::Output;
113 #[inline] fn $fun(self, rhs:RHS) -> Self::Output {(*self).clone().$fun(rhs)}
114 }
115 };
116
117 (impl<$($T:ident),*> $TraitAssign:ident<&$RHS:ident>.$fun_assign:ident for $ty:ty where $($where:tt)*) => {
118
119 //impl of an op with a reference
120 impl<'a, $($T),*> $TraitAssign<&'a $RHS> for $ty where $($where)*, Self:$TraitAssign<$RHS>, $RHS:Clone {
121 #[inline] fn $fun_assign(&mut self, rhs:&'a $RHS) {self.$fun_assign((*rhs).clone())}
122 }
123
124 }
125
126}
127
128pub(self) trait IsZero: Sized {
129 fn _is_zero(&self) -> bool;
130 fn _zero() -> Option<Self>;
131}
132impl<T> IsZero for T {
133 default fn _is_zero(&self) -> bool { false }
134 default fn _zero() -> Option<Self> {None}
135}
136impl<T:Zero> IsZero for T {
137 default fn _is_zero(&self) -> bool { self.is_zero() }
138 default fn _zero() -> Option<Self> { Some(Self::zero()) }
139}
140
141pub use self::specifics::*;
142mod specifics;
143
144pub mod monoid;
145pub mod module;