C++ Mathematical Expression Library (ExprTk) https://www.partow.net/programming/exprtk/index.html
This commit is contained in:
parent
424b4628fa
commit
d3fc062d05
1
Makefile
1
Makefile
|
@ -41,6 +41,7 @@ BUILD_LIST+=exprtk_simple_example_14
|
|||
BUILD_LIST+=exprtk_simple_example_15
|
||||
BUILD_LIST+=exprtk_simple_example_16
|
||||
BUILD_LIST+=exprtk_simple_example_17
|
||||
BUILD_LIST+=exprtk_simple_example_18
|
||||
|
||||
|
||||
all: $(BUILD_LIST)
|
||||
|
|
670
exprtk.hpp
670
exprtk.hpp
|
@ -40,6 +40,7 @@
|
|||
#include <complex>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <deque>
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
|
@ -16487,6 +16488,12 @@ namespace exprtk
|
|||
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, typename> class Sequence>
|
||||
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]);
|
||||
|
||||
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])
|
||||
|
@ -32179,7 +32186,7 @@ namespace exprtk
|
|||
|
||||
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])
|
||||
|
@ -32217,7 +32224,7 @@ namespace exprtk
|
|||
details::free_node(*node_allocator_,branch[0]);
|
||||
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])
|
||||
|
@ -32233,7 +32240,7 @@ namespace exprtk
|
|||
details::free_node(*node_allocator_,branch[0]);
|
||||
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])
|
||||
|
@ -32253,7 +32260,7 @@ namespace exprtk
|
|||
result = node_allocator_->allocate_c<details::literal_node<Type> >(details::ilike_op<Type>::process(s0,s1));
|
||||
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();
|
||||
details::free_node(*node_allocator_,temp);
|
||||
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[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])
|
||||
|
@ -32332,7 +32339,7 @@ namespace exprtk
|
|||
|
||||
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])
|
||||
|
@ -34525,107 +34532,114 @@ namespace exprtk
|
|||
return true;
|
||||
}
|
||||
|
||||
namespace helper
|
||||
namespace rtl
|
||||
{
|
||||
namespace details
|
||||
namespace io
|
||||
{
|
||||
template <typename T>
|
||||
inline void print_type(const std::string& fmt,
|
||||
const T v,
|
||||
exprtk::details::numeric::details::real_type_tag)
|
||||
namespace details
|
||||
{
|
||||
printf(fmt.c_str(),v);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct print_impl
|
||||
{
|
||||
typedef typename igeneric_function<T>::generic_type generic_type;
|
||||
typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
|
||||
typedef typename generic_type::scalar_view scalar_t;
|
||||
typedef typename generic_type::vector_view vector_t;
|
||||
typedef typename generic_type::string_view string_t;
|
||||
|
||||
static void process(const std::string& scalar_format, parameter_list_t parameters)
|
||||
template <typename T>
|
||||
inline void print_type(const std::string& fmt,
|
||||
const T v,
|
||||
exprtk::details::numeric::details::real_type_tag)
|
||||
{
|
||||
for (std::size_t i = 0; i < parameters.size(); ++i)
|
||||
printf(fmt.c_str(),v);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct print_impl
|
||||
{
|
||||
typedef typename igeneric_function<T>::generic_type generic_type;
|
||||
typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
|
||||
typedef typename generic_type::scalar_view scalar_t;
|
||||
typedef typename generic_type::vector_view vector_t;
|
||||
typedef typename generic_type::string_view string_t;
|
||||
|
||||
static void process(const std::string& scalar_format, parameter_list_t parameters)
|
||||
{
|
||||
generic_type& gt = parameters[i];
|
||||
|
||||
typename exprtk::details::numeric::details::number_type<T>::type num_type;
|
||||
|
||||
switch (gt.type)
|
||||
for (std::size_t i = 0; i < parameters.size(); ++i)
|
||||
{
|
||||
case generic_type::e_scalar : print_type(scalar_format,scalar_t(gt)(),num_type);
|
||||
break;
|
||||
generic_type& gt = parameters[i];
|
||||
|
||||
case generic_type::e_vector : {
|
||||
vector_t vector(gt);
|
||||
typename exprtk::details::numeric::details::number_type<T>::type num_type;
|
||||
|
||||
for (std::size_t x = 0; x < vector.size(); ++x)
|
||||
{
|
||||
print_type(scalar_format,vector[x],num_type);
|
||||
switch (gt.type)
|
||||
{
|
||||
case generic_type::e_scalar : print_type(scalar_format,scalar_t(gt)(),num_type);
|
||||
break;
|
||||
|
||||
if ((x + 1) < vector.size())
|
||||
printf(" ");
|
||||
case generic_type::e_vector : {
|
||||
vector_t vector(gt);
|
||||
|
||||
for (std::size_t x = 0; x < vector.size(); ++x)
|
||||
{
|
||||
print_type(scalar_format,vector[x],num_type);
|
||||
|
||||
if ((x + 1) < vector.size())
|
||||
printf(" ");
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
case generic_type::e_string : printf("%s",to_str(string_t(gt)).c_str());
|
||||
break;
|
||||
case generic_type::e_string : printf("%s",to_str(string_t(gt)).c_str());
|
||||
break;
|
||||
|
||||
default : continue;
|
||||
default : continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace exprtk::rtl::io::details
|
||||
|
||||
template <typename T>
|
||||
struct print : public exprtk::igeneric_function<T>
|
||||
{
|
||||
typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
|
||||
|
||||
using exprtk::igeneric_function<T>::operator();
|
||||
|
||||
print(const std::string& scalar_format = "%10.5f")
|
||||
: scalar_format_(scalar_format)
|
||||
{
|
||||
exprtk::enable_zero_parameters(*this);
|
||||
}
|
||||
|
||||
inline T operator()(parameter_list_t parameters)
|
||||
{
|
||||
details::print_impl<T>::process(scalar_format_,parameters);
|
||||
return T(0);
|
||||
}
|
||||
|
||||
std::string scalar_format_;
|
||||
};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct print : public exprtk::igeneric_function<T>
|
||||
{
|
||||
typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
|
||||
|
||||
using exprtk::igeneric_function<T>::operator();
|
||||
|
||||
print(const std::string& scalar_format = "%10.5f")
|
||||
: scalar_format_(scalar_format)
|
||||
template <typename T>
|
||||
struct println : public exprtk::igeneric_function<T>
|
||||
{
|
||||
exprtk::enable_zero_parameters(*this);
|
||||
}
|
||||
typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
|
||||
|
||||
inline T operator()(parameter_list_t parameters)
|
||||
{
|
||||
details::print_impl<T>::process(scalar_format_,parameters);
|
||||
return T(0);
|
||||
}
|
||||
using exprtk::igeneric_function<T>::operator();
|
||||
|
||||
std::string scalar_format_;
|
||||
};
|
||||
println(const std::string& scalar_format = "%10.5f")
|
||||
: scalar_format_(scalar_format)
|
||||
{
|
||||
exprtk::enable_zero_parameters(*this);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct println : public exprtk::igeneric_function<T>
|
||||
{
|
||||
typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
|
||||
inline T operator()(parameter_list_t parameters)
|
||||
{
|
||||
details::print_impl<T>::process(scalar_format_,parameters);
|
||||
printf("\n");
|
||||
return T(0);
|
||||
}
|
||||
|
||||
using exprtk::igeneric_function<T>::operator();
|
||||
std::string scalar_format_;
|
||||
};
|
||||
|
||||
println(const std::string& scalar_format = "%10.5f")
|
||||
: scalar_format_(scalar_format)
|
||||
{
|
||||
exprtk::enable_zero_parameters(*this);
|
||||
}
|
||||
|
||||
inline T operator()(parameter_list_t parameters)
|
||||
{
|
||||
details::print_impl<T>::process(scalar_format_,parameters);
|
||||
printf("\n");
|
||||
return T(0);
|
||||
}
|
||||
|
||||
std::string scalar_format_;
|
||||
};
|
||||
} // namespace exprtk::rtl::io
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34740,6 +34754,496 @@ namespace exprtk
|
|||
#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
|
||||
{
|
||||
static const char* library = "Mathematical Expression Toolkit";
|
||||
|
|
|
@ -34,7 +34,7 @@ void fibonacci()
|
|||
|
||||
compositor
|
||||
.add(
|
||||
function_t(
|
||||
function_t( // define function: fibonacci(x)
|
||||
"fibonacci",
|
||||
" var w := 0; "
|
||||
" var y := 0; "
|
||||
|
|
|
@ -42,7 +42,7 @@ void primes()
|
|||
//Mode 1 - if statement based
|
||||
compositor
|
||||
.add(
|
||||
function_t(
|
||||
function_t( // define function: is_prime_impl1(x,y)
|
||||
"is_prime_impl1",
|
||||
" if (y == 1,true, "
|
||||
" if (0 == (x % y),false, "
|
||||
|
@ -51,7 +51,7 @@ void primes()
|
|||
|
||||
compositor
|
||||
.add(
|
||||
function_t(
|
||||
function_t( // define function: is_prime1(x)
|
||||
"is_prime1",
|
||||
" if (frac(x) != 0, false, "
|
||||
" if (x <= 0, false, "
|
||||
|
@ -61,7 +61,7 @@ void primes()
|
|||
//Mode 2 - switch statement based
|
||||
compositor
|
||||
.add(
|
||||
function_t(
|
||||
function_t( // define function: is_prime_impl2(x,y)
|
||||
"is_prime_impl2",
|
||||
" switch "
|
||||
" { "
|
||||
|
@ -73,7 +73,7 @@ void primes()
|
|||
|
||||
compositor
|
||||
.add(
|
||||
function_t(
|
||||
function_t( // define function: is_prime2(x)
|
||||
"is_prime2",
|
||||
" switch "
|
||||
" { "
|
||||
|
@ -86,7 +86,7 @@ void primes()
|
|||
//Mode 3 - switch statement and while-loop based
|
||||
compositor
|
||||
.add(
|
||||
function_t(
|
||||
function_t( // define function: is_prime_impl3(x,y)
|
||||
"is_prime_impl3",
|
||||
" while (y > 0) "
|
||||
" { "
|
||||
|
@ -101,7 +101,7 @@ void primes()
|
|||
|
||||
compositor
|
||||
.add(
|
||||
function_t(
|
||||
function_t( // define function: is_prime3(x)
|
||||
"is_prime3",
|
||||
" switch "
|
||||
" { "
|
||||
|
|
|
@ -42,7 +42,7 @@ void newton_sqrt()
|
|||
|
||||
compositor
|
||||
.add(
|
||||
function_t(
|
||||
function_t( // define function: newton_sqrt(x)
|
||||
"newton_sqrt",
|
||||
" switch "
|
||||
" { "
|
||||
|
|
124
readme.txt
124
readme.txt
|
@ -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
|
||||
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
|
||||
two.
|
||||
two. In both mentioned cases, the operations will occur element-wise.
|
||||
|
||||
|
||||
(3) String Type
|
||||
|
@ -745,6 +745,25 @@ registration of the symbol_tables to the expression.
|
|||
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
|
||||
A structure that holds an abstract syntax tree or AST for a specified
|
||||
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
|
||||
between two vectors, the operation will only span the size 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
|
||||
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
|
||||
conjunction with a vector or vector expression, the return value is
|
||||
not a vector but rather a single value.
|
||||
Note: When the aggregate or reduction operations denoted above are
|
||||
used in conjunction with a vector or vector expression, the return
|
||||
value is not a vector but rather a single value.
|
||||
|
||||
var x[3] := { 1, 2, 3 };
|
||||
|
||||
|
@ -1321,6 +1341,80 @@ not a vector but rather a single value.
|
|||
max(x / 2) == (3 / 2)
|
||||
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]
|
||||
|
@ -2745,14 +2839,23 @@ into account when using ExprTk:
|
|||
(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
|
||||
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
|
||||
(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 extras distributions. Having an informed general view of
|
||||
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
|
||||
(6) exprtk_disable_string_capabilities
|
||||
(7) exprtk_disable_superscalar_unroll
|
||||
(8) exprtk_disable_rtl_io_file
|
||||
|
||||
|
||||
(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
|
||||
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]
|
||||
|
@ -2947,6 +3056,7 @@ files:
|
|||
(19) exprtk_simple_example_15.cpp
|
||||
(20) exprtk_simple_example_16.cpp
|
||||
(21) exprtk_simple_example_17.cpp
|
||||
(22) exprtk_simple_example_18.cpp
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
Loading…
Reference in New Issue