4 releases (2 breaking)
|0.3.1||Nov 25, 2022|
|0.3.0||Apr 7, 2018|
|0.2.0||Apr 3, 2018|
|0.1.0||Apr 2, 2018|
#630 in Parser implementations
178 downloads per month
Used in morphius
A math expression parsing and evaluation library for Rust
API docs here. Also see the
The main reason I wrote MEXPRP was for a 3D equation grapher I've been working on (vgraph). I can't really say why I didn't choose any existing libraries other than because I wanted a learning experience, and because I wanted flexibility. I'm glad to say I learned a lot from this project, and it's also quite flexible.
- multiple/arbitrary precision (somewhat incomplete)
- low dependencies
- custom variable contexts
- custom function contexts
- builtin constants and functions (eg pi, sin, max)
- implicit multiplication
- support for multiple answers
- complex numbers (somewhat incomplete)
There are several different ways to parse and evaluate an equation.
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 trait. Some
Num types support more operations than others. More info about
Nums can be found in the
mexprp::eval::<f64>("10 / (2 + 3)"); // Ok(Answer::Single(2.0))
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.
let expr: Expression<f64> = Expression::parse("3 ^ 4 / 9").unwrap(); let res = expr.eval(); // Ok(Answer::Single(9.0))
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. One way to bypass this is by disabling implicit multiplication in the context used for parsing, which will then parse all names followed by parentheses as functions, regardless of whether they are defined in the
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
let mut context: Context<f64> = Context::new(); context.set_var("x", 4.0); let expr = Expression::parse_ctx("4x", context).unwrap(); let res = expr.eval(); // Ok(Answer::Single(16.0))
For a list of builtin functions/constants in
Contexts, see the API docs for the
MEXPRP supports evaluating expressions with different precisions and complex numbers with the
Num trait. Currently supported number types are
ComplexRugRat(using the rug crate)
Rational(from the rug crate)
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 or rational numbers.
For more info on the types, see the documentation for the
num module. To see progress on implementations for numbers, see GitHub issues with the
To use another number type, change the type annotation(s) for your MEXPRP types.
extern crate rug; use rug::Rational; mexprp::eval::<Rational>("10/15"); // 2/3
extern crate rug; use rug::Complex; mexprp::eval::<Complex>("(2+3i)(2-3i)"); // 23 + 2i
Any evaluation of an expression in MEXPRP returns an
Answer. An answer is a simple enum that is either
Multiple(Vec<N>) where N is the type of number this expression is using. This represents answers to operations that possibly yield multiple values such as
sqrt() or the
± operator. If you know the result of an expression will be just one answer, you can use the
unwrap_single() method of answer to get that one answer.
Be sure to check the API docs for more in depth explanations of usage.