C++ Mathematical Expression Library (ExprTk) http://www.partow.net/programming/exprtk/index.html
This commit is contained in:
parent
cc4d5ca85e
commit
f0f19b9851
593
exprtk.hpp
593
exprtk.hpp
|
@ -2394,6 +2394,15 @@ namespace exprtk
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
bool remove(const std::string& target_symbol)
|
||||||
|
{
|
||||||
|
replace_map_t::iterator itr = replace_map_.find(target_symbol);
|
||||||
|
if (replace_map_.end() == itr)
|
||||||
|
return false;
|
||||||
|
replace_map_.erase(itr);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool add_replace(const std::string& target_symbol,
|
bool add_replace(const std::string& target_symbol,
|
||||||
const std::string& replace_symbol,
|
const std::string& replace_symbol,
|
||||||
const lexer::token::token_type token_type = lexer::token::e_symbol)
|
const lexer::token::token_type token_type = lexer::token::e_symbol)
|
||||||
|
@ -9337,17 +9346,17 @@ namespace exprtk
|
||||||
std::string diagnostic = "ERR03 - ";
|
std::string diagnostic = "ERR03 - ";
|
||||||
switch (lexer_[i].type)
|
switch (lexer_[i].type)
|
||||||
{
|
{
|
||||||
case lexer::token::e_error : diagnostic + "General token error";
|
case lexer::token::e_error : diagnostic += "General token error";
|
||||||
break;
|
break;
|
||||||
case lexer::token::e_err_symbol : diagnostic + "Symbol error";
|
case lexer::token::e_err_symbol : diagnostic += "Symbol error";
|
||||||
break;
|
break;
|
||||||
case lexer::token::e_err_number : diagnostic + "Invalid numeric token";
|
case lexer::token::e_err_number : diagnostic += "Invalid numeric token";
|
||||||
break;
|
break;
|
||||||
case lexer::token::e_err_string : diagnostic + "Invalid string token";
|
case lexer::token::e_err_string : diagnostic += "Invalid string token";
|
||||||
break;
|
break;
|
||||||
case lexer::token::e_err_sfunc : diagnostic + "Invalid special function token";
|
case lexer::token::e_err_sfunc : diagnostic += "Invalid special function token";
|
||||||
break;
|
break;
|
||||||
default : diagnostic + "Unknown compiler error";
|
default : diagnostic += "Unknown compiler error";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
set_error(
|
set_error(
|
||||||
|
@ -9502,14 +9511,24 @@ namespace exprtk
|
||||||
|
|
||||||
inline bool replace_symbol(const std::string& old_symbol, const std::string& new_symbol)
|
inline bool replace_symbol(const std::string& old_symbol, const std::string& new_symbol)
|
||||||
{
|
{
|
||||||
if (details::is_reserved_word(old_symbol))
|
if (!replacer_enabled())
|
||||||
return false;
|
return false;
|
||||||
else if (!replacer_enabled())
|
else if (details::is_reserved_word(old_symbol))
|
||||||
return false;
|
return false;
|
||||||
else
|
else
|
||||||
return symbol_replacer_.add_replace(old_symbol,new_symbol,lexer::token::e_symbol);
|
return symbol_replacer_.add_replace(old_symbol,new_symbol,lexer::token::e_symbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool remove_replace_symbol(const std::string& symbol)
|
||||||
|
{
|
||||||
|
if (!replacer_enabled())
|
||||||
|
return false;
|
||||||
|
else if (details::is_reserved_word(symbol))
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
return symbol_replacer_.remove(symbol);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
inline bool valid_base_operation(const std::string& symbol)
|
inline bool valid_base_operation(const std::string& symbol)
|
||||||
|
@ -15558,6 +15577,564 @@ namespace exprtk
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class function_compositor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef exprtk::expression<T> expression_t;
|
||||||
|
typedef exprtk::symbol_table<T> symbol_table_t;
|
||||||
|
typedef exprtk::parser<T> parser_t;
|
||||||
|
|
||||||
|
struct function
|
||||||
|
{
|
||||||
|
function(const std::string& n)
|
||||||
|
: name_(n)
|
||||||
|
{}
|
||||||
|
|
||||||
|
inline function& name(const std::string& n)
|
||||||
|
{
|
||||||
|
name_ = n;
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline function& expression(const std::string& e)
|
||||||
|
{
|
||||||
|
expression_ = e;
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline function& var(const std::string& v)
|
||||||
|
{
|
||||||
|
v_.push_back(v);
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string name_;
|
||||||
|
std::string expression_;
|
||||||
|
std::deque<std::string> v_;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
struct base_func : public exprtk::ifunction<T>
|
||||||
|
{
|
||||||
|
typedef const T& type;
|
||||||
|
|
||||||
|
base_func()
|
||||||
|
: exprtk::ifunction<T>(0)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
base_func(T& v0)
|
||||||
|
: exprtk::ifunction<T>(1)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
v[0] = &v0;
|
||||||
|
}
|
||||||
|
|
||||||
|
base_func(T& v0, T& v1)
|
||||||
|
: exprtk::ifunction<T>(2)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
v[0] = &v0; v[1] = &v1;
|
||||||
|
}
|
||||||
|
|
||||||
|
base_func(T& v0, T& v1, T& v2)
|
||||||
|
: exprtk::ifunction<T>(3)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
v[0] = &v0; v[1] = &v1;
|
||||||
|
v[2] = &v2;
|
||||||
|
}
|
||||||
|
|
||||||
|
base_func(T& v0, T& v1, T& v2, T& v3)
|
||||||
|
: exprtk::ifunction<T>(4)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
v[0] = &v0; v[1] = &v1;
|
||||||
|
v[2] = &v2; v[3] = &v3;
|
||||||
|
}
|
||||||
|
|
||||||
|
base_func(T& v0, T& v1, T& v2, T& v3, T& v4)
|
||||||
|
: exprtk::ifunction<T>(5)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
v[0] = &v0; v[1] = &v1;
|
||||||
|
v[2] = &v2; v[3] = &v3;
|
||||||
|
v[4] = &v4;
|
||||||
|
}
|
||||||
|
|
||||||
|
base_func(T& v0, T& v1, T& v2, T& v3, T& v4, T& v5)
|
||||||
|
: exprtk::ifunction<T>(6)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
v[0] = &v0; v[1] = &v1;
|
||||||
|
v[2] = &v2; v[3] = &v3;
|
||||||
|
v[4] = &v4; v[5] = &v5;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void update(const T& v0)
|
||||||
|
{
|
||||||
|
(*v[0]) = v0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void update(const T& v0, const T& v1)
|
||||||
|
{
|
||||||
|
(*v[0]) = v0; (*v[1]) = v1;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void update(const T& v0, const T& v1, const T& v2)
|
||||||
|
{
|
||||||
|
(*v[0]) = v0; (*v[1]) = v1;
|
||||||
|
(*v[2]) = v2;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void update(const T& v0, const T& v1, const T& v2, const T& v3)
|
||||||
|
{
|
||||||
|
(*v[0]) = v0; (*v[1]) = v1;
|
||||||
|
(*v[2]) = v2; (*v[3]) = v3;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4)
|
||||||
|
{
|
||||||
|
(*v[0]) = v0; (*v[1]) = v1;
|
||||||
|
(*v[2]) = v2; (*v[3]) = v3;
|
||||||
|
(*v[4]) = v4;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5)
|
||||||
|
{
|
||||||
|
(*v[0]) = v0; (*v[1]) = v1;
|
||||||
|
(*v[2]) = v2; (*v[3]) = v3;
|
||||||
|
(*v[4]) = v4; (*v[5]) = v5;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum { max_parameters = 6 };
|
||||||
|
|
||||||
|
inline void clear()
|
||||||
|
{
|
||||||
|
std::fill_n(v,(int)max_parameters,reinterpret_cast<T*>(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
T* v[max_parameters];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct func_0param : public base_func
|
||||||
|
{
|
||||||
|
func_0param() : base_func() {}
|
||||||
|
|
||||||
|
func_0param(expression_t& expr)
|
||||||
|
: base_func(),
|
||||||
|
expression(expr)
|
||||||
|
{}
|
||||||
|
|
||||||
|
inline T operator()()
|
||||||
|
{
|
||||||
|
return expression.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
expression_t expression;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef const T& type;
|
||||||
|
|
||||||
|
struct func_1param : public base_func
|
||||||
|
{
|
||||||
|
func_1param() : base_func() {}
|
||||||
|
|
||||||
|
func_1param(expression_t& expr, T& v0)
|
||||||
|
: base_func(v0),
|
||||||
|
expression(expr)
|
||||||
|
{}
|
||||||
|
|
||||||
|
inline T operator()(type v0)
|
||||||
|
{
|
||||||
|
base_func::update(v0);
|
||||||
|
return expression.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
expression_t expression;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct func_2param : public base_func
|
||||||
|
{
|
||||||
|
func_2param() : base_func() {}
|
||||||
|
|
||||||
|
func_2param(expression_t& expr, T& v0, T& v1)
|
||||||
|
: base_func(v0,v1),
|
||||||
|
expression(expr)
|
||||||
|
{}
|
||||||
|
|
||||||
|
inline T operator()(type v0, type v1)
|
||||||
|
{
|
||||||
|
base_func::update(v0,v1);
|
||||||
|
return expression.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
expression_t expression;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct func_3param : public base_func
|
||||||
|
{
|
||||||
|
func_3param() : base_func() {}
|
||||||
|
|
||||||
|
func_3param(expression_t& expr, T& v0, T& v1, T& v2)
|
||||||
|
: base_func(v0,v1,v2),
|
||||||
|
expression(expr)
|
||||||
|
{}
|
||||||
|
|
||||||
|
inline T operator()(type v0, type v1, type v2)
|
||||||
|
{
|
||||||
|
base_func::update(v0,v1,v2);
|
||||||
|
return expression.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
expression_t expression;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct func_4param : public base_func
|
||||||
|
{
|
||||||
|
func_4param() : base_func() {}
|
||||||
|
|
||||||
|
func_4param(expression_t& expr, T& v0, T& v1, T& v2, T& v3)
|
||||||
|
: base_func(v0,v1,v2,v3),
|
||||||
|
expression(expr)
|
||||||
|
{}
|
||||||
|
|
||||||
|
inline T operator()(type v0, type v1, type v2, type v3)
|
||||||
|
{
|
||||||
|
base_func::update(v0,v1,v2,v3);
|
||||||
|
return expression.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
expression_t expression;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct func_5param : public base_func
|
||||||
|
{
|
||||||
|
func_5param() : base_func() {}
|
||||||
|
|
||||||
|
func_5param(expression_t& expr, T& v0, T& v1, T& v2, T& v3, T& v4)
|
||||||
|
: base_func(v0,v1,v2,v3,v4),
|
||||||
|
expression(expr)
|
||||||
|
{}
|
||||||
|
|
||||||
|
inline T operator()(type v0, type v1, type v2, type v3, type v4)
|
||||||
|
{
|
||||||
|
base_func::update(v0,v1,v2,v3,v4);
|
||||||
|
return expression.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
expression_t expression;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct func_6param : public base_func
|
||||||
|
{
|
||||||
|
func_6param() : base_func() {}
|
||||||
|
|
||||||
|
func_6param(expression_t& expr, T& v0, T& v1, T& v2, T& v3, T& v4, T& v5)
|
||||||
|
: base_func(v0,v1,v2,v3,v4,v5),
|
||||||
|
expression(expr)
|
||||||
|
{}
|
||||||
|
|
||||||
|
inline T operator()(type v0, type v1, type v2, type v3, type v4, type v5)
|
||||||
|
{
|
||||||
|
base_func::update(v0,v1,v2,v3,v4,v5);
|
||||||
|
return expression.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
expression_t expression;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
function_compositor()
|
||||||
|
: suffix_index_(1),
|
||||||
|
id_(get_id())
|
||||||
|
{}
|
||||||
|
|
||||||
|
function_compositor(const symbol_table_t& st)
|
||||||
|
: symbol_table_(st),
|
||||||
|
suffix_index_(1),
|
||||||
|
id_(get_id())
|
||||||
|
{}
|
||||||
|
|
||||||
|
inline symbol_table_t& symbol_table()
|
||||||
|
{
|
||||||
|
return symbol_table_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
symbol_table_.clear();
|
||||||
|
expr_map_.clear();
|
||||||
|
f0p_map_.clear();
|
||||||
|
f1p_map_.clear();
|
||||||
|
f2p_map_.clear();
|
||||||
|
f3p_map_.clear();
|
||||||
|
f4p_map_.clear();
|
||||||
|
f5p_map_.clear();
|
||||||
|
f6p_map_.clear();
|
||||||
|
suffix_index_ = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool add(const function& f)
|
||||||
|
{
|
||||||
|
switch(f.v_.size())
|
||||||
|
{
|
||||||
|
case 0 : return add(f.name_,f.expression_);
|
||||||
|
case 1 : return add(f.name_,f.expression_,f.v_[0]);
|
||||||
|
case 2 : return add(f.name_,f.expression_,f.v_[0],f.v_[1]);
|
||||||
|
case 3 : return add(f.name_,f.expression_,f.v_[0],f.v_[1],f.v_[2]);
|
||||||
|
case 4 : return add(f.name_,f.expression_,f.v_[0],f.v_[1],f.v_[2],f.v_[3]);
|
||||||
|
case 5 : return add(f.name_,f.expression_,f.v_[0],f.v_[1],f.v_[2],f.v_[3],f.v_[4]);
|
||||||
|
case 6 : return add(f.name_,f.expression_,f.v_[0],f.v_[1],f.v_[2],f.v_[3],f.v_[4],f.v_[5]);
|
||||||
|
default : return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool add(const std::string& name,
|
||||||
|
const std::string& expression)
|
||||||
|
{
|
||||||
|
if (expr_map_.end() != expr_map_.find(name)) return false;
|
||||||
|
std::vector<std::pair<std::string,std::string> > var_transform_list;
|
||||||
|
if (!compile_expression(name,expression,var_transform_list))
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
f0p_map_[name] = func_0param(expr_map_[name]);
|
||||||
|
return symbol_table_.add_function(name,f0p_map_[name]);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool add(const std::string& name,
|
||||||
|
const std::string& expression,
|
||||||
|
const std::string& v0)
|
||||||
|
{
|
||||||
|
const std::size_t n = 1;
|
||||||
|
T* v[n] = { 0 };
|
||||||
|
std::string sv[n];
|
||||||
|
if (expr_map_.end() != expr_map_.find(name)) return false;
|
||||||
|
else if (!add_variable(v0,v[0],sv[0])) return false;
|
||||||
|
std::vector<std::pair<std::string,std::string> > var_transform_list;
|
||||||
|
var_transform_list.push_back(std::make_pair(v0,sv[0]));
|
||||||
|
if (!compile_expression(name,expression,var_transform_list))
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
f1p_map_[name] = func_1param(expr_map_[name],(*v[0]));
|
||||||
|
return symbol_table_.add_function(name,f1p_map_[name]);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool add(const std::string& name,
|
||||||
|
const std::string& expression,
|
||||||
|
const std::string& v0, const std::string& v1)
|
||||||
|
{
|
||||||
|
const std::size_t n = 2;
|
||||||
|
T* v[n] = { 0 };
|
||||||
|
std::string sv[n];
|
||||||
|
if (expr_map_.end() != expr_map_.find(name)) return false;
|
||||||
|
else if (!add_variable(v0,v[0],sv[0])) return false;
|
||||||
|
else if (!add_variable(v1,v[1],sv[1])) return false;
|
||||||
|
std::vector<std::pair<std::string,std::string> > var_transform_list;
|
||||||
|
var_transform_list.push_back(std::make_pair(v0,sv[0]));
|
||||||
|
var_transform_list.push_back(std::make_pair(v1,sv[1]));
|
||||||
|
if (!compile_expression(name,expression,var_transform_list))
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
f2p_map_[name] = func_2param(expr_map_[name],(*v[0]),(*v[1]));
|
||||||
|
return symbol_table_.add_function(name,f2p_map_[name]);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool add(const std::string& name,
|
||||||
|
const std::string& expression,
|
||||||
|
const std::string& v0, const std::string& v1, const std::string& v2)
|
||||||
|
{
|
||||||
|
const std::size_t n = 3;
|
||||||
|
T* v[n] = { 0 };
|
||||||
|
std::string sv[n];
|
||||||
|
if (expr_map_.end() != expr_map_.find(name)) return false;
|
||||||
|
else if (!add_variable(v0,v[0],sv[0])) return false;
|
||||||
|
else if (!add_variable(v1,v[1],sv[1])) return false;
|
||||||
|
else if (!add_variable(v2,v[2],sv[2])) return false;
|
||||||
|
std::vector<std::pair<std::string,std::string> > var_transform_list;
|
||||||
|
var_transform_list.push_back(std::make_pair(v0,sv[0]));
|
||||||
|
var_transform_list.push_back(std::make_pair(v1,sv[1]));
|
||||||
|
var_transform_list.push_back(std::make_pair(v2,sv[2]));
|
||||||
|
if (!compile_expression(name,expression,var_transform_list))
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
f3p_map_[name] = func_3param(expr_map_[name],(*v[0]),(*v[1]),(*v[2]));
|
||||||
|
return symbol_table_.add_function(name,f3p_map_[name]);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool add(const std::string& name,
|
||||||
|
const std::string& expression,
|
||||||
|
const std::string& v0, const std::string& v1, const std::string& v2,
|
||||||
|
const std::string& v3)
|
||||||
|
{
|
||||||
|
const std::size_t n = 4;
|
||||||
|
T* v[n] = { 0 };
|
||||||
|
std::string sv[n];
|
||||||
|
if (expr_map_.end() != expr_map_.find(name)) return false;
|
||||||
|
else if (!add_variable(v0,v[0],sv[0])) return false;
|
||||||
|
else if (!add_variable(v1,v[1],sv[1])) return false;
|
||||||
|
else if (!add_variable(v2,v[2],sv[2])) return false;
|
||||||
|
else if (!add_variable(v3,v[3],sv[3])) return false;
|
||||||
|
std::vector<std::pair<std::string,std::string> > var_transform_list;
|
||||||
|
var_transform_list.push_back(std::make_pair(v0,sv[0]));
|
||||||
|
var_transform_list.push_back(std::make_pair(v1,sv[1]));
|
||||||
|
var_transform_list.push_back(std::make_pair(v2,sv[2]));
|
||||||
|
var_transform_list.push_back(std::make_pair(v3,sv[3]));
|
||||||
|
if (!compile_expression(name,expression,var_transform_list))
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
f4p_map_[name] = func_4param(expr_map_[name],(*v[0]),(*v[1]),(*v[2]),(*v[3]));
|
||||||
|
return symbol_table_.add_function(name,f4p_map_[name]);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool add(const std::string& name,
|
||||||
|
const std::string& expression,
|
||||||
|
const std::string& v0, const std::string& v1, const std::string& v2,
|
||||||
|
const std::string& v3, const std::string& v4)
|
||||||
|
{
|
||||||
|
const std::size_t n = 5;
|
||||||
|
T* v[n] = { 0 };
|
||||||
|
std::string sv[n];
|
||||||
|
if (expr_map_.end() != expr_map_.find(name)) return false;
|
||||||
|
else if (!add_variable(v0,v[0],sv[0])) return false;
|
||||||
|
else if (!add_variable(v1,v[1],sv[1])) return false;
|
||||||
|
else if (!add_variable(v2,v[2],sv[2])) return false;
|
||||||
|
else if (!add_variable(v3,v[3],sv[3])) return false;
|
||||||
|
else if (!add_variable(v3,v[4],sv[4])) return false;
|
||||||
|
std::vector<std::pair<std::string,std::string> > var_transform_list;
|
||||||
|
var_transform_list.push_back(std::make_pair(v0,sv[0]));
|
||||||
|
var_transform_list.push_back(std::make_pair(v1,sv[1]));
|
||||||
|
var_transform_list.push_back(std::make_pair(v2,sv[2]));
|
||||||
|
var_transform_list.push_back(std::make_pair(v3,sv[3]));
|
||||||
|
var_transform_list.push_back(std::make_pair(v4,sv[4]));
|
||||||
|
if (!compile_expression(name,expression,var_transform_list))
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
f5p_map_[name] = func_5param(expr_map_[name],(*v[0]),(*v[1]),(*v[2]),(*v[3]),(*v[4]));
|
||||||
|
return symbol_table_.add_function(name,f5p_map_[name]);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool add(const std::string& name,
|
||||||
|
const std::string& expression,
|
||||||
|
const std::string& v0, const std::string& v1, const std::string& v2,
|
||||||
|
const std::string& v3, const std::string& v4, const std::string& v5)
|
||||||
|
{
|
||||||
|
const std::size_t n = 6;
|
||||||
|
T* v[n] = { 0 };
|
||||||
|
std::string sv[n];
|
||||||
|
if (expr_map_.end() != expr_map_.find(name)) return false;
|
||||||
|
else if (!add_variable(v0,v[0],sv[0])) return false;
|
||||||
|
else if (!add_variable(v1,v[1],sv[1])) return false;
|
||||||
|
else if (!add_variable(v2,v[2],sv[2])) return false;
|
||||||
|
else if (!add_variable(v3,v[3],sv[3])) return false;
|
||||||
|
else if (!add_variable(v3,v[4],sv[4])) return false;
|
||||||
|
else if (!add_variable(v3,v[5],sv[5])) return false;
|
||||||
|
std::vector<std::pair<std::string,std::string> > var_transform_list;
|
||||||
|
var_transform_list.push_back(std::make_pair(v0,sv[0]));
|
||||||
|
var_transform_list.push_back(std::make_pair(v1,sv[1]));
|
||||||
|
var_transform_list.push_back(std::make_pair(v2,sv[2]));
|
||||||
|
var_transform_list.push_back(std::make_pair(v3,sv[3]));
|
||||||
|
var_transform_list.push_back(std::make_pair(v4,sv[4]));
|
||||||
|
var_transform_list.push_back(std::make_pair(v5,sv[5]));
|
||||||
|
if (!compile_expression(name,expression,var_transform_list))
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
f6p_map_[name] = func_6param(expr_map_[name],(*v[0]),(*v[1]),(*v[2]),(*v[3]),(*v[4]),(*v[5]));
|
||||||
|
return symbol_table_.add_function(name,f6p_map_[name]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
template <typename Allocator,
|
||||||
|
template <typename,typename> class Sequence>
|
||||||
|
bool compile_expression(const std::string& name,
|
||||||
|
const std::string& expression,
|
||||||
|
const Sequence<std::pair<std::string,std::string>,Allocator>& var_transform_list)
|
||||||
|
{
|
||||||
|
expression_t compiled_expression;
|
||||||
|
compiled_expression.register_symbol_table(symbol_table_);
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < var_transform_list.size(); ++i)
|
||||||
|
{
|
||||||
|
parser_.remove_replace_symbol(var_transform_list[i].first);
|
||||||
|
if (!parser_.replace_symbol(var_transform_list[i].first,var_transform_list[i].second))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!parser_.compile(expression,compiled_expression))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < var_transform_list.size(); ++i)
|
||||||
|
{
|
||||||
|
parser_.remove_replace_symbol(var_transform_list[i].first);
|
||||||
|
}
|
||||||
|
|
||||||
|
expr_map_[name] = compiled_expression;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool add_variable(const std::string& v, T*& t, std::string& new_var)
|
||||||
|
{
|
||||||
|
static const unsigned int max_suffix_index = 1000000000;
|
||||||
|
while (suffix_index_ < max_suffix_index)
|
||||||
|
{
|
||||||
|
new_var = generate_name(v);
|
||||||
|
|
||||||
|
bool used = symbol_table_.is_variable (new_var) ||
|
||||||
|
symbol_table_.is_stringvar (new_var) ||
|
||||||
|
symbol_table_.is_function (new_var) ||
|
||||||
|
symbol_table_.is_vararg_function(new_var);
|
||||||
|
|
||||||
|
if (!used)
|
||||||
|
{
|
||||||
|
symbol_table_.create_variable(new_var,T(0));
|
||||||
|
t = 0;
|
||||||
|
t = &symbol_table_.get_variable(new_var)->ref();
|
||||||
|
return (0 != t);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
++suffix_index_;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string generate_name(const std::string v)
|
||||||
|
{
|
||||||
|
//eg: x --> function_compositor_1__x_123
|
||||||
|
return std::string("function_compositor") + exprtk::details::to_str(id_) + "__" +
|
||||||
|
v +
|
||||||
|
exprtk::details::to_str(static_cast<int>(suffix_index_));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int get_id()
|
||||||
|
{
|
||||||
|
static unsigned int base_id = 1;
|
||||||
|
return ++base_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
symbol_table_t symbol_table_;
|
||||||
|
parser_t parser_;
|
||||||
|
std::map<std::string,expression_t> expr_map_;
|
||||||
|
std::map<std::string,func_0param> f0p_map_;
|
||||||
|
std::map<std::string,func_1param> f1p_map_;
|
||||||
|
std::map<std::string,func_2param> f2p_map_;
|
||||||
|
std::map<std::string,func_3param> f3p_map_;
|
||||||
|
std::map<std::string,func_4param> f4p_map_;
|
||||||
|
std::map<std::string,func_5param> f5p_map_;
|
||||||
|
std::map<std::string,func_6param> f6p_map_;
|
||||||
|
unsigned int suffix_index_;
|
||||||
|
unsigned int id_;
|
||||||
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline bool pgo_primer()
|
inline bool pgo_primer()
|
||||||
{
|
{
|
||||||
|
|
158
exprtk_test.cpp
158
exprtk_test.cpp
|
@ -3345,6 +3345,163 @@ inline bool run_test18()
|
||||||
return !failure;
|
return !failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline bool run_test19()
|
||||||
|
{
|
||||||
|
typedef exprtk::symbol_table<T> symbol_table_t;
|
||||||
|
typedef exprtk::expression<T> expression_t;
|
||||||
|
typedef exprtk::parser<T> parser_t;
|
||||||
|
typedef exprtk::parser_error::type error_t;
|
||||||
|
typedef exprtk::function_compositor<T> compositor_t;
|
||||||
|
typedef typename compositor_t::function function_t;
|
||||||
|
|
||||||
|
{
|
||||||
|
T x = T(123.123);
|
||||||
|
|
||||||
|
compositor_t fc;
|
||||||
|
|
||||||
|
// f(x) = x + 2
|
||||||
|
fc.add("f","x + 2","x");
|
||||||
|
|
||||||
|
// g(x) = x^2-3
|
||||||
|
fc.add("g","x^2 - 3","x");
|
||||||
|
|
||||||
|
// fof(x) = f(f(x))
|
||||||
|
fc.add("fof","f(f(x))","x");
|
||||||
|
|
||||||
|
// gog(x) = g(g(x))
|
||||||
|
fc.add("gog","g(g(x))","x");
|
||||||
|
|
||||||
|
// fog(x) = f(g(x))
|
||||||
|
fc.add("fog","f(g(x))","x");
|
||||||
|
|
||||||
|
// gof(x) = g(f(x))
|
||||||
|
fc.add("gof","g(f(x))","x");
|
||||||
|
|
||||||
|
exprtk::symbol_table<T>& symbol_table = fc.symbol_table();
|
||||||
|
symbol_table.add_constants();
|
||||||
|
symbol_table.add_variable("x",x);
|
||||||
|
|
||||||
|
static const std::string expr_str_list[] =
|
||||||
|
{
|
||||||
|
"equal(f(x),(x + 2))",
|
||||||
|
"equal(g(x),(x^2 - 3))",
|
||||||
|
"equal(fof(x),(x + 4))",
|
||||||
|
"equal(gog(x),(x^4 - 6x^2 + 6))",
|
||||||
|
"equal(fog(x),(x^2 - 1))",
|
||||||
|
"equal(gof(x),(x^2 + 4x + 1))",
|
||||||
|
};
|
||||||
|
static const std::size_t expr_str_list_size = sizeof(expr_str_list) / sizeof(std::string);
|
||||||
|
|
||||||
|
std::deque<expression_t> expression_list;
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < expr_str_list_size; ++i)
|
||||||
|
{
|
||||||
|
expression_t expression;
|
||||||
|
expression.register_symbol_table(symbol_table);
|
||||||
|
|
||||||
|
exprtk::parser<T> parser;
|
||||||
|
|
||||||
|
if (!parser.compile(expr_str_list[i],expression))
|
||||||
|
{
|
||||||
|
printf("run_test19() - Error: %s Expression: %s\n",
|
||||||
|
parser.error().c_str(),
|
||||||
|
expr_str_list[i].c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
expression_list.push_back(expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool failure = false;
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < expression_list.size(); ++i)
|
||||||
|
{
|
||||||
|
if (T(1) != expression_list[i].value())
|
||||||
|
{
|
||||||
|
printf("run_test19() - Error in evaluation! (1) Expression: %s\n",
|
||||||
|
expr_str_list[i].c_str());
|
||||||
|
failure = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (failure)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::size_t rounds = 100;
|
||||||
|
for (std::size_t r = 0; r < rounds; ++r)
|
||||||
|
{
|
||||||
|
T x = T(1);
|
||||||
|
T y = T(2);
|
||||||
|
T z = T(3);
|
||||||
|
T w = T(4);
|
||||||
|
T u = T(5);
|
||||||
|
T v = T(6);
|
||||||
|
|
||||||
|
compositor_t fc;
|
||||||
|
|
||||||
|
// f0() = 6
|
||||||
|
fc.add("f0"," 3 * 2");
|
||||||
|
|
||||||
|
// f1(x) = 5 * (f0 + x)
|
||||||
|
fc.add("f1"," 5 * (f0+x)","x");
|
||||||
|
|
||||||
|
// f2(x,y) = 7 * (f1(x) + f1(y))
|
||||||
|
fc.add("f2"," 7 * (f1(x)+f1(y))","x","y");
|
||||||
|
|
||||||
|
// f3(x,y,z) = 9 * (2(x,y) + f2(y,z) + f2(x,z))
|
||||||
|
fc.add("f3"," 9 * (f2(x,y)+f2(y,z)+f2(x,z))","x","y","z");
|
||||||
|
|
||||||
|
// f4(x,y,z,w) = 11 * (f3(x,y,z) + f3(y,z,w) + f3(z,w,z))
|
||||||
|
fc.add("f4","11 * (f3(x,y,z)+f3(y,z,w)+f3(z,w,x))","x","y","z","w");
|
||||||
|
|
||||||
|
// f5(x,y,z,w,u) = 13 * (f4(x,y,z,w) + f4(y,z,w,u) + f4(z,w,u,x) + f4(w,u,x,y))
|
||||||
|
fc.add("f5","13 * (f4(x,y,z,w)+f4(y,z,w,u)+f4(z,w,u,x)+f4(w,u,x,y))","x","y","z","w","u");
|
||||||
|
|
||||||
|
// f6(x,y,z,w,u,v) = 17 * (f5(x,y,z,w,u) + f5(y,z,w,u,v) + f5(z,w,u,v,x) + f5(w,u,v,x,y))
|
||||||
|
fc.add(function_t("f6")
|
||||||
|
.expression("17 * (f5(x,y,z,w,u)+f5(y,z,w,u,v)+f5(z,w,u,v,x)+f5(w,u,v,x,y))")
|
||||||
|
.var("x").var("y").var("z")
|
||||||
|
.var("w").var("u").var("v"));
|
||||||
|
|
||||||
|
exprtk::symbol_table<T>& symbol_table = fc.symbol_table();
|
||||||
|
symbol_table.add_constants();
|
||||||
|
symbol_table.add_variable("x",x);
|
||||||
|
symbol_table.add_variable("y",y);
|
||||||
|
symbol_table.add_variable("z",z);
|
||||||
|
symbol_table.add_variable("w",w);
|
||||||
|
symbol_table.add_variable("u",u);
|
||||||
|
symbol_table.add_variable("v",v);
|
||||||
|
|
||||||
|
expression_t expression;
|
||||||
|
expression.register_symbol_table(symbol_table);
|
||||||
|
|
||||||
|
exprtk::parser<T> parser;
|
||||||
|
|
||||||
|
std::string expression_str = "f6(x,y,z,w,u,v) + 2";
|
||||||
|
|
||||||
|
if (!parser.compile(expression_str,expression))
|
||||||
|
{
|
||||||
|
printf("run_test19() - Error: %s Expression: %s\n",
|
||||||
|
parser.error().c_str(),
|
||||||
|
expression_str.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
T result = expression.value();
|
||||||
|
|
||||||
|
if (T(2122700582) != result)
|
||||||
|
{
|
||||||
|
printf("run_test19() - Error in evaluation! (2) Expression: %s\n",
|
||||||
|
expression_str.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
#define perform_test(Type,Number) \
|
#define perform_test(Type,Number) \
|
||||||
|
@ -3381,6 +3538,7 @@ int main()
|
||||||
perform_test(double,16)
|
perform_test(double,16)
|
||||||
perform_test(double,17)
|
perform_test(double,17)
|
||||||
perform_test(double,18)
|
perform_test(double,18)
|
||||||
|
perform_test(double,19)
|
||||||
|
|
||||||
#undef perform_test
|
#undef perform_test
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue