formulac
A Rust crate for parsing and evaluating mathematical expressions with full complex-number support, extensible user-defined functions, and detailed AST representation.
Features
- Complex number support — Evaluate expressions involving real and imaginary components using
num_complex::Complex<f64>. - Reverse Polish Notation (RPN) — Converts infix expressions to RPN using the Shunting-Yard algorithm for efficient evaluation.
- Built-in mathematical operators & functions — Supports
+,-,*,/,^, and standard functions likesin,cos,exp,log, and more. Seesrc/parser.rsfor the list of available functions, constants, and operator symbols. - Unary & Binary operators — Unary operators (
+,-) and binary operators (+,-,*,/,^) are represented asUnaryOperatorKindandBinaryOperatorKind. - Abstract Syntax Tree (AST) — Expressions are parsed into
AstNodestructures, enabling inspection, simplification, and compilation into executable closures. - User-defined functions — Easily register custom functions or constants at runtime using a simple API (
UserDefinedTable). - Safe and dependency-light — No use of unsafe Rust or heavyweight external parsers.
Usage
Add to your Cargo.toml:
or
[]
= "0.4"
= "0.4"
Basic Example
use Complex;
use ;
Registering a Custom Function
use Complex;
use ;
// Create user-defined function table
let mut users = new;
// Define a function f(x) = x^2 + 1
let func = new;
users.register;
let mut vars = new;
let expr = compile.unwrap;
assert_eq!;
Core Types & API Overview
-
compileCompiles a formula string into a Rust closureFn(&[Complex<f64>]) -> Complex<f64>that evaluates the expression for given variable values. -
VariablesA lookup table mapping variable names (strings) toComplex<f64>values, used during parsing. -
UserDefinedTableAllows registration of custom functions under user-defined names for use in expressions.
Benchmarking
The formulac crate provides benchmarks using the Criterion crate to measure both compilation and execution performance.
Note:
- Criterion is a dev-dependency, so benchmarks are only available in development builds.
- :warning: Some benchmarks (e.g., 1000 nested operations) may take longer to run.
Benchmark Source
The benchmarks are located in benches/benches.rs and cover:
- Linear expressions (many operands like polynomials)
- Nested expressions (e.g., sin(sin(...)))
- Numeric literals
- Expressions with and without parentheses
- Many variable references (up to 100 variables)
- Invalid expressions (error cases)
- Practical expressions (polynomials, wave functions, exponential decay)
- Comparison of direct calls vs. parsed calls for standard functions (sin, cos, pow, etc.)
Run Benchmarks
Run the benchmarks with:
Both compile and exec times are measured. Criterion generates detailed statistics and plots in target/criterion.
Viewing Results
Open the generated HTML report in a browser to view benchmark results and comparisons:
License
Licensed under MIT OR Apache-2.0 — choose the license that best suits your project.
Contribution & Contact
Contributions, feature requests, and bug reports are welcome! Please feel free to open issues or submit pull requests via the GitHub repository.