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

This commit is contained in:
Arash Partow 2016-09-06 08:27:19 +10:00
parent e0b0aa5130
commit 6c37419d62
9 changed files with 175 additions and 109 deletions

View File

@ -1,12 +0,0 @@
language: cpp
sudo: required
dist: trusty
compiler:
- gcc
script:
- make clean all
- ./exprtk_test

View File

@ -1111,13 +1111,21 @@ namespace exprtk
return T(0); return T(0);
} }
#if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER)
#define exprtk_define_erf(TT,impl) \
inline TT erf_impl(TT v) { return impl(v); } \
exprtk_define_erf( float,::erff)
exprtk_define_erf( double,::erf )
exprtk_define_erf(long double,::erfl)
#undef exprtk_define_erf
#endif
template <typename T> template <typename T>
inline T erf_impl(T v, real_type_tag) inline T erf_impl(T v, real_type_tag)
{ {
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) #if defined(_MSC_VER) && (_MSC_VER < 1900)
// Credits: Abramowitz & Stegun Equations 7.1.25-28 // Credits: Abramowitz & Stegun Equations 7.1.25-28
const T t = T(1) / (T(1) + T(0.5) * abs_impl(v,real_type_tag()));
static const T c[] = { static const T c[] = {
T( 1.26551223), T(1.00002368), T( 1.26551223), T(1.00002368),
T( 0.37409196), T(0.09678418), T( 0.37409196), T(0.09678418),
@ -1126,6 +1134,8 @@ namespace exprtk
T(-0.82215223), T(0.17087277) T(-0.82215223), T(0.17087277)
}; };
const T t = T(1) / (T(1) + T(0.5) * abs_impl(v,real_type_tag()));
T result = T(1) - t * std::exp((-v * v) - T result = T(1) - t * std::exp((-v * v) -
c[0] + t * (c[1] + t * c[0] + t * (c[1] + t *
(c[2] + t * (c[3] + t * (c[2] + t * (c[3] + t *
@ -1135,7 +1145,7 @@ namespace exprtk
return (v >= T(0)) ? result : -result; return (v >= T(0)) ? result : -result;
#else #else
return ::erf(v); return erf_impl(v);
#endif #endif
} }
@ -1145,13 +1155,23 @@ namespace exprtk
return erf_impl(static_cast<double>(v),real_type_tag()); return erf_impl(static_cast<double>(v),real_type_tag());
} }
#if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER)
#define exprtk_define_erfc(TT,impl) \
inline TT erfc_impl(TT v) { return impl(v); } \
exprtk_define_erfc( float,::erfcf)
exprtk_define_erfc( double,::erfc )
exprtk_define_erfc(long double,::erfcl)
#undef exprtk_define_erfc
#endif
template <typename T> template <typename T>
inline T erfc_impl(T v, real_type_tag) inline T erfc_impl(T v, real_type_tag)
{ {
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) #if defined(_MSC_VER) && (_MSC_VER < 1900)
return T(1) - erf_impl(v,real_type_tag()); return T(1) - erf_impl(v,real_type_tag());
#else #else
return ::erfc(v); return erfc_impl(v);
#endif #endif
} }
@ -1196,7 +1216,7 @@ namespace exprtk
template <typename T> inline T asin_impl(const T v, real_type_tag) { return std::asin (v); } template <typename T> inline T asin_impl(const T v, real_type_tag) { return std::asin (v); }
template <typename T> inline T asinh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) + T(1))); } template <typename T> inline T asinh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) + T(1))); }
template <typename T> inline T atan_impl(const T v, real_type_tag) { return std::atan (v); } template <typename T> inline T atan_impl(const T v, real_type_tag) { return std::atan (v); }
template <typename T> inline T atanh_impl(const T v, real_type_tag) { return (std::log(T(1) + v) - log(T(1) - v)) / T(2); } template <typename T> inline T atanh_impl(const T v, real_type_tag) { return (std::log(T(1) + v) - std::log(T(1) - v)) / T(2); }
template <typename T> inline T ceil_impl(const T v, real_type_tag) { return std::ceil (v); } template <typename T> inline T ceil_impl(const T v, real_type_tag) { return std::ceil (v); }
template <typename T> inline T cos_impl(const T v, real_type_tag) { return std::cos (v); } template <typename T> inline T cos_impl(const T v, real_type_tag) { return std::cos (v); }
template <typename T> inline T cosh_impl(const T v, real_type_tag) { return std::cosh (v); } template <typename T> inline T cosh_impl(const T v, real_type_tag) { return std::cosh (v); }
@ -9223,7 +9243,7 @@ namespace exprtk
}; };
template <typename T, typename Operation> template <typename T, typename Operation>
class vecarith_vecvec_node : public binary_node <T>, class vec_binop_vecvec_node : public binary_node <T>,
public vector_interface<T> public vector_interface<T>
{ {
public: public:
@ -9232,7 +9252,7 @@ namespace exprtk
typedef vector_node<T>* vector_node_ptr; typedef vector_node<T>* vector_node_ptr;
typedef vector_holder<T>* vector_holder_ptr; typedef vector_holder<T>* vector_holder_ptr;
vecarith_vecvec_node(const operator_type& opr, vec_binop_vecvec_node(const operator_type& opr,
expression_ptr branch0, expression_ptr branch0,
expression_ptr branch1) expression_ptr branch1)
: binary_node<T>(opr,branch0,branch1), : binary_node<T>(opr,branch0,branch1),
@ -9286,7 +9306,7 @@ namespace exprtk
} }
} }
~vecarith_vecvec_node() ~vec_binop_vecvec_node()
{ {
delete[] data_; delete[] data_;
delete temp_; delete temp_;
@ -9388,7 +9408,7 @@ namespace exprtk
}; };
template <typename T, typename Operation> template <typename T, typename Operation>
class vecarith_vecval_node : public binary_node <T>, class vec_binop_vecval_node : public binary_node <T>,
public vector_interface<T> public vector_interface<T>
{ {
public: public:
@ -9397,7 +9417,7 @@ namespace exprtk
typedef vector_node<T>* vector_node_ptr; typedef vector_node<T>* vector_node_ptr;
typedef vector_holder<T>* vector_holder_ptr; typedef vector_holder<T>* vector_holder_ptr;
vecarith_vecval_node(const operator_type& opr, vec_binop_vecval_node(const operator_type& opr,
expression_ptr branch0, expression_ptr branch0,
expression_ptr branch1) expression_ptr branch1)
: binary_node<T>(opr,branch0,branch1), : binary_node<T>(opr,branch0,branch1),
@ -9432,7 +9452,7 @@ namespace exprtk
} }
} }
~vecarith_vecval_node() ~vec_binop_vecval_node()
{ {
delete[] data_; delete[] data_;
delete temp_; delete temp_;
@ -9530,7 +9550,7 @@ namespace exprtk
}; };
template <typename T, typename Operation> template <typename T, typename Operation>
class vecarith_valvec_node : public binary_node <T>, class vec_binop_valvec_node : public binary_node <T>,
public vector_interface<T> public vector_interface<T>
{ {
public: public:
@ -9539,7 +9559,7 @@ namespace exprtk
typedef vector_node<T>* vector_node_ptr; typedef vector_node<T>* vector_node_ptr;
typedef vector_holder<T>* vector_holder_ptr; typedef vector_holder<T>* vector_holder_ptr;
vecarith_valvec_node(const operator_type& opr, vec_binop_valvec_node(const operator_type& opr,
expression_ptr branch0, expression_ptr branch0,
expression_ptr branch1) expression_ptr branch1)
: binary_node<T>(opr,branch0,branch1), : binary_node<T>(opr,branch0,branch1),
@ -9574,7 +9594,7 @@ namespace exprtk
} }
} }
~vecarith_valvec_node() ~vec_binop_valvec_node()
{ {
delete[] data_; delete[] data_;
delete temp_; delete temp_;
@ -24282,7 +24302,7 @@ namespace exprtk
); );
} }
inline bool is_vector_eqineq_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) inline bool is_vector_eqineq_logic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2])
{ {
if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1])) if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1]))
return false; return false;
@ -24294,7 +24314,13 @@ namespace exprtk
(details::e_gte == operation) || (details::e_gte == operation) ||
(details::e_eq == operation) || (details::e_eq == operation) ||
(details::e_ne == operation) || (details::e_ne == operation) ||
(details::e_equal == operation) (details::e_equal == operation) ||
(details::e_and == operation) ||
(details::e_nand == operation) ||
(details:: e_or == operation) ||
(details:: e_nor == operation) ||
(details:: e_xor == operation) ||
(details::e_xnor == operation)
); );
} }
@ -24328,8 +24354,8 @@ namespace exprtk
return synthesize_swap_expression(branch); return synthesize_swap_expression(branch);
else if (is_assignment_operation(operation)) else if (is_assignment_operation(operation))
return synthesize_assignment_operation_expression(operation,branch); return synthesize_assignment_operation_expression(operation,branch);
else if (is_vector_eqineq_operation(operation,branch)) else if (is_vector_eqineq_logic_operation(operation,branch))
return synthesize_veceqineq_operation_expression(operation,branch); return synthesize_veceqineqlogic_operation_expression(operation,branch);
else if (is_vector_arithmetic_operation(operation,branch)) else if (is_vector_arithmetic_operation(operation,branch))
return synthesize_vecarithmetic_operation_expression(operation,branch); return synthesize_vecarithmetic_operation_expression(operation,branch);
else if (is_shortcircuit_expression(operation)) else if (is_shortcircuit_expression(operation))
@ -25778,28 +25804,37 @@ namespace exprtk
} }
} }
inline expression_node_ptr synthesize_veceqineq_operation_expression(const details::operator_type& operation, inline expression_node_ptr synthesize_veceqineqlogic_operation_expression(const details::operator_type& operation,
expression_node_ptr (&branch)[2]) expression_node_ptr (&branch)[2])
{ {
const bool is_b0_ivec = details::is_ivector_node(branch[0]); const bool is_b0_ivec = details::is_ivector_node(branch[0]);
const bool is_b1_ivec = details::is_ivector_node(branch[1]); const bool is_b1_ivec = details::is_ivector_node(branch[1]);
#define batch_eqineq_logic_case \
case_stmt(details:: e_lt,details:: lt_op) \
case_stmt(details:: e_lte,details:: lte_op) \
case_stmt(details:: e_gt,details:: gt_op) \
case_stmt(details:: e_gte,details:: gte_op) \
case_stmt(details:: e_eq,details:: eq_op) \
case_stmt(details:: e_ne,details:: ne_op) \
case_stmt(details::e_equal,details::equal_op) \
case_stmt(details:: e_and, details::and_op) \
case_stmt(details:: e_nand, details::nand_op) \
case_stmt(details:: e_or, details:: or_op) \
case_stmt(details:: e_nor, details:: nor_op) \
case_stmt(details:: e_xor, details:: xor_op) \
case_stmt(details:: e_xnor, details::xnor_op) \
if (is_b0_ivec && is_b1_ivec) if (is_b0_ivec && is_b1_ivec)
{ {
switch (operation) switch (operation)
{ {
#define case_stmt(op0,op1) \ #define case_stmt(op0,op1) \
case op0 : return node_allocator_-> \ case op0 : return node_allocator_-> \
template allocate_rrr<typename details::vecarith_vecvec_node<Type,op1<Type> > > \ template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \
(operation,branch[0],branch[1]); \ (operation,branch[0],branch[1]); \
case_stmt(details:: e_lt,details:: lt_op) batch_eqineq_logic_case
case_stmt(details:: e_lte,details:: lte_op)
case_stmt(details:: e_gt,details:: gt_op)
case_stmt(details:: e_gte,details:: gte_op)
case_stmt(details:: e_eq,details:: eq_op)
case_stmt(details:: e_ne,details:: ne_op)
case_stmt(details::e_equal,details::equal_op)
#undef case_stmt #undef case_stmt
default : return error_node(); default : return error_node();
} }
@ -25810,16 +25845,10 @@ namespace exprtk
{ {
#define case_stmt(op0,op1) \ #define case_stmt(op0,op1) \
case op0 : return node_allocator_-> \ case op0 : return node_allocator_-> \
template allocate_rrr<typename details::vecarith_vecval_node<Type,op1<Type> > > \ template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \
(operation,branch[0],branch[1]); \ (operation,branch[0],branch[1]); \
case_stmt(details:: e_lt,details:: lt_op) batch_eqineq_logic_case
case_stmt(details:: e_lte,details:: lte_op)
case_stmt(details:: e_gt,details:: gt_op)
case_stmt(details:: e_gte,details:: gte_op)
case_stmt(details:: e_eq,details:: eq_op)
case_stmt(details:: e_ne,details:: ne_op)
case_stmt(details::e_equal,details::equal_op)
#undef case_stmt #undef case_stmt
default : return error_node(); default : return error_node();
} }
@ -25830,22 +25859,18 @@ namespace exprtk
{ {
#define case_stmt(op0,op1) \ #define case_stmt(op0,op1) \
case op0 : return node_allocator_-> \ case op0 : return node_allocator_-> \
template allocate_rrr<typename details::vecarith_valvec_node<Type,op1<Type> > > \ template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \
(operation,branch[0],branch[1]); \ (operation,branch[0],branch[1]); \
case_stmt(details:: e_lt,details:: lt_op) batch_eqineq_logic_case
case_stmt(details:: e_lte,details:: lte_op)
case_stmt(details:: e_gt,details:: gt_op)
case_stmt(details:: e_gte,details:: gte_op)
case_stmt(details:: e_eq,details:: eq_op)
case_stmt(details:: e_ne,details:: ne_op)
case_stmt(details::e_equal,details::equal_op)
#undef case_stmt #undef case_stmt
default : return error_node(); default : return error_node();
} }
} }
else else
return error_node(); return error_node();
#undef batch_eqineq_logic_case
} }
inline expression_node_ptr synthesize_vecarithmetic_operation_expression(const details::operator_type& operation, inline expression_node_ptr synthesize_vecarithmetic_operation_expression(const details::operator_type& operation,
@ -25867,7 +25892,7 @@ namespace exprtk
{ {
#define case_stmt(op0,op1) \ #define case_stmt(op0,op1) \
case op0 : return node_allocator_-> \ case op0 : return node_allocator_-> \
template allocate_rrr<typename details::vecarith_vecvec_node<Type,op1<Type> > > \ template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \
(operation,branch[0],branch[1]); \ (operation,branch[0],branch[1]); \
vector_ops vector_ops
@ -25882,7 +25907,7 @@ namespace exprtk
{ {
#define case_stmt(op0,op1) \ #define case_stmt(op0,op1) \
case op0 : return node_allocator_-> \ case op0 : return node_allocator_-> \
template allocate_rrr<typename details::vecarith_vecval_node<Type,op1<Type> > > \ template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \
(operation,branch[0],branch[1]); \ (operation,branch[0],branch[1]); \
vector_ops vector_ops
@ -25897,7 +25922,7 @@ namespace exprtk
{ {
#define case_stmt(op0,op1) \ #define case_stmt(op0,op1) \
case op0 : return node_allocator_-> \ case op0 : return node_allocator_-> \
template allocate_rrr<typename details::vecarith_valvec_node<Type,op1<Type> > > \ template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \
(operation,branch[0],branch[1]); \ (operation,branch[0],branch[1]); \
vector_ops vector_ops

View File

@ -183,7 +183,7 @@ bool run_parse_benchmark(exprtk::symbol_table<T>& symbol_table)
return true; return true;
} }
const double pi = 3.14159265358979323846; const double pi = 3.141592653589793238462643383279502;
template <typename T> template <typename T>
struct native struct native

View File

@ -37,7 +37,7 @@ void square_wave()
" (1/21)*sin(42*pi*f*t)+(1/23)*sin(46*pi*f*t)+" " (1/21)*sin(42*pi*f*t)+(1/23)*sin(46*pi*f*t)+"
" (1/25)*sin(50*pi*f*t)+(1/27)*sin(54*pi*f*t))"; " (1/25)*sin(50*pi*f*t)+(1/27)*sin(54*pi*f*t))";
static const T pi = T(3.14159265358979323846); static const T pi = T(3.141592653589793238462643383279502);
T f = pi / T(10); T f = pi / T(10);
T t = T(0); T t = T(0);

View File

@ -36,7 +36,7 @@ void square_wave2()
" }; " " }; "
" r *= a * (4 / pi); "; " r *= a * (4 / pi); ";
static const T pi = T(3.14159265358979323846); static const T pi = T(3.141592653589793238462643383279502);
T f = pi / T(10); T f = pi / T(10);
T t = T(0); T t = T(0);

View File

@ -61,7 +61,7 @@ void savitzky_golay_filter()
std::vector<T> v_in; std::vector<T> v_in;
std::vector<T> v_out; std::vector<T> v_out;
const T pi = T(3.141592653589793238462); const T pi = T(3.141592653589793238462643383279502);
srand(static_cast<unsigned int>(time(0))); srand(static_cast<unsigned int>(time(0)));

View File

@ -33,7 +33,8 @@ struct rnd_01 : public exprtk::ifunction<T>
inline T operator()() inline T operator()()
{ {
// Note: Do not use this in production // Note: Do not use this in production
return T(::rand() / T(RAND_MAX + 1)); // Result is in the interval [0,1)
return T(::rand() / T(RAND_MAX + 1.0));
} }
}; };
@ -61,7 +62,7 @@ void monte_carlo_pi()
const T approximate_pi = expression.value(); const T approximate_pi = expression.value();
const T real_pi = T(3.141592653589793238462); const T real_pi = T(3.141592653589793238462643383279502); // or close enough...
printf("pi ~ %20.17f\terror: %20.17f\n", printf("pi ~ %20.17f\terror: %20.17f\n",
approximate_pi, approximate_pi,

View File

@ -29,7 +29,12 @@
#include "exprtk.hpp" #include "exprtk.hpp"
#ifdef exprtk_test_float32_type
typedef float numeric_type;
#else
typedef double numeric_type; typedef double numeric_type;
#endif
typedef std::pair<std::string,numeric_type> test_t; typedef std::pair<std::string,numeric_type> test_t;
static const test_t global_test_list[] = static const test_t global_test_list[] =
@ -2750,7 +2755,7 @@ inline bool run_test04()
} }
} }
const T pi = T(3.14159265358979323846); const T pi = T(3.141592653589793238462643383279502);
const T increment = T(0.0001); const T increment = T(0.0001);
while ((x <= T(+1000)) && (y <= T(+1000))) while ((x <= T(+1000)) && (y <= T(+1000)))
@ -2815,7 +2820,7 @@ inline bool run_test05()
expression_list.push_back(e); expression_list.push_back(e);
} }
const T pi = T(3.14159265358979323846); const T pi = T(3.141592653589793238462643383279502);
const T increment = T(0.001); const T increment = T(0.001);
while ((x <= T(+1000)) && (y <= T(+1000))) while ((x <= T(+1000)) && (y <= T(+1000)))
@ -2878,7 +2883,7 @@ inline bool run_test06()
T total_area1 = exprtk::integrate(expression,x,T(-1),T(1)); T total_area1 = exprtk::integrate(expression,x,T(-1),T(1));
T total_area2 = exprtk::integrate(expression,"x",T(-1),T(1)); T total_area2 = exprtk::integrate(expression,"x",T(-1),T(1));
const T pi = T(3.14159265358979323846); const T pi = T(3.141592653589793238462643383279502);
if (not_equal(total_area1,total_area2,T(0.000001))) if (not_equal(total_area1,total_area2,T(0.000001)))
{ {
@ -3196,12 +3201,16 @@ struct myfunc : public exprtk::ifunction<T>
} }
}; };
double foo1(double v0) { return v0; } #define define_free_functions(Type) \
double foo2(double v0, double v1) { return v0 + v1; } Type foo1(Type v0) { return v0; } \
double foo3(double v0, double v1, double v2) { return v0 + v1 + v2; } Type foo2(Type v0, Type v1) { return v0 + v1; } \
double foo4(double v0, double v1, double v2, double v3) { return v0 + v1 + v2 + v3; } Type foo3(Type v0, Type v1, Type v2) { return v0 + v1 + v2; } \
double foo5(double v0, double v1, double v2, double v3, double v4) { return v0 + v1 + v2 + v3 + v4; } Type foo4(Type v0, Type v1, Type v2, Type v3) { return v0 + v1 + v2 + v3; } \
double foo6(double v0, double v1, double v2, double v3, double v4, double v5) { return v0 + v1 + v2 + v3 + v4 + v5; } Type foo5(Type v0, Type v1, Type v2, Type v3, Type v4) { return v0 + v1 + v2 + v3 + v4; } \
Type foo6(Type v0, Type v1, Type v2, Type v3, Type v4, Type v5) { return v0 + v1 + v2 + v3 + v4 + v5; } \
define_free_functions(numeric_type)
#undef define_free_functions
template <typename T> template <typename T>
inline bool run_test09() inline bool run_test09()
@ -3267,7 +3276,7 @@ inline bool run_test09()
} }
} }
const T pi = T(3.141592653589793238462); const T pi = T(3.141592653589793238462643383279502);
T result = expression.value(); T result = expression.value();

View File

@ -1269,12 +1269,13 @@ with vectors:
(b) Exponentiation: vector ^ scalar (b) Exponentiation: vector ^ scalar
(c) Assignment: :=, +=, -=, *=, /=, %=, <=> (c) Assignment: :=, +=, -=, *=, /=, %=, <=>
(d) Inequalities: <, <=, >, >=, ==, =, equal (d) Inequalities: <, <=, >, >=, ==, =, equal
(e) Unary operations: (e) Boolean logic: and, nand, nor, or, xnor, xor
(f) Unary operations:
abs, acos, acosh, asin, asinh, atan, atanh, ceil, cos, cosh, abs, acos, acosh, asin, asinh, atan, atanh, ceil, cos, cosh,
cot, csc, deg2grad, deg2rad, erf, erfc, exp, expm1, floor, cot, csc, deg2grad, deg2rad, erf, erfc, exp, expm1, floor,
frac, grad2deg, log, log10, log1p, log2, rad2deg, round, sec, frac, grad2deg, log, log10, log1p, log2, rad2deg, round, sec,
sgn, sin, sinc, sinh, sqrt, swap, tan, tanh, trunc sgn, sin, sinc, sinh, sqrt, swap, tan, tanh, trunc
(f) Aggregate and Reduce operations: (g) Aggregate and Reduce operations:
avg, max, min, mul, sum avg, max, min, mul, sum
Note: When one of the above described operations is being performed Note: When one of the above described operations is being performed
@ -1315,6 +1316,7 @@ not a vector but rather a single value.
avg(3x + 1) == 7 avg(3x + 1) == 7
min(1 / x) == (1 / 3) min(1 / x) == (1 / 3)
max(x / 2) == (3 / 2) max(x / 2) == (3 / 2)
sum(x > 0 and x < 5) == x[]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -2487,6 +2489,16 @@ in the event of a failed compilation.
} }
Assuming the following expression '2 + (3 / log(1 + x))' which uses a
variable named 'x' that has not been registered with the appropriate
symbol_table instance and is not a locally defined variable, once
compiled the above denoted post compilation error handling code shall
produce the following output:
Error: ERR184 - Undefined symbol: 'x'
Err No.:00 Pos:17 Type:[Syntax] Msg: ERR184 - Undefined symbol: 'x'
For expressions comprised of multiple lines, the error position For expressions comprised of multiple lines, the error position
provided in the parser_error object can be converted into a pair of provided in the parser_error object can be converted into a pair of
line and column numbers by invoking the 'update_error' function as is line and column numbers by invoking the 'update_error' function as is
@ -2730,9 +2742,40 @@ into account when using ExprTk:
(x + y) / (x - y); (x + y) / (x - y);
} }
(30) For performance considerations, one should assume the actions
of expression, symbol table and parser instance instantiation
and destruction, and the expression compilation process itself
to be of high latency. Hence none of them should be part of any
performance critical code paths, and should instead occur
entirely either before or after such code paths.
(31) Before jumping in and using ExprTk, do take the time to peruse
the documentation and all of the examples, both in the main and
the extras distributions. Having an informed general view of
what can and can't be done, and how something should be done
with ExprTk, will likely result in a far more productive and
enjoyable programming experience.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[21 - SIMPLE EXPRTK EXAMPLE] [21 - 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
user defined function, that accepts only two parameters, named myfunc.
The example then proceeds to instantiate an expression object and
register to it the symbol table instance.
A parser is then instantiated, and the string representation of the
expression and the expression object are passed to the parser's
compile method for compilation. If an error occurred during
compilation, the compile method will return false, leading to a series
of error diagnostics being printed to stdout. Otherwise the newly
compiled expression is evaluated by invoking the expression object's
value method, and subsequently printing the result of the computation
to stdout.
--- snip --- --- snip ---
#include <cstdio> #include <cstdio>
#include <string> #include <string>