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
//! # MEXPRP
//! A math expression parsing and evaluating library
//!
//! ## Features
//! - `f64` precision
//! - multiple/arbitrary precision (somewhat incomplete)
//! - low dependencies
//! - custom variable contexts
//! - custom function contexts
//! - builtin constants and functions (eg pi, sin, max)
//! - implicit multiplication
//! - utf8-ready
//! - support for multiple answers
//! - complex numbers (somewhat incomplete)
//!
//! ## Usage
//! There are three different ways to parse and evaluate an equation.
//!
//! #### 1. With `eval()`
//! This function parses and evaluates a string all at once with the default context. There's also
//! an `eval_ctx()` function which takes a reference to a `Context` as well that will be used instead of
//! the default `Context`. The type parameter can be anything that implements the [`Num`](num::Num)
//! trait. Some `Num` types support more operations than others. More info about `Num`s can be found
//! in the [`Num`](num) module.
//!
//! ```rust
//! # let res =
//! mexprp::eval::<f64>("10 / (2 + 3)"); // Ok(Answer::Single(2.0))
//! # assert_eq!(res.unwrap(), mexprp::Answer::Single(2.0));
//! ```
//!
//! #### 2. With `Expression`
//! `Expression::parse()` parses a string into a tree representation (a `Term`). It can also be parsed
//! with a context with `parse_ctx()`, and it will store that context within it for future evaluations.
//! It can also be evaluated with a reference to any other context with `eval_ctx`. It's important to
//! ensure that the custom context contains any definitions the `Expression` depends on.
//!
//! ```rust
//! # use mexprp::{Expression, Answer};
//! let expr: Expression<f64> = Expression::parse("3 ^ 4 / 9").unwrap();
//! let res = expr.eval(); // Ok(Answer::Single(9.0))
//! # assert_eq!(res.unwrap(), Answer::Single(9.0));
//! ```
//!
//! #### 3. With `Term`
//! A `Term` is an `Expression`, but without the extra overhead of a context or the original string
//! representation stored with it. It is literally a tree representing the equation by it's operations.
//!
//! ```rust
//! # use mexprp::{Term, Answer};
//! let term: Term<f64> = Term::parse("10 ^ -3").unwrap();
//! let res = term.eval(); // Ok(Answer::Single(0.001))
//! # assert_eq!(res.unwrap(), Answer::Single(0.001));
//! ```
//!
//! ### Answer Types
//! Evaluating an expression will return an [`Answer`](answer::Answer) enum. An answer represents either
//! a single value, or multiple. The most notable example of an operation that results in multiple
//! answers is `sqrt()` which returns a positive and negative answer. Another obvious example is the
//! `±` operator. When implementing functions, it's important to handle each answer type when evaluating
//! the arguments. More info about that and helper methods for it can be found in the documentation
//! for the `Answer` enum.
//!
//! ### Multiple Precisions
//! MEXPRP supports evaluating expressions with different precisions with the [`Num`](num::Num) trait.
//! Currently supported number types are
//! - f64
//! - [`ComplexFloat`](num::ComplexFloat)
//! - [`ComplexRugRat`](num::ComplexRugRat) (using the rug crate)
//! - [`Rational`](::rug::Rational) (from the rug crate)
//! - [`Complex`](::rug::Complex) (from the rug crate)
//!
//! However, the implementation for certain types is incomplete. Only the `f64` type fully implements
//! all of the operations. `Complex` is the next best, but even it is still missing some. The others
//! only implement a (small) subset of the functionality of the `Num` trait, and return a
//! `MathError::Unimplemented` when an unsupported operation is attempted. It is
//! hopeful that more functions will be implemented in the future, but some are very difficult
//! to implement for arbitrary precision numbers.
//!
//! The `Complex` number also supports selecting the precision to use with a `Context`. Set the `precision`
//! field of the `cfg` field of a Context to set the precision to be used by `Complex` numbers.
//!
//! For more info on the types, see the documentation for the [`num`](num) module.
//!
//! To use another number type, change the type annotation(s) for your MEXPRP types.
//! ```rust
//! extern crate rug;
//! # extern crate mexprp;
//! use rug::Rational;
//! # use mexprp;
//! mexprp::eval::<Rational>("10/15"); // 2/3
//!```
//!
//! ```rust
//! # use mexprp::Expression;
//! # use mexprp::num::ComplexFloat;
//! let expr: Expression<ComplexFloat> = Expression::parse("(3 + 4i) × (6 - 3i)").unwrap();
//! let res = expr.eval(); // 30 + 15i
//! ```
//!
//! To set the precision of types that let you choose it (currently just
//!
//! In case you don't want a dependency on `rug`, compile MEXPRP without the `"rug"` feature.
//!
//! ### Using Contexts
//! You can evaluate expressions with custom variable and function definition's by defining a context.
//! When defining custom functions, it's important to remember to parse the expression with the custom
//! context, or else the parser will recognize your functions as variables instead. `Expression`s will
//! store the context you parse them with, but you have to evaluate `Term`s with a reference to a context
//! using `Term::eval_ctx`. For more info see the [`Context`](context::Context) struct.
//!
//! A `Context` also holds configuration values that define how MEXPRP parses and evaluates equations.
//! These configuration values include enabling/disabling implicit multiplication, the precision to
//! use for types that support selecting precisions (just `Complex` for now), and the behaviour of
//! the `sqrt()` function. More info can be found in the API docs (check the [`context`](context) module).
extern crate rug;
/// Contains Function trait
/// Contains methods for parsing equations into token representations
/// Contains definitions for Operations
/// Contains expressions
/// Contains terms
/// Contains implementations for operations
/// All the errors
/// Context struct
/// Number representation(s)
/// Answer enum
pub use crate Func;
pub use crate Expression;
pub use crate Term;
pub use crate;
pub use crate;
pub use crate Num;
pub use crate Calculation;
pub use crate Answer;
/// Parse and evaluate a string
/// Parse and evaluate a string with the given context