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
#![feature(external_doc)] //! //! Simple implementations of selected abstract algebraic structures. //! //! # Rationale //! //! Mathematical _abstract algebra_ is built on a rich collection of //! algebraic _structures_. Learning about these structures can give //! non-mathematicians insights into the mathematical entities they need //! to work with--for example, real numbers, complex numbers, vectors, //! matrices, and permutations. By definition, these structures must //! comply with sets of _axioms_ and _properties_, which are in turn a //! rich source of properties for generative testing. //! //! `un_algebra` ("***un***derstanding ***algebra***") is a simple //! implementation of selected algebraic structures in Rust. I hope it //! is useful to developers learning abstract algebra concepts for the //! first time. Currently this crate provides _magma_, _semigroup_, //! _quasigroup_, _monoid_, _group_, _ring_ and _field_ implementations. //! //! # Stability //! //!`un_algebra` is still under pre-version 1.0 development, with a //! number of outstanding design and implementation [issues]. Breaking //! changes are likely to the crate API. //! //! # Production use //! //! `un_algebra` is intended to support self-study of abstract algebraic //! structures--it is not optimized for use in a production environment. //! For production environments I recommend using a more sophisticated //! library like [alga]. //! //! # Compatibility //! //! `un_algebra` uses 2018 edition features but unfortunately requires //! Rust _nightly_ as it uses the (experimental) external documentation //! feature. //! //! # Errors //! //! I'm not a mathematician so my implementation of the various //! structures and their respective axioms in `un_algebra` may not be //! strictly correct. Please let me know of any errors. //! //! Please refer to the [references] document for more background on //! each structure and its associated axioms and properties. //! //! # Glossary //! //! The names of the `un_algebra` structures and their respective axioms //! can be long and unwieldy, for example, a "commutative //! multiplicative group". To keep the exported names workable I use //! these abbreviations in trait and function names: //! //! * `Num` for "numeric" //! * `Add` for "additive" //! * `Com` for "commutative" //! * `Mul` for "multiplicative" //! * "Rel" for "relation" //! * `eps` for "epsilon" //! * `prop` for "property" //! //! # Organization //! //! Each algebraic structure implemented in `un_algebra` is bundled as a //! module of structure traits and unit tests of the trait axioms. For //! example, the modules [`group`], [`ring`], or [`field`]. //! //! All structures have an _abstract_ version of the structure trait //! (for example [`group::Group`]), and, where they are commonly used, //! _additive_ and _multiplicative_ versions of the structure trait (for //! example [`add_group::AddGroup`] and [`mul_group::MulGroup`]). These //! traits are defined using the terminology of addition and //! multiplication rather than as abstract binary operations. //! //! Each algebraic structure module has sub-modules for its abstract, //! additive and multiplicative variations, so the group module for //! example has [`group`], [`add_group`], [`mul_group`], sub-modules. //! //! # Axioms and properties //! //! All `un_algebra` structure traits have associated predicate //! functions that implement the structure _axioms_. Some structures //! also have associated predicate functions that implement derived //! _properties_ of the structure. These properties are not strictly //! necessary since they can be derived from the axioms, but they do //! allow richer generative testing of trait implementations, especially //! those using floating point numbers. //! //! Axiom and property functions are bundled into "laws" traits, with a //! blanket implementation for each axiom or property associated trait, //! e.g. [`add_group::AddGroupLaws`] for the [`add_group::AddGroup`] //! trait. //! //! # Macros //! //! User defined traits that are implementable by Rust's built-in //! numeric types seem to quickly lead to a lot of tedious, repeated //! `impl` code, or to using tricky self-referential macros. This could //! be due to missing abstractions in Rust's numeric type hierarchy or //! (more likely) my lack of Rust experience. //! //! Where a trait's `impl` code is only repeated a couple of times //! modules use the boilerplate code approach and in other cases they //! rely on a macro to create the `impl` items. //! //! # Unit tests //! //! Where `un_algebra` traits provide unit tests they are generally //! _generative_ tests built on the [`proptest`] generative testing //! crate. These generative tests test a selection of built-in numeric //! type with every structure. //! //! Generating test values and test functions seems to require a //! surprising amount of repetitive, boilerplate code items. Reducing //! the repeated items is possible via code generation using complex //! self-referential macros, but I'm not sure this is easier to maintain //! than the repeated items. //! //! To avoid cluttering up module source files, the unit tests for most //! modules are defined in separate files. The module source files use //! the `path =` attribute to link the source and test files. //! //! # Integer types //! //! Rust's built-in integer types (for example `i32`) are finite subsets //! of the natural numbers (ℕ). This means they can only satisfy //! abstract structure axioms with modulo, or "wrapping" addition and //! multiplication. //! //! # Floating point types //! //! Many application data types that in theory conform to modern //! algebraic structures make heavy use of IEEE floating point numbers. //! Unfortunately, these numbers are only a finite subset of the real //! numbers (ℝ) and they do not reliably satisfy even the //! simplest real number axioms ([IEEE]). //! //! For working with IEEE floating point types `un_algebra` provides //! "numeric" structure axioms and properties that are handy when //! working with IEEE floating point types, which often require //! "numeric" comparisons using an "epsilon" or error term. //! //! # Examples //! //! `un_algebra` implements the relevant structure traits for all the //! Rust standard library integer and floating point numeric types, for //! example, an _additive_ _group_ for integer types `i8`, `i16`, `i32`, //! etc. It also provides rational number (ℚ) and complex number //! (ℂ) examples, based on the [num] crate. //! //! In addition, the crate examples directory contains abstract //! structure implementations of selected concepts, for example, //! _finite_ _fields_. //! #![doc(include = "../doc/references.md")] // Un-algebra public modules. pub mod helpers; pub mod numeric; pub mod relation; pub mod magma; pub mod quasigroup; pub mod semigroup; pub mod monoid; pub mod group; pub mod com_group; pub mod ring; pub mod com_ring; pub mod field; pub mod prelude; pub mod tests;