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

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

```let expr: Expression<f64> = Expression::parse("3 ^ 4 / 9").unwrap();
let res = expr.eval(); // Ok(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.

```let term: Term<f64> = Term::parse("10 ^ -3").unwrap();
let res = term.eval(); // Ok(Answer::Single(0.001))```

Evaluating an expression will return an `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` trait. Currently supported number types are

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

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

## Re-exports

 `pub use errors::EvalError;` `pub use errors::MathError;` `pub use errors::ParseError;` `pub use num::Num;`

## Modules

 errors All the errors num Number representation(s) This module contains the `Num` trait and its implementations.

## Structs

 Config Struct that holds configuration values used when evaluating expressions Context A context holds values for variables and functions to be used in expressions. It is useful for both parsing and evaluation expressions. During parsing, all names will be treated as variables unless present in the Context the expression is being parsed with as functions at the time. The default context (created with `new()`) contains basic functions and constants such as `sin`, `pi`, etc, as well as the default configuration. Expression The main Expression struct. Contains the string that was originally requested to be parsed, the context the Expression was parsed with, and the Term the raw form was parsed as. For just the parsed version of the expression, use the Term enum.

## Enums

 Answer An answer of an evaluatation. Can be either a single answer or multiple. This struct contains some helper methods for performing operations on single or multiple answers. The `op` method takes another `Num`, and a function with two `Num` arguments, itself and the other (as references). It performs that function on all combinations and returns an answer with all of the results in one. The `unop` function is similar but it performs an operation on only itself, without another value (unary operation). Term The main representation of parsed equations. It is an operand that can contain an operation between more of itself. This form is the only one that can be directly evaluated. Does not include it's own context.

## Traits

 Func Implemented by functions defined in a context

## Functions

 eval Parse and evaluate a string eval_ctx Parse and evaluate a string with the given context

## Type Definitions

 Calculation The result of an evaluation