diff --git a/Makefile b/Makefile index 03d8c68..7ac66d1 100644 --- a/Makefile +++ b/Makefile @@ -24,6 +24,15 @@ LINKER_OPT = -L/usr/lib -lstdc++ BUILD_LIST+=exprtk_test BUILD_LIST+=exprtk_benchmark +BUILD_LIST+=exprtk_simple_example_01 +BUILD_LIST+=exprtk_simple_example_02 +BUILD_LIST+=exprtk_simple_example_03 +BUILD_LIST+=exprtk_simple_example_04 +BUILD_LIST+=exprtk_simple_example_05 +BUILD_LIST+=exprtk_simple_example_06 +BUILD_LIST+=exprtk_simple_example_07 +BUILD_LIST+=exprtk_simple_example_08 +BUILD_LIST+=exprtk_simple_example_09 all: $(BUILD_LIST) @@ -33,6 +42,33 @@ exprtk_test: exprtk_test.cpp exprtk.hpp exprtk_benchmark: exprtk_benchmark.cpp exprtk.hpp $(COMPILER) $(OPTIONS) exprtk_benchmark exprtk_benchmark.cpp $(LINKER_OPT) +exprtk_simple_example_01: exprtk_simple_example_01.cpp exprtk.hpp + $(COMPILER) $(OPTIONS) exprtk_simple_example_01 exprtk_simple_example_01.cpp $(LINKER_OPT) + +exprtk_simple_example_02: exprtk_simple_example_02.cpp exprtk.hpp + $(COMPILER) $(OPTIONS) exprtk_simple_example_02 exprtk_simple_example_02.cpp $(LINKER_OPT) + +exprtk_simple_example_03: exprtk_simple_example_03.cpp exprtk.hpp + $(COMPILER) $(OPTIONS) exprtk_simple_example_03 exprtk_simple_example_03.cpp $(LINKER_OPT) + +exprtk_simple_example_04: exprtk_simple_example_04.cpp exprtk.hpp + $(COMPILER) $(OPTIONS) exprtk_simple_example_04 exprtk_simple_example_04.cpp $(LINKER_OPT) + +exprtk_simple_example_05: exprtk_simple_example_05.cpp exprtk.hpp + $(COMPILER) $(OPTIONS) exprtk_simple_example_05 exprtk_simple_example_05.cpp $(LINKER_OPT) + +exprtk_simple_example_06: exprtk_simple_example_06.cpp exprtk.hpp + $(COMPILER) $(OPTIONS) exprtk_simple_example_06 exprtk_simple_example_06.cpp $(LINKER_OPT) + +exprtk_simple_example_07: exprtk_simple_example_07.cpp exprtk.hpp + $(COMPILER) $(OPTIONS) exprtk_simple_example_07 exprtk_simple_example_07.cpp $(LINKER_OPT) + +exprtk_simple_example_08: exprtk_simple_example_08.cpp exprtk.hpp + $(COMPILER) $(OPTIONS) exprtk_simple_example_08 exprtk_simple_example_08.cpp $(LINKER_OPT) + +exprtk_simple_example_09: exprtk_simple_example_09.cpp exprtk.hpp + $(COMPILER) $(OPTIONS) exprtk_simple_example_09 exprtk_simple_example_09.cpp $(LINKER_OPT) + pgo: exprtk_test.cpp exprtk_benchmark.cpp exprtk.hpp $(COMPILER) $(BASE_OPTIONS) -O3 -march=native -fprofile-generate -o exprtk_benchmark exprtk_benchmark.cpp $(LINKER_OPT) ./exprtk_benchmark @@ -41,10 +77,28 @@ pgo: exprtk_test.cpp exprtk_benchmark.cpp exprtk.hpp strip_bin: strip -s exprtk_test strip -s exprtk_benchmark + strip -s exprtk_simple_example_01 + strip -s exprtk_simple_example_02 + strip -s exprtk_simple_example_03 + strip -s exprtk_simple_example_04 + strip -s exprtk_simple_example_05 + strip -s exprtk_simple_example_06 + strip -s exprtk_simple_example_07 + strip -s exprtk_simple_example_08 + strip -s exprtk_simple_example_09 valgrind_check: valgrind --leak-check=full --show-reachable=yes --track-origins=yes -v ./exprtk_test valgrind --leak-check=full --show-reachable=yes --track-origins=yes -v ./exprtk_benchmark + valgrind --leak-check=full --show-reachable=yes --track-origins=yes -v ./exprtk_simple_example_01 + valgrind --leak-check=full --show-reachable=yes --track-origins=yes -v ./exprtk_simple_example_02 + valgrind --leak-check=full --show-reachable=yes --track-origins=yes -v ./exprtk_simple_example_03 + valgrind --leak-check=full --show-reachable=yes --track-origins=yes -v ./exprtk_simple_example_04 + valgrind --leak-check=full --show-reachable=yes --track-origins=yes -v ./exprtk_simple_example_05 + valgrind --leak-check=full --show-reachable=yes --track-origins=yes -v ./exprtk_simple_example_06 + valgrind --leak-check=full --show-reachable=yes --track-origins=yes -v ./exprtk_simple_example_07 + valgrind --leak-check=full --show-reachable=yes --track-origins=yes -v ./exprtk_simple_example_08 + valgrind --leak-check=full --show-reachable=yes --track-origins=yes -v ./exprtk_simple_example_09 clean: rm -f core.* *~ *.o *.bak *stackdump gmon.out *.gcda *.gcno *.gcnor *.gch diff --git a/exprtk.hpp b/exprtk.hpp index 3da79e0..d604573 100644 --- a/exprtk.hpp +++ b/exprtk.hpp @@ -121,6 +121,7 @@ namespace exprtk ('.' != c) && ('_' != c) && ('$' != c) && + ('~' != c) && ('\'' != c); } @@ -1674,6 +1675,14 @@ namespace exprtk return; } #endif + else if ('~' == (*s_itr_)) + { + token_t t; + t.set_symbol(s_itr_,s_itr_ + 1,base_itr_); + token_list_.push_back(t); + ++s_itr_; + return; + } else { token_t t; @@ -2768,7 +2777,7 @@ namespace exprtk e_r2d , e_d2r , e_d2g , e_g2d , e_hypot , e_notl , e_erf , e_erfc , e_frac , e_trunc , e_assign , e_in , - e_like , e_ilike , + e_like , e_ilike , e_multi , // Do not add new functions/operators after this point. e_sf00 = 1000, e_sf01 = 1001, e_sf02 = 1002, e_sf03 = 1003, @@ -5591,6 +5600,84 @@ namespace exprtk } }; + template + struct vararg_multi_op : public opr_base + { + typedef typename opr_base::Type Type; + + template class Sequence> + static inline T process(const Sequence& arglist) + { + if (arglist.size() > 5) + { + if (arglist.empty()) + return std::numeric_limits::quiet_NaN(); + else + { + for (std::size_t i = 0; i < (arglist.size() - 1); ++i) + { + value(arglist[i]); + } + } + return value(arglist.back()); + } + else + { + switch (arglist.size()) + { + case 1 : return process_1(arglist); + case 2 : return process_2(arglist); + case 3 : return process_3(arglist); + case 4 : return process_4(arglist); + case 5 : return process_5(arglist); + default : return std::numeric_limits::quiet_NaN(); + } + } + } + + template + static inline T process_1(const Sequence& arglist) + { + return value(arglist[0]); + } + + template + static inline T process_2(const Sequence& arglist) + { + value(arglist[0]); + return value(arglist[1]); + } + + template + static inline T process_3(const Sequence& arglist) + { + value(arglist[0]); + value(arglist[1]); + return value(arglist[2]); + } + + template + static inline T process_4(const Sequence& arglist) + { + value(arglist[0]); + value(arglist[1]); + value(arglist[2]); + return value(arglist[3]); + } + + template + static inline T process_5(const Sequence& arglist) + { + value(arglist[0]); + value(arglist[1]); + value(arglist[2]); + value(arglist[3]); + return value(arglist[4]); + } + }; + template class vov_base_node : public expression_node { @@ -9614,22 +9701,24 @@ namespace exprtk inline bool valid_vararg_operation(const std::string& symbol) { - static const std::string s_sum = "sum" ; - static const std::string s_mul = "mul" ; - static const std::string s_avg = "avg" ; - static const std::string s_min = "min" ; - static const std::string s_max = "max" ; - static const std::string s_mand = "mand"; - static const std::string s_mor = "mor" ; + static const std::string s_sum = "sum" ; + static const std::string s_mul = "mul" ; + static const std::string s_avg = "avg" ; + static const std::string s_min = "min" ; + static const std::string s_max = "max" ; + static const std::string s_mand = "mand"; + static const std::string s_mor = "mor" ; + static const std::string s_multi = "~" ; return ( - details::imatch(symbol,s_sum ) || - details::imatch(symbol,s_mul ) || - details::imatch(symbol,s_avg ) || - details::imatch(symbol,s_min ) || - details::imatch(symbol,s_max ) || - details::imatch(symbol,s_mand) || - details::imatch(symbol,s_mor ) + details::imatch(symbol,s_sum ) || + details::imatch(symbol,s_mul ) || + details::imatch(symbol,s_avg ) || + details::imatch(symbol,s_min ) || + details::imatch(symbol,s_max ) || + details::imatch(symbol,s_mand ) || + details::imatch(symbol,s_mor ) || + details::imatch(symbol,s_multi) ); } @@ -10290,6 +10379,7 @@ namespace exprtk else if (details::imatch(symbol,"max" )) opt_type = details::e_max; else if (details::imatch(symbol,"mand")) opt_type = details::e_mand; else if (details::imatch(symbol,"mor" )) opt_type = details::e_mor; + else if (details::imatch(symbol,"~" )) opt_type = details::e_multi; else { set_error( @@ -11679,13 +11769,14 @@ namespace exprtk switch (operation) { #define case_stmt(op0,op1) case op0 : temp_node = node_allocator_->allocate > >(arglist); break; - case_stmt(details::e_sum, details::vararg_add_op ) - case_stmt(details::e_prod, details::vararg_mul_op ) - case_stmt(details::e_avg, details::vararg_avg_op ) - case_stmt(details::e_min, details::vararg_min_op ) - case_stmt(details::e_max, details::vararg_max_op ) - case_stmt(details::e_mand, details::vararg_mand_op) - case_stmt(details::e_mor, details::vararg_mor_op ) + case_stmt(details::e_sum, details::vararg_add_op ) + case_stmt(details::e_prod, details::vararg_mul_op ) + case_stmt(details::e_avg, details::vararg_avg_op ) + case_stmt(details::e_min, details::vararg_min_op ) + case_stmt(details::e_max, details::vararg_max_op ) + case_stmt(details::e_mand, details::vararg_mand_op ) + case_stmt(details::e_mor, details::vararg_mor_op ) + case_stmt(details::e_multi,details::vararg_multi_op) #undef case_stmt default : return error_node(); } @@ -11701,13 +11792,14 @@ namespace exprtk switch (operation) { #define case_stmt(op0,op1) case op0 : return node_allocator_->allocate > >(arglist); - case_stmt(details::e_sum, details::vararg_add_op ) - case_stmt(details::e_prod, details::vararg_mul_op ) - case_stmt(details::e_avg, details::vararg_avg_op ) - case_stmt(details::e_min, details::vararg_min_op ) - case_stmt(details::e_max, details::vararg_max_op ) - case_stmt(details::e_mand, details::vararg_mand_op) - case_stmt(details::e_mor, details::vararg_mor_op ) + case_stmt(details::e_sum, details::vararg_add_op ) + case_stmt(details::e_prod, details::vararg_mul_op ) + case_stmt(details::e_avg, details::vararg_avg_op ) + case_stmt(details::e_min, details::vararg_min_op ) + case_stmt(details::e_max, details::vararg_max_op ) + case_stmt(details::e_mand, details::vararg_mand_op ) + case_stmt(details::e_mor, details::vararg_mor_op ) + case_stmt(details::e_multi,details::vararg_multi_op) #undef case_stmt default : return error_node(); } @@ -11729,13 +11821,14 @@ namespace exprtk switch (operation) { #define case_stmt(op0,op1) case op0 : return node_allocator_->allocate > >(arglist); - case_stmt(details::e_sum, details::vararg_add_op ) - case_stmt(details::e_prod, details::vararg_mul_op ) - case_stmt(details::e_avg, details::vararg_avg_op ) - case_stmt(details::e_min, details::vararg_min_op ) - case_stmt(details::e_max, details::vararg_max_op ) - case_stmt(details::e_mand, details::vararg_mand_op) - case_stmt(details::e_mor, details::vararg_mor_op ) + case_stmt(details::e_sum, details::vararg_add_op ) + case_stmt(details::e_prod, details::vararg_mul_op ) + case_stmt(details::e_avg, details::vararg_avg_op ) + case_stmt(details::e_min, details::vararg_min_op ) + case_stmt(details::e_max, details::vararg_max_op ) + case_stmt(details::e_mand, details::vararg_mand_op ) + case_stmt(details::e_mor, details::vararg_mor_op ) + case_stmt(details::e_multi,details::vararg_multi_op) #undef case_stmt default : return error_node(); } diff --git a/exprtk_simple_example_01.cpp b/exprtk_simple_example_01.cpp new file mode 100644 index 0000000..700d902 --- /dev/null +++ b/exprtk_simple_example_01.cpp @@ -0,0 +1,50 @@ +/* + ************************************************************** + * C++ Mathematical Expression Toolkit Library * + * * + * Simple Example 1 * + * Author: Arash Partow (1999-2013) * + * URL: http://www.partow.net/programming/exprtk/index.html * + * * + * Copyright notice: * + * Free use of the Mathematical Expression Toolkit Library is * + * permitted under the guidelines and in accordance with the * + * most current version of the Common Public License. * + * http://www.opensource.org/licenses/cpl1.0.php * + * * + ************************************************************** +*/ + + +#include +#include +#include "exprtk.hpp" + + +template +void trig_function() +{ + std::string expression_string = "clamp(-1.0,sin(2 * pi * x) + cos(x / 2 * pi),+1.0)"; + T x; + exprtk::symbol_table symbol_table; + symbol_table.add_variable("x",x); + symbol_table.add_constants(); + + exprtk::expression expression; + expression.register_symbol_table(symbol_table); + + exprtk::parser parser; + parser.compile(expression_string,expression); + + for (x = T(-5.0); x <= T(+5.0); x += 0.001) + { + T y = expression.value(); + printf("%19.15f\t%19.15f\n",x,y); + } +} + +int main() +{ + trig_function(); + return 0; +} diff --git a/exprtk_simple_example_02.cpp b/exprtk_simple_example_02.cpp new file mode 100644 index 0000000..2ae670c --- /dev/null +++ b/exprtk_simple_example_02.cpp @@ -0,0 +1,64 @@ +/* + ************************************************************** + * C++ Mathematical Expression Toolkit Library * + * * + * Simple Example 2 * + * Author: Arash Partow (1999-2013) * + * URL: http://www.partow.net/programming/exprtk/index.html * + * * + * Copyright notice: * + * Free use of the Mathematical Expression Toolkit Library is * + * permitted under the guidelines and in accordance with the * + * most current version of the Common Public License. * + * http://www.opensource.org/licenses/cpl1.0.php * + * * + ************************************************************** +*/ + + +#include +#include +#include "exprtk.hpp" + + +template +void square_wave() +{ + std::string expr_string = "a*(4/pi)*" + "((1 /1)*sin( 2*pi*f*t)+(1 /3)*sin( 6*pi*f*t)+" + " (1 /5)*sin(10*pi*f*t)+(1 /7)*sin(14*pi*f*t)+" + " (1 /9)*sin(18*pi*f*t)+(1/11)*sin(22*pi*f*t)+" + " (1/13)*sin(26*pi*f*t)+(1/15)*sin(30*pi*f*t)+" + " (1/17)*sin(34*pi*f*t)+(1/19)*sin(38*pi*f*t)+" + " (1/21)*sin(42*pi*f*t)+(1/23)*sin(46*pi*f*t)+" + " (1/25)*sin(50*pi*f*t)+(1/27)*sin(54*pi*f*t))"; + static const T pi = T(3.14159265358979323846); + T f = pi/10.0; + T t = T(0.0); + T a = T(10.0); + + exprtk::symbol_table symbol_table; + symbol_table.add_variable("f",f); + symbol_table.add_variable("t",t); + symbol_table.add_variable("a",a); + symbol_table.add_constants(); + + exprtk::expression expression; + expression.register_symbol_table(symbol_table); + + exprtk::parser parser; + parser.compile(expr_string,expression); + + const T delta = (4.0*pi)/1000.0; + for (t = -2.0*pi; t <= +2.0*pi; t+=delta) + { + T result = expression.value(); + printf("%19.15f\t%19.15f\n",t,result); + } +} + +int main() +{ + square_wave(); + return 0; +} diff --git a/exprtk_simple_example_03.cpp b/exprtk_simple_example_03.cpp new file mode 100644 index 0000000..3f97659 --- /dev/null +++ b/exprtk_simple_example_03.cpp @@ -0,0 +1,52 @@ +/* + ************************************************************** + * C++ Mathematical Expression Toolkit Library * + * * + * Simple Example 3 * + * Author: Arash Partow (1999-2013) * + * URL: http://www.partow.net/programming/exprtk/index.html * + * * + * Copyright notice: * + * Free use of the Mathematical Expression Toolkit Library is * + * permitted under the guidelines and in accordance with the * + * most current version of the Common Public License. * + * http://www.opensource.org/licenses/cpl1.0.php * + * * + ************************************************************** +*/ + + +#include +#include +#include "exprtk.hpp" + + +template +void polynomial() +{ + std::string expression_string = "25x^5 - 35x^4 - 15x^3 + 40x^2 - 15x + 1"; + T r0 = T(0.0); + T r1 = T(1.0); + T x = T(0.0); + + exprtk::symbol_table symbol_table; + symbol_table.add_variable("x",x); + + exprtk::expression expression; + expression.register_symbol_table(symbol_table); + + exprtk::parser parser; + parser.compile(expression_string,expression); + + const T delta = T(1/100.0); + for (x = r0; x <= r1; x += delta) + { + printf("%19.15f\t%19.15f\n",x,expression.value()); + } +} + +int main() +{ + polynomial(); + return 0; +} diff --git a/exprtk_simple_example_04.cpp b/exprtk_simple_example_04.cpp new file mode 100644 index 0000000..983c2c8 --- /dev/null +++ b/exprtk_simple_example_04.cpp @@ -0,0 +1,87 @@ +/* + ************************************************************** + * C++ Mathematical Expression Toolkit Library * + * * + * Simple Example 4 * + * Author: Arash Partow (1999-2013) * + * URL: http://www.partow.net/programming/exprtk/index.html * + * * + * Copyright notice: * + * Free use of the Mathematical Expression Toolkit Library is * + * permitted under the guidelines and in accordance with the * + * most current version of the Common Public License. * + * http://www.opensource.org/licenses/cpl1.0.php * + * * + ************************************************************** +*/ + + +#include +#include +#include "exprtk.hpp" + + +template +void fibonacci() +{ + typedef exprtk::symbol_table symbol_table_t; + typedef exprtk::expression expression_t; + typedef exprtk::parser parser_t; + typedef exprtk::function_compositor compositor_t; + + compositor_t compositor; + + compositor + .add("fibonacci_impl", + "switch " + "{ " + " case x == 0 : 0; " + " case x == 1 : 1; " + " default : " + " while (~(x := (x - 1)) > 0)" + " {~ " + " ( " + " w := z, " + " z := z + y, " + " y := w, " + " z " + " ) " + " }; " + "} ", + "x","y","z","w"); + + compositor + .add("fibonacci", + "fibonacci_impl(x,0,1,0)", + "x"); + + T x = T(0); + + symbol_table_t& symbol_table = compositor.symbol_table(); + symbol_table.add_constants(); + symbol_table.add_variable("x",x); + + std::string expression_str = "fibonacci(x)"; + + expression_t expression; + expression.register_symbol_table(symbol_table); + + parser_t parser; + + parser.compile(expression_str,expression); + + for (std::size_t i = 0; i < 40; ++i) + { + x = i; + T result = expression.value(); + printf("fibonacci(%3d) = %10.0f\n", + static_cast(i), + result); + } +} + +int main() +{ + fibonacci(); + return 0; +} diff --git a/exprtk_simple_example_05.cpp b/exprtk_simple_example_05.cpp new file mode 100644 index 0000000..438deb5 --- /dev/null +++ b/exprtk_simple_example_05.cpp @@ -0,0 +1,66 @@ +/* + ************************************************************** + * C++ Mathematical Expression Toolkit Library * + * * + * Simple Example 5 * + * Author: Arash Partow (1999-2013) * + * URL: http://www.partow.net/programming/exprtk/index.html * + * * + * Copyright notice: * + * Free use of the Mathematical Expression Toolkit Library is * + * permitted under the guidelines and in accordance with the * + * most current version of the Common Public License. * + * http://www.opensource.org/licenses/cpl1.0.php * + * * + ************************************************************** +*/ + + +#include +#include +#include "exprtk.hpp" + + +template +struct myfunc : public exprtk::ifunction +{ + myfunc() + : exprtk::ifunction(2) + {} + + inline T operator()(const T& v1, const T& v2) + { + return T(1) + (v1 * v2) / T(3); + } +}; + +template +void custom_function() +{ + typedef exprtk::expression expression_t; + std::string expression_string = "myfunc(sin(x*pi),y/2)"; + T x = T(1.0); + T y = T(2.0); + myfunc mf; + + exprtk::symbol_table symbol_table; + symbol_table.add_variable("x",x); + symbol_table.add_variable("y",y); + symbol_table.add_function("myfunc",mf); + symbol_table.add_constants(); + + expression_t expression; + expression.register_symbol_table(symbol_table); + + exprtk::parser parser; + parser.compile(expression_string,expression); + + T result = expression.value(); + printf("Result: %10.5f\n",result); +} + +int main() +{ + custom_function(); + return 0; +} diff --git a/exprtk_simple_example_06.cpp b/exprtk_simple_example_06.cpp new file mode 100644 index 0000000..b771d25 --- /dev/null +++ b/exprtk_simple_example_06.cpp @@ -0,0 +1,63 @@ +/* + ************************************************************** + * C++ Mathematical Expression Toolkit Library * + * * + * Simple Example 6 * + * Author: Arash Partow (1999-2013) * + * URL: http://www.partow.net/programming/exprtk/index.html * + * * + * Copyright notice: * + * Free use of the Mathematical Expression Toolkit Library is * + * permitted under the guidelines and in accordance with the * + * most current version of the Common Public License. * + * http://www.opensource.org/licenses/cpl1.0.php * + * * + ************************************************************** +*/ + + +#include +#include +#include "exprtk.hpp" + + +template +void vector_function() +{ + typedef exprtk::expression expression_t; + std::string expression_string = "z := (3sin(x) + 2log(y))"; + + const std::size_t vec_size = 5; + + T x[vec_size] = { T(1.1), T(2.2), T(3.3), T(4.4), T(5.5) }; + T y[vec_size] = { T(1.1), T(2.2), T(3.3), T(4.4), T(5.5) }; + T z[vec_size] = { T(0.0), T(0.0), T(0.0), T(0.0), T(0.0) }; + + T x_ = x[0]; + T y_ = y[0]; + T z_ = z[0]; + + exprtk::symbol_table symbol_table; + symbol_table.add_variable("x",x_); + symbol_table.add_variable("y",y_); + symbol_table.add_variable("z",z_); + + expression_t expression; + expression.register_symbol_table(symbol_table); + + exprtk::parser parser; + parser.compile(expression_string,expression); + + for (std::size_t i = 0; i < vec_size; ++i) + { + x_ = x[i]; y_ = y[i]; z_ = z[i]; + expression.value(); + x[i] = x_; y[i] = y_; z[i] = z_; + } +} + +int main() +{ + vector_function(); + return 0; +} diff --git a/exprtk_simple_example_07.cpp b/exprtk_simple_example_07.cpp new file mode 100644 index 0000000..fd80643 --- /dev/null +++ b/exprtk_simple_example_07.cpp @@ -0,0 +1,67 @@ +/* + ************************************************************** + * C++ Mathematical Expression Toolkit Library * + * * + * Simple Example 7 * + * Author: Arash Partow (1999-2013) * + * URL: http://www.partow.net/programming/exprtk/index.html * + * * + * Copyright notice: * + * Free use of the Mathematical Expression Toolkit Library is * + * permitted under the guidelines and in accordance with the * + * most current version of the Common Public License. * + * http://www.opensource.org/licenses/cpl1.0.php * + * * + ************************************************************** +*/ + + +#include +#include +#include "exprtk.hpp" + + +template +void logic() +{ + typedef exprtk::expression expression_t; + std::string expression_string = "not(A and B) or C"; + + exprtk::symbol_table symbol_table; + symbol_table.create_variable("A"); + symbol_table.create_variable("B"); + symbol_table.create_variable("C"); + + expression_t expression; + expression.register_symbol_table(symbol_table); + + exprtk::parser parser; + parser.compile(expression_string,expression); + + printf(" # | A | B | C | %s\n" + "---+---+---+---+-%s\n", + expression_string.c_str(), + std::string(expression_string.size(),'-').c_str()); + + for (int i = 0; i < 8; ++i) + { + symbol_table.get_variable("A")->ref() = T(i & 0x01 ? 1 : 0); + symbol_table.get_variable("B")->ref() = T(i & 0x02 ? 1 : 0); + symbol_table.get_variable("C")->ref() = T(i & 0x04 ? 1 : 0); + + int result = static_cast(expression.value()); + + printf(" %d | %d | %d | %d | %d \n", + i, + static_cast(symbol_table.get_variable("A")->value()), + static_cast(symbol_table.get_variable("B")->value()), + static_cast(symbol_table.get_variable("C")->value()), + result); + } +} + +int main() +{ + logic(); + return 0; +} diff --git a/exprtk_simple_example_08.cpp b/exprtk_simple_example_08.cpp new file mode 100644 index 0000000..6436263 --- /dev/null +++ b/exprtk_simple_example_08.cpp @@ -0,0 +1,81 @@ +/* + ************************************************************** + * C++ Mathematical Expression Toolkit Library * + * * + * Simple Example 8 * + * Author: Arash Partow (1999-2013) * + * URL: http://www.partow.net/programming/exprtk/index.html * + * * + * Copyright notice: * + * Free use of the Mathematical Expression Toolkit Library is * + * permitted under the guidelines and in accordance with the * + * most current version of the Common Public License. * + * http://www.opensource.org/licenses/cpl1.0.php * + * * + ************************************************************** +*/ + + +#include +#include +#include "exprtk.hpp" + + +template +void composite() +{ + typedef exprtk::symbol_table symbol_table_t; + typedef exprtk::expression expression_t; + typedef exprtk::parser parser_t; + typedef exprtk::parser_error::type error_t; + typedef exprtk::function_compositor compositor_t; + + compositor_t compositor; + + T x = T(1); + T y = T(2); + + symbol_table_t& symbol_table = compositor.symbol_table(); + symbol_table.add_constants(); + symbol_table.add_variable("x",x); + symbol_table.add_variable("y",y); + + compositor.add("f","sin(x/pi)","x"); // f(x) = sin(x/pi) + compositor.add("g","3*[f(x)+f(y)]","x","y"); // g(x,y) = 3[f(x)+f(y)] + + std::string expression_string = "g(1 + f(x),f(y) / 2)"; + + expression_t expression; + expression.register_symbol_table(symbol_table); + + parser_t parser; + + if (!parser.compile(expression_string,expression)) + { + printf("Error: %s\tExpression: %s\n", + parser.error().c_str(), + expression_string.c_str()); + + for (std::size_t i = 0; i < parser.error_count(); ++i) + { + error_t error = parser.get_error(i); + printf("Error: %02d Position: %02d Type: [%14s] Msg: %s\tExpression: %s\n", + static_cast(i), + static_cast(error.token.position), + exprtk::parser_error::to_str(error.mode).c_str(), + error.diagnostic.c_str(), + expression_string.c_str()); + } + return; + } + + T result = expression.value(); + + printf("%s = %e\n", expression_string.c_str(), result); +} + +int main() +{ + composite(); + return 0; +} diff --git a/exprtk_simple_example_09.cpp b/exprtk_simple_example_09.cpp new file mode 100644 index 0000000..ceb4389 --- /dev/null +++ b/exprtk_simple_example_09.cpp @@ -0,0 +1,136 @@ +/* + ************************************************************** + * C++ Mathematical Expression Toolkit Library * + * * + * Simple Example 9 * + * Author: Arash Partow (1999-2012) * + * URL: http://www.partow.net/programming/exprtk/index.html * + * * + * Copyright notice: * + * Free use of the Mathematical Expression Toolkit Library is * + * permitted under the guidelines and in accordance with the * + * most current version of the Common Public License. * + * http://www.opensource.org/licenses/cpl1.0.php * + * * + ************************************************************** +*/ + + +#include +#include +#include "exprtk.hpp" + + +template +void primes() +{ + typedef exprtk::symbol_table symbol_table_t; + typedef exprtk::expression expression_t; + typedef exprtk::parser parser_t; + typedef exprtk::function_compositor compositor_t; + + T x = T(0); + + exprtk::symbol_table symbol_table; + + symbol_table.add_constants(); + symbol_table.add_variable("x",x); + + compositor_t compositor(symbol_table); + + //Mode 1 - if statement based + compositor + .add("is_prime_impl1", + "if(y == 1,true, " + " if(0 == (x % y),false, " + " is_prime_impl1(x,y-1)))", + "x","y"); + + compositor + .add("is_prime1", + "if(frac(x) != 0, false, " + " if(x <= 0, false, " + " is_prime_impl1(x,min(x - 1,trunc(sqrt(x)) + 1))))", + "x"); + + //Mode 2 - switch statement based + compositor + .add("is_prime_impl2", + "switch " + "{ " + " case y == 1 : true; " + " case (x % y) == 0 : false; " + " default : is_prime_impl2(x,y - 1);" + "} ", + "x","y"); + + compositor + .add("is_prime2", + "switch " + "{ " + " case x <= 0 : false; " + " case frac(x) != 0 : false; " + " default : is_prime_impl2(x,min(x - 1,trunc(sqrt(x)) + 1));" + "} ", + "x"); + + //Mode 3 - switch statement and while-loop based + compositor + .add("is_prime_impl3", + "while (y > 0) " + "{ " + " switch " + " { " + " case y == 1 : ~(y := 0,true); " + " case (x % y) == 0 : ~(y := 0,false);" + " default : y := y - 1; " + " } " + "} ", + "x","y"); + + compositor + .add("is_prime3", + "switch " + "{ " + " case x <= 0 : false; " + " case frac(x) != 0 : false; " + " default : is_prime_impl3(x,min(x - 1,trunc(sqrt(x)) + 1));" + "} ", + "x"); + + std::string expression_str1 = "is_prime1(x)"; + std::string expression_str2 = "is_prime2(x)"; + std::string expression_str3 = "is_prime3(x)"; + + expression_t expression1; + expression_t expression2; + expression_t expression3; + expression1.register_symbol_table(symbol_table); + expression2.register_symbol_table(symbol_table); + expression3.register_symbol_table(symbol_table); + + exprtk::parser parser; + + parser.compile(expression_str1,expression1); + parser.compile(expression_str2,expression2); + parser.compile(expression_str3,expression3); + + for (std::size_t i = 0; i < 100; ++i) + { + x = i; + T result1 = expression1.value(); + T result2 = expression2.value(); + T result3 = expression3.value(); + printf("%03d Result1: %c Result2: %c Result3: %c\n", + static_cast(i), + (result1 == T(1)) ? 'T' : 'F', + (result2 == T(1)) ? 'T' : 'F', + (result3 == T(1)) ? 'T' : 'F'); + } +} + +int main() +{ + primes(); + return 0; +} diff --git a/exprtk_test.cpp b/exprtk_test.cpp index 04dfcb1..6c0b99b 100644 --- a/exprtk_test.cpp +++ b/exprtk_test.cpp @@ -3574,15 +3574,15 @@ inline bool run_test19() compositor .add("is_prime_impl3", - "while (y > 0) " - "{ " - " switch " - " { " - " case y == 1 : true + (y := 0);" - " case (x % y) == 0 : false + (y := 0);" - " default : y := y - 1; " - " } " - "} ", + "while (y > 0) " + "{ " + " switch " + " { " + " case y == 1 : ~(y := 0,true); " + " case (x % y) == 0 : ~(y := 0,false);" + " default : y := y - 1; " + " } " + "} ", "x","y"); compositor @@ -3671,7 +3671,7 @@ inline bool run_test19() { printf("run_test19() - Error in evaluation! (3) Results don't match! Prime: %d " "Expression1: %s Expression2: %s Expression3: %s\n", - prime_list[i], + static_cast(prime_list[i]), expression_str1.c_str(), expression_str2.c_str(), expression_str3.c_str()); @@ -3682,7 +3682,7 @@ inline bool run_test19() { printf("run_test19() - Error in evaluation! (3) Prime: %d " "Expression1: %s Expression2: %s Expression3: %s\n", - (int)prime_list[i], + static_cast(prime_list[i]), expression_str1.c_str(), expression_str2.c_str(), expression_str3.c_str()); @@ -3716,17 +3716,44 @@ inline bool run_test19() "} ", "x"); + compositor + .add("fibonacci_impl3", + "switch " + "{ " + " case x == 0 : 0; " + " case x == 1 : 1; " + " default : while (~(x := (x - 1)) > 0)" + " {~ " + " ( " + " w := z, " + " z := z + y, " + " y := w, " + " z " + " ) " + " }; " + "} ", + "x","y","z","w"); + + compositor + .add("fibonacci3", + "fibonacci_impl3(x,0,1,0)", + "x"); + + exprtk::symbol_table& symbol_table = compositor.symbol_table(); symbol_table.add_constants(); symbol_table.add_variable("x",x); std::string expression_str1 = "fibonacci1(x)"; std::string expression_str2 = "fibonacci2(x)"; + std::string expression_str3 = "fibonacci3(x)"; expression_t expression1; expression_t expression2; + expression_t expression3; expression1.register_symbol_table(symbol_table); expression2.register_symbol_table(symbol_table); + expression3.register_symbol_table(symbol_table); exprtk::parser parser; @@ -3746,6 +3773,14 @@ inline bool run_test19() return false; } + if (!parser.compile(expression_str3,expression3)) + { + printf("run_test19() - Error: %s Expression3: %s\n", + parser.error().c_str(), + expression_str3.c_str()); + return false; + } + bool failure = false; const std::size_t fibonacci_list[] = @@ -3766,22 +3801,29 @@ inline bool run_test19() x = i; T result1 = expression1.value(); T result2 = expression2.value(); - if (result1 != result2) + T result3 = expression3.value(); + + if ((result1 != result2) || (result1 != result3)) { - printf("run_test19() - Error in evaluation! (3) Results don't match! Prime: %d Expression1: %s Expression2: %s\n", - fibonacci_list[i], + printf("run_test19() - Error in evaluation! (3) Results don't match! fibonacci(%d) = %d " + "Expression1: %s Expression2: %s Expression3: %s\n", + static_cast(i), + static_cast(fibonacci_list[i]), expression_str1.c_str(), - expression_str2.c_str()); + expression_str2.c_str(), + expression_str3.c_str()); failure = true; } if (fibonacci_list[i] != expression1.value()) { - printf("run_test19() - Error in evaluation! (4) fibonacci(%d) = %d Expression1: %s Expression2: %s\n", - i, - fibonacci_list[i], + printf("run_test19() - Error in evaluation! (4) fibonacci(%d) = %d " + "Expression1: %s Expression2: %s Expression3: %s\n", + static_cast(i), + static_cast(fibonacci_list[i]), expression_str1.c_str(), - expression_str2.c_str()); + expression_str2.c_str(), + expression_str3.c_str()); failure = true; } } diff --git a/readme.txt b/readme.txt index 0edccf1..713e2dd 100644 --- a/readme.txt +++ b/readme.txt @@ -276,6 +276,11 @@ include path (e.g: /usr/include/). +-----------+--------------------------------------------------------+ | trunc | Integer portion of x | +-----------+--------------------------------------------------------+ +| ~ | Evaluate each sub-expression, then return as the result| +| | the value of the last sub-expression. This is known as | +| | multiple sequence point evaluation. | +| | (eg: ~(x+1,y/z,abs(y^3),sin(w/u)) == (sin(w/u))) | ++-----------+--------------------------------------------------------+ (4) Trigonometry Functions +-----------+--------------------------------------------------------+