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

This commit is contained in:
Arash Partow 2016-10-02 20:23:18 +11:00
parent 424b4628fa
commit d3fc062d05
6 changed files with 713 additions and 98 deletions

View File

@ -41,6 +41,7 @@ BUILD_LIST+=exprtk_simple_example_14
BUILD_LIST+=exprtk_simple_example_15 BUILD_LIST+=exprtk_simple_example_15
BUILD_LIST+=exprtk_simple_example_16 BUILD_LIST+=exprtk_simple_example_16
BUILD_LIST+=exprtk_simple_example_17 BUILD_LIST+=exprtk_simple_example_17
BUILD_LIST+=exprtk_simple_example_18
all: $(BUILD_LIST) all: $(BUILD_LIST)

View File

@ -40,6 +40,7 @@
#include <complex> #include <complex>
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <cstring>
#include <deque> #include <deque>
#include <exception> #include <exception>
#include <functional> #include <functional>
@ -16487,6 +16488,12 @@ namespace exprtk
return add_constant("inf",local_infinity); return add_constant("inf",local_infinity);
} }
template <typename Package>
inline bool add_package(Package& package)
{
return package.register_package(*this);
}
template <typename Allocator, template <typename Allocator,
template <typename, typename> class Sequence> template <typename, typename> class Sequence>
inline std::size_t get_variable_list(Sequence<std::pair<std::string,T>,Allocator>& vlist) const inline std::size_t get_variable_list(Sequence<std::pair<std::string,T>,Allocator>& vlist) const
@ -32153,7 +32160,7 @@ namespace exprtk
free_node(*node_allocator_,branch[1]); free_node(*node_allocator_,branch[1]);
return synthesize_str_xoxr_expression_impl<std::string&,const std::string>(opr,s0,s1,rp1); return synthesize_str_xoxr_expression_impl<std::string&, const std::string>(opr,s0,s1,rp1);
} }
inline expression_node_ptr synthesize_srosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) inline expression_node_ptr synthesize_srosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
@ -32179,7 +32186,7 @@ namespace exprtk
details::free_node(*node_allocator_,branch[1]); details::free_node(*node_allocator_,branch[1]);
return synthesize_sos_expression_impl<std::string&,const std::string>(opr,s0,s1); return synthesize_sos_expression_impl<std::string&, const std::string>(opr,s0,s1);
} }
inline expression_node_ptr synthesize_csos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) inline expression_node_ptr synthesize_csos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
@ -32217,7 +32224,7 @@ namespace exprtk
details::free_node(*node_allocator_,branch[0]); details::free_node(*node_allocator_,branch[0]);
details::free_node(*node_allocator_,branch[1]); details::free_node(*node_allocator_,branch[1]);
return synthesize_str_xrox_expression_impl<std::string&,const std::string>(opr,s0,s1,rp0); return synthesize_str_xrox_expression_impl<std::string&, const std::string>(opr,s0,s1,rp0);
} }
inline expression_node_ptr synthesize_srocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) inline expression_node_ptr synthesize_srocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
@ -32233,7 +32240,7 @@ namespace exprtk
details::free_node(*node_allocator_,branch[0]); details::free_node(*node_allocator_,branch[0]);
details::free_node(*node_allocator_,branch[1]); details::free_node(*node_allocator_,branch[1]);
return synthesize_str_xroxr_expression_impl<std::string&,const std::string>(opr,s0,s1,rp0,rp1); return synthesize_str_xroxr_expression_impl<std::string&, const std::string>(opr,s0,s1,rp0,rp1);
} }
inline expression_node_ptr synthesize_csocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) inline expression_node_ptr synthesize_csocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
@ -32253,7 +32260,7 @@ namespace exprtk
result = node_allocator_->allocate_c<details::literal_node<Type> >(details::ilike_op<Type>::process(s0,s1)); result = node_allocator_->allocate_c<details::literal_node<Type> >(details::ilike_op<Type>::process(s0,s1));
else else
{ {
expression_node_ptr temp = synthesize_sos_expression_impl<const std::string,const std::string>(opr,s0,s1); expression_node_ptr temp = synthesize_sos_expression_impl<const std::string, const std::string>(opr,s0,s1);
Type v = temp->value(); Type v = temp->value();
details::free_node(*node_allocator_,temp); details::free_node(*node_allocator_,temp);
result = node_allocator_->allocate<literal_node_t>(v); result = node_allocator_->allocate<literal_node_t>(v);
@ -32275,7 +32282,7 @@ namespace exprtk
free_node(*node_allocator_,branch[0]); free_node(*node_allocator_,branch[0]);
free_node(*node_allocator_,branch[1]); free_node(*node_allocator_,branch[1]);
return synthesize_str_xoxr_expression_impl<const std::string,const std::string>(opr,s0,s1,rp1); return synthesize_str_xoxr_expression_impl<const std::string, const std::string>(opr,s0,s1,rp1);
} }
inline expression_node_ptr synthesize_csros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) inline expression_node_ptr synthesize_csros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
@ -32332,7 +32339,7 @@ namespace exprtk
details::free_all_nodes(*node_allocator_,branch); details::free_all_nodes(*node_allocator_,branch);
return synthesize_str_xroxr_expression_impl<const std::string,const std::string>(opr,s0,s1,rp0,rp1); return synthesize_str_xroxr_expression_impl<const std::string, const std::string>(opr,s0,s1,rp0,rp1);
} }
inline expression_node_ptr synthesize_strogen_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) inline expression_node_ptr synthesize_strogen_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
@ -34525,7 +34532,9 @@ namespace exprtk
return true; return true;
} }
namespace helper namespace rtl
{
namespace io
{ {
namespace details namespace details
{ {
@ -34580,7 +34589,8 @@ namespace exprtk
} }
} }
}; };
}
} // namespace exprtk::rtl::io::details
template <typename T> template <typename T>
struct print : public exprtk::igeneric_function<T> struct print : public exprtk::igeneric_function<T>
@ -34626,6 +34636,10 @@ namespace exprtk
std::string scalar_format_; std::string scalar_format_;
}; };
} // namespace exprtk::rtl::io
} }
} }
@ -34740,6 +34754,496 @@ namespace exprtk
#endif #endif
}; };
} // namespace exprtk
#ifndef exprtk_disable_rtl_io_file
#include <fstream>
namespace exprtk
{
namespace rtl { namespace io { namespace file { namespace details
{
enum file_mode
{
e_error = 0,
e_read = 1,
e_write = 2,
e_rdwrt = 4
};
struct file_descriptor
{
file_descriptor(const std::string& fname, const std::string& access)
: stream_ptr(0),
mode(get_file_mode(access)),
file_name(fname)
{}
void* stream_ptr;
file_mode mode;
std::string file_name;
bool open()
{
if (e_read == mode)
{
std::ifstream* stream = new std::ifstream(file_name.c_str(),std::ios::binary);
if (!(*stream))
{
file_name.clear();
delete stream;
return false;
}
else
stream_ptr = stream;
return true;
}
else if (e_write == mode)
{
std::ofstream* stream = new std::ofstream(file_name.c_str(),std::ios::binary);
if (!(*stream))
{
file_name.clear();
delete stream;
return false;
}
else
stream_ptr = stream;
return true;
}
else if (e_rdwrt == mode)
{
std::fstream* stream = new std::fstream(file_name.c_str(),std::ios::binary);
if (!(*stream))
{
file_name.clear();
delete stream;
return false;
}
else
stream_ptr = stream;
return true;
}
else
return false;
}
template <typename Stream, typename Ptr>
void close(Ptr& p)
{
Stream* stream = reinterpret_cast<Stream*>(p);
stream->close();
delete stream;
p = reinterpret_cast<Ptr>(0);
}
bool close()
{
switch (mode)
{
case e_read : close<std::ifstream>(stream_ptr);
break;
case e_write : close<std::ofstream>(stream_ptr);
break;
case e_rdwrt : close<std::fstream> (stream_ptr);
break;
default : return false;
}
return true;
}
template <typename View>
bool write(const View& view, const std::size_t amount, const std::size_t offset = 0)
{
switch (mode)
{
case e_write : reinterpret_cast<std::ofstream*>(stream_ptr)->
write(reinterpret_cast<const char*>(view.begin() + offset), amount * sizeof(View::value_t));
break;
case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)->
write(reinterpret_cast<const char*>(view.begin() + offset) , amount * sizeof(View::value_t));
break;
default : return false;
}
return true;
}
template <typename View>
bool read(View& view, const std::size_t amount, const std::size_t offset = 0)
{
switch (mode)
{
case e_read : reinterpret_cast<std::ifstream*>(stream_ptr)->
read(reinterpret_cast<char*>(view.begin() + offset), amount * sizeof(View::value_t));
break;
case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)->
read(reinterpret_cast<char*>(view.begin() + offset) , amount * sizeof(View::value_t));
break;
default : return false;
}
return true;
}
bool getline(std::string& s)
{
switch (mode)
{
case e_read : return (!!std::getline(*reinterpret_cast<std::ifstream*>(stream_ptr),s));
case e_rdwrt : return (!!std::getline(*reinterpret_cast<std::fstream* >(stream_ptr),s));
default : return false;
}
return true;
}
bool eof()
{
switch (mode)
{
case e_read : return reinterpret_cast<std::ifstream*>(stream_ptr)->eof();
case e_write : return reinterpret_cast<std::ofstream*>(stream_ptr)->eof();
case e_rdwrt : return reinterpret_cast<std::fstream* >(stream_ptr)->eof();
default : return true;
}
}
file_mode get_file_mode(const std::string& access)
{
std::size_t w_cnt = 0;
std::size_t r_cnt = 0;
for (std::size_t i = 0; i < access.size(); ++i)
{
switch (std::tolower(access[i]))
{
case 'r' : r_cnt++; break;
case 'w' : w_cnt++; break;
}
}
if ((0 == r_cnt) && (0 == w_cnt))
return e_error;
else if ((r_cnt > 1) || (w_cnt > 1))
return e_error;
else if ((1 == r_cnt) && (1 == w_cnt))
return e_rdwrt;
else if (1 == r_cnt)
return e_read;
else
return e_write;
}
};
template <typename T>
file_descriptor* make_handle(T v)
{
file_descriptor* fd = reinterpret_cast<file_descriptor*>(0);
std::memcpy(reinterpret_cast<char*>(&fd),
reinterpret_cast<const char*>(&v),
sizeof(fd));
return fd;
}
template <typename T>
void perform_check()
{
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4127)
#endif
if (sizeof(T) < sizeof(void*))
{
throw std::runtime_error("exprtk::rtl::io::file - Error - pointer size larger than holder.");
}
#ifdef _MSC_VER
#pragma warning(pop)
#endif
}
} // namespace exprtk::rtl::io::file::details
template <typename T>
class open : public exprtk::igeneric_function<T>
{
public:
typedef typename exprtk::igeneric_function<T> igfun_t;
typedef typename igfun_t::parameter_list_t parameter_list_t;
typedef typename igfun_t::generic_type generic_type;
typedef typename generic_type::string_view string_t;
using exprtk::igeneric_function<T>::operator();
open()
: exprtk::igeneric_function<T>("S|SS")
{ details::perform_check<T>(); }
inline T operator()(const std::size_t& ps_index, parameter_list_t parameters)
{
std::string file_name;
std::string access;
file_name = to_str(string_t(parameters[0]));
if (file_name.empty())
return T(0);
if (0 == ps_index)
access = "r";
else if (0 == string_t(parameters[1]).size())
return T(0);
else
access = to_str(string_t(parameters[1]));
details::file_descriptor* fd = new details::file_descriptor(file_name,access);
if (fd->open())
{
T t = T(0);
std::memcpy(reinterpret_cast<char*>(&t),
reinterpret_cast<char*>(&fd),
sizeof(fd));
return t;
}
else
{
delete fd;
return T(0);
}
}
};
template <typename T>
struct close : public exprtk::ifunction<T>
{
using exprtk::ifunction<T>::operator();
close()
: exprtk::ifunction<T>(1)
{ details::perform_check<T>(); }
inline T operator()(const T& v)
{
details::file_descriptor* fd = details::make_handle(v);
if (!fd->close())
return T(0);
delete fd;
return T(1);
}
};
template <typename T>
class write : public exprtk::igeneric_function<T>
{
public:
typedef typename exprtk::igeneric_function<T> igfun_t;
typedef typename igfun_t::parameter_list_t parameter_list_t;
typedef typename igfun_t::generic_type generic_type;
typedef typename generic_type::string_view string_t;
typedef typename generic_type::scalar_view scalar_t;
typedef typename generic_type::vector_view vector_t;
using exprtk::igeneric_function<T>::operator();
write()
: igfun_t("TS|TST|TV|TVT")
{ details::perform_check<T>(); }
inline T operator()(const std::size_t& ps_index, parameter_list_t parameters)
{
details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])());
std::size_t amount = 0;
switch (ps_index)
{
case 0 : {
string_t buffer(parameters[1]);
amount = buffer.size();
return T(fd->write(buffer,amount) ? 1 : 0);
}
case 1 : {
string_t buffer(parameters[1]);
amount = std::min(buffer.size(),
static_cast<std::size_t>(scalar_t(parameters[2])()));
return T(fd->write(buffer,amount) ? 1 : 0);
}
case 2 : {
vector_t vec(parameters[1]);
amount = vec.size();
return T(fd->write(vec,amount) ? 1 : 0);
}
case 3 : {
vector_t vec(parameters[1]);
amount = std::min(vec.size(),
static_cast<std::size_t>(scalar_t(parameters[2])()));
return T(fd->write(vec,amount) ? 1 : 0);
}
}
return T(0);
}
};
template <typename T>
class read : public exprtk::igeneric_function<T>
{
public:
typedef typename exprtk::igeneric_function<T> igfun_t;
typedef typename igfun_t::parameter_list_t parameter_list_t;
typedef typename igfun_t::generic_type generic_type;
typedef typename generic_type::string_view string_t;
typedef typename generic_type::scalar_view scalar_t;
typedef typename generic_type::vector_view vector_t;
using exprtk::igeneric_function<T>::operator();
read()
: igfun_t("TS|TST|TV|TVT")
{ details::perform_check<T>(); }
inline T operator()(const std::size_t& ps_index, parameter_list_t parameters)
{
details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])());
std::size_t amount = 0;
switch (ps_index)
{
case 0 : {
string_t buffer(parameters[1]);
amount = buffer.size();
return T(fd->read(buffer,amount) ? 1 : 0);
}
case 1 : {
string_t buffer(parameters[1]);
amount = std::min(buffer.size(),
static_cast<std::size_t>(scalar_t(parameters[2])()));
return T(fd->read(buffer,amount) ? 1 : 0);
}
case 2 : {
vector_t vec(parameters[1]);
amount = vec.size();
return T(fd->read(vec,amount) ? 1 : 0);
}
case 3 : {
vector_t vec(parameters[1]);
amount = std::min(vec.size(),
static_cast<std::size_t>(scalar_t(parameters[2])()));
return T(fd->read(vec,amount) ? 1 : 0);
}
}
return T(0);
}
};
template <typename T>
class getline : public exprtk::igeneric_function<T>
{
public:
typedef typename exprtk::igeneric_function<T> igfun_t;
typedef typename igfun_t::parameter_list_t parameter_list_t;
typedef typename igfun_t::generic_type generic_type;
typedef typename generic_type::string_view string_t;
typedef typename generic_type::scalar_view scalar_t;
using exprtk::igeneric_function<T>::operator();
getline()
: igfun_t("T",igfun_t::e_rtrn_string)
{ details::perform_check<T>(); }
inline T operator()(std::string& result,
parameter_list_t parameters)
{
details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])());
return T(fd->getline(result) ? 1 : 0);
}
};
template <typename T>
struct eof : public exprtk::ifunction<T>
{
using exprtk::ifunction<T>::operator();
eof()
: exprtk::ifunction<T>(1)
{ details::perform_check<T>(); }
inline T operator()(const T& v)
{
details::file_descriptor* fd = details::make_handle(v);
return (fd->eof() ? T(1) : T(0));
}
};
template <typename T>
struct package
{
open <T> o;
close <T> c;
write <T> w;
read <T> r;
getline<T> g;
eof <T> e;
bool register_package(exprtk::symbol_table<T>& symtab)
{
if (!symtab.add_function("open" ,o))
return false;
else if (!symtab.add_function("close" ,c))
return false;
else if (!symtab.add_function("write" ,w))
return false;
else if (!symtab.add_function("read" ,r))
return false;
else if (!symtab.add_function("getline",g))
return false;
else if (!symtab.add_function("eof" ,e))
return false;
else
return true;
}
};
} // namespace exprtk::rtl::io::file
} // namespace exprtk::rtl::io
} // namespace exprtk::rtl
} // namespace exprtk
#endif
namespace exprtk
{
namespace information namespace information
{ {
static const char* library = "Mathematical Expression Toolkit"; static const char* library = "Mathematical Expression Toolkit";

View File

@ -34,7 +34,7 @@ void fibonacci()
compositor compositor
.add( .add(
function_t( function_t( // define function: fibonacci(x)
"fibonacci", "fibonacci",
" var w := 0; " " var w := 0; "
" var y := 0; " " var y := 0; "

View File

@ -42,7 +42,7 @@ void primes()
//Mode 1 - if statement based //Mode 1 - if statement based
compositor compositor
.add( .add(
function_t( function_t( // define function: is_prime_impl1(x,y)
"is_prime_impl1", "is_prime_impl1",
" if (y == 1,true, " " if (y == 1,true, "
" if (0 == (x % y),false, " " if (0 == (x % y),false, "
@ -51,7 +51,7 @@ void primes()
compositor compositor
.add( .add(
function_t( function_t( // define function: is_prime1(x)
"is_prime1", "is_prime1",
" if (frac(x) != 0, false, " " if (frac(x) != 0, false, "
" if (x <= 0, false, " " if (x <= 0, false, "
@ -61,7 +61,7 @@ void primes()
//Mode 2 - switch statement based //Mode 2 - switch statement based
compositor compositor
.add( .add(
function_t( function_t( // define function: is_prime_impl2(x,y)
"is_prime_impl2", "is_prime_impl2",
" switch " " switch "
" { " " { "
@ -73,7 +73,7 @@ void primes()
compositor compositor
.add( .add(
function_t( function_t( // define function: is_prime2(x)
"is_prime2", "is_prime2",
" switch " " switch "
" { " " { "
@ -86,7 +86,7 @@ void primes()
//Mode 3 - switch statement and while-loop based //Mode 3 - switch statement and while-loop based
compositor compositor
.add( .add(
function_t( function_t( // define function: is_prime_impl3(x,y)
"is_prime_impl3", "is_prime_impl3",
" while (y > 0) " " while (y > 0) "
" { " " { "
@ -101,7 +101,7 @@ void primes()
compositor compositor
.add( .add(
function_t( function_t( // define function: is_prime3(x)
"is_prime3", "is_prime3",
" switch " " switch "
" { " " { "

View File

@ -42,7 +42,7 @@ void newton_sqrt()
compositor compositor
.add( .add(
function_t( function_t( // define function: newton_sqrt(x)
"newton_sqrt", "newton_sqrt",
" switch " " switch "
" { " " { "

View File

@ -627,7 +627,7 @@ A vector can be indexed resulting in a scalar value. Operations
between a vector and scalar will result in a vector with a size equal between a vector and scalar will result in a vector with a size equal
to that of the original vector, whereas operations between vectors to that of the original vector, whereas operations between vectors
will result in a vector of size equal to that of the smaller of the will result in a vector of size equal to that of the smaller of the
two. two. In both mentioned cases, the operations will occur element-wise.
(3) String Type (3) String Type
@ -745,6 +745,25 @@ registration of the symbol_tables to the expression.
expression.value(); // 123 + 1 expression.value(); // 123 + 1
The symbol table supports adding references to external instances of
types that can be accessed within expressions via the following
methods:
1. bool add_variable (const std::string& name, scalar_t)
2. bool add_constant (const std::string& name,const scalar_t)
3. bool add_stringvar(const std::string& name, std::string)
4. bool add_vector (const std::string& name, vector_type)
The 'vector' type must consist of a contiguous array of scalars which
can be one of the following:
1. std::vector<scalar_t>
2. scalar_t(&v)[N]
3. scalar_t* and array size
4. exprtk::vector_view<scalar_t>
(2) Expression (2) Expression
A structure that holds an abstract syntax tree or AST for a specified A structure that holds an abstract syntax tree or AST for a specified
expression and is used to evaluate said expression. Evaluation of the expression and is used to evaluate said expression. Evaluation of the
@ -1284,7 +1303,8 @@ with vectors:
Note: When one of the above described operations is being performed Note: When one of the above described operations is being performed
between two vectors, the operation will only span the size of the between two vectors, the operation will only span the size of the
smallest vector. The elements of the larger vector outside of the smallest vector. The elements of the larger vector outside of the
range will not be included. range will not be included. The operation itself will be processed
element-wise over values the smaller of the two ranges.
The following simple example demonstrates the vector processing The following simple example demonstrates the vector processing
capabilities by computing the dot-product of the vectors v0 and v1 and capabilities by computing the dot-product of the vectors v0 and v1 and
@ -1308,9 +1328,9 @@ the previously mentioned dot-product computation expression:
} }
Note: When the aggregate operations denoted above are used in Note: When the aggregate or reduction operations denoted above are
conjunction with a vector or vector expression, the return value is used in conjunction with a vector or vector expression, the return
not a vector but rather a single value. value is not a vector but rather a single value.
var x[3] := { 1, 2, 3 }; var x[3] := { 1, 2, 3 };
@ -1321,6 +1341,80 @@ not a vector but rather a single value.
max(x / 2) == (3 / 2) max(x / 2) == (3 / 2)
sum(x > 0 and x < 5) == x[] sum(x > 0 and x < 5) == x[]
When utilizing external user defined vectors via the symbol table as
opposed to expression local defined vectors, the typical 'add_vector'
method from the symbol table will register the entirety of the vector
that is passed. The following example attempts to evaluate the sum of
elements of the external user defined vector within a typical yet
trivial expression:
std::string reduce_program = " sum(2 * v + 1) ";
std::vector<T> v0 { T(1.1), T(2.2), ..... , T(99.99) };
symbol_table_t symbol_table;
symbol_table.add_vector("v",v);
expression_t expression;
expression.register_symbol_table(symbol_table);
parser_t parser;
parser.compile(reduce_program,expression);
T sum = expression.value();
For the most part, this is a very common use-case. However there may
be situations where one may want to evaluate the same vector oriented
expression many times over, but using different vectors or sub ranges
of the same vector of the same size to that of the original upon every
evaluation.
The usual solution is to either recompile the expression for the new
vector instance, or to copy the contents from the new vector to the
symbol table registered vector and then perform the evaluation. When
the vectors are large or the re-evaluation attempts are numerous,
these solutions can become rather time consuming and generally
inefficient.
std::vector<T> v1 { T(2.2), T(2.2), ..... , T(2.2) };
std::vector<T> v2 { T(3.3), T(3.3), ..... , T(3.3) };
std::vector<T> v3 { T(4.4), T(4.4), ..... , T(4.4) };
std::vector<std::vector<T>> vv { v1, v2, v3 };
...
T sum = T(0);
for (auto& w : vv)
{
v = w; // update vector
sum += expression.value();
}
A solution to the above 'efficiency' problem, is to use the
exprtk::vector_view object. The vector_view is instantiated with a
size and backing based upon a vector. Upon evaluations if the backing
needs to be 'updated' to either another vector or sub-range, the
vector_view instance can be efficiently rebased, and the expression
evaluated as normal.
exprtk::vector_view<T> vv = exprtk::make_vector_view(v, v.size());
symbol_table_t symbol_table;
symbol_table.add_vector("v",vv);
...
T sum = T(0);
for (auto& w : vv)
{
vv.rebase(new_vec.data()); // update vector
sum += expression.value();
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[15 - USER DEFINED FUNCTIONS] [15 - USER DEFINED FUNCTIONS]
@ -2745,14 +2839,23 @@ into account when using ExprTk:
(x + y) / (x - y); (x + y) / (x - y);
} }
(30) For performance considerations, one should assume the actions (30) It is recommended when prototyping expressions that the ExprTk
REPL be utilised, as it supports all the features available in
the library, including complete error analysis, benchmarking
and dependency dumps etc which allows for rapid
coding/prototyping and debug cycles without the hassle of
having to recompile test programs with expressions that have
been hard-coded. It's also a good source of truth for how the
library's various features can be applied.
(31) For performance considerations, one should assume the actions
of expression, symbol table and parser instance instantiation of expression, symbol table and parser instance instantiation
and destruction, and the expression compilation process itself and destruction, and the expression compilation process itself
to be of high latency. Hence none of them should be part of any to be of high latency. Hence none of them should be part of any
performance critical code paths, and should instead occur performance critical code paths, and should instead occur
entirely either before or after such code paths. entirely either before or after such code paths.
(31) Before jumping in and using ExprTk, do take the time to peruse (32) 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 documentation and all of the examples, both in the main and
the extras distributions. Having an informed general view of the extras distributions. Having an informed general view of
what can and can't be done, and how something should be done what can and can't be done, and how something should be done
@ -2879,6 +2982,7 @@ the ExprTk header. The defines are as follows:
(5) exprtk_disable_enhanced_features (5) exprtk_disable_enhanced_features
(6) exprtk_disable_string_capabilities (6) exprtk_disable_string_capabilities
(7) exprtk_disable_superscalar_unroll (7) exprtk_disable_superscalar_unroll
(8) exprtk_disable_rtl_io_file
(1) exprtk_enable_debugging (1) exprtk_enable_debugging
@ -2919,6 +3023,11 @@ targeting non-superscalar architectures, it may be recommended to
build using this particular option if efficiency of evaluations is of build using this particular option if efficiency of evaluations is of
concern. concern.
(8) exprtk_disable_rtl_io_file
This define will disable the file I/O RTL package features. When
present, any attempts to register the file I/O package with a given
symbol table will fail causing a compilation error.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[23 - FILES] [23 - FILES]
@ -2947,6 +3056,7 @@ files:
(19) exprtk_simple_example_15.cpp (19) exprtk_simple_example_15.cpp
(20) exprtk_simple_example_16.cpp (20) exprtk_simple_example_16.cpp
(21) exprtk_simple_example_17.cpp (21) exprtk_simple_example_17.cpp
(22) exprtk_simple_example_18.cpp
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~