# mathexpr
A fast, safe mathematical expression parser and evaluator for Rust.
## Features
- **Fast** - Compiles expressions to bytecode for efficient repeated evaluation (~15-80ns per eval)
- **Safe** - No unsafe code, proper error handling
- **`no_std` compatible** - Works in embedded environments with `alloc`
- **Rich function library** - 27 built-in functions including trig, logarithms, rounding, and more
## Quick Start
```rust
use mathexpr::Expression;
// Parse, compile, and evaluate
let expr = Expression::parse("sqrt(x^2 + y^2)")?
.compile(&["x", "y"])?;
assert_eq!(expr.eval(&[3.0, 4.0])?, 5.0);
assert_eq!(expr.eval(&[5.0, 12.0])?, 13.0);
```
## One-liner Evaluation
For simple cases where you don't need to reuse the compiled expression:
```rust
use mathexpr::eval;
let result = eval("2 * pi * r", &["r"], &[5.0])?;
// result ≈ 31.4159
```
## Current Value (`_`)
Use `_` to reference an input value, useful for transformations:
```rust
use mathexpr::Expression;
let normalize = Expression::parse("(_ - min) / (max - min)")?
.compile(&["min", "max"])?;
// Normalize 50 to range [0, 100]
let result = normalize.eval_with_current(50.0, &[0.0, 100.0])?;
assert_eq!(result, 0.5);
```
## Operators
| `+`, `-` | Addition, Subtraction | Lowest |
| `*`, `/`, `%` | Multiplication, Division, Modulo | Medium |
| `^` | Exponentiation (right-associative) | Highest |
| `-x` | Unary negation | Highest |
## Functions
### Core Math
| `abs(x)` | Absolute value |
| `sqrt(x)` | Square root |
| `cbrt(x)` | Cube root |
| `exp(x)` | Exponential (e^x) |
| `log(x)`, `ln(x)` | Natural logarithm |
| `log2(x)` | Base-2 logarithm |
| `log10(x)` | Base-10 logarithm |
| `pow(base, exp)` | Power |
| `mod(a, b)` | Modulo |
| `min(a, b)` | Minimum |
| `max(a, b)` | Maximum |
| `clamp(x, min, max)` | Clamp to range |
### Trigonometric
| `sin(x)`, `cos(x)`, `tan(x)` | Basic trig |
| `asin(x)`, `acos(x)`, `atan(x)` | Inverse trig |
| `sinh(x)`, `cosh(x)`, `tanh(x)` | Hyperbolic |
### Rounding
| `floor(x)` | Round down |
| `ceil(x)` | Round up |
| `round(x)` | Round to nearest |
| `trunc(x)` | Truncate toward zero |
| `signum(x)` | Sign (-1, 0, or 1) |
### Constants
| `pi` or `pi()` | π ≈ 3.14159... |
| `e` or `e()` | Euler's number ≈ 2.71828... |
## Error Handling
mathexpr provides three error types:
```rust
use mathexpr::{Expression, ParseError, CompileError, EvalError};
// Parse errors - invalid syntax
match Expression::parse("@#$") {
Err(ParseError::InvalidSyntax(msg)) => { /* handle */ }
Err(ParseError::UnexpectedTrailingInput(s)) => { /* handle */ }
_ => {}
}
// Compile errors - undefined variables or unknown functions
match Expression::parse("x + y")?.compile(&["x"]) {
Err(CompileError::UndefinedVariable(name)) => { /* handle */ }
Err(CompileError::UnknownFunction(name)) => { /* handle */ }
Err(CompileError::WrongArity { name, expected, got }) => { /* handle */ }
_ => {}
}
// Eval errors - runtime errors
match expr.eval(&[0.0]) {
Err(EvalError::DivisionByZero) => { /* handle */ }
_ => {}
}
```
**Note:** Domain errors (like `sqrt(-1)`) return `NaN` rather than errors.
## Performance
Typical evaluation times on modern hardware:
| Simple (`a + b`) | ~15 ns |
| Medium (`sqrt(x^2 + y^2)`) | ~25 ns |
| Complex (5+ functions) | ~60-80 ns |
## Examples
Run the included examples:
```bash
# Basic API usage
cargo run --example basic
# Error handling patterns
cargo run --example errors
# Interactive calculator with history
cargo run --example repl
```
## Feature Flags
| `std` (default) | Enables `std::error::Error` implementations |
For `no_std` environments:
```toml
[dependencies]
mathexpr = { version = "0.1", default-features = false }
```
Requires the `alloc` crate.
## License
MIT License. See [LICENSE](LICENSE) for details.