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
132
133
134
135
136
137
138
139
//! 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. The functions for adding variables
//! ([add_variable()](exprtk/struct.SymbolTable.html#method.add_variable)), strings
//! ([add_stringvar()](exprtk/struct.SymbolTable.html#method.add_stringvar)), vectors
//! ([add_vector()](exprtk/struct.SymbolTable.html#method.add_vector)) all return
//! `usize`, which is a _variable ID_ representing the index in of the value in
//! an internal data structure. It can be used to later get symbol values and modify them.
//! Scalars are either modified via mutable references, or via `std::cell::Cell` types without
//! the requirement of mutable access to the `SymbolTable`.
//! Strings are changed using [set_string()](exprtk/struct.SymbolTable.html#method.set_string),
//! which requires mutable access.
//! Since access and mutation through variable IDs requires a bounds check, these operations
//! are slower than direct modification through pointers, as done in C++. The performance impact
//! is naturally more severe for small expressions with fast running times, but seems not too
//! problematic in most cases. Run `cargo bench` to see the impact (compare with unsafe variant).
//! For each data type (scalars, strings and vectors), access IDs start at zero
//! and are incremented on addition of new variables of the given type.
//!
//! As 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.
//!
//! ExprTk does not handle non-ASCII encodings, therefore variable names and formulae are
//! checked for non-ASCII characters or null bytes and will fail with an error.
//!
//! # 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();
//!
//! // this value is a reference to a std::cell::Cell that can be changed
//! expression.symbols().value_cell(var_id).set(-5.);
//!
//! while expression.symbols().value(var_id) <= 5. {
//! let y = expression.value();
//! println!("{}\t{}", expression.symbols().value(var_id), y);
//! *expression.symbols_mut().value_mut(var_id) += 0.001;
//! }
//! ```
//!
//! # Unknown variables
//!
//! Unknown variables encountered in an expression can be automatically added to the symbol table.
//! The function `Expression::parse_vars` 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 expr, unknown_vars) = Expression::parse_vars(expr_string, SymbolTable::new()).unwrap();
//!
//! assert_eq!(
//! unknown_vars,
//! vec![("a".to_string(), 0), ("x".to_string(), 1), ("b".to_string(), 2), ("c".to_string(), 3)]
//! );
//!
//! // modify the values
//! expr.symbols().value_cell(0).set(2.); // a
//! expr.symbols().value_cell(2).set(3.); // b
//! expr.symbols().value_cell(3).set(1.); // c
//! expr.symbols().value_cell(1).set(5.); // x
//!
//! assert_eq!(expr.value(), 66.);
//! ```
//!
//! # Example using strings
//!
//! ```
//! use exprtk_rs::*;
//!
//! let mut symbol_table = SymbolTable::new();
//! let s1_id = symbol_table.add_stringvar("s1", "Hello").unwrap().unwrap();
//! let s2_id = symbol_table.add_stringvar("s2", "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_mut().set_string(s1_id, "");
//! assert_eq!(expr.value(), 0.);
//! ```
//!
//! # Functions
//!
//! There is currently the possibility to add functions/closures with up to ten 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.);
//! ```
extern crate enum_primitive;
pub use *;
pub use *;
pub use c_double;