From 365ddd29d6b8300153b17f7e2af1300e88aec4b7 Mon Sep 17 00:00:00 2001 From: Arash Partow Date: Mon, 10 Oct 2016 12:17:33 +1100 Subject: [PATCH] C++ Mathematical Expression Library (ExprTk) https://www.partow.net/programming/exprtk/index.html --- exprtk.hpp | 1016 +++++++++++++++++++++++++++++++++++++++++++++++ exprtk_test.cpp | 127 ++++++ readme.txt | 6 + 3 files changed, 1149 insertions(+) diff --git a/exprtk.hpp b/exprtk.hpp index 0da0960..fea517e 100644 --- a/exprtk.hpp +++ b/exprtk.hpp @@ -35634,6 +35634,1022 @@ namespace exprtk } // namespace exprtk #endif +#ifndef exprtk_disable_rtl_vecops +namespace exprtk +{ + namespace rtl { namespace vecops { + namespace details + { + template + struct load_vector_range + { + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::scalar_view scalar_t; + + static inline bool process(parameter_list_t& parameters, + std::size_t& r0, std::size_t& r1, + const std::size_t& r0_prmidx, + const std::size_t& r1_prmidx) + { + if (r0_prmidx >= parameters.size()) + return false; + + if (r1_prmidx >= parameters.size()) + return false; + + if (!scalar_t(parameters[r0_prmidx]).to_uint(r0)) + return false; + + if (!scalar_t(parameters[r1_prmidx]).to_uint(r1)) + return false; + + return true; + } + }; + + template + inline bool invalid_range(const Vector& v, const std::size_t r0, const std::size_t r1) + { + if (r0 > (v.size() - 1)) + return true; + else if (r1 > (v.size() - 1)) + return true; + else if (r1 < r0) + return true; + else + return false; + } + + template + inline void kahan_sum(T& sum, T& error, T v) + { + T x = v - error; + T y = sum + x; + error = (y - sum) - x; + sum = y; + } + + } // namespace exprtk::rtl::details + + template + class all_true : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::vector_view vector_t; + + using exprtk::igeneric_function::operator(); + + all_true() + : exprtk::igeneric_function("V|VTT") + /* + Overloads: + 0. V - vector + 1. VTT - vector, r0, r1 + */ + {} + + inline T operator()(const std::size_t& ps_index, parameter_list_t parameters) + { + const vector_t& vec(parameters[0]); + + std::size_t r0 = 0; + std::size_t r1 = vec.size() - 1; + + if ((1 == ps_index) && !details::load_vector_range::process(parameters,r0,r1,1,2)) + return std::numeric_limits::quiet_NaN(); + else if (details::invalid_range(vec,r0,r1)) + return std::numeric_limits::quiet_NaN(); + + for (std::size_t i = r0; i <= r1; ++i) + { + if (vec[i] == T(0)) + { + return T(0); + } + } + + return T(1); + } + }; + + template + class all_false : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::vector_view vector_t; + + using exprtk::igeneric_function::operator(); + + all_false() + : exprtk::igeneric_function("V|VTT") + /* + Overloads: + 0. V - vector + 1. VTT - vector, r0, r1 + */ + {} + + inline T operator()(const std::size_t& ps_index, parameter_list_t parameters) + { + const vector_t& vec(parameters[0]); + + std::size_t r0 = 0; + std::size_t r1 = vec.size() - 1; + + if ((1 == ps_index) && !details::load_vector_range::process(parameters,r0,r1,1,2)) + return std::numeric_limits::quiet_NaN(); + else if (details::invalid_range(vec,r0,r1)) + return std::numeric_limits::quiet_NaN(); + + for (std::size_t i = r0; i <= r1; ++i) + { + if (vec[i] != T(0)) + { + return T(0); + } + } + + return T(1); + } + }; + + template + class any_true : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::vector_view vector_t; + + using exprtk::igeneric_function::operator(); + + any_true() + : exprtk::igeneric_function("V|VTT") + /* + Overloads: + 0. V - vector + 1. VTT - vector, r0, r1 + */ + {} + + inline T operator()(const std::size_t& ps_index, parameter_list_t parameters) + { + const vector_t& vec(parameters[0]); + + std::size_t r0 = 0; + std::size_t r1 = vec.size() - 1; + + if ((1 == ps_index) && !details::load_vector_range::process(parameters,r0,r1,1,2)) + return std::numeric_limits::quiet_NaN(); + else if (details::invalid_range(vec,r0,r1)) + return std::numeric_limits::quiet_NaN(); + + for (std::size_t i = r0; i <= r1; ++i) + { + if (vec[i] != T(0)) + { + return T(1); + } + } + + return T(0); + } + }; + + template + class any_false : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::vector_view vector_t; + + using exprtk::igeneric_function::operator(); + + any_false() + : exprtk::igeneric_function("V|VTT") + /* + Overloads: + 0. V - vector + 1. VTT - vector, r0, r1 + */ + {} + + inline T operator()(const std::size_t& ps_index, parameter_list_t parameters) + { + const vector_t& vec(parameters[0]); + + std::size_t r0 = 0; + std::size_t r1 = vec.size() - 1; + + if ((1 == ps_index) && !details::load_vector_range::process(parameters,r0,r1,1,2)) + return std::numeric_limits::quiet_NaN(); + else if (details::invalid_range(vec,r0,r1)) + return std::numeric_limits::quiet_NaN(); + + for (std::size_t i = r0; i <= r1; ++i) + { + if (vec[i] == T(0)) + { + return T(1); + } + } + + return T(0); + } + }; + + template + class count : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::vector_view vector_t; + + using exprtk::igeneric_function::operator(); + + count() + : exprtk::igeneric_function("V|VTT") + /* + Overloads: + 0. V - vector + 1. VTT - vector, r0, r1 + */ + {} + + inline T operator()(const std::size_t& ps_index, parameter_list_t parameters) + { + const vector_t& vec(parameters[0]); + + std::size_t r0 = 0; + std::size_t r1 = vec.size() - 1; + + if ((1 == ps_index) && !details::load_vector_range::process(parameters,r0,r1,1,2)) + return std::numeric_limits::quiet_NaN(); + else if (details::invalid_range(vec,r0,r1)) + return std::numeric_limits::quiet_NaN(); + + std::size_t cnt = 0; + + for (std::size_t i = r0; i <= r1; ++i) + { + if (vec[i] != T(0)) ++cnt; + } + + return T(cnt); + } + }; + + template + class copy : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::scalar_view scalar_t; + typedef typename generic_type::vector_view vector_t; + + using exprtk::igeneric_function::operator(); + + copy() + : exprtk::igeneric_function("VV|VTTVTT") + /* + Overloads: + 0. VV - x(vector), y(vector) + 1. VTTVTT - x(vector), xr0, xr1, y(vector), yr0, yr1, + */ + {} + + inline T operator()(const std::size_t& ps_index, parameter_list_t parameters) + { + vector_t x(parameters[0]); + vector_t y(parameters[(0 == ps_index) ? 1 : 3]); + + std::size_t xr0 = 0; + std::size_t xr1 = x.size() - 1; + + std::size_t yr0 = 0; + std::size_t yr1 = y.size() - 1; + + if ((1 == ps_index) && !details::load_vector_range::process(parameters,xr0,xr1,1,2)) + return T(0); + if ((1 == ps_index) && !details::load_vector_range::process(parameters,yr0,yr1,4,5)) + return T(0); + else if (details::invalid_range(x,xr0,xr1)) + return T(0); + else if (details::invalid_range(y,yr0,yr1)) + return T(0); + + const std::size_t n = std::min(xr1 - xr0 + 1, yr1 - yr0 + 1); + + std::copy(x.begin() + xr0, x.begin() + xr0 + n, y.begin() + yr0); + + return T(n); + } + }; + + template + class rol : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::scalar_view scalar_t; + typedef typename generic_type::vector_view vector_t; + + using exprtk::igeneric_function::operator(); + + rol() + : exprtk::igeneric_function("VT|VTTT") + /* + Overloads: + 0. VT - vector, N + 1. VTTT - vector, N, r0, r1 + */ + {} + + inline T operator()(const std::size_t& ps_index, parameter_list_t parameters) + { + vector_t vec(parameters[0]); + + std::size_t n = 0; + std::size_t r0 = 0; + std::size_t r1 = vec.size() - 1; + + if (!scalar_t(parameters[1]).to_uint(n)) + return T(0); + + if ((1 == ps_index) && !details::load_vector_range::process(parameters,r0,r1,2,3)) + return T(0); + else if (details::invalid_range(vec,r0,r1)) + return T(0); + + std::size_t dist = r1 - r0 + 1; + std::size_t shift = n % dist; + + std::rotate(vec.begin() + r0, vec.begin() + r0 + shift, vec.begin() + r1 + 1); + + return T(1); + } + }; + + template + class ror : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::scalar_view scalar_t; + typedef typename generic_type::vector_view vector_t; + + using exprtk::igeneric_function::operator(); + + ror() + : exprtk::igeneric_function("VT|VTTT") + /* + Overloads: + 0. VT - vector, N + 1. VTTT - vector, N, r0, r1 + */ + {} + + inline T operator()(const std::size_t& ps_index, parameter_list_t parameters) + { + vector_t vec(parameters[0]); + + std::size_t n = 0; + std::size_t r0 = 0; + std::size_t r1 = vec.size() - 1; + + if (!scalar_t(parameters[1]).to_uint(n)) + return T(0); + + if ((1 == ps_index) && !details::load_vector_range::process(parameters,r0,r1,2,3)) + return T(0); + else if (details::invalid_range(vec,r0,r1)) + return T(0); + + std::size_t dist = r1 - r0 + 1; + std::size_t shift = (dist - (n % dist)) % dist; + + std::rotate(vec.begin() + r0, vec.begin() + r0 + shift, vec.begin() + r1 + 1); + + return T(1); + } + }; + + template + class shift_left : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::scalar_view scalar_t; + typedef typename generic_type::vector_view vector_t; + + using exprtk::igeneric_function::operator(); + + shift_left() + : exprtk::igeneric_function("VT|VTTT") + /* + Overloads: + 0. VT - vector, N + 1. VTTT - vector, N, r0, r1 + */ + {} + + inline T operator()(const std::size_t& ps_index, parameter_list_t parameters) + { + vector_t vec(parameters[0]); + + std::size_t n = 0; + std::size_t r0 = 0; + std::size_t r1 = vec.size() - 1; + + if (!scalar_t(parameters[1]).to_uint(n)) + return T(0); + + if ((1 == ps_index) && !details::load_vector_range::process(parameters,r0,r1,2,3)) + return T(0); + else if (details::invalid_range(vec,r0,r1)) + return T(0); + + std::size_t dist = r1 - r0 + 1; + + if (n > dist) + return T(0); + + std::rotate(vec.begin() + r0, vec.begin() + r0 + n, vec.begin() + r1 + 1); + + for (std::size_t i = r1 - n + 1; i <= r1; ++i) + { + vec[i] = T(0); + } + + return T(1); + } + }; + + template + class shift_right : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::scalar_view scalar_t; + typedef typename generic_type::vector_view vector_t; + + using exprtk::igeneric_function::operator(); + + shift_right() + : exprtk::igeneric_function("VT|VTTT") + /* + Overloads: + 0. VT - vector, N + 1. VTTT - vector, N, r0, r1 + */ + {} + + inline T operator()(const std::size_t& ps_index, parameter_list_t parameters) + { + vector_t vec(parameters[0]); + + std::size_t n = 0; + std::size_t r0 = 0; + std::size_t r1 = vec.size() - 1; + + if (!scalar_t(parameters[1]).to_uint(n)) + return T(0); + + if ((1 == ps_index) && !details::load_vector_range::process(parameters,r0,r1,2,3)) + return T(0); + else if (details::invalid_range(vec,r0,r1)) + return T(0); + + std::size_t dist = r1 - r0 + 1; + + if (n > dist) + return T(0); + + std::size_t shift = (dist - (n % dist)) % dist; + + std::rotate(vec.begin() + r0, vec.begin() + r0 + shift, vec.begin() + r1 + 1); + + for (std::size_t i = r0; i < r0 + n; ++i) + { + vec[i] = T(0); + } + + return T(1); + } + }; + + template + class sort : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function 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::vector_view vector_t; + + using exprtk::igeneric_function::operator(); + + sort() + : exprtk::igeneric_function("V|VTT|VS|VSTT") + /* + Overloads: + 0. V - vector + 1. VTT - vector, r0, r1 + 2. VS - vector, string + 3. VSTT - vector, string, r0, r1 + */ + {} + + inline T operator()(const std::size_t& ps_index, parameter_list_t parameters) + { + vector_t vec(parameters[0]); + + std::size_t r0 = 0; + std::size_t r1 = vec.size() - 1; + + if ((1 == ps_index) && !details::load_vector_range::process(parameters,r0,r1,1,2)) + return T(0); + if ((3 == ps_index) && !details::load_vector_range::process(parameters,r0,r1,2,3)) + return T(0); + if (details::invalid_range(vec,r0,r1)) + return T(0); + + bool ascending = true; + + if ((2 == ps_index) || (3 == ps_index)) + { + if (exprtk::details::imatch(to_str(string_t(parameters[1])),"ascending")) + ascending = true; + else if (exprtk::details::imatch(to_str(string_t(parameters[1])),"descending")) + ascending = false; + else + return T(0); + } + + if (ascending) + std::sort(vec.begin() + r0, vec.begin() + r1 + 1, std::less ()); + else + std::sort(vec.begin() + r0, vec.begin() + r1 + 1, std::greater()); + + return T(1); + } + }; + + template + class sumk : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::vector_view vector_t; + + using exprtk::igeneric_function::operator(); + + sumk() + : exprtk::igeneric_function("V|VTT") + /* + Overloads: + 0. V - vector + 1. VTT - vector, r0, r1 + */ + {} + + inline T operator()(const std::size_t& ps_index, parameter_list_t parameters) + { + vector_t vec(parameters[0]); + + std::size_t r0 = 0; + std::size_t r1 = vec.size() - 1; + + if ((1 == ps_index) && !details::load_vector_range::process(parameters,r0,r1,1,2)) + return std::numeric_limits::quiet_NaN(); + else if (details::invalid_range(vec,r0,r1)) + return std::numeric_limits::quiet_NaN(); + + T result = T(0); + T error = T(0); + + for (std::size_t i = r0; i <= r1; ++i) + { + details::kahan_sum(result,error,vec[i]); + } + + return result; + } + }; + + template + class axpy : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::scalar_view scalar_t; + typedef typename generic_type::vector_view vector_t; + + using exprtk::igeneric_function::operator(); + + axpy() + : exprtk::igeneric_function("TVV|TVVTT") + /* + y <- ax + y + Overloads: + 0. TVV - a, x(vector), y(vector) + 1. TVVTT - a, x(vector), y(vector), r0, r1 + */ + {} + + inline T operator()(const std::size_t& ps_index, parameter_list_t parameters) + { + vector_t x(parameters[1]); + vector_t y(parameters[2]); + + std::size_t r0 = 0; + std::size_t r1 = std::min(x.size(),y.size()) - 1; + + if ((1 == ps_index) && !details::load_vector_range::process(parameters,r0,r1,3,4)) + return std::numeric_limits::quiet_NaN(); + else if (details::invalid_range(x,r0,r1)) + return std::numeric_limits::quiet_NaN(); + else if (details::invalid_range(y,r0,r1)) + return std::numeric_limits::quiet_NaN(); + + T a = scalar_t(parameters[0])(); + + for (std::size_t i = r0; i <= r1; ++i) + { + y[i] = a * x[i] + y[i]; + } + + return T(1); + } + }; + + template + class axpby : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::scalar_view scalar_t; + typedef typename generic_type::vector_view vector_t; + + using exprtk::igeneric_function::operator(); + + axpby() + : exprtk::igeneric_function("TVTV|TVTVTT") + /* + y <- ax + by + Overloads: + 0. TVTV - a, x(vector), b, y(vector) + 1. TVTVTT - a, x(vector), b, y(vector), r0, r1 + */ + {} + + inline T operator()(const std::size_t& ps_index, parameter_list_t parameters) + { + vector_t x(parameters[1]); + vector_t y(parameters[3]); + + std::size_t r0 = 0; + std::size_t r1 = std::min(x.size(),y.size()) - 1; + + if ((1 == ps_index) && !details::load_vector_range::process(parameters,r0,r1,4,5)) + return std::numeric_limits::quiet_NaN(); + else if (details::invalid_range(x,r0,r1)) + return std::numeric_limits::quiet_NaN(); + else if (details::invalid_range(y,r0,r1)) + return std::numeric_limits::quiet_NaN(); + + const T a = scalar_t(parameters[0])(); + const T b = scalar_t(parameters[2])(); + + for (std::size_t i = r0; i <= r1; ++i) + { + y[i] = (a * x[i]) + (b * y[i]); + } + + return T(1); + } + }; + + template + class axpyz : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::scalar_view scalar_t; + typedef typename generic_type::vector_view vector_t; + + using exprtk::igeneric_function::operator(); + + axpyz() + : exprtk::igeneric_function("TVVV|TVVVTT") + /* + z <- ax + y + Overloads: + 0. TVVV - a, x(vector), y(vector), z(vector) + 1. TVVVTT - a, x(vector), y(vector), z(vector), r0, r1 + */ + {} + + inline T operator()(const std::size_t& ps_index, parameter_list_t parameters) + { + vector_t x(parameters[1]); + vector_t y(parameters[2]); + vector_t z(parameters[3]); + + std::size_t r0 = 0; + std::size_t r1 = std::min(x.size(),y.size()) - 1; + + if ((1 == ps_index) && !details::load_vector_range::process(parameters,r0,r1,3,4)) + return std::numeric_limits::quiet_NaN(); + else if (details::invalid_range(x,r0,r1)) + return std::numeric_limits::quiet_NaN(); + else if (details::invalid_range(y,r0,r1)) + return std::numeric_limits::quiet_NaN(); + else if (details::invalid_range(z,r0,r1)) + return std::numeric_limits::quiet_NaN(); + + T a = scalar_t(parameters[0])(); + + for (std::size_t i = r0; i <= r1; ++i) + { + z[i] = a * x[i] + y[i]; + } + + return T(1); + } + }; + + template + class axpbyz : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::scalar_view scalar_t; + typedef typename generic_type::vector_view vector_t; + + using exprtk::igeneric_function::operator(); + + axpbyz() + : exprtk::igeneric_function("TVTVV|TVTVVTT") + /* + z <- ax + by + Overloads: + 0. TVTVV - a, x(vector), b, y(vector), z(vector) + 1. TVTVVTT - a, x(vector), b, y(vector), z(vector), r0, r1 + */ + {} + + inline T operator()(const std::size_t& ps_index, parameter_list_t parameters) + { + vector_t x(parameters[1]); + vector_t y(parameters[3]); + vector_t z(parameters[4]); + + std::size_t r0 = 0; + std::size_t r1 = std::min(x.size(),y.size()) - 1; + + if ((1 == ps_index) && !details::load_vector_range::process(parameters,r0,r1,4,5)) + return std::numeric_limits::quiet_NaN(); + else if (details::invalid_range(x,r0,r1)) + return std::numeric_limits::quiet_NaN(); + else if (details::invalid_range(y,r0,r1)) + return std::numeric_limits::quiet_NaN(); + else if (details::invalid_range(z,r0,r1)) + return std::numeric_limits::quiet_NaN(); + + const T a = scalar_t(parameters[0])(); + const T b = scalar_t(parameters[2])(); + + for (std::size_t i = r0; i <= r1; ++i) + { + z[i] = (a * x[i]) + (b * y[i]); + } + + return T(1); + } + }; + + template + class dot : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::scalar_view scalar_t; + typedef typename generic_type::vector_view vector_t; + + using exprtk::igeneric_function::operator(); + + dot() + : exprtk::igeneric_function("VV|VVTT") + /* + Overloads: + 0. VV - x(vector), y(vector) + 1. VVTT - x(vector), y(vector), r0, r1 + */ + {} + + inline T operator()(const std::size_t& ps_index, parameter_list_t parameters) + { + vector_t x(parameters[0]); + vector_t y(parameters[1]); + + std::size_t r0 = 0; + std::size_t r1 = std::min(x.size(),y.size()) - 1; + + if ((1 == ps_index) && !details::load_vector_range::process(parameters,r0,r1,2,3)) + return std::numeric_limits::quiet_NaN(); + else if (details::invalid_range(x,r0,r1)) + return std::numeric_limits::quiet_NaN(); + else if (details::invalid_range(y,r0,r1)) + return std::numeric_limits::quiet_NaN(); + + T result = T(0); + + for (std::size_t i = r0; i <= r1; ++i) + { + result += (x[i] * y[i]); + } + + return result; + } + }; + + template + class dotk : public exprtk::igeneric_function + { + public: + + typedef typename exprtk::igeneric_function igfun_t; + typedef typename igfun_t::parameter_list_t parameter_list_t; + typedef typename igfun_t::generic_type generic_type; + typedef typename generic_type::scalar_view scalar_t; + typedef typename generic_type::vector_view vector_t; + + using exprtk::igeneric_function::operator(); + + dotk() + : exprtk::igeneric_function("VV|VVTT") + /* + Overloads: + 0. VV - x(vector), y(vector) + 1. VVTT - x(vector), y(vector), r0, r1 + */ + {} + + inline T operator()(const std::size_t& ps_index, parameter_list_t parameters) + { + vector_t x(parameters[0]); + vector_t y(parameters[1]); + + std::size_t r0 = 0; + std::size_t r1 = std::min(x.size(),y.size()) - 1; + + if ((1 == ps_index) && !details::load_vector_range::process(parameters,r0,r1,2,3)) + return std::numeric_limits::quiet_NaN(); + else if (details::invalid_range(x,r0,r1)) + return std::numeric_limits::quiet_NaN(); + else if (details::invalid_range(y,r0,r1)) + return std::numeric_limits::quiet_NaN(); + + T result = T(0); + T error = T(0); + + for (std::size_t i = r0; i <= r1; ++i) + { + details::kahan_sum(result,error,(x[i] * y[i])); + } + + return result; + } + }; + + template + struct package + { + all_true at; + all_false af; + any_true nt; + any_false nf; + count c; + copy cp; + rol rl; + ror rr; + shift_left sl; + shift_right sr; + sort st; + sumk sk; + axpy b1_axpy; + axpby b1_axpby; + axpyz b1_axpyz; + axpbyz b1_axpbyz; + dot dt; + dotk dtk; + + bool register_package(exprtk::symbol_table& symtab) + { + if (!symtab.add_function("all_true" ,at)) + return false; + else if (!symtab.add_function("all_false" ,af)) + return false; + else if (!symtab.add_function("any_true" ,nt)) + return false; + else if (!symtab.add_function("any_false" ,nf)) + return false; + else if (!symtab.add_function("count" , c)) + return false; + else if (!symtab.add_function("copy" , cp)) + return false; + else if (!symtab.add_function("rotate_left" ,rl)) + return false; + else if (!symtab.add_function("rol" ,rl)) + return false; + else if (!symtab.add_function("rotate_right" ,rr)) + return false; + else if (!symtab.add_function("ror" ,rr)) + return false; + else if (!symtab.add_function("shftl" ,sl)) + return false; + else if (!symtab.add_function("shftr" ,sr)) + return false; + else if (!symtab.add_function("sort" ,st)) + return false; + else if (!symtab.add_function("sumk" ,sk)) + return false; + else if (!symtab.add_function("axpy" ,b1_axpy)) + return false; + else if (!symtab.add_function("axpby" ,b1_axpby)) + return false; + else if (!symtab.add_function("axpyz" ,b1_axpyz)) + return false; + else if (!symtab.add_function("axpbyz",b1_axpbyz)) + return false; + else if (!symtab.add_function("dot" ,dt)) + return false; + else if (!symtab.add_function("dotk" ,dtk)) + return false; + else + return true; + } + }; + + } // namespace exprtk::rtl::vecops + } // namespace exprtk::rtl +} // namespace exprtk +#endif + namespace exprtk { namespace information diff --git a/exprtk_test.cpp b/exprtk_test.cpp index d161ca8..d3d62a6 100644 --- a/exprtk_test.cpp +++ b/exprtk_test.cpp @@ -6462,6 +6462,133 @@ inline bool run_test18() return false; } + { + bool failure = false; + + typedef exprtk::symbol_table symbol_table_t; + typedef exprtk::expression expression_t; + typedef exprtk::parser parser_t; + + exprtk::rtl::vecops::package vecops_pkg; + + symbol_table_t symbol_table; + symbol_table.add_package(vecops_pkg); + + std::string expr_str_list[] = + { + "var v[9] := {1,2,3,4,5,6,7,8,9}; all_true(v) == true" , + "var v[6] := {-1,-2,-3,-4,-5,-6}; all_true(v) == true" , + "var v[8] := {1,2,3,0,0,0,0,0}; all_true(v) == false", + "var v[8] := {-1,-2,-3,0,0,0,0,0}; all_true(v) == false", + "var v[9] := {0,0,0,0,0,0,0,0,0}; all_true(v + 1) == true", + + "var v[9] := {0,0,0,0,0,0,0,0,0}; all_false(v) == true" , + "var v[9] := {0,0,0,0,0,1,2,3,4}; all_false(v) == false" , + "var v[8] := {0,0,0,0,0,-1,-2,-3}; all_false(v) == false" , + "var v[9] := {1,1,1,1,1,1,1,1,1}; any_false(v - 1) == true", + + "var v[9] := {0,0,0,0,0,0,0,0,1}; any_true(v) == true" , + "var v[9] := {0,0,0,0,1,0,0,0,0}; any_true(v) == true" , + "var v[9] := {0,0,0,0,0,0,0,0,0}; any_true(v) == false" , + "var v[9] := {0,0,0,0,0,0,0,0,0}; any_true(v + 1) == true", + + "var v[9] := {1,1,1,1,1,1,1,1,0}; any_false(v) == true" , + "var v[9] := {1,1,1,1,0,1,1,1,1}; any_false(v) == true" , + "var v[9] := {1,1,1,1,1,1,1,1,1}; any_false(v) == false" , + "var v[9] := {1,1,1,1,1,1,1,1,1}; any_false(v - 1) == true", + + "var v[9] := {0,0,0,0,0,0,0,0,0}; count(v) == 0" , + "var v[9] := {0,0,0,0,0,0,0,0,1}; count(v) == 1" , + "var v[9] := {0,0,0,0,0,0,0,2,1}; count(v) == 2" , + "var v[9] := {0,0,0,0,0,0,3,2,1}; count(v) == 3" , + "var v[9] := {0,0,0,0,0,0,0,0,0}; count(v + 1) == v[]", + "var v[9] := {1,1,1,1,1,1,1,1,1}; count(v - 1) == 0", + + "var v[9] := {1,2,3,4,5,6,7,8,9}; var r[9] := [0]; copy(v,r); sum(v == r) == v[]", + "var v[9] := {1,2,3,4,5,6,7,8,9}; var r[9] := [0]; copy(v,0,8,r,0,8); sum(r) == 45", + "var v[9] := {1,2,3,4,5,6,7,8,9}; var r[9] := [0]; copy(v,1,7,r,1,7); sum(r) == 35", + "var v[9] := {1,2,3,4,5,6,7,8,9}; var r[5] := [0]; copy(v,0,4,r,0,4); sum(r) == 15", + + "var v[5] := {1,2,3,4,5}; var r[5] := {4,5,1,2,3}; rol(v,3); sum(v == r) == v[]", + "var v[5] := {1,2,3,4,5}; var r[5] := {3,4,5,1,2}; ror(v,3); sum(v == r) == v[]", + + "var v[5] := {1,2,3,4,5}; var r[5] := {3,4,5,1,2}; rol(v,2); sum(v == r) == v[]", + "var v[5] := {1,2,3,4,5}; var r[5] := {4,5,1,2,3}; ror(v,2); sum(v == r) == v[]", + + "var v[5] := {1,2,3,4,5}; var r[5] := {1,3,4,2,5}; rol(v,1,1,3); sum(v == r) == v[]", + "var v[5] := {1,2,3,4,5}; var r[5] := {1,4,2,3,5}; ror(v,1,1,3); sum(v == r) == v[]", + + "var v[5] := {1,2,3,4,5}; var r[5] := {3,4,5,0,0}; shftl(v,2); sum(v == r) == v[]", + "var v[5] := {1,2,3,4,5}; var r[5] := {5,0,0,0,0}; shftl(v,4); sum(v == r) == v[]", + "var v[5] := {1,2,3,4,5}; var r[5] := {0,0,0,0,0}; shftl(v,5); sum(v == r) == v[]", + + "var v[5] := {1,2,3,4,5}; var r[5] := {0,0,1,2,3}; shftr(v,2); sum(v == r) == v[]", + "var v[5] := {1,2,3,4,5}; var r[5] := {0,0,0,0,1}; shftr(v,4); sum(v == r) == v[]", + "var v[5] := {1,2,3,4,5}; var r[5] := {0,0,0,0,0}; shftr(v,5); sum(v == r) == v[]", + + "var v[5] := {1,2,3,4,5}; var r[5] := {1,3,4,0,5}; shftl(v,1,1,3); sum(v == r) == v[]", + "var v[5] := {1,2,3,4,5}; var r[5] := {1,0,2,3,5}; shftr(v,1,1,3); sum(v == r) == v[]", + + "var v[5] := {1,3,5,2,4}; var r[5] := {1,2,3,4,5}; sort(v); sum(v == r) == v[]", + "var v[5] := {5,4,3,2,1}; var r[5] := {1,2,3,4,5}; sort(v); sum(v == r) == v[]", + "var v[5] := {1,4,2,3,5}; var r[5] := {1,2,3,4,5}; sort(v,1,3); sum(v == r) == v[]", + "var v[5] := {3,1,2,4,5}; var r[5] := {1,2,3,4,5}; sort(v,0,2); sum(v == r) == v[]", + "var v[5] := {1,2,5,3,4}; var r[5] := {1,2,3,4,5}; sort(v,2,4); sum(v == r) == v[]", + + "var v[5] := {1,3,5,2,4}; var r[5] := {1,2,3,4,5}; sort(v,'ascending'); sum(v == r) == v[]", + "var v[5] := {5,4,3,2,1}; var r[5] := {1,2,3,4,5}; sort(v,'ascending'); sum(v == r) == v[]", + "var v[5] := {1,4,2,3,5}; var r[5] := {1,2,3,4,5}; sort(v,'ascending',1,3); sum(v == r) == v[]", + "var v[5] := {3,1,2,4,5}; var r[5] := {1,2,3,4,5}; sort(v,'ascending',0,2); sum(v == r) == v[]", + "var v[5] := {1,2,5,3,4}; var r[5] := {1,2,3,4,5}; sort(v,'ascending',2,4); sum(v == r) == v[]", + + "var v[5] := {1,3,5,2,4}; var r[5] := {5,4,3,2,1}; sort(v,'descending'); sum(v == r) == v[]", + "var v[5] := {5,4,3,2,1}; var r[5] := {5,4,3,2,1}; sort(v,'descending'); sum(v == r) == v[]", + "var v[5] := {1,4,2,3,5}; var r[5] := {1,4,3,2,5}; sort(v,'descending',1,3); sum(v == r) == v[]", + "var v[5] := {3,1,2,4,5}; var r[5] := {3,2,1,4,5}; sort(v,'descending',0,2); sum(v == r) == v[]", + "var v[5] := {1,2,5,3,4}; var r[5] := {1,2,5,4,3}; sort(v,'descending',2,4); sum(v == r) == v[]", + + " var a := 2; var x[3] := {1,2,3}; var y[3] := {1,2,3}; var r[3] := [0]; r := a*x+y; axpy(a,x,y); sum(y == r) == y[]", + " var a := 2; var b := 3; var x[3] := {1,2,3}; var y[3] := {1,2,3}; var r[3] := [0]; r := a*x+b*y; axpby(a,x,b,y); sum(y == r) == y[]", + + " var a := 2; var x[3] := {1,2,3}; var y[3] := {1,2,3}; var z[3] := [0]; var r[3] := [0]; r := a*x+y; axpyz(a,x,y,z); sum(z == r) == z[]", + " var a := 2; var b := 3; var x[3] := {1,2,3}; var y[3] := {1,2,3}; var z[3] := [0]; var r[3] := [0]; r := a*x+b*y; axpbyz(a,x,b,y,z); sum(z == r) == z[]", + }; + + const std::size_t expr_str_list_size = sizeof(expr_str_list) / sizeof(std::string); + + parser_t parser; + + for (std::size_t i = 0; i < expr_str_list_size; ++i) + { + expression_t expression; + expression.register_symbol_table(symbol_table); + + if (!parser.compile(expr_str_list[i], expression)) + { + printf("run_test18() - Error: %s Expression: %s\n", + parser.error().c_str(), + expr_str_list[i].c_str()); + + failure = true; + + continue; + } + + T result = expression.value(); + + if (result != T(1)) + { + printf("run_test18() - Error in evaluation! (10) Expression: %s\n", + expr_str_list[i].c_str()); + + failure = true; + } + } + + if (failure) + return false; + } + return true; } diff --git a/readme.txt b/readme.txt index eb17d2d..ce00678 100644 --- a/readme.txt +++ b/readme.txt @@ -3028,6 +3028,12 @@ 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. +(9) exprtk_disable_rtl_vecops +This define will disable the extended vector operations RTL package +features. When present, any attempts to register the vector operations +package with a given symbol table will fail causing a compilation +error. + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [23 - FILES]