C++ Mathematical Expression Library (ExprTk) http://www.partow.net/programming/exprtk/index.html

This commit is contained in:
Arash Partow 2013-07-12 23:08:57 +10:00
parent 2a9a16fd66
commit 45a1a275dc
3 changed files with 229 additions and 81 deletions

View File

@ -18,7 +18,7 @@
* (03) 1 - sin(2 * x) + cos(pi / y) * * (03) 1 - sin(2 * x) + cos(pi / y) *
* (04) a * exp(2 * t) + c * * (04) a * exp(2 * t) + c *
* (05) if(((x + 2) == 3) and ((y + 5) <= 9),1 + w, 2 / z) * * (05) if(((x + 2) == 3) and ((y + 5) <= 9),1 + w, 2 / z) *
* (06) if(avg(x,y) <= x + y,x - y,x * y) + 2 * pi / x * * (06) if(avg(x,y) <= x + y, x - y, x * y) + 2 * pi / x *
* (07) z := x + sin(2 * pi / y) * * (07) z := x + sin(2 * pi / y) *
* (08) u := 2 * (pi * z) / (w := x + cos(y / pi)) * * (08) u := 2 * (pi * z) / (w := x + cos(y / pi)) *
* (09) clamp(-1,sin(2 * pi * x) + cos(y / 2 * pi),+1) * * (09) clamp(-1,sin(2 * pi * x) + cos(y / 2 * pi),+1) *
@ -39,6 +39,7 @@
#include <cmath> #include <cmath>
#include <cstdio> #include <cstdio>
#include <deque> #include <deque>
#include <iterator>
#include <limits> #include <limits>
#include <list> #include <list>
#include <map> #include <map>
@ -174,6 +175,48 @@ namespace exprtk
return result; return result;
} }
inline void cleanup_espaces(std::string& s)
{
std::string::iterator itr1 = s.begin();
std::string::iterator itr2 = s.begin();
std::string::iterator end = s.end();
std::size_t removal_count = 0;
while (end != itr1)
{
bool bypass = false;
if ('\\' == (*itr1))
{
bypass = true;
++removal_count;
if (end == ++itr1)
break;
else if ('\\' != (*itr1))
{
switch (*itr1)
{
case 'n' : (*itr1) = '\n'; break;
case 'r' : (*itr1) = '\r'; break;
case 't' : (*itr1) = '\t'; break;
}
continue;
}
else
bypass = false;
}
if (!bypass)
{
if (itr1 != itr2)
{
(*itr2) = (*itr1);
}
++itr1;
++itr2;
}
}
s.resize(s.size() - removal_count);
}
class build_string class build_string
{ {
public: public:
@ -238,12 +281,13 @@ namespace exprtk
{ {
"abs", "acos", "and", "asin", "atan", "atan2", "avg", "case", "ceil", "abs", "acos", "and", "asin", "atan", "atan2", "avg", "case", "ceil",
"clamp", "cos", "cosh", "cot", "csc", "default", "deg2grad", "deg2rad", "clamp", "cos", "cosh", "cot", "csc", "default", "deg2grad", "deg2rad",
"equal", "erf", "erfc", "exp", "false", "floor", "for", "frac", "grad2deg", "equal", "erf", "erfc", "exp", "expm1", "false", "floor", "for", "frac",
"hypot", "if", "ilike", "in", "inrange", "like", "log", "log10", "log2", "grad2deg", "hypot", "if", "ilike", "in", "inrange", "like", "log", "log10",
"logn", "log1p", "mand", "max", "min", "mod", "mor", "mul", "nand", "nor", "log2", "logn", "log1p", "mand", "max", "min", "mod", "mor", "mul", "nand",
"not", "not_equal", "null", "or", "pow", "rad2deg", "repeat", "root", "round", "nor", "not", "not_equal", "null", "or", "pow", "rad2deg", "repeat", "root",
"roundn", "sec", "sgn", "shl", "shr", "sin", "sinh", "sqrt", "sum", "switch", "round", "roundn", "sec", "sgn", "shl", "shr", "sin", "sinh", "sqrt", "sum",
"tan", "tanh", "true", "trunc", "until", "while", "xnor", "xor", "&", "|" "switch", "tan", "tanh", "true", "trunc", "until", "while", "xnor", "xor",
"&", "|"
}; };
static const std::size_t reserved_symbols_size = sizeof(reserved_symbols) / sizeof(std::string); static const std::size_t reserved_symbols_size = sizeof(reserved_symbols) / sizeof(std::string);
@ -441,6 +485,22 @@ namespace exprtk
return (v0 == v1) ? 1 : 0; return (v0 == v1) ? 1 : 0;
} }
template <typename T>
inline T expm1_impl(const T v, real_type_tag)
{
//return std::expm1<T>(v);
if (std::abs(v) < T(0.00001))
return v + (T(0.5) * v * v);
else
return std::exp(v) - T(1);
}
template <typename T>
inline T expm1_impl(const T v, int_type_tag)
{
return T(std::exp<double>(v)) - T(1);
}
template <typename T> template <typename T>
inline T nequal_impl(const T v0, const T v1, real_type_tag) inline T nequal_impl(const T v0, const T v1, real_type_tag)
{ {
@ -1000,6 +1060,7 @@ namespace exprtk
exprtk_define_unary_function(cos ) exprtk_define_unary_function(cos )
exprtk_define_unary_function(cosh ) exprtk_define_unary_function(cosh )
exprtk_define_unary_function(exp ) exprtk_define_unary_function(exp )
exprtk_define_unary_function(expm1)
exprtk_define_unary_function(floor) exprtk_define_unary_function(floor)
exprtk_define_unary_function(log ) exprtk_define_unary_function(log )
exprtk_define_unary_function(log10) exprtk_define_unary_function(log10)
@ -1453,6 +1514,14 @@ namespace exprtk
return *this; return *this;
} }
inline token& set_string(const std::string& s, const std::size_t p)
{
type = e_string;
value = s;
position = p;
return *this;
}
template <typename Iterator> template <typename Iterator>
inline token& set_error(const token_type et, const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0)) inline token& set_error(const token_type et, const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
{ {
@ -1943,12 +2012,14 @@ namespace exprtk
} }
++s_itr_; ++s_itr_;
bool escaped_found = false;
bool escaped = false; bool escaped = false;
while (!is_end(s_itr_)) while (!is_end(s_itr_))
{ {
if ('\\' == *s_itr_) if ('\\' == *s_itr_)
{ {
escaped_found = true;
escaped = true; escaped = true;
++s_itr_; ++s_itr_;
continue; continue;
@ -1970,7 +2041,15 @@ namespace exprtk
return; return;
} }
if (!escaped_found)
t.set_string(begin,s_itr_,base_itr_); t.set_string(begin,s_itr_,base_itr_);
else
{
std::string parsed_string(begin,s_itr_);
details::cleanup_espaces(parsed_string);
t.set_string(parsed_string, std::distance(base_itr_,begin));
}
token_list_.push_back(t); token_list_.push_back(t);
++s_itr_; ++s_itr_;
return; return;
@ -2839,16 +2918,16 @@ namespace exprtk
e_mand , e_mor , e_scand , e_scor , e_mand , e_mor , e_scand , e_scor ,
e_shr , e_shl , e_abs , e_acos , e_shr , e_shl , e_abs , e_acos ,
e_asin , e_atan , e_ceil , e_cos , e_asin , e_atan , e_ceil , e_cos ,
e_cosh , e_exp , e_floor , e_log , e_cosh , e_exp , e_expm1 , e_floor ,
e_log10 , e_log2 , e_log1p , e_logn , e_log , e_log10 , e_log2 , e_log1p ,
e_neg , e_pos , e_round , e_roundn , e_logn , e_neg , e_pos , e_round ,
e_root , e_sqrt , e_sin , e_sinh , e_roundn , e_root , e_sqrt , e_sin ,
e_sec , e_csc , e_tan , e_tanh , e_sinh , e_sec , e_csc , e_tan ,
e_cot , e_clamp , e_inrange , e_sgn , e_tanh , e_cot , e_clamp , e_inrange ,
e_r2d , e_d2r , e_d2g , e_g2d , e_sgn , e_r2d , e_d2r , e_d2g ,
e_hypot , e_notl , e_erf , e_erfc , e_g2d , e_hypot , e_notl , e_erf ,
e_frac , e_trunc , e_assign , e_in , e_erfc , e_frac , e_trunc , e_assign ,
e_like , e_ilike , e_multi , e_in , e_like , e_ilike , e_multi ,
// Do not add new functions/operators after this point. // Do not add new functions/operators after this point.
e_sf00 = 1000, e_sf01 = 1001, e_sf02 = 1002, e_sf03 = 1003, e_sf00 = 1000, e_sf01 = 1001, e_sf02 = 1002, e_sf03 = 1003,
@ -2918,6 +2997,7 @@ namespace exprtk
case e_cos : return numeric::cos (arg); case e_cos : return numeric::cos (arg);
case e_cosh : return numeric::cosh (arg); case e_cosh : return numeric::cosh (arg);
case e_exp : return numeric::exp (arg); case e_exp : return numeric::exp (arg);
case e_expm1 : return numeric::expm1(arg);
case e_floor : return numeric::floor(arg); case e_floor : return numeric::floor(arg);
case e_log : return numeric::log (arg); case e_log : return numeric::log (arg);
case e_log10 : return numeric::log10(arg); case e_log10 : return numeric::log10(arg);
@ -2955,6 +3035,7 @@ namespace exprtk
{ {
case e_abs : return numeric::abs (arg); case e_abs : return numeric::abs (arg);
case e_exp : return numeric::exp (arg); case e_exp : return numeric::exp (arg);
case e_expm1 : return numeric::expm1(arg);
case e_log : return numeric::log (arg); case e_log : return numeric::log (arg);
case e_log10 : return numeric::log10(arg); case e_log10 : return numeric::log10(arg);
case e_log2 : return numeric::log2 (arg); case e_log2 : return numeric::log2 (arg);
@ -3078,19 +3159,20 @@ namespace exprtk
e_in , e_like , e_ilike , e_inranges , e_in , e_like , e_ilike , e_inranges ,
e_ipow , e_ipowinv , e_abs , e_acos , e_ipow , e_ipowinv , e_abs , e_acos ,
e_asin , e_atan , e_ceil , e_cos , e_asin , e_atan , e_ceil , e_cos ,
e_cosh , e_exp , e_floor , e_log , e_cosh , e_exp , e_expm1 , e_floor ,
e_log10 , e_log2 , e_log1p , e_neg , e_log , e_log10 , e_log2 , e_log1p ,
e_pos , e_round , e_sin , e_sinh , e_neg , e_pos , e_round , e_sin ,
e_sqrt , e_tan , e_tanh , e_cot , e_sinh , e_sqrt , e_tan , e_tanh ,
e_sec , e_csc , e_r2d , e_d2r , e_cot , e_sec , e_csc , e_r2d ,
e_d2g , e_g2d , e_notl , e_sgn , e_d2r , e_d2g , e_g2d , e_notl ,
e_erf , e_erfc , e_frac , e_trunc , e_sgn , e_erf , e_erfc , e_frac ,
e_uvouv , e_vov , e_cov , e_voc , e_trunc , e_uvouv , e_vov , e_cov ,
e_vob , e_bov , e_cob , e_boc , e_voc , e_vob , e_bov , e_cob ,
e_vovov , e_vovoc , e_vocov , e_covov , e_boc , e_vovov , e_vovoc , e_vocov ,
e_covoc , e_vovovov , e_vovovoc , e_vovocov , e_covov , e_covoc , e_vovovov , e_vovovoc ,
e_vocovov , e_covovov , e_covocov , e_vocovoc , e_vovocov , e_vocovov , e_covovov , e_covocov ,
e_covovoc , e_vococov , e_sf3ext , e_sf4ext e_vocovoc , e_covovoc , e_vococov , e_sf3ext ,
e_sf4ext
}; };
typedef T value_type; typedef T value_type;
@ -4609,27 +4691,28 @@ namespace exprtk
expression_ptr branch0, expression_ptr branch0,
expression_ptr branch1) expression_ptr branch1)
: binary_node<T>(operation,branch0,branch1), : binary_node<T>(operation,branch0,branch1),
is_lefthand_variable_(is_variable_node(binary_node<T>::branch_[0].first)) var_node_ptr_(0)
{} {
if (is_variable_node(binary_node<T>::branch_[0].first))
{
var_node_ptr_ = dynamic_cast<variable_node<T>*>(binary_node<T>::branch_[0].first);
}
}
inline T value() const inline T value() const
{ {
if (is_lefthand_variable_) if (var_node_ptr_)
{ {
variable_node<T>* var_node_ptr = dynamic_cast<variable_node<T>*>(binary_node<T>::branch_[0].first); T& result = var_node_ptr_->ref();
if (var_node_ptr)
{
T& result = var_node_ptr->ref();
result = binary_node<T>::branch_[1].first->value(); result = binary_node<T>::branch_[1].first->value();
return result; return result;
} }
}
return std::numeric_limits<T>::quiet_NaN(); return std::numeric_limits<T>::quiet_NaN();
} }
private: private:
bool is_lefthand_variable_; variable_node<T>* var_node_ptr_;
}; };
template <typename T> template <typename T>
@ -5092,6 +5175,7 @@ namespace exprtk
exprtk_def_unary_op(erf ) exprtk_def_unary_op(erf )
exprtk_def_unary_op(erfc ) exprtk_def_unary_op(erfc )
exprtk_def_unary_op(exp ) exprtk_def_unary_op(exp )
exprtk_def_unary_op(expm1)
exprtk_def_unary_op(floor) exprtk_def_unary_op(floor)
exprtk_def_unary_op(frac ) exprtk_def_unary_op(frac )
exprtk_def_unary_op(g2d ) exprtk_def_unary_op(g2d )
@ -8246,6 +8330,7 @@ namespace exprtk
register_op( "cos",e_cos , 1) register_op( "cos",e_cos , 1)
register_op( "cosh",e_cosh , 1) register_op( "cosh",e_cosh , 1)
register_op( "exp",e_exp , 1) register_op( "exp",e_exp , 1)
register_op( "expm1",e_expm1 , 1)
register_op( "floor",e_floor , 1) register_op( "floor",e_floor , 1)
register_op( "log",e_log , 1) register_op( "log",e_log , 1)
register_op( "log10",e_log10 , 1) register_op( "log10",e_log10 , 1)
@ -10219,7 +10304,8 @@ namespace exprtk
return 0; return 0;
if (symbol_name_cache_.empty()) if (symbol_name_cache_.empty())
return 0; return 0;
std::copy(symbol_name_cache_.begin(), std::sort(symbol_name_cache_.begin(),symbol_name_cache_.end());
std::unique_copy(symbol_name_cache_.begin(),
symbol_name_cache_.end(), symbol_name_cache_.end(),
std::back_inserter(symbols_list)); std::back_inserter(symbols_list));
return symbol_name_cache_.size(); return symbol_name_cache_.size();
@ -11454,6 +11540,14 @@ namespace exprtk
return true; return true;
} }
inline void cache_symbol(const std::string& symbol)
{
if (symbol_name_caching_)
{
symbol_name_cache_.push_back(symbol);
}
}
inline expression_node_ptr parse_string() inline expression_node_ptr parse_string()
{ {
const std::string symbol = current_token_.value; const std::string symbol = current_token_.value;
@ -11474,10 +11568,7 @@ namespace exprtk
result = expression_generator_(dynamic_cast<details::string_literal_node<T>*>(result)->str()); result = expression_generator_(dynamic_cast<details::string_literal_node<T>*>(result)->str());
} }
if (symbol_name_caching_) cache_symbol(symbol);
{
symbol_name_cache_.push_back(symbol);
}
if (peek_token_is(token_t::e_lsqrbracket)) if (peek_token_is(token_t::e_lsqrbracket))
{ {
@ -11677,10 +11768,7 @@ namespace exprtk
expression_node_ptr variable = symbol_table_.get_variable(symbol); expression_node_ptr variable = symbol_table_.get_variable(symbol);
if (variable) if (variable)
{ {
if (symbol_name_caching_) cache_symbol(symbol);
{
symbol_name_cache_.push_back(symbol);
}
if (symbol_table_.is_constant_node(symbol)) if (symbol_table_.is_constant_node(symbol))
{ {
variable = expression_generator_(variable->value()); variable = expression_generator_(variable->value());
@ -11793,10 +11881,7 @@ namespace exprtk
expression_node_ptr variable = symbol_table_.get_variable(symbol); expression_node_ptr variable = symbol_table_.get_variable(symbol);
if (variable) if (variable)
{ {
if (symbol_name_caching_) cache_symbol(symbol);
{
symbol_name_cache_.push_back(symbol);
}
if (symbol_table_.is_constant_node(symbol)) if (symbol_table_.is_constant_node(symbol))
{ {
variable = expression_generator_(variable->value()); variable = expression_generator_(variable->value());
@ -12133,19 +12218,20 @@ namespace exprtk
(details::e_asin == operation) || (details::e_atan == operation) || (details::e_asin == operation) || (details::e_atan == operation) ||
(details::e_ceil == operation) || (details::e_cos == operation) || (details::e_ceil == operation) || (details::e_cos == operation) ||
(details::e_cosh == operation) || (details::e_exp == operation) || (details::e_cosh == operation) || (details::e_exp == operation) ||
(details::e_floor == operation) || (details::e_log == operation) || (details::e_expm1 == operation) || (details::e_floor == operation) ||
(details::e_log10 == operation) || (details::e_log2 == operation) || (details::e_log == operation) || (details::e_log10 == operation) ||
(details::e_log1p == operation) || (details::e_neg == operation) || (details::e_log2 == operation) || (details::e_log1p == operation) ||
(details::e_pos == operation) || (details::e_round == operation) || (details::e_neg == operation) || (details::e_pos == operation) ||
(details::e_sin == operation) || (details::e_sinh == operation) || (details::e_round == operation) || (details::e_sin == operation) ||
(details::e_sqrt == operation) || (details::e_tan == operation) || (details::e_sinh == operation) || (details::e_sqrt == operation) ||
(details::e_tanh == operation) || (details::e_cot == operation) || (details::e_tan == operation) || (details::e_tanh == operation) ||
(details::e_sec == operation) || (details::e_csc == operation) || (details::e_cot == operation) || (details::e_sec == operation) ||
(details::e_r2d == operation) || (details::e_d2r == operation) || (details::e_csc == operation) || (details::e_r2d == operation) ||
(details::e_d2g == operation) || (details::e_g2d == operation) || (details::e_d2r == operation) || (details::e_d2g == operation) ||
(details::e_notl == operation) || (details::e_sgn == operation) || (details::e_g2d == operation) || (details::e_notl == operation) ||
(details::e_erf == operation) || (details::e_erfc == operation) || (details::e_sgn == operation) || (details::e_erf == operation) ||
(details::e_frac == operation) || (details::e_trunc == operation); (details::e_erfc == operation) || (details::e_frac == operation) ||
(details::e_trunc == operation);
} }
inline bool sf3_optimizable(const std::string sf3id, trinary_functor_t& tfunc) inline bool sf3_optimizable(const std::string sf3id, trinary_functor_t& tfunc)
@ -12673,6 +12759,7 @@ namespace exprtk
case_stmt(details:: e_cos,details:: cos_op) \ case_stmt(details:: e_cos,details:: cos_op) \
case_stmt(details:: e_cosh,details:: cosh_op) \ case_stmt(details:: e_cosh,details:: cosh_op) \
case_stmt(details:: e_exp,details:: exp_op) \ case_stmt(details:: e_exp,details:: exp_op) \
case_stmt(details::e_expm1,details::expm1_op) \
case_stmt(details::e_floor,details::floor_op) \ case_stmt(details::e_floor,details::floor_op) \
case_stmt(details:: e_log,details:: log_op) \ case_stmt(details:: e_log,details:: log_op) \
case_stmt(details::e_log10,details::log10_op) \ case_stmt(details::e_log10,details::log10_op) \
@ -16652,6 +16739,7 @@ namespace exprtk
register_unary_op(details:: e_cos,details:: cos_op) register_unary_op(details:: e_cos,details:: cos_op)
register_unary_op(details:: e_cosh,details:: cosh_op) register_unary_op(details:: e_cosh,details:: cosh_op)
register_unary_op(details:: e_exp,details:: exp_op) register_unary_op(details:: e_exp,details:: exp_op)
register_unary_op(details::e_expm1,details::expm1_op)
register_unary_op(details::e_floor,details::floor_op) register_unary_op(details::e_floor,details::floor_op)
register_unary_op(details:: e_log,details:: log_op) register_unary_op(details:: e_log,details:: log_op)
register_unary_op(details::e_log10,details::log10_op) register_unary_op(details::e_log10,details::log10_op)

View File

@ -1270,6 +1270,7 @@ inline bool run_test01()
test_xy<T>("0 * (sin (x) + sinh (y) + sqrt (x) + tan (y))",T(1.0),T(1.0),T(0.0)), test_xy<T>("0 * (sin (x) + sinh (y) + sqrt (x) + tan (y))",T(1.0),T(1.0),T(0.0)),
test_xy<T>("0 * (sec (x) + csc (y) + tanh (x) + cot (y))",T(1.0),T(1.0),T(0.0)), test_xy<T>("0 * (sec (x) + csc (y) + tanh (x) + cot (y))",T(1.0),T(1.0),T(0.0)),
test_xy<T>("0 * (erf (x) + erfc (y) + sgn (y) + frac (y))",T(1.0),T(1.0),T(0.0)), test_xy<T>("0 * (erf (x) + erfc (y) + sgn (y) + frac (y))",T(1.0),T(1.0),T(0.0)),
test_xy<T>("0 * (log1p(x) + expm1(y) )",T(1.0),T(1.0),T(0.0)),
test_xy<T>("0 * (deg2grad(x) + grad2deg(y) + rad2deg(x) + deg2rad(y))",T(1.0),T(1.0),T(0.0)), test_xy<T>("0 * (deg2grad(x) + grad2deg(y) + rad2deg(x) + deg2rad(y))",T(1.0),T(1.0),T(0.0)),
test_xy<T>("switch { case (x <= y) : (y - x); default: 1.12345; }",T(1.0),T(2.0),T(1.0)), test_xy<T>("switch { case (x <= y) : (y - x); default: 1.12345; }",T(1.0),T(2.0),T(1.0)),
test_xy<T>("switch { case (x > y) : 0; case (x <= y) : (y - x); default: 1.12345; }",T(1.0),T(2.0),T(1.0)), test_xy<T>("switch { case (x > y) : 0; case (x <= y) : (y - x); default: 1.12345; }",T(1.0),T(2.0),T(1.0)),
@ -1582,7 +1583,9 @@ inline bool run_test02()
test_ab<T>("{[('!@#$%^&*([{}])-=')]} != [{(')]}{[(*&^%$#@!')}]","","",T(1.0)), test_ab<T>("{[('!@#$%^&*([{}])-=')]} != [{(')]}{[(*&^%$#@!')}]","","",T(1.0)),
test_ab<T>("'!@#$%^&*([{}])-=' == '!@#$%^&*([{}])-='","","",T(1.0)), test_ab<T>("'!@#$%^&*([{}])-=' == '!@#$%^&*([{}])-='","","",T(1.0)),
test_ab<T>("('!@#$%^&*([{}])-=') == ('!@#$%^&*([{}])-=')","","",T(1.0)), test_ab<T>("('!@#$%^&*([{}])-=') == ('!@#$%^&*([{}])-=')","","",T(1.0)),
test_ab<T>("{[('!@#$%^&*([{}])-=')]} == [{('!@#$%^&*([{}])-=')}]","","",T(1.0)) test_ab<T>("{[('!@#$%^&*([{}])-=')]} == [{('!@#$%^&*([{}])-=')}]","","",T(1.0)),
test_ab<T>("'1234\\\\abc\nxyz\r890\tqaz\\'567' == a","1234\\abc\nxyz\r890\tqaz'567","",T(1.0)),
test_ab<T>("a == '1234\\\\abc\nxyz\r890\tqaz\\'567'","1234\\abc\nxyz\r890\tqaz'567","",T(1.0))
}; };
static const std::size_t test_list_size = sizeof(test_list) / sizeof(test_ab<T>); static const std::size_t test_list_size = sizeof(test_list) / sizeof(test_ab<T>);
@ -2713,6 +2716,60 @@ inline bool run_test10()
} }
} }
{
T a = T(1);
T b = T(2);
T c = T(3);
T d = T(4);
std::string e = "string";
exprtk::symbol_table<T> symbol_table;
symbol_table.add_variable ("a",a);
symbol_table.add_variable ("b",b);
symbol_table.add_variable ("c",c);
symbol_table.add_variable ("d",d);
symbol_table.add_stringvar("e",e);
expression_t expression;
expression.register_symbol_table(symbol_table);
std::string expression_string = "(e == '1234') and (sin(a) + c) / b";
std::deque<std::string> variable_list;
{
exprtk::parser<T> parser;
parser.cache_symbols() = true;
if (!parser.compile(expression_string,expression))
{
printf("run_test10() - Error: %s Expression: %s\n",
parser.error().c_str(),
expression_string.c_str());
return false;
}
parser.expression_symbols(variable_list);
}
std::deque<std::string> expected_variable_list;
expected_variable_list.push_back("a");
expected_variable_list.push_back("b");
expected_variable_list.push_back("c");
expected_variable_list.push_back("e");
bool result = (variable_list.size() == expected_variable_list.size()) &&
std::equal(variable_list.begin(),
variable_list.end(),
expected_variable_list.begin());
if (!result)
{
printf("run_test10() - Failed variable list comparison.(5)\n");
return false;
}
}
return true; return true;
} }
@ -4187,7 +4244,7 @@ inline bool run_test20()
{ {
typedef exprtk::expression<T> expression_t; typedef exprtk::expression<T> expression_t;
for (std::size_t i = 0; i < 400; ++i) for (std::size_t i = 0; i < 100; ++i)
{ {
exprtk::symbol_table<T> symbol_table; exprtk::symbol_table<T> symbol_table;
symbol_table.add_constants(); symbol_table.add_constants();

View File

@ -15,10 +15,10 @@ operations, functions and processes:
(0) Basic operators: +, -, *, /, %, ^ (0) Basic operators: +, -, *, /, %, ^
(1) Functions: abs, avg, ceil, clamp, erf, erfc, exp, floor, (1) Functions: abs, avg, ceil, clamp, erf, erfc, exp, expm1,
frac, inrange, log, log10, log1p, log2, logn, floor, frac, inrange, log, log10, log1p, log2,
max, min, root, round, roundn, sgn, sqrt, sum, logn, max, min, root, round, roundn, sgn, sqrt,
trunc sum, trunc
(2) Trigonometry: acos, asin, atan, atan2, cos, cosh, cot, csc, (2) Trigonometry: acos, asin, atan, atan2, cos, cosh, cot, csc,
deg2grad, deg2rad, grad2deg, hypot, rad2deg, deg2grad, deg2rad, grad2deg, hypot, rad2deg,
@ -219,6 +219,9 @@ include path (e.g: /usr/include/).
+----------+---------------------------------------------------------+ +----------+---------------------------------------------------------+
| exp | e to the power of x | | exp | e to the power of x |
+----------+---------------------------------------------------------+ +----------+---------------------------------------------------------+
| expm1 | e to the power of x minus 1, where x is very small. |
| | (eg: expm1(x)) |
+----------+---------------------------------------------------------+
| floor | Largest integer that is less than or equal to x. | | floor | Largest integer that is less than or equal to x. |
+----------+---------------------------------------------------------+ +----------+---------------------------------------------------------+
| frac | Fractional portion of x | | frac | Fractional portion of x |
@ -331,10 +334,10 @@ include path (e.g: /usr/include/).
| | 3. x[ : ] == 'abcdefgh' | | | 3. x[ : ] == 'abcdefgh' |
| | 4. x[4/2:3+2] == x[2:5] == 'cdef' | | | 4. x[4/2:3+2] == x[2:5] == 'cdef' |
| | | | | |
| | Note: Both r0 and r1 are assumed to be integers. They | | | Note: Both r0 and r1 are assumed to be integers, where |
| | may also be the result of an expression, in the event | | | r0 <= r1. They may also be the result of an expression, |
| | they have fractional components truncation will be | | | in the event they have fractional components truncation |
| | performed. (eg: 1.67 -> 1) | | | will be performed. (eg: 1.67 -> 1) |
+----------+---------------------------------------------------------+ +----------+---------------------------------------------------------+
(6) Control Structures (6) Control Structures
@ -517,7 +520,7 @@ correctly optimize such expressions for a given architecture.
that have been defined prior to their own definition. that have been defined prior to their own definition.
(17) Recursive calls made from within composited functions will have (17) Recursive calls made from within composited functions will have
a stack size bound by the stack of executing architecture. a stack size bound by the stack of the executing architecture.
(18) Expressions may contain any of the following comment styles: (18) Expressions may contain any of the following comment styles:
1. // .... \n 1. // .... \n