C++ Mathematical Expression Library (ExprTk) https://www.partow.net/programming/exprtk/index.html
This commit is contained in:
parent
f75c3934ed
commit
71bba0b6fa
257
exprtk.hpp
257
exprtk.hpp
|
@ -4333,7 +4333,7 @@ namespace exprtk
|
|||
e_sf4ext48 = 2048, e_sf4ext49 = 2049, e_sf4ext50 = 2050, e_sf4ext51 = 2051,
|
||||
e_sf4ext52 = 2052, e_sf4ext53 = 2053, e_sf4ext54 = 2054, e_sf4ext55 = 2055,
|
||||
e_sf4ext56 = 2056, e_sf4ext57 = 2057, e_sf4ext58 = 2058, e_sf4ext59 = 2059,
|
||||
e_sf4ext60 = 2060
|
||||
e_sf4ext60 = 2060, e_sf4ext61 = 2061
|
||||
};
|
||||
|
||||
inline std::string to_str(const operator_type opr)
|
||||
|
@ -5422,6 +5422,7 @@ namespace exprtk
|
|||
virtual const range_t& range_ref() const = 0;
|
||||
};
|
||||
|
||||
#ifndef exprtk_disable_string_capabilities
|
||||
template <typename T>
|
||||
class string_base_node
|
||||
{
|
||||
|
@ -5505,6 +5506,7 @@ namespace exprtk
|
|||
const std::string value_;
|
||||
range_t rp_;
|
||||
};
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
class unary_node : public expression_node<T>
|
||||
|
@ -5532,6 +5534,7 @@ namespace exprtk
|
|||
inline T value() const
|
||||
{
|
||||
const T arg = branch_->value();
|
||||
|
||||
return numeric::process<T>(operation_,arg);
|
||||
}
|
||||
|
||||
|
@ -5664,6 +5667,7 @@ namespace exprtk
|
|||
{
|
||||
const T arg0 = branch_[0].first->value();
|
||||
const T arg1 = branch_[1].first->value();
|
||||
|
||||
return numeric::process<T>(operation_,arg0,arg1);
|
||||
}
|
||||
|
||||
|
@ -6229,6 +6233,7 @@ namespace exprtk
|
|||
inline T value() const
|
||||
{
|
||||
T result = T(0);
|
||||
|
||||
while (is_true(condition_))
|
||||
{
|
||||
try
|
||||
|
@ -6242,6 +6247,7 @@ namespace exprtk
|
|||
catch(const continue_exception&)
|
||||
{}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -7375,6 +7381,7 @@ namespace exprtk
|
|||
{
|
||||
rp_.n1_c.second = (*value_).size() - 1;
|
||||
rp_.cache.second = rp_.n1_c.second;
|
||||
|
||||
return std::numeric_limits<T>::quiet_NaN();
|
||||
}
|
||||
|
||||
|
@ -8876,57 +8883,58 @@ namespace exprtk
|
|||
define_sfop4(ext07,((x - y) - (z / w)),"(t-t)-(t/t)")
|
||||
define_sfop4(ext08,((x + y) - (z - w)),"(t+t)-(t-t)")
|
||||
define_sfop4(ext09,((x + y) + (z - w)),"(t+t)+(t-t)")
|
||||
define_sfop4(ext10,((x + y) * (z - w)),"(t+t)*(t-t)")
|
||||
define_sfop4(ext11,((x + y) / (z - w)),"(t+t)/(t-t)")
|
||||
define_sfop4(ext12,((x - y) - (z + w)),"(t-t)-(t+t)")
|
||||
define_sfop4(ext13,((x - y) + (z + w)),"(t-t)+(t+t)")
|
||||
define_sfop4(ext14,((x - y) * (z + w)),"(t-t)*(t+t)")
|
||||
define_sfop4(ext15,((x - y) / (z + w)),"(t-t)/(t+t)")
|
||||
define_sfop4(ext16,((x * y) - (z + w)),"(t*t)-(t+t)")
|
||||
define_sfop4(ext17,((x / y) - (z + w)),"(t/t)-(t+t)")
|
||||
define_sfop4(ext18,((x * y) + (z + w)),"(t*t)+(t+t)")
|
||||
define_sfop4(ext19,((x / y) + (z + w)),"(t/t)+(t+t)")
|
||||
define_sfop4(ext20,((x * y) + (z - w)),"(t*t)+(t-t)")
|
||||
define_sfop4(ext21,((x / y) + (z - w)),"(t/t)+(t-t)")
|
||||
define_sfop4(ext22,((x * y) - (z - w)),"(t*t)-(t-t)")
|
||||
define_sfop4(ext23,((x / y) - (z - w)),"(t/t)-(t-t)")
|
||||
define_sfop4(ext24,((x + y) * (z * w)),"(t+t)*(t*t)")
|
||||
define_sfop4(ext25,((x + y) * (z / w)),"(t+t)*(t/t)")
|
||||
define_sfop4(ext26,((x + y) / (z * w)),"(t+t)/(t*t)")
|
||||
define_sfop4(ext27,((x + y) / (z / w)),"(t+t)/(t/t)")
|
||||
define_sfop4(ext28,((x - y) / (z * w)),"(t-t)/(t*t)")
|
||||
define_sfop4(ext29,((x - y) / (z / w)),"(t-t)/(t/t)")
|
||||
define_sfop4(ext30,((x - y) * (z * w)),"(t-t)*(t*t)")
|
||||
define_sfop4(ext31,((x - y) * (z / w)),"(t-t)*(t/t)")
|
||||
define_sfop4(ext32,((x * y) * (z + w)),"(t*t)*(t+t)")
|
||||
define_sfop4(ext33,((x / y) * (z + w)),"(t/t)*(t+t)")
|
||||
define_sfop4(ext34,((x * y) / (z + w)),"(t*t)/(t+t)")
|
||||
define_sfop4(ext35,((x / y) / (z + w)),"(t/t)/(t+t)")
|
||||
define_sfop4(ext36,((x * y) / (z - w)),"(t*t)/(t-t)")
|
||||
define_sfop4(ext37,((x / y) / (z - w)),"(t/t)/(t-t)")
|
||||
define_sfop4(ext38,((x * y) * (z - w)),"(t*t)*(t-t)")
|
||||
define_sfop4(ext39,((x * y) / (z * w)),"(t*t)/(t*t)")
|
||||
define_sfop4(ext40,((x / y) * (z / w)),"(t/t)*(t/t)")
|
||||
define_sfop4(ext41,((x / y) * (z - w)),"(t/t)*(t-t)")
|
||||
define_sfop4(ext42,((x * y) * (z * w)),"(t*t)*(t*t)")
|
||||
define_sfop4(ext43,(x + (y * (z / w))),"t+(t*(t/t))")
|
||||
define_sfop4(ext44,(x - (y * (z / w))),"t-(t*(t/t))")
|
||||
define_sfop4(ext45,(x + (y / (z * w))),"t+(t/(t*t))")
|
||||
define_sfop4(ext46,(x - (y / (z * w))),"t-(t/(t*t))")
|
||||
define_sfop4(ext47,(((x - y) - z) * w),"((t-t)-t)*t")
|
||||
define_sfop4(ext48,(((x - y) - z) / w),"((t-t)-t)/t")
|
||||
define_sfop4(ext49,(((x - y) + z) * w),"((t-t)+t)*t")
|
||||
define_sfop4(ext50,(((x - y) + z) / w),"((t-t)+t)/t")
|
||||
define_sfop4(ext51,((x + (y - z)) * w),"(t+(t-t))*t")
|
||||
define_sfop4(ext52,((x + (y - z)) / w),"(t+(t-t))/t")
|
||||
define_sfop4(ext53,((x + y) / (z + w)),"(t+t)/(t+t)")
|
||||
define_sfop4(ext54,((x - y) / (z - w)),"(t-t)/(t-t)")
|
||||
define_sfop4(ext55,((x + y) * (z + w)),"(t+t)*(t+t)")
|
||||
define_sfop4(ext56,((x - y) * (z - w)),"(t-t)*(t-t)")
|
||||
define_sfop4(ext57,((x - y) + (z - w)),"(t-t)+(t-t)")
|
||||
define_sfop4(ext58,((x - y) - (z - w)),"(t-t)-(t-t)")
|
||||
define_sfop4(ext59,((x / y) + (z * w)),"(t/t)+(t*t)")
|
||||
define_sfop4(ext60,(((x * y) * z) / w),"((t*t)*t)/t")
|
||||
define_sfop4(ext10,((x + y) + (z + w)),"(t+t)+(t+t)")
|
||||
define_sfop4(ext11,((x + y) * (z - w)),"(t+t)*(t-t)")
|
||||
define_sfop4(ext12,((x + y) / (z - w)),"(t+t)/(t-t)")
|
||||
define_sfop4(ext13,((x - y) - (z + w)),"(t-t)-(t+t)")
|
||||
define_sfop4(ext14,((x - y) + (z + w)),"(t-t)+(t+t)")
|
||||
define_sfop4(ext15,((x - y) * (z + w)),"(t-t)*(t+t)")
|
||||
define_sfop4(ext16,((x - y) / (z + w)),"(t-t)/(t+t)")
|
||||
define_sfop4(ext17,((x * y) - (z + w)),"(t*t)-(t+t)")
|
||||
define_sfop4(ext18,((x / y) - (z + w)),"(t/t)-(t+t)")
|
||||
define_sfop4(ext19,((x * y) + (z + w)),"(t*t)+(t+t)")
|
||||
define_sfop4(ext20,((x / y) + (z + w)),"(t/t)+(t+t)")
|
||||
define_sfop4(ext21,((x * y) + (z - w)),"(t*t)+(t-t)")
|
||||
define_sfop4(ext22,((x / y) + (z - w)),"(t/t)+(t-t)")
|
||||
define_sfop4(ext23,((x * y) - (z - w)),"(t*t)-(t-t)")
|
||||
define_sfop4(ext24,((x / y) - (z - w)),"(t/t)-(t-t)")
|
||||
define_sfop4(ext25,((x + y) * (z * w)),"(t+t)*(t*t)")
|
||||
define_sfop4(ext26,((x + y) * (z / w)),"(t+t)*(t/t)")
|
||||
define_sfop4(ext27,((x + y) / (z * w)),"(t+t)/(t*t)")
|
||||
define_sfop4(ext28,((x + y) / (z / w)),"(t+t)/(t/t)")
|
||||
define_sfop4(ext29,((x - y) / (z * w)),"(t-t)/(t*t)")
|
||||
define_sfop4(ext30,((x - y) / (z / w)),"(t-t)/(t/t)")
|
||||
define_sfop4(ext31,((x - y) * (z * w)),"(t-t)*(t*t)")
|
||||
define_sfop4(ext32,((x - y) * (z / w)),"(t-t)*(t/t)")
|
||||
define_sfop4(ext33,((x * y) * (z + w)),"(t*t)*(t+t)")
|
||||
define_sfop4(ext34,((x / y) * (z + w)),"(t/t)*(t+t)")
|
||||
define_sfop4(ext35,((x * y) / (z + w)),"(t*t)/(t+t)")
|
||||
define_sfop4(ext36,((x / y) / (z + w)),"(t/t)/(t+t)")
|
||||
define_sfop4(ext37,((x * y) / (z - w)),"(t*t)/(t-t)")
|
||||
define_sfop4(ext38,((x / y) / (z - w)),"(t/t)/(t-t)")
|
||||
define_sfop4(ext39,((x * y) * (z - w)),"(t*t)*(t-t)")
|
||||
define_sfop4(ext40,((x * y) / (z * w)),"(t*t)/(t*t)")
|
||||
define_sfop4(ext41,((x / y) * (z / w)),"(t/t)*(t/t)")
|
||||
define_sfop4(ext42,((x / y) * (z - w)),"(t/t)*(t-t)")
|
||||
define_sfop4(ext43,((x * y) * (z * w)),"(t*t)*(t*t)")
|
||||
define_sfop4(ext44,(x + (y * (z / w))),"t+(t*(t/t))")
|
||||
define_sfop4(ext45,(x - (y * (z / w))),"t-(t*(t/t))")
|
||||
define_sfop4(ext46,(x + (y / (z * w))),"t+(t/(t*t))")
|
||||
define_sfop4(ext47,(x - (y / (z * w))),"t-(t/(t*t))")
|
||||
define_sfop4(ext48,(((x - y) - z) * w),"((t-t)-t)*t")
|
||||
define_sfop4(ext49,(((x - y) - z) / w),"((t-t)-t)/t")
|
||||
define_sfop4(ext50,(((x - y) + z) * w),"((t-t)+t)*t")
|
||||
define_sfop4(ext51,(((x - y) + z) / w),"((t-t)+t)/t")
|
||||
define_sfop4(ext52,((x + (y - z)) * w),"(t+(t-t))*t")
|
||||
define_sfop4(ext53,((x + (y - z)) / w),"(t+(t-t))/t")
|
||||
define_sfop4(ext54,((x + y) / (z + w)),"(t+t)/(t+t)")
|
||||
define_sfop4(ext55,((x - y) / (z - w)),"(t-t)/(t-t)")
|
||||
define_sfop4(ext56,((x + y) * (z + w)),"(t+t)*(t+t)")
|
||||
define_sfop4(ext57,((x - y) * (z - w)),"(t-t)*(t-t)")
|
||||
define_sfop4(ext58,((x - y) + (z - w)),"(t-t)+(t-t)")
|
||||
define_sfop4(ext59,((x - y) - (z - w)),"(t-t)-(t-t)")
|
||||
define_sfop4(ext60,((x / y) + (z * w)),"(t/t)+(t*t)")
|
||||
define_sfop4(ext61,(((x * y) * z) / w),"((t*t)*t)/t")
|
||||
|
||||
#undef define_sfop3
|
||||
#undef define_sfop4
|
||||
|
@ -11174,6 +11182,7 @@ namespace exprtk
|
|||
ts.data = vi->vds().data();
|
||||
ts.type = type_store_t::e_vector;
|
||||
}
|
||||
#ifndef exprtk_disable_string_capabilities
|
||||
else if (is_generally_string_node(arg_list_[i]))
|
||||
{
|
||||
string_base_node<T>* sbn = reinterpret_cast<string_base_node<T>*>(0);
|
||||
|
@ -11209,6 +11218,7 @@ namespace exprtk
|
|||
else
|
||||
range_list_[i].range = &(ri->range_ref());
|
||||
}
|
||||
#endif
|
||||
else if (is_variable_node(arg_list_[i]))
|
||||
{
|
||||
variable_node_ptr_t var = variable_node_ptr_t(0);
|
||||
|
@ -11282,10 +11292,11 @@ namespace exprtk
|
|||
type_store_t& ts = typestore_list_[i];
|
||||
|
||||
ts.size = rp.cache_size();
|
||||
|
||||
#ifndef exprtk_disable_string_capabilities
|
||||
if (ts.type == type_store_t::e_string)
|
||||
ts.data = const_cast<char*>(rdt.str_node->base()) + rp.cache.first;
|
||||
else
|
||||
#endif
|
||||
ts.data = static_cast<char*>(rdt.data) + (rp.cache.first * rdt.type_size);
|
||||
}
|
||||
else
|
||||
|
@ -11307,6 +11318,7 @@ namespace exprtk
|
|||
mutable range_list_t range_list_;
|
||||
};
|
||||
|
||||
#ifndef exprtk_disable_string_capabilities
|
||||
template <typename T, typename StringFunction>
|
||||
class string_function_node : public generic_function_node<T,StringFunction>,
|
||||
public string_base_node<T>,
|
||||
|
@ -11390,6 +11402,7 @@ namespace exprtk
|
|||
mutable range_t range_;
|
||||
mutable std::string ret_string_;
|
||||
};
|
||||
#endif
|
||||
|
||||
template <typename T, typename GenericFunction>
|
||||
class multimode_genfunction_node : public generic_function_node<T,GenericFunction>
|
||||
|
@ -11434,6 +11447,7 @@ namespace exprtk
|
|||
std::size_t param_seq_index_;
|
||||
};
|
||||
|
||||
#ifndef exprtk_disable_string_capabilities
|
||||
template <typename T, typename StringFunction>
|
||||
class multimode_strfunction_node : public string_function_node<T,StringFunction>
|
||||
{
|
||||
|
@ -11482,6 +11496,7 @@ namespace exprtk
|
|||
|
||||
std::size_t param_seq_index_;
|
||||
};
|
||||
#endif
|
||||
|
||||
class return_exception
|
||||
{};
|
||||
|
@ -16286,13 +16301,19 @@ namespace exprtk
|
|||
local_data().vector_store.clear();
|
||||
}
|
||||
|
||||
inline void clear_local_constants()
|
||||
{
|
||||
local_data().local_symbol_list_.clear();
|
||||
}
|
||||
|
||||
inline void clear()
|
||||
{
|
||||
if (!valid()) return;
|
||||
clear_variables();
|
||||
clear_functions();
|
||||
clear_strings ();
|
||||
clear_vectors ();
|
||||
clear_variables ();
|
||||
clear_functions ();
|
||||
clear_strings ();
|
||||
clear_vectors ();
|
||||
clear_local_constants();
|
||||
}
|
||||
|
||||
inline std::size_t variable_count() const
|
||||
|
@ -18711,11 +18732,13 @@ namespace exprtk
|
|||
case e_st_string :
|
||||
case e_st_local_variable :
|
||||
case e_st_local_vector :
|
||||
case e_st_local_string :
|
||||
case e_st_function :
|
||||
if (collect_variables_ || collect_functions_)
|
||||
symbol_name_list_.push_back(std::make_pair(symbol,st));
|
||||
break;
|
||||
case e_st_local_string : if (collect_variables_)
|
||||
symbol_name_list_.push_back(std::make_pair(symbol,st));
|
||||
break;
|
||||
|
||||
case e_st_function : if (collect_functions_)
|
||||
symbol_name_list_.push_back(std::make_pair(symbol,st));
|
||||
break;
|
||||
|
||||
default : return;
|
||||
}
|
||||
|
@ -22776,6 +22799,7 @@ namespace exprtk
|
|||
return result;
|
||||
}
|
||||
|
||||
#ifndef exprtk_disable_string_capabilities
|
||||
inline expression_node_ptr parse_string_function_call(igeneric_function<T>* function, const std::string& function_name)
|
||||
{
|
||||
std::vector<expression_node_ptr> arg_list;
|
||||
|
@ -22856,6 +22880,7 @@ namespace exprtk
|
|||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename Type, std::size_t NumberOfParameters>
|
||||
struct parse_special_function_impl
|
||||
|
@ -24235,6 +24260,7 @@ namespace exprtk
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef exprtk_disable_string_capabilities
|
||||
{
|
||||
// Are we dealing with a vararg string returning function?
|
||||
igeneric_function<T>* string_function = symtab_store_.get_string_function(symbol);
|
||||
|
@ -24259,6 +24285,7 @@ namespace exprtk
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Are we dealing with a vector?
|
||||
if (symtab_store_.is_vector(symbol))
|
||||
|
@ -26373,6 +26400,7 @@ namespace exprtk
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef exprtk_disable_string_capabilities
|
||||
inline expression_node_ptr string_function_call(igeneric_function_t* gf,
|
||||
std::vector<expression_node_ptr>& arg_list,
|
||||
const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max())
|
||||
|
@ -26425,6 +26453,7 @@ namespace exprtk
|
|||
return error_node();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
inline expression_node_ptr return_call(std::vector<expression_node_ptr>& arg_list)
|
||||
{
|
||||
|
@ -28078,6 +28107,7 @@ namespace exprtk
|
|||
return false;
|
||||
|
||||
const std::string node_id = branch_to_id(branch);
|
||||
|
||||
typename synthesize_map_t::iterator itr = synthesize_map_.find(node_id);
|
||||
|
||||
if (synthesize_map_.end() != itr)
|
||||
|
@ -28278,7 +28308,7 @@ namespace exprtk
|
|||
case_stmt1(48) case_stmt1(49) case_stmt1(50) case_stmt1(51)
|
||||
case_stmt1(52) case_stmt1(53) case_stmt1(54) case_stmt1(55)
|
||||
case_stmt1(56) case_stmt1(57) case_stmt1(58) case_stmt1(59)
|
||||
case_stmt1(60)
|
||||
case_stmt1(60) case_stmt1(61)
|
||||
|
||||
#undef case_stmt0
|
||||
#undef case_stmt1
|
||||
|
@ -28357,6 +28387,7 @@ namespace exprtk
|
|||
typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr;
|
||||
|
||||
sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node);
|
||||
|
||||
std::string id = "(" + n->type_id() + ")" + expr_gen.to_str(operation) + "t";
|
||||
|
||||
switch (n->type())
|
||||
|
@ -33404,7 +33435,7 @@ namespace exprtk
|
|||
register_sf4ext(48) register_sf4ext(49) register_sf4ext(50) register_sf4ext(51)
|
||||
register_sf4ext(52) register_sf4ext(53) register_sf4ext(54) register_sf4ext(55)
|
||||
register_sf4ext(56) register_sf4ext(57) register_sf4ext(58) register_sf4ext(59)
|
||||
register_sf4ext(60)
|
||||
register_sf4ext(60) register_sf4ext(61)
|
||||
#undef register_sf4ext
|
||||
}
|
||||
|
||||
|
@ -33466,6 +33497,76 @@ namespace exprtk
|
|||
lexer::helper::sequence_validator sequence_validator_;
|
||||
};
|
||||
|
||||
template <typename Allocator,
|
||||
template <typename, typename> class Sequence>
|
||||
inline bool collect_variables(const std::string& expr_str,
|
||||
Sequence<std::string, Allocator>& symbol_list)
|
||||
{
|
||||
typedef double T;
|
||||
typedef exprtk::symbol_table<T> symbol_table_t;
|
||||
typedef exprtk::expression<T> expression_t;
|
||||
typedef exprtk::parser<T> parser_t;
|
||||
typedef parser_t::dependent_entity_collector::symbol_t symbol_t;
|
||||
|
||||
symbol_table_t symbol_table;
|
||||
expression_t expression;
|
||||
parser_t parser;
|
||||
|
||||
expression.register_symbol_table(symbol_table);
|
||||
|
||||
parser.enable_unknown_symbol_resolver();
|
||||
parser.dec().collect_variables() = true;
|
||||
|
||||
if (!parser.compile(expr_str, expression))
|
||||
return false;
|
||||
|
||||
std::deque<symbol_t> symb_list;
|
||||
|
||||
parser.dec().symbols(symb_list);
|
||||
|
||||
for (std::size_t i = 0; i < symb_list.size(); ++i)
|
||||
{
|
||||
symbol_list.push_back(symb_list[i].first);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Allocator,
|
||||
template <typename, typename> class Sequence>
|
||||
inline bool collect_functions(const std::string& expr_str,
|
||||
Sequence<std::string, Allocator>& symbol_list)
|
||||
{
|
||||
typedef double T;
|
||||
typedef exprtk::symbol_table<T> symbol_table_t;
|
||||
typedef exprtk::expression<T> expression_t;
|
||||
typedef exprtk::parser<T> parser_t;
|
||||
typedef parser_t::dependent_entity_collector::symbol_t symbol_t;
|
||||
|
||||
symbol_table_t symbol_table;
|
||||
expression_t expression;
|
||||
parser_t parser;
|
||||
|
||||
expression.register_symbol_table(symbol_table);
|
||||
|
||||
parser.enable_unknown_symbol_resolver();
|
||||
parser.dec().collect_functions() = true;
|
||||
|
||||
if (!parser.compile(expr_str, expression))
|
||||
return false;
|
||||
|
||||
std::deque<symbol_t> symb_list;
|
||||
|
||||
parser.dec().symbols(symb_list);
|
||||
|
||||
for (std::size_t i = 0; i < symb_list.size(); ++i)
|
||||
{
|
||||
symbol_list.push_back(symb_list[i].first);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T integrate(const expression<T>& e,
|
||||
T& x,
|
||||
|
@ -33673,6 +33774,8 @@ namespace exprtk
|
|||
symbol_table.add_constants();
|
||||
|
||||
expression<T> expression;
|
||||
expression.register_symbol_table(symbol_table);
|
||||
|
||||
parser<T> parser;
|
||||
|
||||
if (parser.compile(expression_string,expression))
|
||||
|
@ -33695,9 +33798,11 @@ namespace exprtk
|
|||
|
||||
symbol_table<T> symbol_table;
|
||||
symbol_table.add_constants();
|
||||
symbol_table.add_variable(x_var,x);
|
||||
symbol_table.add_constant(x_var,x);
|
||||
|
||||
expression<T> expression;
|
||||
expression.register_symbol_table(symbol_table);
|
||||
|
||||
parser<T> parser;
|
||||
|
||||
if (parser.compile(expression_string,expression))
|
||||
|
@ -33721,10 +33826,12 @@ namespace exprtk
|
|||
|
||||
symbol_table<T> symbol_table;
|
||||
symbol_table.add_constants();
|
||||
symbol_table.add_variable(x_var,x);
|
||||
symbol_table.add_variable(y_var,y);
|
||||
symbol_table.add_constant(x_var,x);
|
||||
symbol_table.add_constant(y_var,y);
|
||||
|
||||
expression<T> expression;
|
||||
expression.register_symbol_table(symbol_table);
|
||||
|
||||
parser<T> parser;
|
||||
|
||||
if (parser.compile(expression_string,expression))
|
||||
|
@ -33749,11 +33856,13 @@ namespace exprtk
|
|||
|
||||
symbol_table<T> symbol_table;
|
||||
symbol_table.add_constants();
|
||||
symbol_table.add_variable(x_var,x);
|
||||
symbol_table.add_variable(y_var,y);
|
||||
symbol_table.add_variable(z_var,z);
|
||||
symbol_table.add_constant(x_var,x);
|
||||
symbol_table.add_constant(y_var,y);
|
||||
symbol_table.add_constant(z_var,z);
|
||||
|
||||
expression<T> expression;
|
||||
expression.register_symbol_table(symbol_table);
|
||||
|
||||
parser<T> parser;
|
||||
|
||||
if (parser.compile(expression_string,expression))
|
||||
|
@ -34948,7 +35057,7 @@ namespace exprtk
|
|||
else_stmt(46) else_stmt(47) else_stmt(48) else_stmt(49)
|
||||
else_stmt(50) else_stmt(51) else_stmt(52) else_stmt(53)
|
||||
else_stmt(54) else_stmt(55) else_stmt(56) else_stmt(57)
|
||||
else_stmt(58) else_stmt(59) else_stmt(60)
|
||||
else_stmt(58) else_stmt(59) else_stmt(60) else_stmt(61)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -36831,9 +36940,9 @@ namespace exprtk
|
|||
namespace information
|
||||
{
|
||||
static const char* library = "Mathematical Expression Toolkit";
|
||||
static const char* version = "2.71828182845904523536028747135266249775"
|
||||
"7247093699959574966967627724076630353547";
|
||||
static const char* date = "20161010";
|
||||
static const char* version = "2.7182818284590452353602874713526624977572"
|
||||
"470936999595749669676277240766303535475945";
|
||||
static const char* date = "20161212";
|
||||
|
||||
static inline std::string data()
|
||||
{
|
||||
|
|
|
@ -4029,6 +4029,42 @@ inline bool run_test10()
|
|||
}
|
||||
}
|
||||
|
||||
{
|
||||
T a = T(1);
|
||||
T b = T(2);
|
||||
T c = T(3);
|
||||
T d = T(4);
|
||||
|
||||
std::string e = "a string";
|
||||
|
||||
exprtk::symbol_table<T> symbol_table0;
|
||||
exprtk::symbol_table<T> symbol_table1;
|
||||
expression_t expression;
|
||||
|
||||
for (std::size_t i = 0; i < 10000; ++i)
|
||||
{
|
||||
symbol_table0.clear();
|
||||
symbol_table1.clear();
|
||||
|
||||
symbol_table0.add_variable ("a",a);
|
||||
symbol_table0.add_variable ("b",b);
|
||||
symbol_table0.add_variable ("c",c);
|
||||
symbol_table0.add_variable ("d",d);
|
||||
symbol_table0.add_stringvar("e",e);
|
||||
symbol_table0.add_constants( );
|
||||
|
||||
symbol_table1.add_variable ("a",a);
|
||||
symbol_table1.add_variable ("b",b);
|
||||
symbol_table1.add_variable ("c",c);
|
||||
symbol_table1.add_variable ("d",d);
|
||||
symbol_table1.add_stringvar("e",e);
|
||||
symbol_table1.add_constants( );
|
||||
|
||||
expression.register_symbol_table(symbol_table0);
|
||||
expression.register_symbol_table(symbol_table1);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
std::string expression_list[] =
|
||||
{
|
||||
|
|
731
readme.txt
731
readme.txt
|
@ -1,11 +1,42 @@
|
|||
C++ Mathematical Expression Toolkit Library
|
||||
C++ Mathematical Expression Toolkit Library Documentation
|
||||
|
||||
Section 00 - Introduction
|
||||
Section 01 - Capabilities
|
||||
Section 02 - Example Expressions
|
||||
Section 03 - Copyright Notice
|
||||
Section 04 - Downloads & Updates
|
||||
Section 05 - Installation
|
||||
Section 06 - Compilation
|
||||
Section 07 - Compiler Compatibility
|
||||
Section 08 - Built-In Operations & Functions
|
||||
Section 09 - Fundamental Types
|
||||
Section 10 - Components
|
||||
Section 11 - Compilation Options
|
||||
Section 12 - Special Functions
|
||||
Section 13 - Variable, Vector & String Definition
|
||||
Section 14 - Vector Processing
|
||||
Section 15 - User Defined Functions
|
||||
Section 16 - Expression Dependents
|
||||
Section 17 - Hierarchies Of Symbol Tables
|
||||
Section 18 - Unknown Unknowns
|
||||
Section 19 - Enabling & Disabling Features
|
||||
Section 20 - Expression Return Values
|
||||
Section 21 - Compilation Errors
|
||||
Section 22 - Runtime Library Packages
|
||||
Section 23 - Helpers & Utils
|
||||
Section 24 - Exprtk Notes
|
||||
Section 25 - Simple Exprtk Example
|
||||
Section 26 - Build Options
|
||||
Section 27 - Files
|
||||
Section 28 - Language Structure
|
||||
|
||||
|
||||
[00 - INTRODUCTION]
|
||||
The C++ Mathematical Expression Toolkit Library (ExprTk) is a simple
|
||||
to use, easy to integrate and extremely efficient run-time
|
||||
mathematical expression parsing and evaluation engine. The parsing
|
||||
engine supports numerous forms of functional and logic processing
|
||||
semantics and is easily extendible.
|
||||
semantics and is easily extensible.
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -116,7 +147,7 @@ include path (e.g: /usr/include/).
|
|||
ExprTk has been built error and warning free using the following set
|
||||
of C++ compilers:
|
||||
|
||||
(*) GNU Compiler Collection (3.3+)
|
||||
(*) GNU Compiler Collection (3.5+)
|
||||
(*) Intel C++ Compiler (8.x+)
|
||||
(*) Clang/LLVM (1.1+)
|
||||
(*) PGI C++ (10.x+)
|
||||
|
@ -608,7 +639,7 @@ appropriate may represent any of one the following:
|
|||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
[09 - Fundamental Types]
|
||||
[09 - FUNDAMENTAL TYPES]
|
||||
ExprTk supports three fundamental types which can be used freely in
|
||||
expressions. The types are as follows:
|
||||
|
||||
|
@ -719,7 +750,9 @@ Note: It is possible to register multiple symbol_tables with a single
|
|||
expression object. In the event an expression has multiple symbol
|
||||
tables, and where there exists conflicts between symbols, the
|
||||
compilation stage will resolve the conflicts based on the order of
|
||||
registration of the symbol_tables to the expression.
|
||||
registration of the symbol_tables to the expression. For a more
|
||||
expansive discussion please review section [17 - Hierarchies Of
|
||||
Symbol Tables]
|
||||
|
||||
typedef exprtk::symbol_table<double> symbol_table_t;
|
||||
typedef exprtk::expression<double> expression_t;
|
||||
|
@ -1144,7 +1177,7 @@ correctly optimize such expressions for a given architecture.
|
|||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
[13 - VARIABLE , VECTOR & STRING DEFINITION]
|
||||
[13 - VARIABLE, VECTOR & STRING DEFINITION]
|
||||
ExprTk supports the definition of expression local variables, vectors
|
||||
and strings. The definitions must be unique as shadowing is not
|
||||
allowed and object life-times are based on scope. Definitions use the
|
||||
|
@ -1964,7 +1997,7 @@ carried out:
|
|||
|
||||
|
||||
Note: For the igeneric_function type, there also needs to be a 'Z'
|
||||
parameter sequence defined inorder for the zero parameter trait to
|
||||
parameter sequence defined in order for the zero parameter trait to
|
||||
properly take effect otherwise a compilation error will occur.
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -2115,7 +2148,410 @@ will not contain symbols denoting functions.
|
|||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
[17 - ENABLING AND DISABLING FEATURES]
|
||||
[17 - HIERARCHIES OF SYMBOL TABLES]
|
||||
Most situations will only require a single symbol_table instance to be
|
||||
associated with a given expression instance.
|
||||
|
||||
However as an expression can have more than one symbol table instance
|
||||
associated with itself, when building more complex systems that
|
||||
utilize many expressions where each can in turn utilize one or more
|
||||
variables from a large set of potential variables, functions or
|
||||
constants, it becomes evident that grouping variables into layers of
|
||||
symbol_tables will simplify and streamline the overall process.
|
||||
|
||||
A suggested hierarchy of symbol tables is as follows:
|
||||
|
||||
(a) Global constant value symbol table
|
||||
(b) Global non side-effect functions symbol table
|
||||
(c) Global variable symbol table
|
||||
(d) Expression specific variable symbol table
|
||||
|
||||
|
||||
(a) Global constant value symbol table
|
||||
This symbol table will contain constant variables denoting immutable
|
||||
values. These variables can be made available to all expressions, and
|
||||
in turn expressions will assume the values themselves will never be
|
||||
modified for the duration of the process run-time. Examples of such
|
||||
variables are:
|
||||
|
||||
(1) pi or e
|
||||
(2) speed_of_light
|
||||
(3) avogadro_number
|
||||
(4) num_cpus
|
||||
|
||||
|
||||
(b) Global non side-effect functions symbol table
|
||||
This symbol table will contain only user defined functions that will
|
||||
not incur any side-effects that are visible to any of the expressions
|
||||
that invoke them. These functions will be thread-safe or threading
|
||||
invariant and will not maintain any form of state between invocations.
|
||||
Examples of such functions are:
|
||||
|
||||
(1) calc_volume_of_sphere(r)
|
||||
(2) distance(x0,y0,x1,y1)
|
||||
|
||||
|
||||
(c) Global variable symbol table
|
||||
This symbol table will contain variables that will be accessible to
|
||||
all associated expressions and will not be specific to exclusive to
|
||||
any one expression. This variant differs from (a) in that the values
|
||||
of the variables can change (or be updated) between evaluations of
|
||||
expressions - but through properly scheduled evaluations are
|
||||
guaranteed to never change during the evaluation of any dependent
|
||||
expressions. Furthermore it is assumed that these variables will be
|
||||
used in a read-only context and that no expressions will attempt to
|
||||
modify these variables via assignments or other means.
|
||||
|
||||
(1) price_of_stock_xyz
|
||||
(2) outside_temperature or inside_temperature
|
||||
(3) fuel_in_tank
|
||||
(4) num_customers_in_store
|
||||
(5) num_items_on_shelf
|
||||
|
||||
|
||||
(d) Expression specific variable symbol table
|
||||
This symbol_table is the most common form, and is used to store
|
||||
variables that are specific and exclusive to a particular expression.
|
||||
That is to say references to variables in this symbol_table will not
|
||||
be part of another expression. Though it may be possible to have
|
||||
expressions that contain the variables with the same name, in that
|
||||
case those variables will be distinct different. Which would mean if a
|
||||
particular expression were to be compiled twice, that each expression
|
||||
would have it's own unique symbol_table which in turn would have it's
|
||||
own instances of those variables. Examples of such variables could be:
|
||||
|
||||
(1) x or y
|
||||
(2) customer_name
|
||||
|
||||
|
||||
The following is a diagram depicting the possible version of the
|
||||
denoted symbol table hierarchies. In the diagram there are two unique
|
||||
expressions, each of which have a reference to the Global constant,
|
||||
functions and variables symbol tables and an exclusive reference to a
|
||||
local symbol table.
|
||||
|
||||
+-------------------------+ +-------------------------+
|
||||
| Global Constants | | Global Functions |
|
||||
| Symbol Table | | Symbol Table |
|
||||
+----o--o-----------------+ +--------------------o----+
|
||||
| | |
|
||||
| | +-------+
|
||||
| +------------------->----------------------------+ |
|
||||
| +----------------------------+ | |
|
||||
| | Global Variables | | |
|
||||
| +------o Symbol Table o-----+ | V
|
||||
| | +----------------------------+ | | |
|
||||
| | | | |
|
||||
| | +----------------+ +----------------+ | | |
|
||||
| | | Symbol Table 0 | | Symbol Table 1 | | V |
|
||||
| | +--o-------------+ +--o-------------+ | | |
|
||||
| | | | | | |
|
||||
| | | | | | |
|
||||
+--V--V----V---------+ +-V---------------V--+ | |
|
||||
| Expression 0 | | Expression 1 |<--+--+
|
||||
| '2 * sin(x) - y' | | 'k + abs(x - y)' |
|
||||
+--------------------+ +--------------------+
|
||||
|
||||
|
||||
Bringing all of the above together, in the following example the
|
||||
hierarchy of symbol tables are instantiated and initialised. An
|
||||
expression that makes use of various elements of each symbol table is
|
||||
then compiled and later on evaluated:
|
||||
|
||||
typedef exprtk::symbol_table<double> symbol_table_t;
|
||||
typedef exprtk::expression<double> expression_t;
|
||||
|
||||
// Setup global constants symbol table
|
||||
symbol_table_t glbl_const_symbol_table;
|
||||
glbl_const_symbtab.add_constants(); // pi, epsilon and inf
|
||||
glbl_const_symbtab.add_constant("speed_of_light",299e6);
|
||||
glbl_const_symbtab.add_constant("avogadro_number",6e23);
|
||||
|
||||
// Setup global function symbol table
|
||||
symbol_table_t glbl_funcs_symbol_table;
|
||||
glbl_func_symbtab.add_function('distance',distance);
|
||||
glbl_func_symbtab.add_function('calc_spherevol',calc_sphrvol);
|
||||
|
||||
......
|
||||
|
||||
// Setup global variable symbol table
|
||||
symbol_table_t glbl_variable_symbol_table;
|
||||
glbl_variable_symbtab.add_variable('temp_outside',thermo.outside);
|
||||
glbl_variable_symbtab.add_variable('temp_inside' ,thermo.inside );
|
||||
glbl_variable_symbtab.add_variable('num_cstmrs',store.num_cstmrs);
|
||||
|
||||
......
|
||||
|
||||
double x,y,z;
|
||||
|
||||
// Setup expression specific symbol table
|
||||
symbol_table_t symbol_table;
|
||||
symbol_table.add_variable('x',x);
|
||||
symbol_table.add_variable('y',y);
|
||||
symbol_table.add_variable('z',z);
|
||||
|
||||
expression_t expression;
|
||||
|
||||
// Register the various symbol tables
|
||||
expression
|
||||
.register_symbol_table(symbol_table);
|
||||
|
||||
expression
|
||||
.register_symbol_table(glbl_funcs_symbol_table);
|
||||
|
||||
expression
|
||||
.register_symbol_table(glbl_const_symbol_table);
|
||||
|
||||
expression
|
||||
.register_symbol_table(glbl_variable_symbol_table);
|
||||
|
||||
std::string expression_str =
|
||||
"abs(temp_inside - temp_outside) + 2 * speed_of_light / x";
|
||||
|
||||
parser_t parser;
|
||||
parser.compile(expression_str,expression);
|
||||
|
||||
......
|
||||
|
||||
while (keep_evaluating)
|
||||
{
|
||||
....
|
||||
|
||||
T result = expression.value();
|
||||
|
||||
....
|
||||
}
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
[18 - UNKNOWN UNKNOWNS]
|
||||
In this section we will discuss the process of handling expressions
|
||||
with a mix of known and unknown variables. Initially a discussion into
|
||||
the types of expressions that exist will be provided, then a series of
|
||||
possible solutions will be presented for each scenario.
|
||||
|
||||
When parsing an expression, there may be situations where one is not
|
||||
fully aware of what if any variables will be used prior to the
|
||||
expression being compiled.
|
||||
|
||||
This can become problematic, as in the default scenario it is assumed
|
||||
the symbol_table that is registered with the expression instance will
|
||||
already posses the externally available variables, functions and
|
||||
constants needed during the compilation of the expression.
|
||||
|
||||
In the event there are symbols in the expression that can't be mapped
|
||||
to either a reserved word, or located in the associated
|
||||
symbol_table(s), an "Undefined symbol" error will be raised and the
|
||||
compilation process will fail.
|
||||
|
||||
The numerous scenarios that can occur when compiling an expression
|
||||
with ExprTk generally fall into one of the following three categories:
|
||||
|
||||
(a) No external variables
|
||||
(b) Predetermined set of external variables
|
||||
(c) Unknown set of variables
|
||||
|
||||
|
||||
(a) No external variables
|
||||
These are expressions that contain no external variables but may
|
||||
contain local variables. As local variables cannot be accessed
|
||||
externally from the expression, it is assumed that such expressions
|
||||
will not have a need for a symbol_table and furthermore expressions
|
||||
which don't make use of functions that have side-effects will be
|
||||
evaluated completely at compile time resulting in a constant return
|
||||
value. The following are examples of such expressions:
|
||||
|
||||
(1) 1 + 2
|
||||
(2) var x := 3; 2 * x - 3
|
||||
(3) var x := 3; var y := abs(x - 8); x - y / 7
|
||||
|
||||
|
||||
(b) Predetermined set of external variables
|
||||
These are expressions that are comprised of externally available
|
||||
variables and functions and will only compile successfully if the
|
||||
symbols that correspond to the variables and functions are already
|
||||
defined in their associated symbol_table(s). This is by far the most
|
||||
common scenario when using ExprTk.
|
||||
|
||||
As an example, one may have three external variables: x, y and z which
|
||||
have been registered with the associated symbol_table, and will then
|
||||
need to compile and evaluate expressions comprised of any subset of
|
||||
these three variables. The following are a few examples of such
|
||||
expressions:
|
||||
|
||||
(1) 1 + x
|
||||
(2) x / y
|
||||
(3) 2 * x * y / z
|
||||
|
||||
|
||||
In this scenario one can use the 'dependent_entity_collector'
|
||||
component as described in [Section 16] to further determine which of
|
||||
the registered variables were actually used in the given expression.
|
||||
As an example once the set of utilized variables are known, any
|
||||
further 'attention' can be restricted to only those variables when
|
||||
evaluating the expression. This can be quite useful when dealing with
|
||||
expressions that can draw from a set of hundreds or even thousands of
|
||||
variables.
|
||||
|
||||
|
||||
(c) Unknown set of variables
|
||||
These are expressions that are comprised of symbols other than the
|
||||
standard ExprTk reserved words or what has been registered with their
|
||||
associated symbol_table, and will normally fail compilation due to the
|
||||
associated symbol_table not having a reference to them. As such this
|
||||
scenario can be seen as a combination of scenario B, where one may
|
||||
have a symbol_table with registered variables, but would also like to
|
||||
handle the situation of variables that aren't present in said
|
||||
symbol_table.
|
||||
|
||||
When dealing with expressions of category (c), one must perform all of
|
||||
the following:
|
||||
|
||||
(1) Determine the variables used in the expression
|
||||
(2) Populate a symbol_table(s) with the entities from (1)
|
||||
(3) Compile the expression
|
||||
(4) Provide a means by which the entities from (1) can be modified
|
||||
|
||||
|
||||
Depending on the nature of processing, steps (1) and (2) can be done
|
||||
either independently of each other or combined into one. The following
|
||||
example will initially look at solving the problem of unknown
|
||||
variables with the latter method using the 'unknown_symbol_resolver'
|
||||
component.
|
||||
|
||||
typedef exprtk::symbol_table<T> symbol_table_t;
|
||||
typedef exprtk::expression<T> expression_t;
|
||||
typedef exprtk::parser<T> parser_t;
|
||||
|
||||
symbol_table_t unknown_var_symbol_table;
|
||||
|
||||
symbol_table_t symbol_table;
|
||||
symbol_table.add_variable("x",x);
|
||||
symbol_table.add_variable("y",y);
|
||||
|
||||
expression_t expression;
|
||||
expression.register_symbol_table(unknown_var_symbol_table);
|
||||
expression.register_symbol_table(symbol_table);
|
||||
|
||||
parser_t parser;
|
||||
parser.enable_unknown_symbol_resolver();
|
||||
|
||||
std::string expression_str = "x + abs(y / 3k) * z + 2";
|
||||
|
||||
parser.compile(expression_str,expression);
|
||||
|
||||
|
||||
In the example above, the symbols 'k' and 'z' will be treated as
|
||||
unknown symbols. The parser in the example is set to handle unknown
|
||||
symbols using the built-in default unknown_symbol_resolver (USR). The
|
||||
default USR will automatically resolve any unknown symbols as a
|
||||
variable (scalar type). The new variables will be added to the primary
|
||||
symbol_table, which in this case is the 'unknown_var_symbol_table'
|
||||
instance. Once the compilation has completed successfully, the
|
||||
variables that were resolved during compilation can be accessed from
|
||||
the primary symbol_table using the 'get_variable_list' and
|
||||
'variable_ref' methods and then if needed can be modified accordingly
|
||||
after which the expression itself can be evaluated.
|
||||
|
||||
std::vector<std::string> variable_list;
|
||||
|
||||
unknown_var_symbol_table.get_variable_list(variable_list);
|
||||
|
||||
for (auto& var_name : variable_list)
|
||||
{
|
||||
T& v = symbol_table.variable_ref(var_name);
|
||||
|
||||
v = ...;
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
expression.value();
|
||||
|
||||
|
||||
Note: As previously mentioned the default USR will automatically
|
||||
assume any unknown symbol to be a valid scalar variable, and will then
|
||||
proceed to add said symbol as a variable to the primary symbol_table
|
||||
of the associated expression during the compilation process. However a
|
||||
problem that may arise, is that expressions that are parsed with the
|
||||
USR enabled, but contain 'typos' or otherwise syntactic errors may
|
||||
inadvertently compile successfully due to the simplistic nature of the
|
||||
default USR. The following are some example expressions:
|
||||
|
||||
(1) 1 + abz(x + 1)
|
||||
(2) sine(y / 2) - coz(3x)
|
||||
|
||||
|
||||
The two expression above contain misspelt symbols (abz, sine, coz)
|
||||
which if implied multiplications and default USR are enabled during
|
||||
compilation will result in them being assumed to be valid 'variables',
|
||||
which obviously is not the intended outcome by the user. A possible
|
||||
solution to this problem is for one to implement their own specific
|
||||
USR that will perform a user defined business logic in determining if
|
||||
an encountered unknown symbol should be treated as a variable or if it
|
||||
should raise a compilation error. The following example demonstrated a
|
||||
simple user defined USR:
|
||||
|
||||
typedef exprtk::symbol_table<T> symbol_table_t;
|
||||
typedef exprtk::expression<T> expression_t;
|
||||
typedef exprtk::parser<T> parser_t;
|
||||
|
||||
template <typename T>
|
||||
struct my_usr : public parser_t::unknown_symbol_resolver
|
||||
{
|
||||
typedef typename parser_t::unknown_symbol_resolver usr_t;
|
||||
|
||||
bool process(const std::string& unknown_symbol,
|
||||
typename usr_t::usr_symbol_type& st,
|
||||
T& default_value,
|
||||
std::string& error_message)
|
||||
{
|
||||
if (0 != unknown_symbol.find('var_'))
|
||||
{
|
||||
error_message = "Invalid symbol: " + unknown_symbol;
|
||||
return false;
|
||||
}
|
||||
|
||||
st = usr_t::e_usr_variable_type;
|
||||
default_value = T(123.123);
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
...
|
||||
|
||||
symbol_table_t unknown_var_symbol_table;
|
||||
|
||||
symbol_table_t symbol_table;
|
||||
symbol_table.add_variable("x",x);
|
||||
symbol_table.add_variable("y",y);
|
||||
|
||||
expression_t expression;
|
||||
expression.register_symbol_table(unknown_var_symbol_table);
|
||||
expression.register_symbol_table(symbol_table);
|
||||
|
||||
my_usr<T> musr;
|
||||
|
||||
parser_t parser;
|
||||
parser.enable_unknown_symbol_resolver(&musr);
|
||||
|
||||
std::string expression_str = "var_x + abs(var_y - 3) * var_z";
|
||||
|
||||
parser.compile(expression_str,expression);
|
||||
|
||||
|
||||
In the example above, a user specified USR is defined, and is
|
||||
registered with the parser enabling the USR functionality. The when an
|
||||
unknown symbol is encountered during the compilation process, the
|
||||
USR's process method will be invoked. The USR in the example will only
|
||||
'accept' unknown symbols that have a prefix of 'var_' as being valid
|
||||
variables, all other unknown symbols will result in a compilation
|
||||
error being raised.
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
[19 - ENABLING & DISABLING FEATURES]
|
||||
The parser can be configured via its settings instance to either allow
|
||||
or disallow certain features that are available within the ExprTk
|
||||
grammar. The features fall into one of the following six categories:
|
||||
|
@ -2438,9 +2874,7 @@ redefined as a function taking degree input.
|
|||
}
|
||||
};
|
||||
|
||||
.
|
||||
.
|
||||
.
|
||||
...
|
||||
|
||||
typedef exprtk::symbol_table<T> symbol_table_t;
|
||||
typedef exprtk::expression<T> expression_t;
|
||||
|
@ -2473,7 +2907,7 @@ ExprTk reserved words, the add_function call will fail.
|
|||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
[18 - EXPRESSION RETURN VALUES]
|
||||
[20 - EXPRESSION RETURN VALUES]
|
||||
ExprTk expressions can return immediately from any point by utilizing
|
||||
the return call. Furthermore the return call can be used to transfer
|
||||
out multiple return values from within the expression.
|
||||
|
@ -2550,7 +2984,7 @@ generic function call parameters.
|
|||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
[19 - COMPILATION ERRORS]
|
||||
[21 - COMPILATION ERRORS]
|
||||
When attempting to compile a malformed or otherwise erroneous ExprTk
|
||||
expression, the compilation process will result in an error, as is
|
||||
indicated by the 'compile' method returning a false value. A
|
||||
|
@ -2670,7 +3104,7 @@ via the 'unknown symbol resolver' mechanism.
|
|||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
[20 - RUNTIME LIBRARY PACKAGES]
|
||||
[22 - RUNTIME LIBRARY PACKAGES]
|
||||
ExprTk contains a set of simple extensions, that provide
|
||||
functionalities beyond basic numerical calculations. Currently the
|
||||
available packages are:
|
||||
|
@ -2745,7 +3179,266 @@ file I/O package is made available for the given expression:
|
|||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
[21 - EXPRTK NOTES]
|
||||
[23 - HELPERS & UTILS]
|
||||
The ExprTk library provides a series of usage simplifications via
|
||||
helper routines that combine various processes into a single 'function
|
||||
call' making certain actions easier to carry out though not
|
||||
necessarily in the most efficient way possible. A list of the routines
|
||||
are as follows:
|
||||
|
||||
(a) collect_variables
|
||||
(b) collect_functions
|
||||
(c) compute
|
||||
(d) integrate
|
||||
(e) derivative
|
||||
(f) second_derivative
|
||||
(g) third_derivative
|
||||
|
||||
|
||||
(a) collect_variables
|
||||
This function will collect all the variable symbols in a given string
|
||||
representation of an expression and return them in an STL compatible
|
||||
sequence data structure (eg: std::vector, dequeue etc) specialised
|
||||
upon a std::string type. An example use of the routine is as follows:
|
||||
|
||||
std::string expression = "x + abs(y / z)";
|
||||
|
||||
std::vector<std::string> variable_list;
|
||||
|
||||
exprtk::collect_variables(expression,variable_list);
|
||||
|
||||
for (auto var : variable_list)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
|
||||
(b) collect_functions
|
||||
This function will collect all the function symbols in a given string
|
||||
representation of an expression and return them in an STL compatible
|
||||
sequence data structure (eg: std::vector, dequeue etc) specialised
|
||||
upon a std::string type. An example use of the routine is as follows:
|
||||
|
||||
std::string expression = "x + abs(y / cos(1 + z))";
|
||||
|
||||
std::deque<std::string> variable_list;
|
||||
|
||||
exprtk::collect_functions(expression,function_list);
|
||||
|
||||
for (auto func : function_list)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
|
||||
(c) compute
|
||||
This free function will compute the value of an expression from its
|
||||
string form. If an invalid expression is passed, the result of the
|
||||
function will be false indicating an error, otherwise the return value
|
||||
will be true indicating success. The compute function has three
|
||||
overloads, the definitions of which are:
|
||||
|
||||
(1) No variables
|
||||
(2) One variable called x
|
||||
(3) Two variable called x and y
|
||||
(3) Three variable called x, y and z
|
||||
|
||||
|
||||
An example use of each of the three overloads for the compute routine
|
||||
is as follows:
|
||||
|
||||
T result = T(0);
|
||||
|
||||
// No variables overload
|
||||
std::string no_vars = "abs(1 - (3 / pi)) * 5";
|
||||
|
||||
if (!exprtk::compute(no_vars,result))
|
||||
printf("Failed to compute: %s",no_vars.c_str());
|
||||
else
|
||||
printf("Result: %15.5f\n",result);
|
||||
|
||||
// One variable 'x' overload
|
||||
T x = 123.456;
|
||||
|
||||
std::string one_var = "abs(x - (3 / pi)) * 5";
|
||||
|
||||
if (!exprtk::compute(one_var, x, result))
|
||||
printf("Failed to compute: %s",one_var.c_str());
|
||||
else
|
||||
printf("Result: %15.5f\n",result);
|
||||
|
||||
// Two variables 'x' and 'y' overload
|
||||
T y = 789.012;
|
||||
|
||||
std::string two_var = "abs(x - (y / pi)) * 5";
|
||||
|
||||
if (!exprtk::compute(two_var, x, y, result))
|
||||
printf("Failed to compute: %s",two_var.c_str());
|
||||
else
|
||||
printf("Result: %15.5f\n",result);
|
||||
|
||||
// Three variables 'x', 'y' and 'z' overload
|
||||
T z = 345.678;
|
||||
|
||||
std::string three_var = "abs(x - (y / pi)) * z";
|
||||
|
||||
if (!exprtk::compute(three_var, x, y, z, result))
|
||||
printf("Failed to compute: %s",three_var.c_str());
|
||||
else
|
||||
printf("Result: %15.5f\n",result);
|
||||
|
||||
|
||||
(d) integrate
|
||||
This free function will attempt to perform a numerical integration of
|
||||
a single variable compiled expression over a defined range and given
|
||||
step size. The numerical integration is based on the three point form
|
||||
of the Simpson's rule. The integrate function has two overloads, where
|
||||
the variable of integration can either be passed as a reference or as
|
||||
a name in string form. Example usage of the function is as follows:
|
||||
|
||||
typedef exprtk::parser<T> parser_t;
|
||||
typedef exprtk::expression<T> expression_t;
|
||||
typedef exprtk::symbol_table<T> symbol_table_t;
|
||||
|
||||
std::string expression_string = "sqrt(1 - (x^2))";
|
||||
|
||||
T x = T(0);
|
||||
|
||||
symbol_table_t symbol_table;
|
||||
symbol_table.add_variable("x",x);
|
||||
|
||||
expression_t expression;
|
||||
expression.register_symbol_table(symbol_table);
|
||||
|
||||
parser_t parser;
|
||||
parser.compile(expression_string,expression);
|
||||
|
||||
....
|
||||
|
||||
// Integrate in domain [-1,1] using a reference to x variable
|
||||
T area1 = exprtk::integrate(expression, x, T(-1), T(1));
|
||||
|
||||
// Integrate in domain [-1,1] using name of x variable
|
||||
T area2 = exprtk::integrate(expression, "x", T(-1), T(1));
|
||||
|
||||
|
||||
(e) derivative
|
||||
This free function will attempt to perform a numerical differentiation
|
||||
of a single variable compiled expression at a given point for a given
|
||||
epsilon, using a variant of Newton's difference quotient called the
|
||||
five-point stencil method. The derivative function has two overloads,
|
||||
where the variable of differentiation can either be passed as a
|
||||
reference or as a name in string form. A example usage of the function
|
||||
is as follows:
|
||||
|
||||
typedef exprtk::parser<T> parser_t;
|
||||
typedef exprtk::expression<T> expression_t;
|
||||
typedef exprtk::symbol_table<T> symbol_table_t;
|
||||
|
||||
std::string expression_string = "sqrt(1 - (x^2))";
|
||||
|
||||
T x = T(0);
|
||||
|
||||
symbol_table_t symbol_table;
|
||||
symbol_table.add_variable("x",x);
|
||||
|
||||
expression_t expression;
|
||||
expression.register_symbol_table(symbol_table);
|
||||
|
||||
parser_t parser;
|
||||
parser.compile(expression_string,expression);
|
||||
|
||||
....
|
||||
|
||||
// Differentiate expression where value of x = 12.3 using a reference
|
||||
// to x variable
|
||||
x = T(12.3);
|
||||
T derivative1 = exprtk::derivative(expression,x);
|
||||
|
||||
// Differentiate expression where value x = 45.6 using name
|
||||
// of x variable
|
||||
x = T(45.6);
|
||||
T derivative2 = exprtk::derivative(expression, "x");
|
||||
|
||||
|
||||
(f) second_derivative
|
||||
This free function will attempt to perform a numerical second
|
||||
derivative of a single variable compiled expression at a given point
|
||||
for a given epsilon, using a variant of Newton's difference quotient
|
||||
method. The second_derivative function has two overloads, where the
|
||||
variable of differentiation can either be passed as a reference or as
|
||||
a name in string form. Example usage of the function is as follows:
|
||||
|
||||
typedef exprtk::parser<T> parser_t;
|
||||
typedef exprtk::expression<T> expression_t;
|
||||
typedef exprtk::symbol_table<T> symbol_table_t;
|
||||
|
||||
std::string expression_string = "sqrt(1 - (x^2))";
|
||||
|
||||
T x = T(0);
|
||||
|
||||
symbol_table_t symbol_table;
|
||||
symbol_table.add_variable("x",x);
|
||||
|
||||
expression_t expression;
|
||||
expression.register_symbol_table(symbol_table);
|
||||
|
||||
parser_t parser;
|
||||
parser.compile(expression_string,expression);
|
||||
|
||||
....
|
||||
|
||||
// Second derivative of expression where value of x = 12.3 using a
|
||||
// reference to x variable
|
||||
x = T(12.3);
|
||||
T derivative1 = exprtk::second_derivative(expression,x);
|
||||
|
||||
// Second derivative of expression where value of x = 45.6 using
|
||||
// name of x variable
|
||||
x = T(45.6);
|
||||
T derivative2 = exprtk::second_derivative(expression, "x");
|
||||
|
||||
|
||||
(g) third_derivative
|
||||
This free function will attempt to perform a numerical third
|
||||
derivative of a single variable compiled expression at a given point
|
||||
for a given epsilon, using a variant of Newton's difference quotient
|
||||
method. The third_derivative function has two overloads, where the
|
||||
variable of differentiation can either be passed as a reference or as
|
||||
a name in string form. Example usage of the function is as follows:
|
||||
|
||||
typedef exprtk::parser<T> parser_t;
|
||||
typedef exprtk::expression<T> expression_t;
|
||||
typedef exprtk::symbol_table<T> symbol_table_t;
|
||||
|
||||
std::string expression_string = "sqrt(1 - (x^2))";
|
||||
|
||||
T x = T(0);
|
||||
|
||||
symbol_table_t symbol_table;
|
||||
symbol_table.add_variable("x",x);
|
||||
|
||||
expression_t expression;
|
||||
expression.register_symbol_table(symbol_table);
|
||||
|
||||
parser_t parser;
|
||||
parser.compile(expression_string,expression);
|
||||
|
||||
....
|
||||
|
||||
// Third derivative of expression where value of x = 12.3 using a
|
||||
// reference to x variable
|
||||
x = T(12.3);
|
||||
T derivative1 = exprtk::third_derivative(expression,x);
|
||||
|
||||
// Third derivative of expression where value of x = 45.6 using
|
||||
// name of x variable
|
||||
x = T(45.6);
|
||||
T derivative2 = exprtk::third_derivative(expression, "x");
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
[24 - EXPRTK NOTES]
|
||||
The following is a list of facts and suggestions one may want to take
|
||||
into account when using ExprTk:
|
||||
|
||||
|
@ -2946,7 +3639,7 @@ into account when using ExprTk:
|
|||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
[22 - SIMPLE EXPRTK EXAMPLE]
|
||||
[25 - SIMPLE EXPRTK EXAMPLE]
|
||||
The following is a simple yet complete example demonstrating typical
|
||||
usage of the ExprTk Library. The example instantiates a symbol table
|
||||
object, adding to it three variables named x, y and z, and a custom
|
||||
|
@ -3051,7 +3744,7 @@ int main()
|
|||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
[23 - BUILD OPTIONS]
|
||||
[26 - BUILD OPTIONS]
|
||||
When building ExprTk there are a number of defines that will enable or
|
||||
disable certain features and capabilities. The defines can either be
|
||||
part of a compiler command line switch or scoped around the include to
|
||||
|
@ -3118,7 +3811,7 @@ error.
|
|||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
[24 - FILES]
|
||||
[27 - FILES]
|
||||
The source distribution of ExprTk is comprised of the following set of
|
||||
files:
|
||||
|
||||
|
@ -3149,7 +3842,7 @@ files:
|
|||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
[25 - LANGUAGE STRUCTURE]
|
||||
[28 - LANGUAGE STRUCTURE]
|
||||
+-------------------------------------------------------------+
|
||||
|00 - If Statement |
|
||||
| |
|
||||
|
|
Loading…
Reference in New Issue