meval 0.0.3

A simple math expression parser and evaluator.
Documentation

meval-rs

Build Status

This Rust crate provides a simple math expression parsing and evaluation. Its main goal is to be convenient to use, while allowing for some flexibility. Currently works only with f64 types.

Documentation

Full API documentation

Installation

Simply add the corresponding entry to your Cargo.toml dependency list:

[dependencies]
meval = "0.0.3"

and add this to your crate root:

extern crate meval;

Simple examples

extern crate meval;

fn main() {
    let r = meval::eval_str("1 + 2").unwrap();

    println!("1 + 2 = {}", r);
}

Need to define a Rust function from an expression? No problem, use Expr for this and more:

extern crate meval;

fn main() {
    let expr = meval::Expr::from_str("sin(pi * x)").unwrap();
    let func = expr.bind("x").unwrap();

    let vs: Vec<_> = (0..100+1).map(|i| func(i as f64 / 100.)).collect();

    println!("sin(pi * x), 0 <= x <= 1: {:?}", vs);
}

Expr::bind returns a boxed closure that is slightly less convenient than an unboxed closure since Box<Fn(f64) -> f64> does not implement FnOnce, Fn or FnMut. So to use it directly as a function argument where a closure is expected, it has to be manually dereferenced:

let func = meval::Expr::from_str("x").unwrap().bind("x").unwrap();
let r = Some(2.).map(&*func);

Custom constants and functions? Define a context!

let y = 1.;
let expr = meval::Expr::from_str("phi(-2 * zeta + x)").unwrap();

// create a context with function definitions and variables
let ctx = (meval::CustomFunc("phi", |x| x + y), ("zeta", -1.));
// bind function with builtins as well as custom context
let func = expr.bind_with_context((meval::builtin(), ctx), "x").unwrap();
assert_eq!(func(2.), -2. * -1. + 2. + 1.);

For functions with 2, 3, and N variables use CustomFunc2, CustomFunc3 and CustomFuncN respectively.

If you need a custom function depending on mutable parameters, you will need to use a Cell:

use std::cell::Cell;
let y = Cell::new(0.);
let expr = meval::Expr::from_str("phi(x)").unwrap();

let ctx = meval::CustomFunc("phi", |x| x + y.get());
let func = expr.bind_with_context(ctx, "x").unwrap();
assert_eq!(func(2.), 2.);
y.set(3.);
assert_eq!(func(2.), 5.);

Supported expressions

meval supports basic mathematical operations on floating point numbers:

  • binary operators: +, -, *, /, ^ (power)
  • unary operators: +, -

It supports custom variables like x, weight, C_0, etc. A variable must start with [a-zA-Z_] and can contain only [a-zA-Z0-9_].

Build-ins (given by context meval::builtin()) currently supported:

  • functions implemented using functions of the same name in Rust std library:

    • sqrt, abs
    • exp, ln
    • sin, cos, tan, asin, acos, atan, atan2
    • sinh, cosh, tanh, asinh, acosh, atanh
    • floor, ceil, round
    • signum
  • other functions:

    • max(x, ...), min(x, ...): maximum and minimumum of 1 or more numbers
  • constants:

    • pi
    • e

Related projects

This is a toy project of mine for learning Rust, and to be hopefully useful when writing command line scripts. For other similar projects see:

License

This project is dual-licensed under the Unlicense and MIT licenses.

You may use this code under the terms of either license.