mathexpr/
lib.rs

1//! # mathexpr
2//!
3//! A fast, safe mathematical expression parser and evaluator with bytecode compilation.
4//!
5//! ## Features
6//!
7//! - **Fast**: Compiles to bytecode for efficient repeated evaluation (~15-80ns per eval)
8//! - **Safe**: No unsafe code, handles errors gracefully
9//! - **`no_std` compatible**: Works in embedded environments with `alloc`
10//! - **Rich function library**: 27 built-in functions including trig, rounding, and more
11//!
12//! ## Quick Start
13//!
14//! ```rust
15//! use mathexpr::Expression;
16//!
17//! // Parse and compile an expression
18//! let expr = Expression::parse("sqrt(x^2 + y^2)")?
19//!     .compile(&["x", "y"])?;
20//!
21//! // Evaluate with different values
22//! assert_eq!(expr.eval(&[3.0, 4.0])?, 5.0);
23//! assert_eq!(expr.eval(&[5.0, 12.0])?, 13.0);
24//! # Ok::<(), Box<dyn std::error::Error>>(())
25//! ```
26//!
27//! ## One-liner Evaluation
28//!
29//! For simple cases where you don't need to reuse the expression:
30//!
31//! ```rust
32//! use mathexpr::eval;
33//!
34//! let result = eval("2 * pi * r", &["r"], &[5.0])?;
35//! # Ok::<(), Box<dyn std::error::Error>>(())
36//! ```
37//!
38//! ## Current Value (`_`)
39//!
40//! Use `_` to reference an input value, useful for transformations:
41//!
42//! ```rust
43//! use mathexpr::Expression;
44//!
45//! let normalize = Expression::parse("(_ - min) / (max - min)")?
46//!     .compile(&["min", "max"])?;
47//!
48//! // Normalize 50 to range [0, 100]
49//! let result = normalize.eval_with_current(50.0, &[0.0, 100.0])?;
50//! assert_eq!(result, 0.5);
51//! # Ok::<(), Box<dyn std::error::Error>>(())
52//! ```
53//!
54//! ## Supported Operators
55//!
56//! | Operator | Description | Precedence |
57//! |----------|-------------|------------|
58//! | `+`, `-` | Addition, Subtraction | Lowest |
59//! | `*`, `/`, `%` | Multiplication, Division, Modulo | Medium |
60//! | `^` | Exponentiation (right-associative) | Highest |
61//! | `-x` | Unary negation | Highest |
62//!
63//! ## Supported Functions
64//!
65//! ### Core Math
66//! - `abs(x)`, `sqrt(x)`, `cbrt(x)` - Absolute value, roots
67//! - `log(x)`/`ln(x)`, `log2(x)`, `log10(x)` - Logarithms
68//! - `exp(x)`, `pow(base, exp)` - Exponentials
69//! - `min(a, b)`, `max(a, b)`, `clamp(x, min, max)` - Bounds
70//! - `mod(a, b)` - Modulo (same as `%`)
71//!
72//! ### Trigonometric
73//! - `sin(x)`, `cos(x)`, `tan(x)` - Basic trig
74//! - `asin(x)`, `acos(x)`, `atan(x)` - Inverse trig
75//! - `sinh(x)`, `cosh(x)`, `tanh(x)` - Hyperbolic
76//!
77//! ### Rounding
78//! - `floor(x)`, `ceil(x)`, `round(x)`, `trunc(x)`
79//! - `signum(x)` - Sign of number
80//!
81//! ### Constants
82//! - `pi` or `pi()` - π ≈ 3.14159...
83//! - `e` or `e()` - Euler's number ≈ 2.71828...
84//!
85//! ## Performance
86//!
87//! Typical evaluation times (single-threaded, release build):
88//!
89//! | Expression Complexity | Time per Eval |
90//! |-----------------------|---------------|
91//! | Simple (`a + b`) | ~15 ns |
92//! | Medium (`sqrt(x^2 + y^2)`) | ~35 ns |
93//! | Complex (5+ functions) | ~70-80 ns |
94//!
95//! ## Feature Flags
96//!
97//! - `std` (default): Enables `std::error::Error` implementations
98//! - Without `std`: Requires `alloc` crate, suitable for `no_std` environments
99
100#![cfg_attr(not(feature = "std"), no_std)]
101#![cfg_attr(docsrs, feature(doc_cfg))]
102#![warn(missing_docs)]
103#![warn(rust_2018_idioms)]
104
105#[cfg(not(feature = "std"))]
106extern crate alloc;
107
108pub mod ast;
109pub mod builder;
110pub mod compiler;
111pub mod error;
112pub mod parser;
113pub mod vm;
114
115// Re-export main types at crate root for convenience
116pub use ast::{BinOp, BuiltinFn, Expr};
117pub use builder::{eval, eval_with_current, Executable, Expression};
118pub use compiler::CompiledExpr;
119pub use error::{CompileError, EvalError, ParseError};
120pub use parser::parse;
121
122#[cfg(test)]
123mod tests;