1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
//! This crate provides bindings for the [ExprTk](http://www.partow.net/programming/exprtk/index.html) //! library. //! //! For an overview of the data structures [see the ExprTk main page](http://www.partow.net/programming/exprtk/index.html). //! While `exprtk-sys` maps most functions of the library to Rust, the high level bindings //! were considerably simplified. Each [Expression](struct.Expression.html) owns a //! [SymbolTable](struct.SymbolTable.html), they cannot be shared between different instances, //! and multiple symbol tables per expression are not possible. //! Variables are owned by the `SymbolTable` instance. [add_variable()](exprtk/struct.SymbolTable.html#method.add_variable) //! returns an `usize`, which is a _variable ID_. This ID can be used to later modify the value //! Using [set_value()](exprtk/struct.SymbolTable.html#method.set_value). The same is true for //! string and vector variables. //! //! Modifying a value is therefore more expensive than in C++. In a quick comparison, //! the performance loss varied between ~ 3% and 70% depending on the expression (see *benches.rs*). //! Using *unsafe*, value pointers can still be modified directly if desired (use //! [get_value_ptr()](exprtk/struct.SymbolTable.html#method.get_value_ptr) to obtain them). //! //! There may be a more idiomatic way to represent the whole API in Rust, but it seems difficult to //! me to integrate with Rust's concepts of lifetimes and mutable/immutable borrowing. //! Suggestions are of course welcome. //! //! Since there is no guarantee that `double` is always `f64`, the `c_double` type is used all //! over the library. Other precisions are currently not supported. //! //! # Examples: //! //! This code corresponds to the [example 1](http://www.partow.net/programming/exprtk/index.html#simpleexample01) //! in the ExprTk documentation: //! //! ```no_run //! use exprtk_rs::*; //! //! let expression_string = "clamp(-1.0,sin(2 * pi * x) + cos(x / 2 * pi),+1.0)"; //! //! let mut symbol_table = SymbolTable::new(); //! symbol_table.add_constants(); //! let var_id = symbol_table.add_variable("x", 0.).unwrap().unwrap(); //! //! let mut expression = Expression::new(expression_string, symbol_table).unwrap(); //! //! let mut i = -5.; //! while i <= 5. { //! expression.symbols().set_value(var_id, i); //! let y = expression.value(); //! println!("{}\t{}", i, y); //! i += 0.001; //! } //! ``` //! //! # Unknown variables //! //! Unknown variables encountered in an expression can be automatically added to the symbol table //! They will return a `Vec` containing the newly added variable names and their variable IDs. //! This works only for regular variables, not for strings or vectors. //! //! ``` //! use exprtk_rs::*; //! //! let expr_string = "a*x^2 + b*x + c"; //! //! let mut symbol_table = SymbolTable::new(); //! let x_id = symbol_table.add_variable("x", 0.).unwrap().unwrap(); //! //! let (mut expr, unknown_vars) = Expression::with_vars(expr_string, symbol_table).unwrap(); //! //! assert_eq!( //! unknown_vars, //! vec![("a".to_string(), 1), ("b".to_string(), 2), ("c".to_string(), 3)] //! ); //! //! // modify the values //! expr.symbols().set_value(1, 2.); // a //! expr.symbols().set_value(2, 3.); // b //! expr.symbols().set_value(3, 1.); // c //! expr.symbols().set_value(x_id, 5.); // x //! //! assert_eq!(expr.value(), 66.); //! ``` //! //! # Strings //! //! The string variables are not Utf-8 encoded like in Rust, but byte strings. They are //! still called 'string' variables in the API. //! //! ``` //! use exprtk_rs::*; //! //! let mut symbol_table = SymbolTable::new(); //! let s1_id = symbol_table.add_stringvar("s1", b"Hello").unwrap().unwrap(); //! let s2_id = symbol_table.add_stringvar("s2", b"world!").unwrap().unwrap(); //! //! // concatenation //! let mut expr = Expression::new("s1 + ' ' + s2 == 'Hello world!'", symbol_table).unwrap(); //! // a boolean `true` is represented by `1` //! assert_eq!(expr.value(), 1.); //! //! // Modifying a string //! expr.symbols().set_string(s1_id, b"What a"); //! assert_eq!(expr.value(), 0.); //! ``` //! //! # Functions //! //! There is currently the possibility to add functions/closures with up to four scalar arguments. //! Example: //! //! ``` //! use exprtk_rs::*; //! //! let mut symbol_table = SymbolTable::new(); //! symbol_table.add_func2("add", |x, y| x + y); //! symbol_table.add_variable("x", 1.).unwrap(); //! //! let mut expr = Expression::new("add(x, 1)", symbol_table).unwrap(); //! assert_eq!(expr.value(), 2.); //! ``` #[macro_use] extern crate enum_primitive; extern crate exprtk_sys; extern crate libc; pub use libc::c_double; pub use exprtk::*; pub use error::*; mod exprtk; mod error; #[cfg(test)] mod tests;