yarer 0.1.5

Yarer (Yet another (Rusty||Rpn) expression resolver) is a library for the processing, compilation and evaluation of Reverse Polish mathematical expressions.
Documentation
yarer-0.1.5 has been yanked.

YARER - Rpn Resolver

Downloads Project Status: Active – The project has reached a stable, usable state and is being actively developed.

Yarer (Yet another (Rusty || Rpn) expression resolver) is a flexible library, written in Rust, for the processing, compilation and evaluation of mathematical expressions using Reverse Polish Notation.

Example of usage of the library:

      let session = Session::init();
      let exp = "atan(cos(10 + e) + 3 * sin(9 / 3))^2";
      let mut resolver = session.build_resolver_for(&exp);
      println!("The result of {} is {}", exp, resolver.resolve());

All that's needed is to create a new instance of the RpnResolver and hand over the expression to be analysed. The library just returns a variant natural number, or a decimal number if one exists in the expression (i.e '2.1+1') or there's a trigonometric function (i.e. 1/cos(x+1)).

Yarer handles variables and functions. Here an example:

      let session: Session = Session::init();
      let mut resolver: RpnResolver = session.build_resolver_for("1/cos(x^2)");

      session.set("x",1);
      println!("The result is {}", resolver.resolve());

and of course, the expression can be re-evaluated if the variable changes.

      //...
      session.set("x",-1);
      println!("The result is {}", resolver.resolve());

      session.set("x",0.001); 
      println!("The result is {}", resolver.resolve());
      //...

The result can be simply casted into a i32 or a f64 (if decimal) simply with

      let result: Number = resolver.resolve().unwrap();

      let int : i32 = i32::from(result);
      // or
      let float : f64 = f64::from(result);

Yarer can be used also from command line, and behaves in a very similar manner to GNU bc

      $ yarer
      Yarer v.0.1.1 - Yet Another (Rusty||Rpn) Expression Resolver.
      License MIT OR Apache-2.0
      > (1+9)*(8+2)
      100
      > (1./2)+atan(10)
      1.1483608274590869
      > x=10
      > 3/sin(5*x^2)
      -6.41338354698791
      > ln(1)
      0
      > log(10)
      1
      > -2^-2
      0.25
      > 1/(log(10)+cos(0))^-2
      4
      > 4.5+7.9*2.2
      21.88
      > 9801/(2206*sqrt(2)) // approx of PI
      3.1415927300133055
      

From Yarer version 0.1.5 it's possible to share a single session, and therefore a single heap of variables, for multiple resolvers. The library is not intended to be thread-safe.

    let session = Session::init();
    
    let mut res = session.build_resolver_for("x ^ 2");
    let mut res2 = session.build_resolver_for("x + 2");

    session.set("x",10);
   
    if let (Ok(a), Ok(b)) = (res.resolve(),res2.resolve()) {
        println!("{} {}", a, b); // 100 12
    }

Built-in Defined Functions

There are several math functions defined that you can use in your expression. More to come! There are many examples of processed expressions in the integration test file.

    Sin
    Cos
    Tan
    ASin
    ACos
    ATan
    Ln
    Log
    Abs
    Sqrt

Built-in Defined Constants

There are 2 predefined math constants at the moment:

    PI -> 3.14159265...
    e -> 2.7182818...

Execute

To run it from cargo, just type:

cargo run -q -- 

For logging debug just run with:

env RUST_LOG=yarer=debug cargo run -q -- 

or to build a release from the code:

cargo build --release
./target/release/yarer

Internal Implementation

Each expression is the result of an evaluation by the following actors

Step1 - Parser: A string is "regexed" and converted into a token array.

Step 2 - RpnResolver: Using the Shunting Yard algorithm the token array is converted from infix to postfix notation.

Step 3 - RpnResolver: The resulting RPN (Reverse Polish Notation) expression is evaluated.

Worth to mention that the Session is responsible to store all variables (and constants) that are borrowed by all the RpnResolvers.

Contribution

Besides being stable, Yarer is a work in progress. If you have suggestions for features (i.e. more math functions to implement), or if you find any issues in the code, design, interface, etc, please feel free to share them on our GitHub.

I appreciate very much your feedback!