formulac
formulac is a Rust library for parsing, evaluating, and differentiating mathematical expressions.
It supports complex numbers, user-defined functions, and higher-order derivatives.
Ideal for symbolic computation, mathematical simulations, and evaluating formulas in Rust applications.
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/astnode.rsor API Overview for 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). - Differentiation support — Parse and evaluate differential expressions using the
diffoperator (e.g.,diff(sin(x), x)). - Safe and dependency-light — No use of unsafe Rust or heavyweight external parsers.
Usage
Add to your Cargo.toml:
Basic Example
use Complex;
use ;
Registering a Custom Function
use Complex;
use ;
Differentiation Support
formulac can represent derivative expressions in the AST.
Built-in functions (e.g. sin, cos, exp, log, …) already have derivative rules,
but user-defined functions require the user to explicitly register their derivative form.
Note on Differential Order:
- Only integer-order derivatives are supported; fractional derivatives are not allowed.
- The maximum allowed order is
i8::MAX(127). Attempting to compute a derivative higher than this will result in a runtime error.
Differentiation Example
You can directly write differentiation expressions using the diff operator:
use Complex;
use ;
When computing derivatives of order 2 or higher, specify the order:
use Complex;
use ;
Example: User-defined function with derivative
You can define your own functions and provide derivatives for them. The derivative must be registered in the same order as the function arguments.
use Complex;
use ;
User-defined function without derivative
You can also define your own functions without providing derivatives for them. In the case, the derivatives will be calculated automatically by numerical differentiation.
The step size is determined automatically used by the argument value:
$$ dh = x_i \times 10^{-6} $$
Note: Numerical differentiation is an aproximation, so it may be less accurate than analytical derivatives.
use Complex;
use ;
Example: Multi-variable functions (Partial derivatives)
For functions with multiple variables, you can register partial derivatives with respect to each argument. Use the same order as the function arguments.
use Complex;
use ;
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.
Available mathematical constants
| String | Value | Description |
|---|---|---|
E |
e |
The base of natural logarithm (≈ 2.71828) |
FRAC_1_PI |
1 / π |
Reciprocal of π |
FRAC_1_SQRT_2 |
1 / √2 |
Reciprocal of square root of 2 |
FRAC_2_PI |
2 / π |
2 divided by π |
FRAC_2_SQRT_PI |
2 / √π |
2 divided by square root of π |
FRAC_PI_2 |
π / 2 |
Half of π |
FRAC_PI_3 |
π / 3 |
One-third of π |
FRAC_PI_4 |
π / 4 |
One-fourth of π |
FRAC_PI_6 |
π / 6 |
One-sixth of π |
FRAC_PI_8 |
π / 8 |
One-eighth of π |
LN_2 |
ln(2) |
Natural logarithm of 2 |
LN_10 |
ln(10) |
Natural logarithm of 10 |
LOG2_10 |
log2(10) |
Base-2 logarithm of 10 |
LOG2_E |
log2(e) |
Base-2 logarithm of e |
LOG10_2 |
log10(2) |
Base-10 logarithm of 2 |
LOG10_E |
log10(e) |
Base-10 logarithm of e |
PI |
π |
Ratio of circle circumference to diameter |
SQRT_2 |
√2 |
Square root of 2 |
TAU |
2 * π |
Full circle in radians |
Available unary operators
| String | Function | Description |
|---|---|---|
+ |
Positive |
Identity operator |
- |
Negative |
Negation operator |
Available binary operators
| String | Function | Description |
|---|---|---|
+ |
Add |
Addition |
- |
Sub |
Subtraction |
* |
Mul |
Multiplication |
/ |
Div |
Division |
^ |
Pow |
Power (x^y) |
Available Functions
| String | Function | Description |
|---|---|---|
sin |
Sin(x) |
Sine function |
cos |
Cos(x) |
Cosine function |
tan |
Tan(x) |
Tangent function |
asin |
Asin(x) |
Arc sine |
acos |
Acos(x) |
Arc cosine |
atan |
Atan(x) |
Arc tangent |
sinh |
Sinh(x) |
Hyperbolic sine |
cosh |
Cosh(x) |
Hyperbolic cosine |
tanh |
Tanh(x) |
Hyperbolic tangent |
asinh |
Asinh(x) |
Hyperbolic arcsine |
acosh |
Acosh(x) |
Hyperbolic arccosine |
atanh |
Atanh(x) |
Hyperbolic arctangent |
exp |
Exp(x) |
Exponential function e^x |
ln |
Ln(x) |
Natural logarithm |
log10 |
Log10(x) |
Base-10 logarithm |
sqrt |
Sqrt(x) |
Square root |
abs |
Abs(x) |
Absolute value |
conj |
Conj(x) |
Complex conjugate |
pow |
Pow(x, y) |
x raised to y (complex exponent) |
powi |
Powi(x, n) |
x raised to integer n |
Available differential operator
| String | Function | Description |
|---|---|---|
diff(f, x) |
diff(f, x) |
First-order derivative of f with respect to x |
diff(f, x, n) |
diff(f, x, n) |
n-th order derivative of f with respect to x (max i8::MAX) |
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.
- Benchmarks require the
criterioncrate as a dev-dependency and are intended for development/testing purposes only.
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)
- Differentiate expressions
- 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.