C++ Mathematical Expression Library (ExprTk) https://www.partow.net/programming/exprtk/index.html
diff --git a/Makefile b/Makefile
index e55105a..332628f 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
# **************************************************************
# * C++ Mathematical Expression Toolkit Library *
# * *
-# * Author: Arash Partow (1999-2016) *
+# * Author: Arash Partow (1999-2017) *
# * URL: http://www.partow.net/programming/exprtk/index.html *
# * *
# * Copyright notice: *
diff --git a/exprtk.hpp b/exprtk.hpp
index 29ac3a6..f4a872d 100644
--- a/exprtk.hpp
+++ b/exprtk.hpp
@@ -2,7 +2,7 @@
******************************************************************
* C++ Mathematical Expression Toolkit Library *
* *
- * Author: Arash Partow (1999-2016) *
+ * Author: Arash Partow (1999-2017) *
* URL: http://www.partow.net/programming/exprtk/index.html *
* *
* Copyright notice: *
@@ -15681,73 +15681,185 @@
{
public:
- typedef T (*ff1_functor)(T);
- typedef T (*ff2_functor)(T,T);
- typedef T (*ff3_functor)(T,T,T);
- typedef T (*ff4_functor)(T,T,T,T);
- typedef T (*ff5_functor)(T,T,T,T,T);
- typedef T (*ff6_functor)(T,T,T,T,T,T);
+ typedef T (*ff01_functor)(T);
+ typedef T (*ff02_functor)(T,T);
+ typedef T (*ff03_functor)(T,T,T);
+ typedef T (*ff04_functor)(T,T,T,T);
+ typedef T (*ff05_functor)(T,T,T,T,T);
+ typedef T (*ff06_functor)(T,T,T,T,T,T);
+ typedef T (*ff07_functor)(T,T,T,T,T,T,T);
+ typedef T (*ff08_functor)(T,T,T,T,T,T,T,T);
+ typedef T (*ff09_functor)(T,T,T,T,T,T,T,T,T);
+ typedef T (*ff10_functor)(T,T,T,T,T,T,T,T,T,T);
+ typedef T (*ff11_functor)(T,T,T,T,T,T,T,T,T,T,T);
+ typedef T (*ff12_functor)(T,T,T,T,T,T,T,T,T,T,T,T);
+ typedef T (*ff13_functor)(T,T,T,T,T,T,T,T,T,T,T,T,T);
+ typedef T (*ff14_functor)(T,T,T,T,T,T,T,T,T,T,T,T,T,T);
+ typedef T (*ff15_functor)(T,T,T,T,T,T,T,T,T,T,T,T,T,T,T);
protected:
- struct freefunc1 : public exprtk::ifunction<T>
+ struct freefunc01 : public exprtk::ifunction<T>
{
using exprtk::ifunction<T>::operator();
- freefunc1(ff1_functor ff) : exprtk::ifunction<T>(1), f(ff) {}
+ freefunc01(ff01_functor ff) : exprtk::ifunction<T>(1), f(ff) {}
inline T operator()(const T& v0)
{ return f(v0); }
- ff1_functor f;
+ ff01_functor f;
};
- struct freefunc2 : public exprtk::ifunction<T>
+ struct freefunc02 : public exprtk::ifunction<T>
{
using exprtk::ifunction<T>::operator();
- freefunc2(ff2_functor ff) : exprtk::ifunction<T>(2), f(ff) {}
+ freefunc02(ff02_functor ff) : exprtk::ifunction<T>(2), f(ff) {}
inline T operator()(const T& v0, const T& v1)
{ return f(v0,v1); }
- ff2_functor f;
+ ff02_functor f;
};
- struct freefunc3 : public exprtk::ifunction<T>
+ struct freefunc03 : public exprtk::ifunction<T>
{
using exprtk::ifunction<T>::operator();
- freefunc3(ff3_functor ff) : exprtk::ifunction<T>(3), f(ff) {}
+ freefunc03(ff03_functor ff) : exprtk::ifunction<T>(3), f(ff) {}
inline T operator()(const T& v0, const T& v1, const T& v2)
{ return f(v0,v1,v2); }
- ff3_functor f;
+ ff03_functor f;
};
- struct freefunc4 : public exprtk::ifunction<T>
+ struct freefunc04 : public exprtk::ifunction<T>
{
using exprtk::ifunction<T>::operator();
- freefunc4(ff4_functor ff) : exprtk::ifunction<T>(4), f(ff) {}
+ freefunc04(ff04_functor ff) : exprtk::ifunction<T>(4), f(ff) {}
inline T operator()(const T& v0, const T& v1, const T& v2, const T& v3)
{ return f(v0,v1,v2,v3); }
- ff4_functor f;
+ ff04_functor f;
};
- struct freefunc5 : public exprtk::ifunction<T>
+ struct freefunc05 : public exprtk::ifunction<T>
{
using exprtk::ifunction<T>::operator();
- freefunc5(ff5_functor ff) : exprtk::ifunction<T>(5), f(ff) {}
+ freefunc05(ff05_functor ff) : exprtk::ifunction<T>(5), f(ff) {}
inline T operator()(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4)
{ return f(v0,v1,v2,v3,v4); }
- ff5_functor f;
+ ff05_functor f;
};
- struct freefunc6 : public exprtk::ifunction<T>
+ struct freefunc06 : public exprtk::ifunction<T>
{
using exprtk::ifunction<T>::operator();
- freefunc6(ff6_functor ff) : exprtk::ifunction<T>(6), f(ff) {}
+ freefunc06(ff06_functor ff) : exprtk::ifunction<T>(6), f(ff) {}
inline T operator()(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5)
{ return f(v0,v1,v2,v3,v4,v5); }
- ff6_functor f;
+ ff06_functor f;
+ };
+
+ struct freefunc07 : public exprtk::ifunction<T>
+ {
+ using exprtk::ifunction<T>::operator();
+
+ freefunc07(ff07_functor ff) : exprtk::ifunction<T>(7), f(ff) {}
+ inline T operator()(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
+ const T& v5, const T& v6)
+ { return f(v0,v1,v2,v3,v4,v5,v6); }
+ ff07_functor f;
+ };
+
+ struct freefunc08 : public exprtk::ifunction<T>
+ {
+ using exprtk::ifunction<T>::operator();
+
+ freefunc08(ff08_functor ff) : exprtk::ifunction<T>(8), f(ff) {}
+ inline T operator()(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
+ const T& v5, const T& v6, const T& v7)
+ { return f(v0,v1,v2,v3,v4,v5,v6,v7); }
+ ff08_functor f;
+ };
+
+ struct freefunc09 : public exprtk::ifunction<T>
+ {
+ using exprtk::ifunction<T>::operator();
+
+ freefunc09(ff09_functor ff) : exprtk::ifunction<T>(9), f(ff) {}
+ inline T operator()(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
+ const T& v5, const T& v6, const T& v7, const T& v8)
+ { return f(v0,v1,v2,v3,v4,v5,v6,v7,v8); }
+ ff09_functor f;
+ };
+
+ struct freefunc10 : public exprtk::ifunction<T>
+ {
+ using exprtk::ifunction<T>::operator();
+
+ freefunc10(ff10_functor ff) : exprtk::ifunction<T>(10), f(ff) {}
+ inline T operator()(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
+ const T& v5, const T& v6, const T& v7, const T& v8, const T& v9)
+ { return f(v0,v1,v2,v3,v4,v5,v6,v7,v8,v9); }
+ ff10_functor f;
+ };
+
+ struct freefunc11 : public exprtk::ifunction<T>
+ {
+ using exprtk::ifunction<T>::operator();
+
+ freefunc11(ff11_functor ff) : exprtk::ifunction<T>(11), f(ff) {}
+ inline T operator()(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
+ const T& v5, const T& v6, const T& v7, const T& v8, const T& v9, const T& v10)
+ { return f(v0,v1,v2,v3,v4,v5,v6,v7,v8,v9,v10); }
+ ff11_functor f;
+ };
+
+ struct freefunc12 : public exprtk::ifunction<T>
+ {
+ using exprtk::ifunction<T>::operator();
+
+ freefunc12(ff12_functor ff) : exprtk::ifunction<T>(12), f(ff) {}
+ inline T operator()(const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
+ const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
+ const T& v10, const T& v11)
+ { return f(v00,v01,v02,v03,v04,v05,v06,v07,v08,v09,v10,v11); }
+ ff12_functor f;
+ };
+
+ struct freefunc13 : public exprtk::ifunction<T>
+ {
+ using exprtk::ifunction<T>::operator();
+
+ freefunc13(ff13_functor ff) : exprtk::ifunction<T>(13), f(ff) {}
+ inline T operator()(const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
+ const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
+ const T& v10, const T& v11, const T& v12)
+ { return f(v00,v01,v02,v03,v04,v05,v06,v07,v08,v09,v10,v11,v12); }
+ ff13_functor f;
+ };
+
+ struct freefunc14 : public exprtk::ifunction<T>
+ {
+ using exprtk::ifunction<T>::operator();
+
+ freefunc14(ff14_functor ff) : exprtk::ifunction<T>(14), f(ff) {}
+ inline T operator()(const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
+ const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
+ const T& v10, const T& v11, const T& v12, const T& v13)
+ { return f(v00,v01,v02,v03,v04,v05,v06,v07,v08,v09,v10,v11,v12,v13); }
+ ff14_functor f;
+ };
+
+ struct freefunc15 : public exprtk::ifunction<T>
+ {
+ using exprtk::ifunction<T>::operator();
+
+ freefunc15(ff15_functor ff) : exprtk::ifunction<T>(15), f(ff) {}
+ inline T operator()(const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
+ const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
+ const T& v10, const T& v11, const T& v12, const T& v13, const T& v14)
+ { return f(v00,v01,v02,v03,v04,v05,v06,v07,v08,v09,v10,v11,v12,v13,v14); }
+ ff15_functor f;
};
template <typename Type, typename RawType>
@@ -16596,101 +16708,33 @@
return false;
}
- inline bool add_function(const std::string& function_name, ff1_functor function)
- {
- if (!valid())
- return false;
- else if (!valid_symbol(function_name))
- return false;
- else if (symbol_exists(function_name))
- return false;
+ #define exprtk_define_freefunction(NN) \
+ inline bool add_function(const std::string& function_name, ff##NN##_functor function) \
+ { \
+ if (!valid()) \
+ return false; \
+ else if (!valid_symbol(function_name)) \
+ return false; \
+ else if (symbol_exists(function_name)) \
+ return false; \
+ \
+ exprtk::ifunction<T>* ifunc = new freefunc##NN(function); \
+ \
+ local_data().free_function_list_.push_back(ifunc); \
+ \
+ return add_function(function_name,(*local_data().free_function_list_.back())); \
+ } \
- exprtk::ifunction<T>* ifunc = new freefunc1(function);
+ exprtk_define_freefunction(01) exprtk_define_freefunction(02)
+ exprtk_define_freefunction(03) exprtk_define_freefunction(04)
+ exprtk_define_freefunction(05) exprtk_define_freefunction(06)
+ exprtk_define_freefunction(07) exprtk_define_freefunction(08)
+ exprtk_define_freefunction(09) exprtk_define_freefunction(10)
+ exprtk_define_freefunction(11) exprtk_define_freefunction(12)
+ exprtk_define_freefunction(13) exprtk_define_freefunction(14)
+ exprtk_define_freefunction(15)
- local_data().free_function_list_.push_back(ifunc);
-
- return add_function(function_name,(*local_data().free_function_list_.back()));
- }
-
- inline bool add_function(const std::string& function_name, ff2_functor function)
- {
- if (!valid())
- return false;
- else if (!valid_symbol(function_name))
- return false;
- else if (symbol_exists(function_name))
- return false;
-
- exprtk::ifunction<T>* ifunc = new freefunc2(function);
-
- local_data().free_function_list_.push_back(ifunc);
-
- return add_function(function_name,(*local_data().free_function_list_.back()));
- }
-
- inline bool add_function(const std::string& function_name, ff3_functor function)
- {
- if (!valid())
- return false;
- else if (!valid_symbol(function_name))
- return false;
- else if (symbol_exists(function_name))
- return false;
-
- exprtk::ifunction<T>* ifunc = new freefunc3(function);
-
- local_data().free_function_list_.push_back(ifunc);
-
- return add_function(function_name,(*local_data().free_function_list_.back()));
- }
-
- inline bool add_function(const std::string& function_name, ff4_functor function)
- {
- if (!valid())
- return false;
- else if (!valid_symbol(function_name))
- return false;
- else if (symbol_exists(function_name))
- return false;
-
- exprtk::ifunction<T>* ifunc = new freefunc4(function);
-
- local_data().free_function_list_.push_back(ifunc);
-
- return add_function(function_name,(*local_data().free_function_list_.back()));
- }
-
- inline bool add_function(const std::string& function_name, ff5_functor function)
- {
- if (!valid())
- return false;
- else if (!valid_symbol(function_name))
- return false;
- else if (symbol_exists(function_name))
- return false;
-
- exprtk::ifunction<T>* ifunc = new freefunc5(function);
-
- local_data().free_function_list_.push_back(ifunc);
-
- return add_function(function_name,(*local_data().free_function_list_.back()));
- }
-
- inline bool add_function(const std::string& function_name, ff6_functor function)
- {
- if (!valid())
- return false;
- else if (!valid_symbol(function_name))
- return false;
- else if (symbol_exists(function_name))
- return false;
-
- exprtk::ifunction<T>* ifunc = new freefunc6(function);
-
- local_data().free_function_list_.push_back(ifunc);
-
- return add_function(function_name,(*local_data().free_function_list_.back()));
- }
+ #undef exprtk_define_freefunction
inline bool add_reserved_function(const std::string& function_name, function_t& function)
{
@@ -17672,6 +17716,15 @@
}
}
+ namespace details
+ {
+ template <typename Parser>
+ inline void disable_type_checking(Parser& p)
+ {
+ p.state_.type_check_enabled = false;
+ }
+ }
+
template <typename T>
class parser : public lexer::parser_helper
{
@@ -18534,6 +18587,7 @@
struct parser_state
{
parser_state()
+ : type_check_enabled(true)
{
reset();
}
@@ -18565,6 +18619,7 @@
bool parsing_break_stmt;
bool return_stmt_present;
bool side_effect_present;
+ bool type_check_enabled;
std::size_t scope_depth;
};
@@ -22775,7 +22830,10 @@
std::size_t param_seq_index = 0;
- if (!tc.verify(param_type_list, param_seq_index))
+ if (
+ state_.type_check_enabled &&
+ !tc.verify(param_type_list, param_seq_index)
+ )
{
set_error(
make_error(parser_error::e_syntax,
@@ -24845,7 +24903,7 @@
(details::e_g2d == operation) || (details::e_notl == operation) ||
(details::e_sgn == operation) || (details::e_erf == operation) ||
(details::e_erfc == operation) || (details::e_ncdf == operation) ||
- (details::e_frac == operation) || (details::e_trunc == operation);
+ (details::e_frac == operation) || (details::e_trunc == operation) ;
}
inline bool sf3_optimisable(const std::string& sf3id, trinary_functor_t& tfunc)
@@ -26377,8 +26435,9 @@
alloc_type1* genfunc_node_ptr = static_cast<alloc_type1*>(result);
if (
- !arg_list.empty() &&
- !gf->has_side_effects() &&
+ !arg_list.empty() &&
+ !gf->has_side_effects() &&
+ parser_->state_.type_check_enabled &&
is_constant_foldable(arg_list)
)
{
@@ -33495,6 +33554,9 @@
lexer::helper::bracket_checker bracket_checker_;
lexer::helper::numeric_checker numeric_checker_;
lexer::helper::sequence_validator sequence_validator_;
+
+ template <typename ParserType>
+ friend void details::disable_type_checking(ParserType& p);
};
template <typename Allocator,
@@ -33532,6 +33594,45 @@
return true;
}
+ template <typename T,
+ typename Allocator,
+ template <typename, typename> class Sequence>
+ inline bool collect_variables(const std::string& expr_str,
+ exprtk::symbol_table<T>& extrnl_symbol_table,
+ Sequence<std::string, Allocator>& symbol_list)
+ {
+ typedef exprtk::symbol_table<T> symbol_table_t;
+ typedef exprtk::expression<T> expression_t;
+ typedef exprtk::parser<T> parser_t;
+ typedef typename 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);
+ expression.register_symbol_table(extrnl_symbol_table);
+
+ parser.enable_unknown_symbol_resolver();
+ parser.dec().collect_variables() = true;
+
+ details::disable_type_checking(parser);
+
+ 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,
@@ -33567,6 +33668,45 @@
return true;
}
+ template <typename T,
+ typename Allocator,
+ template <typename, typename> class Sequence>
+ inline bool collect_functions(const std::string& expr_str,
+ exprtk::symbol_table<T>& extrnl_symbol_table,
+ Sequence<std::string, Allocator>& symbol_list)
+ {
+ typedef exprtk::symbol_table<T> symbol_table_t;
+ typedef exprtk::expression<T> expression_t;
+ typedef exprtk::parser<T> parser_t;
+ typedef typename 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);
+ expression.register_symbol_table(extrnl_symbol_table);
+
+ parser.enable_unknown_symbol_resolver();
+ parser.dec().collect_functions() = true;
+
+ details::disable_type_checking(parser);
+
+ 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,
@@ -33622,14 +33762,16 @@
T& x,
const T& h = T(0.00000001))
{
- T x_init = x;
- x = x_init + T(2) * h;
+ const T x_init = x;
+ const T _2h = T(2) * h;
+
+ x = x_init + _2h;
T y0 = e.value();
- x = x_init + h;
+ x = x_init + h;
T y1 = e.value();
- x = x_init - h;
+ x = x_init - h;
T y2 = e.value();
- x = x_init - T(2) * h;
+ x = x_init - _2h;
T y3 = e.value();
x = x_init;
@@ -33641,15 +33783,17 @@
T& x,
const T& h = T(0.00001))
{
+ const T x_init = x;
+ const T _2h = T(2) * h;
+
T y = e.value();
- T x_init = x;
- x = x_init + T(2) * h;
+ x = x_init + _2h;
T y0 = e.value();
- x = x_init + h;
+ x = x_init + h;
T y1 = e.value();
- x = x_init - h;
+ x = x_init - h;
T y2 = e.value();
- x = x_init - T(2) * h;
+ x = x_init - _2h;
T y3 = e.value();
x = x_init;
@@ -33661,14 +33805,16 @@
T& x,
const T& h = T(0.0001))
{
- T x_init = x;
- x = x_init + T(2) * h;
+ const T x_init = x;
+ const T _2h = T(2) * h;
+
+ x = x_init + _2h;
T y0 = e.value();
- x = x_init + h;
+ x = x_init + h;
T y1 = e.value();
- x = x_init - h;
+ x = x_init - h;
T y2 = e.value();
- x = x_init - T(2) * h;
+ x = x_init - _2h;
T y3 = e.value();
x = x_init;
@@ -33763,8 +33909,8 @@
there will be an overhead with regards to their setup and
teardown and hence should not be used in time critical
sections of code.
- Furthermore they only assume a small sub set of variables - no
- string variables or user defined functions.
+ Furthermore they only assume a small sub set of variables,
+ no string variables or user defined functions.
*/
template <typename T>
inline bool compute(const std::string& expression_string, T& result)
@@ -35482,6 +35628,9 @@
file_mode get_file_mode(const std::string& access)
{
+ if (access.empty() || access.size() > 2)
+ return e_error;
+
std::size_t w_cnt = 0;
std::size_t r_cnt = 0;
@@ -35491,6 +35640,7 @@
{
case 'r' : r_cnt++; break;
case 'w' : w_cnt++; break;
+ default : return e_error;
}
}
@@ -36940,9 +37090,9 @@
namespace information
{
static const char* library = "Mathematical Expression Toolkit";
- static const char* version = "2.7182818284590452353602874713526624977572"
- "470936999595749669676277240766303535475945";
- static const char* date = "20161212";
+ static const char* version = "2.718281828459045235360287471352662497757247"
+ "09369995957496696762772407663035354759457138";
+ static const char* date = "20170107";
static inline std::string data()
{
diff --git a/exprtk_benchmark.cpp b/exprtk_benchmark.cpp
index e64c395..4992967 100644
--- a/exprtk_benchmark.cpp
+++ b/exprtk_benchmark.cpp
@@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library *
* *
* ExprTk vs Native Benchmarks *
- * Author: Arash Partow (1999-2016) *
+ * Author: Arash Partow (1999-2017) *
* URL: http://www.partow.net/programming/exprtk/index.html *
* *
* Copyright notice: *
diff --git a/exprtk_simple_example_01.cpp b/exprtk_simple_example_01.cpp
index 165c711..04dcaf4 100644
--- a/exprtk_simple_example_01.cpp
+++ b/exprtk_simple_example_01.cpp
@@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library *
* *
* Simple Example 1 *
- * Author: Arash Partow (1999-2016) *
+ * Author: Arash Partow (1999-2017) *
* URL: http://www.partow.net/programming/exprtk/index.html *
* *
* Copyright notice: *
diff --git a/exprtk_simple_example_02.cpp b/exprtk_simple_example_02.cpp
index d8859d9..a2a6892 100644
--- a/exprtk_simple_example_02.cpp
+++ b/exprtk_simple_example_02.cpp
@@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library *
* *
* Simple Example 2 *
- * Author: Arash Partow (1999-2016) *
+ * Author: Arash Partow (1999-2017) *
* URL: http://www.partow.net/programming/exprtk/index.html *
* *
* Copyright notice: *
diff --git a/exprtk_simple_example_03.cpp b/exprtk_simple_example_03.cpp
index 49c484a..324c6ae 100644
--- a/exprtk_simple_example_03.cpp
+++ b/exprtk_simple_example_03.cpp
@@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library *
* *
* Simple Example 3 *
- * Author: Arash Partow (1999-2016) *
+ * Author: Arash Partow (1999-2017) *
* URL: http://www.partow.net/programming/exprtk/index.html *
* *
* Copyright notice: *
diff --git a/exprtk_simple_example_04.cpp b/exprtk_simple_example_04.cpp
index 72f1ddf..75b4bb5 100644
--- a/exprtk_simple_example_04.cpp
+++ b/exprtk_simple_example_04.cpp
@@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library *
* *
* Simple Example 4 *
- * Author: Arash Partow (1999-2016) *
+ * Author: Arash Partow (1999-2017) *
* URL: http://www.partow.net/programming/exprtk/index.html *
* *
* Copyright notice: *
diff --git a/exprtk_simple_example_05.cpp b/exprtk_simple_example_05.cpp
index 723bea3..ae06204 100644
--- a/exprtk_simple_example_05.cpp
+++ b/exprtk_simple_example_05.cpp
@@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library *
* *
* Simple Example 5 *
- * Author: Arash Partow (1999-2016) *
+ * Author: Arash Partow (1999-2017) *
* URL: http://www.partow.net/programming/exprtk/index.html *
* *
* Copyright notice: *
diff --git a/exprtk_simple_example_06.cpp b/exprtk_simple_example_06.cpp
index 71f0512..a34fb7f 100644
--- a/exprtk_simple_example_06.cpp
+++ b/exprtk_simple_example_06.cpp
@@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library *
* *
* Simple Example 6 *
- * Author: Arash Partow (1999-2016) *
+ * Author: Arash Partow (1999-2017) *
* URL: http://www.partow.net/programming/exprtk/index.html *
* *
* Copyright notice: *
diff --git a/exprtk_simple_example_07.cpp b/exprtk_simple_example_07.cpp
index 07eebc9..f37783d 100644
--- a/exprtk_simple_example_07.cpp
+++ b/exprtk_simple_example_07.cpp
@@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library *
* *
* Simple Example 7 *
- * Author: Arash Partow (1999-2016) *
+ * Author: Arash Partow (1999-2017) *
* URL: http://www.partow.net/programming/exprtk/index.html *
* *
* Copyright notice: *
diff --git a/exprtk_simple_example_08.cpp b/exprtk_simple_example_08.cpp
index 5f48808..78db38e 100644
--- a/exprtk_simple_example_08.cpp
+++ b/exprtk_simple_example_08.cpp
@@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library *
* *
* Simple Example 8 *
- * Author: Arash Partow (1999-2016) *
+ * Author: Arash Partow (1999-2017) *
* URL: http://www.partow.net/programming/exprtk/index.html *
* *
* Copyright notice: *
diff --git a/exprtk_simple_example_09.cpp b/exprtk_simple_example_09.cpp
index ef59202..aeebd75 100644
--- a/exprtk_simple_example_09.cpp
+++ b/exprtk_simple_example_09.cpp
@@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library *
* *
* Simple Example 9 *
- * Author: Arash Partow (1999-2016) *
+ * Author: Arash Partow (1999-2017) *
* URL: http://www.partow.net/programming/exprtk/index.html *
* *
* Copyright notice: *
diff --git a/exprtk_simple_example_10.cpp b/exprtk_simple_example_10.cpp
index 3e1dbe8..4c6d04d 100644
--- a/exprtk_simple_example_10.cpp
+++ b/exprtk_simple_example_10.cpp
@@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library *
* *
* Simple Example 10 *
- * Author: Arash Partow (1999-2016) *
+ * Author: Arash Partow (1999-2017) *
* URL: http://www.partow.net/programming/exprtk/index.html *
* *
* Copyright notice: *
diff --git a/exprtk_simple_example_11.cpp b/exprtk_simple_example_11.cpp
index 628285e..f5b3871 100644
--- a/exprtk_simple_example_11.cpp
+++ b/exprtk_simple_example_11.cpp
@@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library *
* *
* Simple Example 11 *
- * Author: Arash Partow (1999-2016) *
+ * Author: Arash Partow (1999-2017) *
* URL: http://www.partow.net/programming/exprtk/index.html *
* *
* Copyright notice: *
diff --git a/exprtk_simple_example_12.cpp b/exprtk_simple_example_12.cpp
index 61af16b..9d5cdca 100644
--- a/exprtk_simple_example_12.cpp
+++ b/exprtk_simple_example_12.cpp
@@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library *
* *
* Simple Example 12 *
- * Author: Arash Partow (1999-2016) *
+ * Author: Arash Partow (1999-2017) *
* URL: http://www.partow.net/programming/exprtk/index.html *
* *
* Copyright notice: *
diff --git a/exprtk_simple_example_13.cpp b/exprtk_simple_example_13.cpp
index 627af65..a4d79a8 100644
--- a/exprtk_simple_example_13.cpp
+++ b/exprtk_simple_example_13.cpp
@@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library *
* *
* Simple Example 13 *
- * Author: Arash Partow (1999-2016) *
+ * Author: Arash Partow (1999-2017) *
* URL: http://www.partow.net/programming/exprtk/index.html *
* *
* Copyright notice: *
diff --git a/exprtk_simple_example_14.cpp b/exprtk_simple_example_14.cpp
index b7e71f1..dc11f29 100644
--- a/exprtk_simple_example_14.cpp
+++ b/exprtk_simple_example_14.cpp
@@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library *
* *
* Simple Example 14 *
- * Author: Arash Partow (1999-2016) *
+ * Author: Arash Partow (1999-2017) *
* URL: http://www.partow.net/programming/exprtk/index.html *
* *
* Copyright notice: *
diff --git a/exprtk_simple_example_15.cpp b/exprtk_simple_example_15.cpp
index bae566b..d40a486 100644
--- a/exprtk_simple_example_15.cpp
+++ b/exprtk_simple_example_15.cpp
@@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library *
* *
* Simple Example 15 *
- * Author: Arash Partow (1999-2016) *
+ * Author: Arash Partow (1999-2017) *
* URL: http://www.partow.net/programming/exprtk/index.html *
* *
* Copyright notice: *
diff --git a/exprtk_simple_example_16.cpp b/exprtk_simple_example_16.cpp
index 1b8ba44..c23ff83 100644
--- a/exprtk_simple_example_16.cpp
+++ b/exprtk_simple_example_16.cpp
@@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library *
* *
* Simple Example 16 *
- * Author: Arash Partow (1999-2016) *
+ * Author: Arash Partow (1999-2017) *
* URL: http://www.partow.net/programming/exprtk/index.html *
* *
* Copyright notice: *
diff --git a/exprtk_simple_example_17.cpp b/exprtk_simple_example_17.cpp
index f231085..8020a1d 100644
--- a/exprtk_simple_example_17.cpp
+++ b/exprtk_simple_example_17.cpp
@@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library *
* *
* Simple Example 17 *
- * Author: Arash Partow (1999-2016) *
+ * Author: Arash Partow (1999-2017) *
* URL: http://www.partow.net/programming/exprtk/index.html *
* *
* Copyright notice: *
diff --git a/exprtk_simple_example_18.cpp b/exprtk_simple_example_18.cpp
index a6ac9e4..be56785 100644
--- a/exprtk_simple_example_18.cpp
+++ b/exprtk_simple_example_18.cpp
@@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library *
* *
* Simple Example 18 *
- * Author: Arash Partow (1999-2016) *
+ * Author: Arash Partow (1999-2017) *
* URL: http://www.partow.net/programming/exprtk/index.html *
* *
* Copyright notice: *
diff --git a/exprtk_simple_example_19.cpp b/exprtk_simple_example_19.cpp
index 186cd5a..26a2878 100644
--- a/exprtk_simple_example_19.cpp
+++ b/exprtk_simple_example_19.cpp
@@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library *
* *
* Simple Example 19 *
- * Author: Arash Partow (1999-2016) *
+ * Author: Arash Partow (1999-2017) *
* URL: http://www.partow.net/programming/exprtk/index.html *
* *
* Copyright notice: *
diff --git a/exprtk_test.cpp b/exprtk_test.cpp
index c44a7a0..d0f6ccd 100644
--- a/exprtk_test.cpp
+++ b/exprtk_test.cpp
@@ -3,7 +3,7 @@
* C++ Mathematical Expression Toolkit Library *
* *
* Examples and Unit-Tests *
- * Author: Arash Partow (1999-2016) *
+ * Author: Arash Partow (1999-2017) *
* URL: http://www.partow.net/programming/exprtk/index.html *
* *
* Copyright notice: *
diff --git a/readme.txt b/readme.txt
index 7e1ab09..0c644fc 100644
--- a/readme.txt
+++ b/readme.txt
@@ -12,7 +12,7 @@
Section 09 - Fundamental Types
Section 10 - Components
Section 11 - Compilation Options
- Section 12 - Special Functions
+ Section 12 - Expression Structures
Section 13 - Variable, Vector & String Definition
Section 14 - Vector Processing
Section 15 - User Defined Functions
@@ -32,7 +32,7 @@
Section 29 - Language Structure
-[00 - INTRODUCTION]
+[SECTION 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
@@ -41,7 +41,7 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-[01 - CAPABILITIES]
+[SECTION 01 - CAPABILITIES]
The ExprTk expression evaluator supports the following fundamental
arithmetic operations, functions and processes:
@@ -54,7 +54,7 @@
(03) Equalities &
Inequalities: =, ==, <>, !=, <, <=, >, >=
- (04) Boolean logic: and, mand, mor, nand, nor, not, or, shl, shr,
+ (04) Logic operators: and, mand, mor, nand, nor, not, or, shl, shr,
xnor, xor, true, false
(05) Functions: abs, avg, ceil, clamp, equal, erf, erfc, exp,
@@ -83,7 +83,7 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-[02 - EXAMPLE EXPRESSIONS]
+[SECTION 02 - EXAMPLE EXPRESSIONS]
The following is a short listing of the types of mathematical
expressions that can be parsed and evaluated using the ExprTk library.
@@ -110,7 +110,7 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-[03 - COPYRIGHT NOTICE]
+[SECTION 03 - COPYRIGHT NOTICE]
Free use of the C++ Mathematical Expression Toolkit Library is
permitted under the guidelines and in accordance with the most current
version of the Common Public License.
@@ -119,7 +119,7 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-[04 - DOWNLOADS & UPDATES]
+[SECTION 04 - DOWNLOADS & UPDATES]
The most recent version of the C++ Mathematical Expression Toolkit
Library including all updates and tests can be found at the following
locations:
@@ -130,13 +130,13 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-[05 - INSTALLATION]
+[SECTION 05 - INSTALLATION]
The header file exprtk.hpp should be placed in a project or system
include path (e.g: /usr/include/).
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-[06 - COMPILATION]
+[SECTION 06 - COMPILATION]
(a) For a complete build: make clean all
(b) For a PGO build: make clean pgo
(c) To strip executables: make strip_bin
@@ -144,7 +144,7 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-[07 - COMPILER COMPATIBILITY]
+[SECTION 07 - COMPILER COMPATIBILITY]
ExprTk has been built error and warning free using the following set
of C++ compilers:
@@ -158,7 +158,7 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-[08 - BUILT-IN OPERATIONS & FUNCTIONS]
+[SECTION 08 - BUILT-IN OPERATIONS & FUNCTIONS]
(0) Arithmetic & Assignment Operators
+----------+---------------------------------------------------------+
@@ -640,7 +640,7 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-[09 - FUNDAMENTAL TYPES]
+[SECTION 09 - FUNDAMENTAL TYPES]
ExprTk supports three fundamental types which can be used freely in
expressions. The types are as follows:
@@ -672,7 +672,7 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-[10 - COMPONENTS]
+[SECTION 10 - COMPONENTS]
There are three primary components, that are specialized upon a given
numeric type, which make up the core of ExprTk. The components are as
follows:
@@ -965,14 +965,14 @@
std::cout << "Error in " << expression_str[i] << "\n";
}
- for (auto e : expression_list)
+ for (auto& e : expression_list)
{
e.value();
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-[11 - COMPILATION OPTIONS]
+[SECTION 11 - COMPILATION OPTIONS]
The exprtk::parser when being instantiated takes as input a set of
options to be used during the compilation process of expressions.
An example instantiation of exprtk::parser where only the joiner,
@@ -1107,7 +1107,296 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-[12 - SPECIAL FUNCTIONS]
+[SECTION 12 - EXPRESSION STRUCTURES]
+Exprtk supports mathematical expressions in numerous forms based on a
+simple imperative programming model. This section will cover the
+following topics related to general structure and programming of
+expression using ExprTk:
+
+ (1) Multi-Statement Expressions
+ (2) Statements And Side-Effects
+ (3) Conditional Statements
+ (4) Special Functions
+
+
+(1) Multi-Statement Expressions
+Expressions in ExprTk can be comprised of one more statements, which
+may sometimes be called sub-expressions. The following are two
+examples of expressions stored in std::string variables, the first a
+single statement and the second a multi-statement expression:
+
+ std::string single_statement = " z := x + y ";
+
+ std::string multi_statement = " var temp := x; "
+ " x := y + z; "
+ " y := temp; ";
+
+
+In a multi-statement expression, the final statement will determine
+the overall result of the expression. In the following multi-statement
+expression, the result of the expression when evaluated will be '2.3',
+which will also be the value stored in the 'y' variable.
+
+ z := x + y;
+ y := 2.3;
+
+
+As demonstrated in the expression above, statements within an
+expression are separated using the semi-colon ';' operator. In the
+event two statements are not separated by a semi-colon, and the
+implied multiplication feature is active (enabled by default), the
+compiler will assume a multiplication operation between the two
+statements.
+
+In the following example we have a multi-statement expression composed
+of two variable definitions and initialisations for variables x and y
+and two seemingly separate mathematical operations.
+
+ var x:= 2;
+ var y:= 3;
+ x + 1
+ y * 2
+
+
+However the result of the expression will not be 6 as may have been
+assumed based on the calculation of 'y * 2', but rather the result
+will be 8. This is because the compiler will have conjoined the two
+mathematical statements into one via a multiplication operation. The
+expression when compiled will actually evaluate as the following:
+
+ var x:= 2;
+ var y:= 3;
+ x + 1 * y * 2; // 2 + 1 * 3 * 2 == 8
+
+
+In ExprTk any valid statement will itself return a value. This value
+can further be used in conjunction with other statements. This
+includes language structures such as if-statements, loops (for, while)
+and the switch statement. Typically the last statement executed in the
+given construct (conditional, loop etc), will be the value that is
+returned.
+
+In the following example, the return value of the expression will be
+11, which is the sum of the variable 'x' and the final value computed
+within the loop body on its last iteration:
+
+ var x := 1;
+ x + for (var i := i; i < 10; i += 1)
+ {
+ i / 2;
+ i + 1;
+ }
+
+
+(2) Statements And Side-Effects
+Statements themselves may have side effects, which in-turn effect the
+proceeding statements in multi-statement expressions.
+
+A statement is said to have a side-effect if it causes the state of
+the expression to change in some way - this includes but is not
+limited to the modification of the state of external variables used
+within the expression. Currently the following actions being present
+in a statement will cause it to have a side-effect:
+
+ (a) Assignment operation (explicit or potentially)
+ (b) Invoking a user-defined function that has side-effects
+
+The following are examples of expressions where the side-effect status
+of the statements (or sub-exressions) within the expressions have been
+noted:
+
+ +-+----------------------+------------------------------+
+ |#| Expression | Side Effect Status |
+ +-+----------------------+------------------------------+
+ |0| x + y | False |
+ +-+----------------------+------------------------------+
+ |1| z := x + y | True - Due to assignment |
+ +-+----------------------+------------------------------+
+ |2| abs(x - y) | False |
+ +-+----------------------+------------------------------+
+ |3| abs(x - y); | False |
+ | | z := (x += y); | True - Due to assignments |
+ +-+----------------------+------------------------------+
+ |4| abs(x - y); | False |
+ | | z := (x += y); | True - Due to assignments |
+ +-+----------------------+------------------------------+
+ |5| var t := abs(x - y); | True - Due to initialisation |
+ | | t + x; | False |
+ | | z := (x += y); | True - Due to assignments |
+ +-+----------------------+------------------------------+
+ |6| foo(x - y) | True - user defined function |
+ +-+----------------------+------------------------------+
+
+
+Note: In example 6 from the above set, it is assumed the user defined
+function foo has been registered as having a side_effect. By default
+all user defined functions are assumed to have side-effects, unless
+they are configured in their constructors to not have side-effects
+using the 'disable_has_side_effects' free function. For more
+information review Section 15 - User Defined Functions sub-section 7
+Function Side-Effects.
+
+At this point we can see that there will be expressions composed of
+certain kinds of statements that when executed will not effect the
+nature of the expression's result. These statements are typically
+called 'dead code'. These statements though not effecting the final
+result will still be executed and as such they will consume processing
+time that could otherwise be saved. As such ExprTk attempts to detect
+and remove such statements from expressions.
+
+The 'Dead Code Elimination' (DCE) optimisation process, which is
+enabled by default, will remove any statements that are determined to
+not have a side effect in a multi-statement expression, excluding the
+final or last statement.
+
+By default the final statement in an expression will always be present
+regardless of its side-effect status, as it is the statement whose
+value will be used as the result of the expression.
+
+In order to further explain the actions taken during the DCE process,
+lets review the following expression:
+
+ var x := 2; // Statement 1
+ var y := x + 2; // Statement 2
+ x + y // Statement 3
+ y := x + 3y; // Statement 4
+ x - y; // Statement 5
+
+
+The above expression has five statements. Three of them (1, 2 and 4)
+actively have side-effects. The first two are variable declaration and
+initialisations, where as the third is due to an assignment operation.
+There are two statements (3 and 5), that do not explicitly have
+side-effects, however the latter, statement 5, is the final statement
+in the expression and hence will be assumed to have a side-effect.
+
+During compilation when the DCE optimisation is applied to the above
+expression, statement 2 will be removed from the expression, as it has
+no bearing on the final result of expression, the rest of the
+statements will all remain. Hence optimised version of the expression
+is as follows:
+
+ var x := 2; // Statement 1
+ var y := x + 2; // Statement 2
+ y := x + 3y; // Statement 3
+ x - y; // Statement 4
+
+
+(3) Conditional Statements (If-Then-Else)
+ExprTk support two forms of conditional branching or otherwise known
+as if-statements. The first form, is a simple function based
+conditional statement, that takes exactly three input expressions:
+condition, consequent and alternative. The following is an example
+expression that utilizes the function based if-statement.
+
+ x := if (y < z, y + 1, 2* z)
+
+
+In the example above, if the condition 'y < z' is true, then the
+consequent 'y + 1' will be evaluated, it's value will be returned and
+subsequently assigned to the variable 'x'. Otherwise the alternative
+'2 * z' will be evaluated and its value will be returned. This is
+essentially the simplest form of an if-then-else statement, As simple
+variation of the expression where the value of the if-statement is
+used within another statement is as follows:
+
+ x := 3 * if (y < z, y + 1, 2* z) / 2
+
+
+The second form of if-statement resembles the standard syntax found in
+most imperative languages. There are two variations of the statement:
+
+ (a) If-Statement
+ (b) If-Then-Else Statement
+
+
+(a) If-Statement
+This version of the conditional statement returns the value of the
+consequent expression when the condition expression is true, else it
+will require a quiet NaN value as its result.
+
+ Example 1:
+ x := if (y < z) y + 3;
+
+ Example 2:
+ x := if (y < z)
+ {
+ y + 3
+ }
+
+The two example expressions above are equivalent. If the condition
+'y < z' is true, the 'x' variable will be assigned the value of the
+consequent 'y + 3', otherwise it will be assigned the value of quiet
+NaN. As previously discussed, if-statements are value returning
+constructs, and if not properly terminated using a semi-colon, will
+end-up combining with the next statement via a multiplication
+operation. The following example will NOT result in the expected value
+of 'w + x' being returned:
+
+ x := if (y < z) y + 3 // missing semi-colon ';'
+ w + x
+
+
+When the above supposed multi-statement expression is compiled, the
+expression will have a multiplication inserted between the two
+'intended' statements resulting in the unanticipated expression:
+
+ x := (if (y < z) y + 3) * w + x
+
+
+The solution to the above situation is to simply terminate the
+conditional statement with a semi-colon as follows:
+
+ x := if (y < z) y + 3;
+ w + x
+
+
+(b) If-Then-Else Statement
+The second variation of the if-statement is to allow for the use of
+Else and If-Else cascading statements. Examples of such statements are
+as follows:
+
+ Example 1: Example 2:
+ if (x < y) if (x < y)
+ z := x + 3; {
+ else y := z + x;
+ y := x - z; z := x + 3;
+ }
+ else
+ y := x - z;
+
+ Example 3: Example 4:
+ if (x > y + 1) if (2 * x < max(y,3))
+ y := abs(x - z); {
+ else y := z + x;
+ { z := x + 3;
+ y := z + x; }
+ z := x + 3; else if (2y - z)
+ }; y := x - z;
+
+ Example 5: Example 6:
+ if (x < y) if (x < y or (x + z) > y)
+ z := x + 3; {
+ else if (2y != z) z := x + 3;
+ { y := x - z;
+ z := x + 3; }
+ y := x - z; else if (abs(2y - z) >= 3)
+ } y := x - z;
+ else else
+ x * x; {
+ z := abs(x * x);
+ x * y * z;
+ };
+
+
+In the case where there is no final else statement and the flow
+through the conditional arrives at this final point, the same rules
+apply to this form of if-statement as to the previous. That is a quiet
+NaN will be returned as the result of the if-statement. Furthermore
+the same requirements of terminating the statement with a semi-colon
+apply.
+
+(4) Special Functions
The purpose of special functions in ExprTk is to provide compiler
generated equivalents of common mathematical expressions which can be
invoked by using the 'special function' syntax (eg: $f12(x,y,z) or
@@ -1178,7 +1467,7 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-[13 - VARIABLE, VECTOR & STRING DEFINITION]
+[SECTION 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
@@ -1311,7 +1600,7 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-[14 - VECTOR PROCESSING]
+[SECTION 14 - VECTOR PROCESSING]
ExprTk provides support for various forms of vector oriented
arithmetic, inequalities and processing. The various supported pairs
are as follows:
@@ -1458,7 +1747,7 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-[15 - USER DEFINED FUNCTIONS]
+[SECTION 15 - USER DEFINED FUNCTIONS]
ExprTk provides a means whereby custom functions can be defined and
utilized within expressions. The concept requires the user to
provide a reference to the function coupled with an associated name
@@ -2003,7 +2292,7 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-[16 - EXPRESSION DEPENDENTS]
+[SECTION 16 - EXPRESSION DEPENDENTS]
Any expression that is not a literal (aka constant) will have
dependencies. The types of 'dependencies' an expression can have are
as follows:
@@ -2149,7 +2438,7 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-[17 - HIERARCHIES OF SYMBOL TABLES]
+[SECTION 17 - HIERARCHIES OF SYMBOL TABLES]
Most situations will only require a single symbol_table instance to be
associated with a given expression instance.
@@ -2194,7 +2483,7 @@
(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
+all associated expressions and will not be specific or 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
@@ -2211,14 +2500,14 @@
(d) Expression specific variable symbol table
-This symbol_table is the most common form, and is used to store
+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
+case those variables will be distinctly different. Which would mean if
+a particular expression were to be compiled twice, each expression
+would have its own unique symbol_table which in turn would have its
own instances of those variables. Examples of such variables could be:
(1) x or y
@@ -2325,7 +2614,7 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-[18 - UNKNOWN UNKNOWNS]
+[SECTION 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
@@ -2552,7 +2841,7 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-[19 - ENABLING & DISABLING FEATURES]
+[SECTION 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:
@@ -2699,8 +2988,9 @@
.compile("1 or not(0 and 1)",expression); // compilation success
-One can also enable or disable specific logical operators. The following
-example demonstrates the disabling of the 'and' logical operator:
+One can also enable or disable specific logical operators. The
+following example demonstrates the disabling of the 'and' logical
+operator:
parser_t parser;
expression_t expression;
@@ -2724,7 +3014,7 @@
+, -, *, /, %, ^
-The above mentioned arithmetic operators can be either enabled or
+The above mentioned arithmetic operators can be either enabled or
disabled 'all' at once, as is demonstrated below:
parser_t parser;
@@ -2741,8 +3031,9 @@
.compile("1 + 2 / 3",expression); // compilation success
-One can also enable or disable specific arithmetic operators. The following
-example demonstrates the disabling of the addition '+' arithmetic operator:
+One can also enable or disable specific arithmetic operators. The
+following example demonstrates the disabling of the addition '+'
+arithmetic operator:
parser_t parser;
expression_t expression;
@@ -2766,7 +3057,7 @@
<, <=, >, >=, ==, =, != <>
-The above mentioned inequality operators can be either enabled or
+The above mentioned inequality operators can be either enabled or
disabled 'all' at once, as is demonstrated below:
parser_t parser;
@@ -2783,8 +3074,9 @@
.compile("1 < 3",expression); // compilation success
-One can also enable or disable specific inequality operators. The following
-example demonstrates the disabling of the less-than '<' inequality operator:
+One can also enable or disable specific inequality operators. The
+following example demonstrates the disabling of the less-than '<'
+inequality operator:
parser_t parser;
expression_t expression;
@@ -2808,7 +3100,7 @@
:=, +=, -=, *=, /=, %=
-The above mentioned assignment operators can be either enabled or
+The above mentioned assignment operators can be either enabled or
disabled 'all' at once, as is demonstrated below:
parser_t parser;
@@ -2832,8 +3124,9 @@
.compile("x := 3",expression); // compilation success
-One can also enable or disable specific assignment operators. The following
-example demonstrates the disabling of the '+=' addition assignment operator:
+One can also enable or disable specific assignment operators. The
+following example demonstrates the disabling of the '+=' addition
+assignment operator:
parser_t parser;
expression_t expression;
@@ -2908,7 +3201,7 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-[20 - EXPRESSION RETURN VALUES]
+[SECTION 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.
@@ -2983,9 +3276,55 @@
Note: Processing of the return results is similar to that of the
generic function call parameters.
+It is however recommended that if there is to be only a single flow of
+execution through the expression, that the simpler approach of
+registering external variables of appropriate type be used.
+
+This method simply requires the variables that are to hold the various
+results that are to be computed within the expression to be registered
+with an associated symbol_table instance. Then within the expression
+itself to have the result variables be assigned the appropriate
+values.
+
+ typedef exprtk::symbol_table<double> symbol_table_t;
+ typedef exprtk::expression<double> expression_t;
+ typedef exprtk::parser<double> parser_t;
+
+ std::string expression_string =
+ " var x := 123.456; "
+ " var s := 'ijk'; "
+ " result0 := x + 78.90; "
+ " result1 := s + '123' ";
+
+ double result0;
+ std::string result1;
+
+ symbol_table_t symbol_table;
+ symbol_table.add_variable ("result0",result0);
+ symbol_table.add_stringvar("result1",result1);
+
+ expression_t expression;
+ expression.register_symbol_table(symbol_table);
+
+ parser_t parser;
+ parser.compile(expression_string,expression);
+
+ expression.value();
+
+ printf("Result0: %15.5f\n",result0 );
+ printf("Result1: %s\n" ,result1.c_str());
+
+
+In the example above, the expression will compute two results. As such
+two result variables are defined to hold the values named result0 and
+result1 respectively. The first is of scalar type (double), the second
+is of string type. Once the expression has been evaluated, the two
+variables will have been updated with the new result values, and can
+then be further utilized from within the calling program.
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-[21 - COMPILATION ERRORS]
+[SECTION 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
@@ -3105,7 +3444,7 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-[22 - RUNTIME LIBRARY PACKAGES]
+[SECTION 22 - RUNTIME LIBRARY PACKAGES]
ExprTk contains a set of simple extensions, that provide
functionalities beyond basic numerical calculations. Currently the
available packages are:
@@ -3180,7 +3519,7 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-[23 - HELPERS & UTILS]
+[SECTION 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
@@ -3200,36 +3539,93 @@
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:
+upon a std::string type. If an error occurs during the parsing of the
+expression then the return value of the function will be false,
+otherwise it will be true. An example use of the given 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)
+ if (exprtk::collect_variables(expression, variable_list))
{
- ...
+ for (auto var : variable_list)
+ {
+ ...
+ }
}
+ else
+ printf("An error occured.");
(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:
+upon a std::string type. If an error occurs during the parsing of the
+expression then the return value of the function will be false,
+otherwise it will be true. An example use of the given routine is as
+follows:
std::string expression = "x + abs(y / cos(1 + z))";
- std::deque<std::string> variable_list;
+ std::deque<std::string> function_list;
- exprtk::collect_functions(expression,function_list);
-
- for (auto func : function_list)
+ if (exprtk::collect_functions(expression, function_list))
{
- ...
+ for (auto func : function_list)
+ {
+ ...
+ }
}
+ else
+ printf("An error occured.");
+
+
+Note: When either the 'collect_variables' or 'collect_functions' free
+functions return true - that does not necessarily indicate the
+expression itself is valid. It is still possible that when compiled
+the expression may have certain 'type' related errors - though it is
+highly likely that no semantic errors will occur if either return
+true.
+
+Note: The default interface provided for both the collect_variables
+and collect_functions free_functions, assumes that expressions will
+only be utilising the ExprTk reserved funnctions (eg: abs, cos, min
+etc). When user defined functions are to be used in an expression, a
+symbol_table instance containing said functions can be passed to
+either routine, and will be incorparated during the compilation and
+Dependent Entity Collection processes. In the following example, a
+user defined free function named 'foo' is registered with a
+symbol_table. Finally the symbol_table instance and associated
+expression string are passed to the exprtk::collect_functions routine.
+
+ template <typename T>
+ T foo(T v)
+ {
+ return std::abs(v + T(2)) / T(3);
+ }
+
+ ......
+
+ exprtk::symbol_table<T> sym_tab;
+
+ symbol_table.add_function("foo",foo);
+
+ std::string expression = "x + foo(y / cos(1 + z))";
+
+ std::deque<std::string> function_list;
+
+ if (exprtk::collect_functions(expression, sym_tab, function_list))
+ {
+ for (auto func : function_list)
+ {
+ ...
+ }
+ }
+ else
+ printf("An error occured.");
(c) compute
@@ -3329,8 +3725,8 @@
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:
+reference or as a name in string form. Example usage of the derivative
+function is as follows:
typedef exprtk::parser<T> parser_t;
typedef exprtk::expression<T> expression_t;
@@ -3352,12 +3748,12 @@
....
// Differentiate expression where value of x = 12.3 using a reference
- // to x variable
+ // to the x variable
x = T(12.3);
T derivative1 = exprtk::derivative(expression,x);
// Differentiate expression where value x = 45.6 using name
- // of x variable
+ // of the x variable
x = T(45.6);
T derivative2 = exprtk::derivative(expression, "x");
@@ -3368,7 +3764,8 @@
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:
+a name in string form. Example usage of the second_derivative function
+is as follows:
typedef exprtk::parser<T> parser_t;
typedef exprtk::expression<T> expression_t;
@@ -3406,7 +3803,8 @@
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:
+a name in string form. Example usage of the third_derivative function
+is as follows:
typedef exprtk::parser<T> parser_t;
typedef exprtk::expression<T> expression_t;
@@ -3428,18 +3826,18 @@
....
// Third derivative of expression where value of x = 12.3 using a
- // reference to x variable
+ // reference to the 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
+ // name of the x variable
x = T(45.6);
T derivative2 = exprtk::third_derivative(expression, "x");
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-[24 - BENCHMARKING]
+[SECTION 24 - BENCHMARKING]
As part of the ExprTk package there is an expression benchmark utility
named 'exprtk_benchmark'. The utility attempts to determine expression
evaluation speed (or rate of evaluations - evals per second), by
@@ -3447,7 +3845,7 @@
variables of the expression between each evaluation. The utility
assumes any valid ExprTk expression (containing conditionals, loops
etc), however it will only make use of a predefined set of scalar
-variables, namely: a, b, c, x, y, z, w. That being said expressions
+variables, namely: a, b, c, x, y, z and w. That being said expressions
themselves can contain any number of local variables, vectors or
strings. There are two modes of operation:
@@ -3583,7 +3981,7 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-[25 - EXPRTK NOTES]
+[SECTION 25 - EXPRTK NOTES]
The following is a list of facts and suggestions one may want to take
into account when using ExprTk:
@@ -3784,7 +4182,7 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-[26 - SIMPLE EXPRTK EXAMPLE]
+[SECTION 26 - 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
@@ -3889,7 +4287,7 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-[27 - BUILD OPTIONS]
+[SECTION 27 - 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
@@ -3956,7 +4354,7 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-[28 - FILES]
+[SECTION 28 - FILES]
The source distribution of ExprTk is comprised of the following set of
files:
@@ -3987,9 +4385,28 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-[29 - LANGUAGE STRUCTURE]
+[SECTION 29 - LANGUAGE STRUCTURE]
+The following are the various language structures available within
+ExprTk and their structural representations.
+
+ (00) If Statement
+ (01) Else Statement
+ (02) Ternary Statement
+ (03) While Loop
+ (04) Repeat Until Loop
+ (05) For Loop
+ (06) Switch Statement
+ (07) Multi Subexpression Statement
+ (08) Multi Case-Consequent Statement
+ (09) Variable Definition Statement
+ (10) Vector Definition Statement
+ (11) String Definition Statement
+ (12) Range Statement
+ (13) Return Statement
+
+
+(00) - If Statement
+-------------------------------------------------------------+
-|00 - If Statement |
| |
| [if] ---> [(] ---> [condition] -+-> [,] -+ |
| | | |
@@ -4007,7 +4424,10 @@
| +--> [consequent] --> [;] -{*}-> [else-statement] |
| |
+-------------------------------------------------------------+
-|01 - Else Statement |
+
+
+(01) - Else Statement
++-------------------------------------------------------------+
| |
| [else] -+-> [alternative] ---> [;] |
| | |
@@ -4016,7 +4436,10 @@
| +--> [if-statement] |
| |
+-------------------------------------------------------------+
-|02 - Ternary Statement |
+
+
+(02) - Ternary Statement
++-------------------------------------------------------------+
| |
| [condition] ---> [?] ---> [consequent] ---> [:] --+ |
| | |
@@ -4025,7 +4448,10 @@
| +--> [alternative] --> [;] |
| |
+-------------------------------------------------------------+
-|03 - While Loop |
+
+
+(03) - While Loop
++-------------------------------------------------------------+
| |
| [while] ---> [(] ---> [condition] ---> [)] ---+ |
| | |
@@ -4034,7 +4460,10 @@
| +--> [{] ---> [expression*] ---> [}] |
| |
+-------------------------------------------------------------+
-|04 - Repeat Until Loop |
+
+
+(04) - Repeat Until Loop
++-------------------------------------------------------------+
| |
| [repeat] ---> [expression*] ---+ |
| | |
@@ -4043,7 +4472,10 @@
| +--> [until] ---> [(] ---> [condition] --->[)] |
| |
+-------------------------------------------------------------+
-|05 - For Loop |
+
+
+(05) - For Loop
++-------------------------------------------------------------+
| |
| [for] ---> [(] -+-> [initialise expression] --+--+ |
| | | | |
@@ -4064,7 +4496,10 @@
| +--> [{] ---> [expression*] ---> [}] |
| |
+-------------------------------------------------------------+
-|06 - Switch Statement |
+
+
+(06) - Switch Statement
++-------------------------------------------------------------+
| |
| [switch] ---> [{] ---+ |
| | |
@@ -4084,7 +4519,10 @@
| +--> [}] |
| |
+-------------------------------------------------------------+
-|07 - Multi Subexpression Statement |
+
+
+(07) - Multi Subexpression Statement
++-------------------------------------------------------------+
| |
| +--------------<---------------+ |
| | | |
@@ -4095,7 +4533,10 @@
| +--> [}\)] |
| |
+-------------------------------------------------------------+
-|08 - Multi Case-Consequent Statement |
+
+
+(08) - Multi Case-Consequent Statement
++-------------------------------------------------------------+
| |
| [[*]] ---> [{] ---+ |
| | |
@@ -4110,7 +4551,10 @@
| +--> [}] |
| |
+-------------------------------------------------------------+
-|09 - Variable Definition Statement |
+
+
+(09) - Variable Definition Statement
++-------------------------------------------------------------+
| |
| [var] ---> [symbol] -+-> [:=] -+-> [expression] -+-> [;] |
| | | | |
@@ -4119,7 +4563,10 @@
| +------------->-------------+ |
| |
+-------------------------------------------------------------+
-|10 - Vector Definition Statement |
+
+
+(10) - Vector Definition Statement
++-------------------------------------------------------------+
| |
| [var] ---> [symbol] ---> [[] ---> [constant] ---> []] --+ |
| | |
@@ -4132,12 +4579,18 @@
| +--<--- [,] <-----+ |
| |
+-------------------------------------------------------------+
-|11 - String Definition Statement |
+
+
+(11) - String Definition Statement
++-------------------------------------------------------------+
| |
| [var] --> [symbol] --> [:=] --> [str-expression] ---> [;] |
| |
+-------------------------------------------------------------+
-|12 - Range Statement |
+
+
+(12) - Range Statement
++-------------------------------------------------------------+
| |
| +-------->--------+ |
| | | |
@@ -4146,10 +4599,13 @@
| +-------->--------+ |
| |
+-------------------------------------------------------------+
-|13 - Return Statement |
+
+
+(13) - Return Statement
++-------------------------------------------------------------+
| |
| [return] ---> [[] -+-> [expression] -+-> []] ---> [;] |
| | | |
| +--<--- [,] <-----+ |
| |
-+-------------------------------------------------------------+
++-------------------------------------------------------------+
\ No newline at end of file