Crate evaluatorrs

Source
Expand description

§Evaluator rs

evaluatorrs is a library for evaluating mathematical expressions into f64 numbers.

§Design

Where other libraries have predefined set of functions, evaluatorrs has ways to define new once by user.

§Evaluate simple expression

use evaluatorrs::eval;
use evaluatorrs::formulas::ParserError;

fn evaluate() -> Result<(), ParserError> {
    let expression = "1 + 2";
    let result = eval(expression)?;
    debug_assert_eq!(result, 3.0);
    Ok(())
}

§Create your own functions

Create function, that computes average of all it’s arguments.

use std::sync::Arc;
use evaluatorrs::formulas::{IsConst, Evaluate, FunctionLike, Function, RootFormula, EvaluationError, MathError, ParserError};
use evaluatorrs::function_stores::{GetFunction, RegisterParser, VectorFunctionStore};
use evaluatorrs::variable_stores::{EmptyVariableStore, GetVariable, Variable};

#[derive(Debug)]
struct Average {
    arguments: Box<[RootFormula]>,
}

impl IsConst for Average {
    fn is_const(&self) -> bool {
       self.arguments.iter().all(|x| x.is_const())
    }
}

impl Evaluate for Average {
    fn eval(&self, args: &dyn GetVariable) -> Result<f64, EvaluationError> {
        let mut res = 0.0;
        for val in self.arguments.iter() {
            let new_val = val.eval(args)?;
            if new_val.is_nan() {
                return Ok(f64::NAN);
            }
            res += new_val;
        }
        Ok(res / self.arguments.len() as f64)
    }
}

impl FunctionLike for Average {
    fn collapse_inner(&mut self) -> Result<(), MathError> {
        for val in self.arguments.iter_mut() {
            val.collapse_inner()?;
        }
        Ok(())
    }

    fn set_all_variables_shared(&mut self, args: &dyn GetVariable) {
        for val in self.arguments.iter_mut() {
            val.set_all_variables_shared(args);
        }
    }

    fn set_all_variables_owned(&mut self, args: &dyn GetVariable) {
        for val in self.arguments.iter_mut() {
            val.set_all_variables_owned(args);
        }
    }

    fn set_variable_shared(&mut self, name: &Variable, function: &Arc<RootFormula>) {
        for val in self.arguments.iter_mut() {
            val.set_variable_shared(name, function);
        }
    }

    fn set_variable_owned(&mut self, name: &Variable, function: &RootFormula) {
        for val in self.arguments.iter_mut() {
            val.set_variable_owned(name, function);
        }
    }

    fn clone_into_box(&self) -> Box<dyn FunctionLike> {
        Box::new(Self {arguments: self.arguments.iter().map(|x| RootFormula::new(x.clone_into_box())).collect()})
    }
}

impl Function for Average {
    const MIN_NUMBER_OF_ARGUMENTS: usize = 1;
    const MAX_NUMBER_OF_ARGUMENTS: usize = 999;
    const NAME: &'static str = "avg";

    fn parse<T: for<'a> GetFunction<'a>>(arguments: &[&str], formulas: &T) -> Result<Self, ParserError>
    where
        Self: Sized
    {
        let parsed_arguments: Result<Box<[_]>, _> = arguments.iter().map(|x| RootFormula::parse(*x, formulas)).collect();
        parsed_arguments.map(|x| Self {arguments: x})
    }
}

fn try_parse() -> Result<(), ParserError> {
    let mut function_store = VectorFunctionStore::new();
    function_store.register::<Average>();
    let parsed = RootFormula::parse("avg(1, 2, 3)", &function_store);
    assert!(parsed.is_ok());
    let parsed = parsed?;
    let res = parsed.eval(&EmptyVariableStore);
    assert!(res.is_ok());
    assert_eq!(res?, 2.0);
    Ok(())
}

§Evaluate functions with variables

fn example() -> Result<(), ParserError> {

    let formula = RootFormula::parse("a + b", &EmptyFunctionStore)?;
    let mut variable_store = HashMapVariableStore::new();
    variable_store.set("a", RootFormula::parse("1", &EmptyFunctionStore)?);
    variable_store.set("b", RootFormula::parse("10", &EmptyFunctionStore)?);
    let evaluated = formula.eval(&variable_store);
    assert!(evaluated.is_ok());
    let evaluated = evaluated?;
    assert_eq!(evaluated, 11.0);
}

Modules§

formulas
Provides basic set of functions and traits to implement new once.
function_stores
Provides basic ways to store function parsers and traits to implement new once.
variable_stores
Provides basic ways to store variables and traits to implement new once.

Macros§

impl_one_arg_function
Macros for creating function with only one argument. And implementing IsConst, Evaluate, FunctionLike, Function.

Structs§

Context
Struct for interacting with variable store and function store.

Functions§

eval
Parses and evaluates &str into f64.