| Crates.io | expr-solver-lib |
| lib.rs | expr-solver-lib |
| version | 1.2.0 |
| created_at | 2025-10-17 14:01:34.152026+00 |
| updated_at | 2025-10-21 09:13:51.879264+00 |
| description | Mathematical expression evaluator with bytecode compilation and configurable numeric precision (f64 or 128-bit Decimal) |
| homepage | |
| repository | https://github.com/albeva/expr-solver |
| max_upload_size | |
| id | 1887640 |
| size | 168,475 |
A mathematical expression evaluator library written in Rust with support for custom functions, constants, and bytecode compilation.
Need to evaluate math but don't want to embed an entire scripting language? You're in the right place. 🎯
Perfect for:
price * 0.9 instead of forcing them to update every value manually(revenue - cost) / usersClassic compiler pipeline with type-safe state transitions:
Input → Lexer → Parser → Compiler → Program<Compiled>
↓ link
Program<Linked> → Execute
The Program type uses Rust's type system to enforce correct usage at compile time. You cannot execute an unlinked program, and you cannot link a program twice.
Add this to your Cargo.toml:
[dependencies]
expr-solver-lib = "1.2.0"
Numeric Type Selection:
The library supports two numeric backends via feature flags (mutually exclusive):
f64-floats (default) - Standard f64 floating-point arithmetic. Faster and simpler, allows Inf and NaN results.decimal-precision - 128-bit Decimal for high precision. No floating-point errors, checked arithmetic with overflow detection.To use high-precision Decimal:
[dependencies]
expr-solver-lib = { version = "1.2.0", default-features = false, features = ["decimal-precision"] }
To enable bytecode serialization with f64:
[dependencies]
expr-solver-lib = { version = "1.2.0", features = ["serialization"] }
To enable bytecode serialization with Decimal:
[dependencies]
expr-solver-lib = { version = "1.2.0", default-features = false, features = ["decimal-precision", "serialization"] }
Add this to your Cargo.toml:
[dependencies]
expr-solver-bin = "1.2.0"
use expr_solver::eval;
// Simple one-liner
let result = eval("2 + 3 * 4").unwrap();
assert_eq!(result.to_string(), "14");
// With built-in functions
let result = eval("sqrt(16) + sin(pi/2)").unwrap();
use expr_solver::{eval_with_table, SymTable, Number, ParseNumber};
let mut table = SymTable::stdlib();
table.add_const("x", Number::parse_number("10").unwrap()).unwrap();
table.add_func("double", 1, false, |args| {
Ok(args[0] * Number::parse_number("2").unwrap())
}).unwrap();
let result = eval_with_table("double(x)", table).unwrap();
assert_eq!(result.to_string(), "20");
Or with f64 (default):
use expr_solver::{eval_with_table, SymTable};
let mut table = SymTable::stdlib();
table.add_const("x", 10.0).unwrap();
table.add_func("double", 1, false, |args| Ok(args[0] * 2.0)).unwrap();
let result = eval_with_table("double(x)", table).unwrap();
assert_eq!(result, 20.0);
use expr_solver::{Program, SymTable};
// Compile expression
let program = Program::new_from_source("x * 2 + y").unwrap();
// Execute with different values
let mut table = SymTable::new();
table.add_const("x", 10.0).unwrap();
table.add_const("y", 5.0).unwrap();
let linked = program.link(table).unwrap();
let result = linked.execute().unwrap(); // 25.0
assert_eq!(result, 25.0);
The library supports two numeric backends:
Inf and NaN results (e.g., 1/0 → Inf, sqrt(-1) → NaN)rust_decimalsqrt(-1) returns an error)Choosing the right mode:
| Category | Functions |
|---|---|
| Arithmetic | abs, sign, floor, ceil, round, trunc, fract, mod, clamp |
| Trig | sin, cos, tan, asin, acos, atan, atan2 |
| Hyperbolic | sinh, cosh, tanh |
| Exp/Log | sqrt, cbrt, pow, exp, exp2, log, log2, log10, hypot |
| Variadic | min, max, sum, avg (1+ args) |
| Special | if(cond, then, else) |
Note: In
decimal-precisionmode, some operations (inverse trig,pow) use internal f64 conversion due torust_decimallimitations, which may introduce small precision loss.
pi, e, tau, ln2, ln10, sqrt2
All names are case-insensitive.
Arithmetic: +, -, *, /, ^ (power), ! (factorial), unary -
Comparison: ==, !=, <, <=, >, >= (returns 1 or 0)
Grouping: ( )
# Evaluate an expression
expr-solver "2 + 3 * 4"
# Use the -e flag
expr-solver -e "sin(pi/2)"
# Define custom constants
expr-solver -D x=10 -D y=20 "x + y"
# Compile to binary
expr-solver -e "2+3*4" -o expr.bin
# Execute compiled binary
expr-solver -i expr.bin
# View assembly from expression or file
expr-solver -e "2+3" -a
expr-solver -i expr.bin -a
# Recompile bytecode (e.g., version migration)
expr-solver -i old.bin -o new.bin
# List available functions and constants
expr-solver -t
Run the test suite:
# Run all tests with default f64 mode
cargo test
# Test with decimal-precision mode
cargo test -p expr-solver-lib --no-default-features --features decimal-precision
# Test binary with f64 mode
cargo test -p expr-solver-bin
This project is licensed under the MIT License.