From 4bae39ed67e7128f9c7196f7702e9fe86f1e0591 Mon Sep 17 00:00:00 2001 From: Arash Partow Date: Thu, 29 Sep 2016 08:53:05 +1000 Subject: [PATCH] C++ Mathematical Expression Library (ExprTk) https://www.partow.net/programming/exprtk/index.html --- exprtk.hpp | 154 +++++++++++++++++++++++++++++++++++++++++++++++- exprtk_test.cpp | 139 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 292 insertions(+), 1 deletion(-) diff --git a/exprtk.hpp b/exprtk.hpp index 8320539..4cce6f4 100644 --- a/exprtk.hpp +++ b/exprtk.hpp @@ -3919,6 +3919,81 @@ namespace exprtk }; } + template + class vector_view + { + public: + + typedef T* data_ptr_t; + + vector_view(data_ptr_t data, const std::size_t& size) + : size_(size), + data_(data), + data_ref_(0) + {} + + vector_view(const vector_view& vv) + : size_(vv.size_), + data_(vv.data_), + data_ref_(0) + {} + + inline void rebase(data_ptr_t data) + { + data_ = data; + + if (data_ref_) + { + (*data_ref_) = data; + } + } + + inline data_ptr_t data() const + { + return data_; + } + + inline std::size_t size() const + { + return size_; + } + + inline const T& operator[](const std::size_t index) const + { + return data_[index]; + } + + inline T& operator[](const std::size_t index) + { + return data_[index]; + } + + void set_ref(data_ptr_t* data_ref) + { + data_ref_ = data_ref; + } + + private: + + std::size_t size_; + data_ptr_t data_; + data_ptr_t* data_ref_; + }; + + template + inline vector_view make_vector_view(T* data, + const std::size_t size, const std::size_t offset = 0) + { + return vector_view(data + offset,size); + } + + template + inline vector_view make_vector_view(std::vector& v, + const std::size_t size, const std::size_t offset = 0) + { + return vector_view(v.data() + offset,size); + } + template class results_context; template @@ -4442,6 +4517,11 @@ namespace exprtk return control_block_->size; } + inline data_t& ref() + { + return control_block_->data; + } + inline void dump() const { #ifdef exprtk_enable_debugging @@ -4983,6 +5063,8 @@ namespace exprtk return value_at(0); } + virtual void set_ref(value_ptr*) {} + protected: virtual value_ptr value_at(const std::size_t&) const = 0; @@ -5052,6 +5134,40 @@ namespace exprtk sequence_t& sequence_; }; + class vector_view_impl : public vector_holder_base + { + public: + + typedef exprtk::vector_view vector_view_t; + + vector_view_impl(vector_view_t& vec_view) + : vec_view_(vec_view) + {} + + void set_ref(value_ptr* ref) + { + vec_view_.set_ref(ref); + } + + protected: + + value_ptr value_at(const std::size_t& index) const + { + return (index < vec_view_.size()) ? (&vec_view_[index]) : const_value_ptr(0); + } + + std::size_t vector_size() const + { + return vec_view_.size(); + } + + private: + + vector_view_impl operator=(const vector_view_impl&); + + vector_view_t& vec_view_; + }; + public: typedef typename details::vec_data_store vds_t; @@ -5069,6 +5185,10 @@ namespace exprtk : vector_holder_base_(new(buffer)sequence_vector_impl(vec)) {} + vector_holder(exprtk::vector_view& vec) + : vector_holder_base_(new(buffer)vector_view_impl(vec)) + {} + inline value_ptr operator[](const std::size_t& index) const { return (*vector_holder_base_)[index]; @@ -5084,6 +5204,11 @@ namespace exprtk return vector_holder_base_->data(); } + void set_ref(value_ptr* ref) + { + return vector_holder_base_->set_ref(ref); + } + private: mutable vector_holder_base* vector_holder_base_; @@ -6666,7 +6791,9 @@ namespace exprtk vector_node(vector_holder_t* vh) : vector_holder_(vh), vds_((*vector_holder_).size(),(*vector_holder_)[0]) - {} + { + vector_holder_->set_ref(&vds_.ref()); + } vector_node(const vds_t& vds, vector_holder_t* vh) : vector_holder_(vh), @@ -15382,6 +15509,14 @@ namespace exprtk } }; + struct tie_vecview + { + static inline std::pair make(exprtk::vector_view& v, const bool is_const = false) + { + return std::make_pair(is_const,new vector_t(v)); + } + }; + struct tie_stddeq { template @@ -15408,6 +15543,11 @@ namespace exprtk return add_impl&>(symbol_name,v,is_const); } + inline bool add(const std::string& symbol_name, exprtk::vector_view& v, const bool is_const = false) + { + return add_impl&>(symbol_name,v,is_const); + } + template inline bool add(const std::string& symbol_name, std::deque& v, const bool is_const = false) { @@ -16268,6 +16408,18 @@ namespace exprtk return local_data().vector_store.add(vector_name,v); } + inline bool add_vector(const std::string& vector_name, exprtk::vector_view& v) + { + if (!valid()) + return false; + else if (!valid_symbol(vector_name)) + return false; + else if (symbol_exists(vector_name)) + return false; + else + return local_data().vector_store.add(vector_name,v); + } + inline bool remove_variable(const std::string& variable_name, const bool delete_node = true) { if (!valid()) diff --git a/exprtk_test.cpp b/exprtk_test.cpp index 10dba03..b2c1d74 100644 --- a/exprtk_test.cpp +++ b/exprtk_test.cpp @@ -1796,6 +1796,7 @@ inline bool run_test01() for (std::size_t r = 0; r < rounds; ++r) { bool loop_result = true; + for (std::size_t i = 0; i < expr_list_size; ++i) { T v[] = { T(0.0), T(1.1), T(2.2), T(3.3), T(4.4), T(5.5) }; @@ -1832,6 +1833,66 @@ inline bool run_test01() T result = expression.value(); + if (not_equal(result,T(1))) + { + printf("run_test01() - Computation Error: Expression: [%s]\tExpected: %19.15f\tResult: %19.15f\n", + expr_list[i].c_str(), + (double)1.0, + (double)result); + + loop_result = false; + } + } + + if (!loop_result) + { + return false; + } + } + + for (std::size_t r = 0; r < rounds; ++r) + { + bool loop_result = true; + + for (std::size_t i = 0; i < expr_list_size; ++i) + { + T v_[] = { T(0.0), T(1.1), T(2.2), T(3.3), T(4.4), T(5.5) }; + T index_[] = { T(0) , T(1) , T(2) , T(3) , T(4) , T(5) }; + + T x = T(6.6); + T y = T(7.7); + T z = T(8.8); + + exprtk::vector_view v = exprtk::make_vector_view(v_ ,6); + exprtk::vector_view index = exprtk::make_vector_view(index_,6); + + exprtk::symbol_table symbol_table; + symbol_table.add_variable("x",x); + symbol_table.add_variable("y",y); + symbol_table.add_variable("z",z); + symbol_table.add_vector ("v",v); + symbol_table.add_vector ("i",index); + + exprtk::expression expression; + expression.register_symbol_table(symbol_table); + + { + exprtk::parser parser; + + if (!parser.compile(expr_list[i],expression)) + { + printf("run_test01() - Error: %s Expression: %s\n", + parser.error().c_str(), + expr_list[i].c_str()); + + loop_result = false; + + continue; + } + } + + T result = expression.value(); + if (not_equal(result,T(1))) { printf("run_test01() - Computation Error: Expression: [%s]\tExpected: %19.15f\tResult: %19.15f\n", @@ -6125,6 +6186,84 @@ 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; + + std::vector v0 { 0, 0, 0, 0, 0, 0, 0 }; + std::vector v1 { 0, 2, 4, 6, 8, 10, 12 }; + std::vector v2 { 1, 3, 5, 7, 9, 11, 13 }; + std::vector v3 { 0, 1, 2, 3, 4, 5, 6 }; + + const std::string expr_string = "sum(v + 1)"; + + exprtk::vector_view v = exprtk::make_vector_view(v0,v0.size()); + + symbol_table_t symbol_table; + symbol_table.add_vector("v",v); + + expression_t expression; + expression.register_symbol_table(symbol_table); + + parser_t parser; + + if (!parser.compile(expr_string,expression)) + { + printf("run_test18() - Error: %s\tExpression: %s\n", + parser.error().c_str(), + expr_string.c_str()); + + failure = true; + } + + T sum = { T(0) }; + + sum = expression.value(); + + if (not_equal(sum,T(7))) + { + printf("run_test18() - Error in evaluation! (6) Expression: %s\n", + expr_string.c_str()); + failure = true; + } + + v.rebase(v1.data()); + sum = expression.value(); + + if (not_equal(sum,T(49))) + { + printf("run_test18() - Error in evaluation! (7) Expression: %s\n", + expr_string.c_str()); + failure = true; + } + + v.rebase(v2.data()); + sum = expression.value(); + + if (not_equal(sum,T(56))) + { + printf("run_test18() - Error in evaluation! (8) Expression: %s\n", + expr_string.c_str()); + failure = true; + } + + v.rebase(v3.data()); + sum = expression.value(); + + if (not_equal(sum,T(28))) + { + printf("run_test18() - Error in evaluation! (9) Expression: %s\n", + expr_string.c_str()); + failure = true; + } + + if (failure) + return false; + } + return true; }