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 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
//! //!# Maths Traits //! //!A simple crate for sane and usable abstractions of common (and uncommon) mathematical constructs //!using the Rust trait system //! //!# Design Philosophy //! //!The framework in this crate is written to fit four design goals: //!* Traits should be flexible and assume as much mathematical abstraction as possible. //!* Trait names, functions, and categorization should fit their corresponding //! mathematical conventions. //!* Usage must be simple enough so that working with these generics instead of primitives add //! minimal complication //!* Implementation should utilize the [standard Rust][std::ops] or well established //! libraries (such as [`num_traits`]) as much as possible instead of creating new systems //! requiring significant special attention to support. //! //!# Usage //! //!The traits in this framework are split into two collections, one for individual features and mathematical //!properties and one for common mathematical structures, where the second set of traits is automatically //!implemented by grouping together functionality from the first set. This way, to support the system, //!structs need only implement each relevant property, and end users can simply use the single //!trait for whichever mathematical struct fits their needs. //! //!For example, to implement the [algebraic](algebra) features for a `Rational` type, //!you would implement [`Clone`](Clone), [`Add`](std::ops::Add), [`Sub`](std::ops::Sub), [`Mul`](std::ops::Mul), //![`Div`](std::ops::Div), [`Neg`](std::ops::Neg), [`Inv`](num_traits::Inv), [`Zero`](num_traits::Zero), //![`One`](num_traits::One), and their assign variants as normal. Then, by implementing the new traits //![`AddCommutative`](algebra::AddCommutative), [`AddAssociative`](algebra::AddAssociative), //![`MulCommutative`](algebra::MulCommutative), [`MulCommutative`](algebra::MulAssociative), and //![`Distributive`](algebra::Distributive), all of the categorization traits (such as [`Ring`](algebra::Ring) //!and [`MulMonoid`](algebra::MulMonoid)) will automatically be implemented and usable for our type. //! //!``` //!use math_traits::algebra::*; //! //!#[derive(Clone)] //necessary to auto-implement Ring and MulMonoid //!#[derive(Copy, PartialEq, Eq, Debug)] //for convenience and displaying output //!pub struct Rational { //! n: i32, //! d: i32 //!} //! //!impl Rational { //! pub fn new(numerator:i32, denominator:i32) -> Self { //! let gcd = numerator.gcd(denominator); //! Rational{n: numerator/gcd, d: denominator/gcd} //! } //!} //! //!//Unary Operations from std::ops and num_traits //! //!impl Neg for Rational { //! type Output = Self; //! fn neg(self) -> Self { Rational::new(-self.n, self.d) } //!} //! //!impl Inv for Rational { //! type Output = Self; //! fn inv(self) -> Self { Rational::new(self.d, self.n) } //!} //! //!//Binary Operations from std::ops //! //!impl Add for Rational { //! type Output = Self; //! fn add(self, rhs:Self) -> Self { //! Rational::new(self.n*rhs.d + rhs.n*self.d, self.d*rhs.d) //! } //!} //! //!impl AddAssign for Rational { //! fn add_assign(&mut self, rhs:Self) {*self = *self+rhs;} //!} //! //!impl Sub for Rational { //! type Output = Self; //! fn sub(self, rhs:Self) -> Self { //! Rational::new(self.n*rhs.d - rhs.n*self.d, self.d*rhs.d) //! } //!} //! //!impl SubAssign for Rational { //! fn sub_assign(&mut self, rhs:Self) {*self = *self-rhs;} //!} //! //!impl Mul for Rational { //! type Output = Self; //! fn mul(self, rhs:Self) -> Self { Rational::new(self.n*rhs.n, self.d*rhs.d) } //!} //! //!impl MulAssign for Rational { //! fn mul_assign(&mut self, rhs:Self) {*self = *self*rhs;} //!} //! //!impl Div for Rational { //! type Output = Self; //! fn div(self, rhs:Self) -> Self { Rational::new(self.n*rhs.d, self.d*rhs.n) } //!} //! //!impl DivAssign for Rational { //! fn div_assign(&mut self, rhs:Self) {*self = *self/rhs;} //!} //! //!//Identities from num_traits //! //!impl Zero for Rational { //! fn zero() -> Self {Rational::new(0,1)} //! fn is_zero(&self) -> bool {self.n==0} //!} //! //!impl One for Rational { //! fn one() -> Self {Rational::new(1, 1)} //! fn is_one(&self) -> bool {self.n==1 && self.d==1} //!} //! //!//algebraic properties from math_traits::algebra //! //!impl AddAssociative for Rational {} //!impl AddCommutative for Rational {} //!impl MulAssociative for Rational {} //!impl MulCommutative for Rational {} //!impl Distributive for Rational {} //! //!//Now, Ring and MulMonoid are automatically implemented for us //! //!fn mul_add<R:Ring>(a:R, b:R, c:R) -> R { a*b + c } //!use math_traits::algebra::group_like::repeated_squaring; //! //!let half = Rational::new(1, 2); //!let two_thirds = Rational::new(2, 3); //!let sixth = Rational::new(1, 6); //! //!assert_eq!(mul_add(half, two_thirds, sixth), half); //!assert_eq!(repeated_squaring(half, 7u32), Rational::new(1, 128)); //!``` //! //!# Supported Constructs //! //!Currently, the mathematical structures supported in `math_traits` consist of a system of //![group-like](algebra::group_like), [ring-like](algebra::ring_like), [integer-like](algebra::integer), //!and [module-like](algebra::module_like) algebraic structures and a system of analytical constructions including //![ordered and Archimedean groups](analysis::ordered), [real and complex numbers](analysis::real), //!and [metric and inner product spaces](analysis::metric). For more information, see each respective //!module. //! #![feature(specialization)] #![feature(euclidean_division)] #![feature(extra_log_consts)] #![recursion_limit="8096"] // #![no_std]s extern crate core; extern crate num_traits; macro_rules! auto { ({} @split ) => { }; ({$($line:tt)+} @split ) => { compile_error!("Expected ;"); }; ({$($line:tt)*} @split ; $($code:tt)*) => { auto!(@create $($line)*); auto!({} @split $($code)*); }; ({$($line:tt)*} @split $t:tt $($code:tt)*) => { auto!({$($line)* $t} @split $($code)*); }; //start the line parsing (@create $($line:tt)*) => {auto!({} @create $($line)*);}; //parse the trait name and generic attributes ({$($kw:tt)*} @create trait $t:ident = $($line:tt)*) => { auto!({$($kw)*} {$t} {} {} @create $($line)*); }; ({$($kw:tt)*} @create trait $t:ident<$($T:ident),*> = $($line:tt)*) => { auto!({$($kw)*} {$t} {$($T),*} {} @create $($line)*); }; //bucket the keywords and attributes at the beginning of the line ({$($kws:tt)*} @create $kw:ident $($line:tt)*) => { auto!({$($kws)* $kw} @create $($line)*); }; ({$($kws:tt)*} @create #[$meta:meta] $($line:tt)*) => { auto!({$($kws)* #[$meta]} @create $($line)*); }; ({$($kw:tt)*} @create) => {compile_error!(concat!("Expected trait alias", stringify!($($line)*))); }; ({$($kw:tt)*} @create $t:tt $($line:tt)*) => {compile_error!(concat!("Expected trait alias, found ", stringify!($t)));}; //parse the trait dependencies and super traits ({$($kw:tt)*} {$name:ident} {$($T:tt)*} {$($deps:tt)*} @create) => { auto!({$($kw)*} {$name} {$($T)*} {$($deps)*} {} @create); }; ({$($kw:tt)*} {$name:ident} {$($T:tt)*} {$($deps:tt)*} @create where $($line:tt)*) => { auto!({$($kw)*} {$name} {$($T)*} {$($deps)*} {where $($line)*} @create); }; ({$($kw:tt)*} {$name:ident} {$($T:tt)*} {$($deps:tt)*} @create $dep:tt $($line:tt)*) => { auto!({$($kw)*} {$name} {$($T)*} {$($deps)* $dep} @create $($line)*); }; //create the trait and its auto-implementation ({$($kw:tt)*} {$name:ident} {$($T:tt)*} {$($deps:tt)*} {$($wh:tt)*} @create) => { $($kw)* trait $name<$($T)*>: $($deps)* $($wh)* {} impl<_G: $($deps)*, $($T)*> $name<$($T)*> for _G $($wh)* {} }; //start the parsing ($($code:tt)*) => { auto!({} @split $($code)*); }; } pub mod algebra; pub mod analysis;