Crates.io | mexprp |

lib.rs | mexprp |

version | 0.3.1 |

source | src |

created_at | 2018-04-02 22:14:19.362207 |

updated_at | 2022-11-25 22:53:30.269095 |

description | A math expression parsing and evaluation library |

homepage | https://intrepidpig.github.io/projects/mexprp |

repository | https://github.com/IntrepidPig/mexprp |

max_upload_size | |

id | 58709 |

size | 110,074 |

https://docs.rs/mexprp

A math expression parsing and evaluation library for Rust

API docs here. Also see the `examples/`

directory.

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.

`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)

There are several different ways to parse and evaluate an equation.

`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`

trait. Some `Num`

types support more operations than others. More info about `Num`

s can be found in the `Num`

module.

```
mexprp::eval::<f64>("10 / (2 + 3)"); // Ok(Answer::Single(2.0))
```

`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.

```
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`

.

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`

module).

```
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 `Context`

s, see the API docs for the `Context`

struct.

MEXPRP supports evaluating expressions with different precisions and complex numbers with the `Num`

trait. Currently supported number types are

`f64`

`ComplexFloat`

`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 `number`

label.

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 `Single(N)`

or `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.