CMakeLists.txt: Remove -Wunqualified-std-cast-call
[pulseview.git] / pv / exprtk.hpp
blob84e35b61ffc152ef754638acb9a12e0647ab9267
1 /*
2 ******************************************************************
3 * C++ Mathematical Expression Toolkit Library *
4 * *
5 * Author: Arash Partow (1999-2020) *
6 * URL: http://www.partow.net/programming/exprtk/index.html *
7 * *
8 * Copyright notice: *
9 * Free use of the C++ Mathematical Expression Toolkit Library is *
10 * permitted under the guidelines and in accordance with the most *
11 * current version of the MIT License. *
12 * http://www.opensource.org/licenses/MIT *
13 * *
14 * Example expressions: *
15 * (00) (y + x / y) * (x - y / x) *
16 * (01) (x^2 / sin(2 * pi / y)) - x / 2 *
17 * (02) sqrt(1 - (x^2)) *
18 * (03) 1 - sin(2 * x) + cos(pi / y) *
19 * (04) a * exp(2 * t) + c *
20 * (05) if(((x + 2) == 3) and ((y + 5) <= 9),1 + w, 2 / z) *
21 * (06) (avg(x,y) <= x + y ? x - y : x * y) + 2 * pi / x *
22 * (07) z := x + sin(2 * pi / y) *
23 * (08) u := 2 * (pi * z) / (w := x + cos(y / pi)) *
24 * (09) clamp(-1,sin(2 * pi * x) + cos(y / 2 * pi),+1) *
25 * (10) inrange(-2,m,+2) == if(({-2 <= m} and [m <= +2]),1,0) *
26 * (11) (2sin(x)cos(2y)7 + 1) == (2 * sin(x) * cos(2*y) * 7 + 1) *
27 * (12) (x ilike 's*ri?g') and [y < (3 z^7 + w)] *
28 * *
29 ******************************************************************
33 #ifndef INCLUDE_EXPRTK_HPP
34 #define INCLUDE_EXPRTK_HPP
37 #include <algorithm>
38 #include <cctype>
39 #include <cmath>
40 #include <complex>
41 #include <cstdio>
42 #include <cstdlib>
43 #include <cstring>
44 #include <deque>
45 #include <exception>
46 #include <functional>
47 #include <iterator>
48 #include <limits>
49 #include <list>
50 #include <map>
51 #include <set>
52 #include <stack>
53 #include <stdexcept>
54 #include <string>
55 #include <utility>
56 #include <vector>
59 namespace exprtk
61 #ifdef exprtk_enable_debugging
62 #define exprtk_debug(params) printf params
63 #else
64 #define exprtk_debug(params) (void)0
65 #endif
67 #define exprtk_error_location \
68 "exprtk.hpp:" + details::to_str(__LINE__) \
70 #if defined(__GNUC__) && (__GNUC__ >= 7)
72 #define exprtk_disable_fallthrough_begin \
73 _Pragma ("GCC diagnostic push") \
74 _Pragma ("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") \
76 #define exprtk_disable_fallthrough_end \
77 _Pragma ("GCC diagnostic pop") \
79 #else
80 #define exprtk_disable_fallthrough_begin (void)0;
81 #define exprtk_disable_fallthrough_end (void)0;
82 #endif
84 namespace details
86 typedef unsigned char uchar_t;
87 typedef char char_t;
88 typedef uchar_t* uchar_ptr;
89 typedef char_t* char_ptr;
90 typedef uchar_t const* uchar_cptr;
91 typedef char_t const* char_cptr;
92 typedef unsigned long long int _uint64_t;
93 typedef long long int _int64_t;
95 inline bool is_whitespace(const char_t c)
97 return (' ' == c) || ('\n' == c) ||
98 ('\r' == c) || ('\t' == c) ||
99 ('\b' == c) || ('\v' == c) ||
100 ('\f' == c) ;
103 inline bool is_operator_char(const char_t c)
105 return ('+' == c) || ('-' == c) ||
106 ('*' == c) || ('/' == c) ||
107 ('^' == c) || ('<' == c) ||
108 ('>' == c) || ('=' == c) ||
109 (',' == c) || ('!' == c) ||
110 ('(' == c) || (')' == c) ||
111 ('[' == c) || (']' == c) ||
112 ('{' == c) || ('}' == c) ||
113 ('%' == c) || (':' == c) ||
114 ('?' == c) || ('&' == c) ||
115 ('|' == c) || (';' == c) ;
118 inline bool is_letter(const char_t c)
120 return (('a' <= c) && (c <= 'z')) ||
121 (('A' <= c) && (c <= 'Z')) ;
124 inline bool is_digit(const char_t c)
126 return ('0' <= c) && (c <= '9');
129 inline bool is_letter_or_digit(const char_t c)
131 return is_letter(c) || is_digit(c);
134 inline bool is_left_bracket(const char_t c)
136 return ('(' == c) || ('[' == c) || ('{' == c);
139 inline bool is_right_bracket(const char_t c)
141 return (')' == c) || (']' == c) || ('}' == c);
144 inline bool is_bracket(const char_t c)
146 return is_left_bracket(c) || is_right_bracket(c);
149 inline bool is_sign(const char_t c)
151 return ('+' == c) || ('-' == c);
154 inline bool is_invalid(const char_t c)
156 return !is_whitespace (c) &&
157 !is_operator_char(c) &&
158 !is_letter (c) &&
159 !is_digit (c) &&
160 ('.' != c) &&
161 ('_' != c) &&
162 ('$' != c) &&
163 ('~' != c) &&
164 ('\'' != c);
167 #ifndef exprtk_disable_caseinsensitivity
168 inline void case_normalise(std::string& s)
170 for (std::size_t i = 0; i < s.size(); ++i)
172 s[i] = static_cast<std::string::value_type>(std::tolower(s[i]));
176 inline bool imatch(const char_t c1, const char_t c2)
178 return std::tolower(c1) == std::tolower(c2);
181 inline bool imatch(const std::string& s1, const std::string& s2)
183 if (s1.size() == s2.size())
185 for (std::size_t i = 0; i < s1.size(); ++i)
187 if (std::tolower(s1[i]) != std::tolower(s2[i]))
189 return false;
193 return true;
196 return false;
199 struct ilesscompare
201 inline bool operator() (const std::string& s1, const std::string& s2) const
203 const std::size_t length = std::min(s1.size(),s2.size());
205 for (std::size_t i = 0; i < length; ++i)
207 const char_t c1 = static_cast<char>(std::tolower(s1[i]));
208 const char_t c2 = static_cast<char>(std::tolower(s2[i]));
210 if (c1 > c2)
211 return false;
212 else if (c1 < c2)
213 return true;
216 return s1.size() < s2.size();
220 #else
221 inline void case_normalise(std::string&)
224 inline bool imatch(const char_t c1, const char_t c2)
226 return c1 == c2;
229 inline bool imatch(const std::string& s1, const std::string& s2)
231 return s1 == s2;
234 struct ilesscompare
236 inline bool operator() (const std::string& s1, const std::string& s2) const
238 return s1 < s2;
241 #endif
243 inline bool is_valid_sf_symbol(const std::string& symbol)
245 // Special function: $f12 or $F34
246 return (4 == symbol.size()) &&
247 ('$' == symbol[0]) &&
248 imatch('f',symbol[1]) &&
249 is_digit(symbol[2]) &&
250 is_digit(symbol[3]);
253 inline const char_t& front(const std::string& s)
255 return s[0];
258 inline const char_t& back(const std::string& s)
260 return s[s.size() - 1];
263 inline std::string to_str(int i)
265 if (0 == i)
266 return std::string("0");
268 std::string result;
270 if (i < 0)
272 for ( ; i; i /= 10)
274 result += '0' + char(-(i % 10));
277 result += '-';
279 else
281 for ( ; i; i /= 10)
283 result += '0' + char(i % 10);
287 std::reverse(result.begin(), result.end());
289 return result;
292 inline std::string to_str(std::size_t i)
294 return to_str(static_cast<int>(i));
297 inline bool is_hex_digit(const std::string::value_type digit)
299 return (('0' <= digit) && (digit <= '9')) ||
300 (('A' <= digit) && (digit <= 'F')) ||
301 (('a' <= digit) && (digit <= 'f')) ;
304 inline uchar_t hex_to_bin(uchar_t h)
306 if (('0' <= h) && (h <= '9'))
307 return (h - '0');
308 else
309 return static_cast<unsigned char>(std::toupper(h) - 'A');
312 template <typename Iterator>
313 inline void parse_hex(Iterator& itr, Iterator end, std::string::value_type& result)
315 if (
316 (end != (itr )) &&
317 (end != (itr + 1)) &&
318 (end != (itr + 2)) &&
319 (end != (itr + 3)) &&
320 ('0' == *(itr )) &&
322 ('x' == *(itr + 1)) ||
323 ('X' == *(itr + 1))
324 ) &&
325 (is_hex_digit(*(itr + 2))) &&
326 (is_hex_digit(*(itr + 3)))
329 result = hex_to_bin(static_cast<uchar_t>(*(itr + 2))) << 4 |
330 hex_to_bin(static_cast<uchar_t>(*(itr + 3))) ;
331 itr += 3;
333 else
334 result = '\0';
337 inline void cleanup_escapes(std::string& s)
339 typedef std::string::iterator str_itr_t;
341 str_itr_t itr1 = s.begin();
342 str_itr_t itr2 = s.begin();
343 str_itr_t end = s.end ();
345 std::size_t removal_count = 0;
347 while (end != itr1)
349 if ('\\' == (*itr1))
351 ++removal_count;
353 if (end == ++itr1)
354 break;
355 else if ('\\' != (*itr1))
357 switch (*itr1)
359 case 'n' : (*itr1) = '\n'; break;
360 case 'r' : (*itr1) = '\r'; break;
361 case 't' : (*itr1) = '\t'; break;
362 case '0' : parse_hex(itr1, end, (*itr1));
363 removal_count += 3;
364 break;
367 continue;
371 if (itr1 != itr2)
373 (*itr2) = (*itr1);
376 ++itr1;
377 ++itr2;
380 s.resize(s.size() - removal_count);
383 class build_string
385 public:
387 build_string(const std::size_t& initial_size = 64)
389 data_.reserve(initial_size);
392 inline build_string& operator << (const std::string& s)
394 data_ += s;
395 return (*this);
398 inline build_string& operator << (char_cptr s)
400 data_ += std::string(s);
401 return (*this);
404 inline operator std::string () const
406 return data_;
409 inline std::string as_string() const
411 return data_;
414 private:
416 std::string data_;
419 const std::string reserved_words[] =
421 "break", "case", "continue", "default", "false", "for",
422 "if", "else", "ilike", "in", "like", "and", "nand", "nor",
423 "not", "null", "or", "repeat", "return", "shl", "shr",
424 "swap", "switch", "true", "until", "var", "while", "xnor",
425 "xor", "&", "|"
428 static const std::size_t reserved_words_size = sizeof(reserved_words) / sizeof(std::string);
430 const std::string reserved_symbols[] =
432 "abs", "acos", "acosh", "and", "asin", "asinh", "atan",
433 "atanh", "atan2", "avg", "break", "case", "ceil", "clamp",
434 "continue", "cos", "cosh", "cot", "csc", "default",
435 "deg2grad", "deg2rad", "equal", "erf", "erfc", "exp",
436 "expm1", "false", "floor", "for", "frac", "grad2deg",
437 "hypot", "iclamp", "if", "else", "ilike", "in", "inrange",
438 "like", "log", "log10", "log2", "logn", "log1p", "mand",
439 "max", "min", "mod", "mor", "mul", "ncdf", "nand", "nor",
440 "not", "not_equal", "null", "or", "pow", "rad2deg",
441 "repeat", "return", "root", "round", "roundn", "sec", "sgn",
442 "shl", "shr", "sin", "sinc", "sinh", "sqrt", "sum", "swap",
443 "switch", "tan", "tanh", "true", "trunc", "until", "var",
444 "while", "xnor", "xor", "&", "|"
447 static const std::size_t reserved_symbols_size = sizeof(reserved_symbols) / sizeof(std::string);
449 const std::string base_function_list[] =
451 "abs", "acos", "acosh", "asin", "asinh", "atan", "atanh",
452 "atan2", "avg", "ceil", "clamp", "cos", "cosh", "cot",
453 "csc", "equal", "erf", "erfc", "exp", "expm1", "floor",
454 "frac", "hypot", "iclamp", "like", "log", "log10", "log2",
455 "logn", "log1p", "mand", "max", "min", "mod", "mor", "mul",
456 "ncdf", "pow", "root", "round", "roundn", "sec", "sgn",
457 "sin", "sinc", "sinh", "sqrt", "sum", "swap", "tan", "tanh",
458 "trunc", "not_equal", "inrange", "deg2grad", "deg2rad",
459 "rad2deg", "grad2deg"
462 static const std::size_t base_function_list_size = sizeof(base_function_list) / sizeof(std::string);
464 const std::string logic_ops_list[] =
466 "and", "nand", "nor", "not", "or", "xnor", "xor", "&", "|"
469 static const std::size_t logic_ops_list_size = sizeof(logic_ops_list) / sizeof(std::string);
471 const std::string cntrl_struct_list[] =
473 "if", "switch", "for", "while", "repeat", "return"
476 static const std::size_t cntrl_struct_list_size = sizeof(cntrl_struct_list) / sizeof(std::string);
478 const std::string arithmetic_ops_list[] =
480 "+", "-", "*", "/", "%", "^"
483 static const std::size_t arithmetic_ops_list_size = sizeof(arithmetic_ops_list) / sizeof(std::string);
485 const std::string assignment_ops_list[] =
487 ":=", "+=", "-=",
488 "*=", "/=", "%="
491 static const std::size_t assignment_ops_list_size = sizeof(assignment_ops_list) / sizeof(std::string);
493 const std::string inequality_ops_list[] =
495 "<", "<=", "==",
496 "=", "!=", "<>",
497 ">=", ">"
500 static const std::size_t inequality_ops_list_size = sizeof(inequality_ops_list) / sizeof(std::string);
502 inline bool is_reserved_word(const std::string& symbol)
504 for (std::size_t i = 0; i < reserved_words_size; ++i)
506 if (imatch(symbol, reserved_words[i]))
508 return true;
512 return false;
515 inline bool is_reserved_symbol(const std::string& symbol)
517 for (std::size_t i = 0; i < reserved_symbols_size; ++i)
519 if (imatch(symbol, reserved_symbols[i]))
521 return true;
525 return false;
528 inline bool is_base_function(const std::string& function_name)
530 for (std::size_t i = 0; i < base_function_list_size; ++i)
532 if (imatch(function_name, base_function_list[i]))
534 return true;
538 return false;
541 inline bool is_control_struct(const std::string& cntrl_strct)
543 for (std::size_t i = 0; i < cntrl_struct_list_size; ++i)
545 if (imatch(cntrl_strct, cntrl_struct_list[i]))
547 return true;
551 return false;
554 inline bool is_logic_opr(const std::string& lgc_opr)
556 for (std::size_t i = 0; i < logic_ops_list_size; ++i)
558 if (imatch(lgc_opr, logic_ops_list[i]))
560 return true;
564 return false;
567 struct cs_match
569 static inline bool cmp(const char_t c0, const char_t c1)
571 return (c0 == c1);
575 struct cis_match
577 static inline bool cmp(const char_t c0, const char_t c1)
579 return (std::tolower(c0) == std::tolower(c1));
583 template <typename Iterator, typename Compare>
584 inline bool match_impl(const Iterator pattern_begin,
585 const Iterator pattern_end ,
586 const Iterator data_begin ,
587 const Iterator data_end ,
588 const typename std::iterator_traits<Iterator>::value_type& zero_or_more,
589 const typename std::iterator_traits<Iterator>::value_type& zero_or_one )
591 const Iterator null_itr(0);
593 Iterator d_itr = data_begin;
594 Iterator p_itr = pattern_begin;
595 Iterator tb_p_itr = null_itr;
596 Iterator tb_d_itr = null_itr;
598 while (d_itr != data_end)
600 if (zero_or_more == *p_itr)
602 while ((pattern_end != p_itr) && ((zero_or_more == *p_itr) || (zero_or_one == *p_itr)))
604 ++p_itr;
607 if (pattern_end == p_itr)
608 return true;
610 const typename std::iterator_traits<Iterator>::value_type c = *(p_itr);
612 while ((data_end != d_itr) && !Compare::cmp(c,*d_itr))
614 ++d_itr;
617 tb_p_itr = p_itr;
618 tb_d_itr = d_itr;
620 continue;
622 else if (!Compare::cmp(*p_itr, *d_itr) && (zero_or_one != *p_itr))
624 if (null_itr == tb_d_itr)
625 return false;
627 d_itr = tb_d_itr++;
628 p_itr = tb_p_itr;
630 continue;
633 ++p_itr;
634 ++d_itr;
637 while ((pattern_end != p_itr) && ((zero_or_more == *p_itr) || (zero_or_one == *p_itr)))
639 ++p_itr;
642 return (pattern_end == p_itr);
645 inline bool wc_match(const std::string& wild_card,
646 const std::string& str)
648 return match_impl<char_cptr,cs_match>(wild_card.data(),
649 wild_card.data() + wild_card.size(),
650 str.data(),
651 str.data() + str.size(),
652 '*',
653 '?');
656 inline bool wc_imatch(const std::string& wild_card,
657 const std::string& str)
659 return match_impl<char_cptr,cis_match>(wild_card.data(),
660 wild_card.data() + wild_card.size(),
661 str.data(),
662 str.data() + str.size(),
663 '*',
664 '?');
667 inline bool sequence_match(const std::string& pattern,
668 const std::string& str,
669 std::size_t& diff_index,
670 char_t& diff_value)
672 if (str.empty())
674 return ("Z" == pattern);
676 else if ('*' == pattern[0])
677 return false;
679 typedef std::string::const_iterator itr_t;
681 itr_t p_itr = pattern.begin();
682 itr_t s_itr = str .begin();
684 itr_t p_end = pattern.end();
685 itr_t s_end = str .end();
687 while ((s_end != s_itr) && (p_end != p_itr))
689 if ('*' == (*p_itr))
691 const char_t target = static_cast<char>(std::toupper(*(p_itr - 1)));
693 if ('*' == target)
695 diff_index = static_cast<std::size_t>(std::distance(str.begin(),s_itr));
696 diff_value = static_cast<char>(std::toupper(*p_itr));
698 return false;
700 else
701 ++p_itr;
703 while (s_itr != s_end)
705 if (target != std::toupper(*s_itr))
706 break;
707 else
708 ++s_itr;
711 continue;
713 else if (
714 ('?' != *p_itr) &&
715 std::toupper(*p_itr) != std::toupper(*s_itr)
718 diff_index = static_cast<std::size_t>(std::distance(str.begin(),s_itr));
719 diff_value = static_cast<char>(std::toupper(*p_itr));
721 return false;
724 ++p_itr;
725 ++s_itr;
728 return (
729 (s_end == s_itr) &&
731 (p_end == p_itr) ||
732 ('*' == *p_itr)
737 static const double pow10[] = {
738 1.0,
739 1.0E+001, 1.0E+002, 1.0E+003, 1.0E+004,
740 1.0E+005, 1.0E+006, 1.0E+007, 1.0E+008,
741 1.0E+009, 1.0E+010, 1.0E+011, 1.0E+012,
742 1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016
745 static const std::size_t pow10_size = sizeof(pow10) / sizeof(double);
747 namespace numeric
749 namespace constant
751 static const double e = 2.71828182845904523536028747135266249775724709369996;
752 static const double pi = 3.14159265358979323846264338327950288419716939937510;
753 static const double pi_2 = 1.57079632679489661923132169163975144209858469968755;
754 static const double pi_4 = 0.78539816339744830961566084581987572104929234984378;
755 static const double pi_180 = 0.01745329251994329576923690768488612713442871888542;
756 static const double _1_pi = 0.31830988618379067153776752674502872406891929148091;
757 static const double _2_pi = 0.63661977236758134307553505349005744813783858296183;
758 static const double _180_pi = 57.29577951308232087679815481410517033240547246656443;
759 static const double log2 = 0.69314718055994530941723212145817656807550013436026;
760 static const double sqrt2 = 1.41421356237309504880168872420969807856967187537695;
763 namespace details
765 struct unknown_type_tag { unknown_type_tag() {} };
766 struct real_type_tag { real_type_tag () {} };
767 struct complex_type_tag { complex_type_tag() {} };
768 struct int_type_tag { int_type_tag () {} };
770 template <typename T>
771 struct number_type
773 typedef unknown_type_tag type;
774 number_type() {}
777 #define exprtk_register_real_type_tag(T) \
778 template<> struct number_type<T> \
779 { typedef real_type_tag type; number_type() {} }; \
781 #define exprtk_register_complex_type_tag(T) \
782 template<> struct number_type<std::complex<T> > \
783 { typedef complex_type_tag type; number_type() {} }; \
785 #define exprtk_register_int_type_tag(T) \
786 template<> struct number_type<T> \
787 { typedef int_type_tag type; number_type() {} }; \
789 exprtk_register_real_type_tag(double )
790 exprtk_register_real_type_tag(long double)
791 exprtk_register_real_type_tag(float )
793 exprtk_register_complex_type_tag(double )
794 exprtk_register_complex_type_tag(long double)
795 exprtk_register_complex_type_tag(float )
797 exprtk_register_int_type_tag(short )
798 exprtk_register_int_type_tag(int )
799 exprtk_register_int_type_tag(_int64_t )
800 exprtk_register_int_type_tag(unsigned short)
801 exprtk_register_int_type_tag(unsigned int )
802 exprtk_register_int_type_tag(_uint64_t )
804 #undef exprtk_register_real_type_tag
805 #undef exprtk_register_int_type_tag
807 template <typename T>
808 struct epsilon_type
810 static inline T value()
812 const T epsilon = T(0.0000000001);
813 return epsilon;
817 template <>
818 struct epsilon_type <float>
820 static inline float value()
822 const float epsilon = float(0.000001f);
823 return epsilon;
827 template <>
828 struct epsilon_type <long double>
830 static inline long double value()
832 const long double epsilon = (long double)(0.000000000001);
833 return epsilon;
837 template <typename T>
838 inline bool is_nan_impl(const T v, real_type_tag)
840 return std::not_equal_to<T>()(v,v);
843 template <typename T>
844 inline int to_int32_impl(const T v, real_type_tag)
846 return static_cast<int>(v);
849 template <typename T>
850 inline _int64_t to_int64_impl(const T v, real_type_tag)
852 return static_cast<_int64_t>(v);
855 template <typename T>
856 inline bool is_true_impl(const T v)
858 return std::not_equal_to<T>()(T(0),v);
861 template <typename T>
862 inline bool is_false_impl(const T v)
864 return std::equal_to<T>()(T(0),v);
867 template <typename T>
868 inline T abs_impl(const T v, real_type_tag)
870 return ((v < T(0)) ? -v : v);
873 template <typename T>
874 inline T min_impl(const T v0, const T v1, real_type_tag)
876 return std::min<T>(v0,v1);
879 template <typename T>
880 inline T max_impl(const T v0, const T v1, real_type_tag)
882 return std::max<T>(v0,v1);
885 template <typename T>
886 inline T equal_impl(const T v0, const T v1, real_type_tag)
888 const T epsilon = epsilon_type<T>::value();
889 return (abs_impl(v0 - v1,real_type_tag()) <= (std::max(T(1),std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? T(1) : T(0);
892 inline float equal_impl(const float v0, const float v1, real_type_tag)
894 const float epsilon = epsilon_type<float>::value();
895 return (abs_impl(v0 - v1,real_type_tag()) <= (std::max(1.0f,std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? 1.0f : 0.0f;
898 template <typename T>
899 inline T equal_impl(const T v0, const T v1, int_type_tag)
901 return (v0 == v1) ? 1 : 0;
904 template <typename T>
905 inline T expm1_impl(const T v, real_type_tag)
907 // return std::expm1<T>(v);
908 if (abs_impl(v,real_type_tag()) < T(0.00001))
909 return v + (T(0.5) * v * v);
910 else
911 return std::exp(v) - T(1);
914 template <typename T>
915 inline T expm1_impl(const T v, int_type_tag)
917 return T(std::exp<double>(v)) - T(1);
920 template <typename T>
921 inline T nequal_impl(const T v0, const T v1, real_type_tag)
923 typedef real_type_tag rtg;
924 const T epsilon = epsilon_type<T>::value();
925 return (abs_impl(v0 - v1,rtg()) > (std::max(T(1),std::max(abs_impl(v0,rtg()),abs_impl(v1,rtg()))) * epsilon)) ? T(1) : T(0);
928 inline float nequal_impl(const float v0, const float v1, real_type_tag)
930 typedef real_type_tag rtg;
931 const float epsilon = epsilon_type<float>::value();
932 return (abs_impl(v0 - v1,rtg()) > (std::max(1.0f,std::max(abs_impl(v0,rtg()),abs_impl(v1,rtg()))) * epsilon)) ? 1.0f : 0.0f;
935 template <typename T>
936 inline T nequal_impl(const T v0, const T v1, int_type_tag)
938 return (v0 != v1) ? 1 : 0;
941 template <typename T>
942 inline T modulus_impl(const T v0, const T v1, real_type_tag)
944 return std::fmod(v0,v1);
947 template <typename T>
948 inline T modulus_impl(const T v0, const T v1, int_type_tag)
950 return v0 % v1;
953 template <typename T>
954 inline T pow_impl(const T v0, const T v1, real_type_tag)
956 return std::pow(v0,v1);
959 template <typename T>
960 inline T pow_impl(const T v0, const T v1, int_type_tag)
962 return std::pow(static_cast<double>(v0),static_cast<double>(v1));
965 template <typename T>
966 inline T logn_impl(const T v0, const T v1, real_type_tag)
968 return std::log(v0) / std::log(v1);
971 template <typename T>
972 inline T logn_impl(const T v0, const T v1, int_type_tag)
974 return static_cast<T>(logn_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag()));
977 template <typename T>
978 inline T log1p_impl(const T v, real_type_tag)
980 if (v > T(-1))
982 if (abs_impl(v,real_type_tag()) > T(0.0001))
984 return std::log(T(1) + v);
986 else
987 return (T(-0.5) * v + T(1)) * v;
989 else
990 return std::numeric_limits<T>::quiet_NaN();
993 template <typename T>
994 inline T log1p_impl(const T v, int_type_tag)
996 if (v > T(-1))
998 return std::log(T(1) + v);
1000 else
1001 return std::numeric_limits<T>::quiet_NaN();
1004 template <typename T>
1005 inline T root_impl(const T v0, const T v1, real_type_tag)
1007 if (v1 < T(0))
1008 return std::numeric_limits<T>::quiet_NaN();
1010 const std::size_t n = static_cast<std::size_t>(v1);
1012 if ((v0 < T(0)) && (0 == (n % 2)))
1013 return std::numeric_limits<T>::quiet_NaN();
1015 return std::pow(v0, T(1) / n);
1018 template <typename T>
1019 inline T root_impl(const T v0, const T v1, int_type_tag)
1021 return root_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag());
1024 template <typename T>
1025 inline T round_impl(const T v, real_type_tag)
1027 return ((v < T(0)) ? std::ceil(v - T(0.5)) : std::floor(v + T(0.5)));
1030 template <typename T>
1031 inline T roundn_impl(const T v0, const T v1, real_type_tag)
1033 const int index = std::max<int>(0, std::min<int>(pow10_size - 1, (int)std::floor(v1)));
1034 const T p10 = T(pow10[index]);
1036 if (v0 < T(0))
1037 return T(std::ceil ((v0 * p10) - T(0.5)) / p10);
1038 else
1039 return T(std::floor((v0 * p10) + T(0.5)) / p10);
1042 template <typename T>
1043 inline T roundn_impl(const T v0, const T, int_type_tag)
1045 return v0;
1048 template <typename T>
1049 inline T hypot_impl(const T v0, const T v1, real_type_tag)
1051 return std::sqrt((v0 * v0) + (v1 * v1));
1054 template <typename T>
1055 inline T hypot_impl(const T v0, const T v1, int_type_tag)
1057 return static_cast<T>(std::sqrt(static_cast<double>((v0 * v0) + (v1 * v1))));
1060 template <typename T>
1061 inline T atan2_impl(const T v0, const T v1, real_type_tag)
1063 return std::atan2(v0,v1);
1066 template <typename T>
1067 inline T atan2_impl(const T, const T, int_type_tag)
1069 return 0;
1072 template <typename T>
1073 inline T shr_impl(const T v0, const T v1, real_type_tag)
1075 return v0 * (T(1) / std::pow(T(2),static_cast<T>(static_cast<int>(v1))));
1078 template <typename T>
1079 inline T shr_impl(const T v0, const T v1, int_type_tag)
1081 return v0 >> v1;
1084 template <typename T>
1085 inline T shl_impl(const T v0, const T v1, real_type_tag)
1087 return v0 * std::pow(T(2),static_cast<T>(static_cast<int>(v1)));
1090 template <typename T>
1091 inline T shl_impl(const T v0, const T v1, int_type_tag)
1093 return v0 << v1;
1096 template <typename T>
1097 inline T sgn_impl(const T v, real_type_tag)
1099 if (v > T(0)) return T(+1);
1100 else if (v < T(0)) return T(-1);
1101 else return T( 0);
1104 template <typename T>
1105 inline T sgn_impl(const T v, int_type_tag)
1107 if (v > T(0)) return T(+1);
1108 else if (v < T(0)) return T(-1);
1109 else return T( 0);
1112 template <typename T>
1113 inline T and_impl(const T v0, const T v1, real_type_tag)
1115 return (is_true_impl(v0) && is_true_impl(v1)) ? T(1) : T(0);
1118 template <typename T>
1119 inline T and_impl(const T v0, const T v1, int_type_tag)
1121 return v0 && v1;
1124 template <typename T>
1125 inline T nand_impl(const T v0, const T v1, real_type_tag)
1127 return (is_false_impl(v0) || is_false_impl(v1)) ? T(1) : T(0);
1130 template <typename T>
1131 inline T nand_impl(const T v0, const T v1, int_type_tag)
1133 return !(v0 && v1);
1136 template <typename T>
1137 inline T or_impl(const T v0, const T v1, real_type_tag)
1139 return (is_true_impl(v0) || is_true_impl(v1)) ? T(1) : T(0);
1142 template <typename T>
1143 inline T or_impl(const T v0, const T v1, int_type_tag)
1145 return (v0 || v1);
1148 template <typename T>
1149 inline T nor_impl(const T v0, const T v1, real_type_tag)
1151 return (is_false_impl(v0) && is_false_impl(v1)) ? T(1) : T(0);
1154 template <typename T>
1155 inline T nor_impl(const T v0, const T v1, int_type_tag)
1157 return !(v0 || v1);
1160 template <typename T>
1161 inline T xor_impl(const T v0, const T v1, real_type_tag)
1163 return (is_false_impl(v0) != is_false_impl(v1)) ? T(1) : T(0);
1166 template <typename T>
1167 inline T xor_impl(const T v0, const T v1, int_type_tag)
1169 return v0 ^ v1;
1172 template <typename T>
1173 inline T xnor_impl(const T v0, const T v1, real_type_tag)
1175 const bool v0_true = is_true_impl(v0);
1176 const bool v1_true = is_true_impl(v1);
1178 if ((v0_true && v1_true) || (!v0_true && !v1_true))
1179 return T(1);
1180 else
1181 return T(0);
1184 template <typename T>
1185 inline T xnor_impl(const T v0, const T v1, int_type_tag)
1187 const bool v0_true = is_true_impl(v0);
1188 const bool v1_true = is_true_impl(v1);
1190 if ((v0_true && v1_true) || (!v0_true && !v1_true))
1191 return T(1);
1192 else
1193 return T(0);
1196 #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER)
1197 #define exprtk_define_erf(TT,impl) \
1198 inline TT erf_impl(TT v) { return impl(v); } \
1200 exprtk_define_erf( float,::erff)
1201 exprtk_define_erf( double,::erf )
1202 exprtk_define_erf(long double,::erfl)
1203 #undef exprtk_define_erf
1204 #endif
1206 template <typename T>
1207 inline T erf_impl(T v, real_type_tag)
1209 #if defined(_MSC_VER) && (_MSC_VER < 1900)
1210 // Credits: Abramowitz & Stegun Equations 7.1.25-28
1211 static const T c[] = {
1212 T( 1.26551223), T(1.00002368),
1213 T( 0.37409196), T(0.09678418),
1214 T(-0.18628806), T(0.27886807),
1215 T(-1.13520398), T(1.48851587),
1216 T(-0.82215223), T(0.17087277)
1219 const T t = T(1) / (T(1) + T(0.5) * abs_impl(v,real_type_tag()));
1221 T result = T(1) - t * std::exp((-v * v) -
1222 c[0] + t * (c[1] + t *
1223 (c[2] + t * (c[3] + t *
1224 (c[4] + t * (c[5] + t *
1225 (c[6] + t * (c[7] + t *
1226 (c[8] + t * (c[9]))))))))));
1228 return (v >= T(0)) ? result : -result;
1229 #else
1230 return erf_impl(v);
1231 #endif
1234 template <typename T>
1235 inline T erf_impl(T v, int_type_tag)
1237 return erf_impl(static_cast<double>(v),real_type_tag());
1240 #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER)
1241 #define exprtk_define_erfc(TT,impl) \
1242 inline TT erfc_impl(TT v) { return impl(v); } \
1244 exprtk_define_erfc( float,::erfcf)
1245 exprtk_define_erfc( double,::erfc )
1246 exprtk_define_erfc(long double,::erfcl)
1247 #undef exprtk_define_erfc
1248 #endif
1250 template <typename T>
1251 inline T erfc_impl(T v, real_type_tag)
1253 #if defined(_MSC_VER) && (_MSC_VER < 1900)
1254 return T(1) - erf_impl(v,real_type_tag());
1255 #else
1256 return erfc_impl(v);
1257 #endif
1260 template <typename T>
1261 inline T erfc_impl(T v, int_type_tag)
1263 return erfc_impl(static_cast<double>(v),real_type_tag());
1266 template <typename T>
1267 inline T ncdf_impl(T v, real_type_tag)
1269 T cnd = T(0.5) * (T(1) + erf_impl(
1270 abs_impl(v,real_type_tag()) /
1271 T(numeric::constant::sqrt2),real_type_tag()));
1272 return (v < T(0)) ? (T(1) - cnd) : cnd;
1275 template <typename T>
1276 inline T ncdf_impl(T v, int_type_tag)
1278 return ncdf_impl(static_cast<double>(v),real_type_tag());
1281 template <typename T>
1282 inline T sinc_impl(T v, real_type_tag)
1284 if (std::abs(v) >= std::numeric_limits<T>::epsilon())
1285 return(std::sin(v) / v);
1286 else
1287 return T(1);
1290 template <typename T>
1291 inline T sinc_impl(T v, int_type_tag)
1293 return sinc_impl(static_cast<double>(v),real_type_tag());
1296 template <typename T> inline T acos_impl(const T v, real_type_tag) { return std::acos (v); }
1297 template <typename T> inline T acosh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) - T(1))); }
1298 template <typename T> inline T asin_impl(const T v, real_type_tag) { return std::asin (v); }
1299 template <typename T> inline T asinh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) + T(1))); }
1300 template <typename T> inline T atan_impl(const T v, real_type_tag) { return std::atan (v); }
1301 template <typename T> inline T atanh_impl(const T v, real_type_tag) { return (std::log(T(1) + v) - std::log(T(1) - v)) / T(2); }
1302 template <typename T> inline T ceil_impl(const T v, real_type_tag) { return std::ceil (v); }
1303 template <typename T> inline T cos_impl(const T v, real_type_tag) { return std::cos (v); }
1304 template <typename T> inline T cosh_impl(const T v, real_type_tag) { return std::cosh (v); }
1305 template <typename T> inline T exp_impl(const T v, real_type_tag) { return std::exp (v); }
1306 template <typename T> inline T floor_impl(const T v, real_type_tag) { return std::floor(v); }
1307 template <typename T> inline T log_impl(const T v, real_type_tag) { return std::log (v); }
1308 template <typename T> inline T log10_impl(const T v, real_type_tag) { return std::log10(v); }
1309 template <typename T> inline T log2_impl(const T v, real_type_tag) { return std::log(v)/T(numeric::constant::log2); }
1310 template <typename T> inline T neg_impl(const T v, real_type_tag) { return -v; }
1311 template <typename T> inline T pos_impl(const T v, real_type_tag) { return +v; }
1312 template <typename T> inline T sin_impl(const T v, real_type_tag) { return std::sin (v); }
1313 template <typename T> inline T sinh_impl(const T v, real_type_tag) { return std::sinh (v); }
1314 template <typename T> inline T sqrt_impl(const T v, real_type_tag) { return std::sqrt (v); }
1315 template <typename T> inline T tan_impl(const T v, real_type_tag) { return std::tan (v); }
1316 template <typename T> inline T tanh_impl(const T v, real_type_tag) { return std::tanh (v); }
1317 template <typename T> inline T cot_impl(const T v, real_type_tag) { return T(1) / std::tan(v); }
1318 template <typename T> inline T sec_impl(const T v, real_type_tag) { return T(1) / std::cos(v); }
1319 template <typename T> inline T csc_impl(const T v, real_type_tag) { return T(1) / std::sin(v); }
1320 template <typename T> inline T r2d_impl(const T v, real_type_tag) { return (v * T(numeric::constant::_180_pi)); }
1321 template <typename T> inline T d2r_impl(const T v, real_type_tag) { return (v * T(numeric::constant::pi_180)); }
1322 template <typename T> inline T d2g_impl(const T v, real_type_tag) { return (v * T(20.0/9.0)); }
1323 template <typename T> inline T g2d_impl(const T v, real_type_tag) { return (v * T(9.0/20.0)); }
1324 template <typename T> inline T notl_impl(const T v, real_type_tag) { return (std::not_equal_to<T>()(T(0),v) ? T(0) : T(1)); }
1325 template <typename T> inline T frac_impl(const T v, real_type_tag) { return (v - static_cast<long long>(v)); }
1326 template <typename T> inline T trunc_impl(const T v, real_type_tag) { return T(static_cast<long long>(v)); }
1328 template <typename T> inline T const_pi_impl(real_type_tag) { return T(numeric::constant::pi); }
1329 template <typename T> inline T const_e_impl (real_type_tag) { return T(numeric::constant::e); }
1331 template <typename T> inline T abs_impl(const T v, int_type_tag) { return ((v >= T(0)) ? v : -v); }
1332 template <typename T> inline T exp_impl(const T v, int_type_tag) { return std::exp (v); }
1333 template <typename T> inline T log_impl(const T v, int_type_tag) { return std::log (v); }
1334 template <typename T> inline T log10_impl(const T v, int_type_tag) { return std::log10(v); }
1335 template <typename T> inline T log2_impl(const T v, int_type_tag) { return std::log(v)/T(numeric::constant::log2); }
1336 template <typename T> inline T neg_impl(const T v, int_type_tag) { return -v; }
1337 template <typename T> inline T pos_impl(const T v, int_type_tag) { return +v; }
1338 template <typename T> inline T ceil_impl(const T v, int_type_tag) { return v; }
1339 template <typename T> inline T floor_impl(const T v, int_type_tag) { return v; }
1340 template <typename T> inline T round_impl(const T v, int_type_tag) { return v; }
1341 template <typename T> inline T notl_impl(const T v, int_type_tag) { return !v; }
1342 template <typename T> inline T sqrt_impl(const T v, int_type_tag) { return std::sqrt (v); }
1343 template <typename T> inline T frac_impl(const T , int_type_tag) { return T(0); }
1344 template <typename T> inline T trunc_impl(const T v, int_type_tag) { return v; }
1345 template <typename T> inline T acos_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1346 template <typename T> inline T acosh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1347 template <typename T> inline T asin_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1348 template <typename T> inline T asinh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1349 template <typename T> inline T atan_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1350 template <typename T> inline T atanh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1351 template <typename T> inline T cos_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1352 template <typename T> inline T cosh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1353 template <typename T> inline T sin_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1354 template <typename T> inline T sinh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1355 template <typename T> inline T tan_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1356 template <typename T> inline T tanh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1357 template <typename T> inline T cot_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1358 template <typename T> inline T sec_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1359 template <typename T> inline T csc_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1361 template <typename T>
1362 inline bool is_integer_impl(const T& v, real_type_tag)
1364 return std::equal_to<T>()(T(0),std::fmod(v,T(1)));
1367 template <typename T>
1368 inline bool is_integer_impl(const T&, int_type_tag)
1370 return true;
1374 template <typename Type>
1375 struct numeric_info { enum { length = 0, size = 32, bound_length = 0, min_exp = 0, max_exp = 0 }; };
1377 template<> struct numeric_info<int> { enum { length = 10, size = 16, bound_length = 9}; };
1378 template<> struct numeric_info<float> { enum { min_exp = -38, max_exp = +38}; };
1379 template<> struct numeric_info<double> { enum { min_exp = -308, max_exp = +308}; };
1380 template<> struct numeric_info<long double> { enum { min_exp = -308, max_exp = +308}; };
1382 template <typename T>
1383 inline int to_int32(const T v)
1385 const typename details::number_type<T>::type num_type;
1386 return to_int32_impl(v, num_type);
1389 template <typename T>
1390 inline _int64_t to_int64(const T v)
1392 const typename details::number_type<T>::type num_type;
1393 return to_int64_impl(v, num_type);
1396 template <typename T>
1397 inline bool is_nan(const T v)
1399 const typename details::number_type<T>::type num_type;
1400 return is_nan_impl(v, num_type);
1403 template <typename T>
1404 inline T min(const T v0, const T v1)
1406 const typename details::number_type<T>::type num_type;
1407 return min_impl(v0, v1, num_type);
1410 template <typename T>
1411 inline T max(const T v0, const T v1)
1413 const typename details::number_type<T>::type num_type;
1414 return max_impl(v0, v1, num_type);
1417 template <typename T>
1418 inline T equal(const T v0, const T v1)
1420 const typename details::number_type<T>::type num_type;
1421 return equal_impl(v0, v1, num_type);
1424 template <typename T>
1425 inline T nequal(const T v0, const T v1)
1427 const typename details::number_type<T>::type num_type;
1428 return nequal_impl(v0, v1, num_type);
1431 template <typename T>
1432 inline T modulus(const T v0, const T v1)
1434 const typename details::number_type<T>::type num_type;
1435 return modulus_impl(v0, v1, num_type);
1438 template <typename T>
1439 inline T pow(const T v0, const T v1)
1441 const typename details::number_type<T>::type num_type;
1442 return pow_impl(v0, v1, num_type);
1445 template <typename T>
1446 inline T logn(const T v0, const T v1)
1448 const typename details::number_type<T>::type num_type;
1449 return logn_impl(v0, v1, num_type);
1452 template <typename T>
1453 inline T root(const T v0, const T v1)
1455 const typename details::number_type<T>::type num_type;
1456 return root_impl(v0, v1, num_type);
1459 template <typename T>
1460 inline T roundn(const T v0, const T v1)
1462 const typename details::number_type<T>::type num_type;
1463 return roundn_impl(v0, v1, num_type);
1466 template <typename T>
1467 inline T hypot(const T v0, const T v1)
1469 const typename details::number_type<T>::type num_type;
1470 return hypot_impl(v0, v1, num_type);
1473 template <typename T>
1474 inline T atan2(const T v0, const T v1)
1476 const typename details::number_type<T>::type num_type;
1477 return atan2_impl(v0, v1, num_type);
1480 template <typename T>
1481 inline T shr(const T v0, const T v1)
1483 const typename details::number_type<T>::type num_type;
1484 return shr_impl(v0, v1, num_type);
1487 template <typename T>
1488 inline T shl(const T v0, const T v1)
1490 const typename details::number_type<T>::type num_type;
1491 return shl_impl(v0, v1, num_type);
1494 template <typename T>
1495 inline T and_opr(const T v0, const T v1)
1497 const typename details::number_type<T>::type num_type;
1498 return and_impl(v0, v1, num_type);
1501 template <typename T>
1502 inline T nand_opr(const T v0, const T v1)
1504 const typename details::number_type<T>::type num_type;
1505 return nand_impl(v0, v1, num_type);
1508 template <typename T>
1509 inline T or_opr(const T v0, const T v1)
1511 const typename details::number_type<T>::type num_type;
1512 return or_impl(v0, v1, num_type);
1515 template <typename T>
1516 inline T nor_opr(const T v0, const T v1)
1518 const typename details::number_type<T>::type num_type;
1519 return nor_impl(v0, v1, num_type);
1522 template <typename T>
1523 inline T xor_opr(const T v0, const T v1)
1525 const typename details::number_type<T>::type num_type;
1526 return xor_impl(v0, v1, num_type);
1529 template <typename T>
1530 inline T xnor_opr(const T v0, const T v1)
1532 const typename details::number_type<T>::type num_type;
1533 return xnor_impl(v0, v1, num_type);
1536 template <typename T>
1537 inline bool is_integer(const T v)
1539 const typename details::number_type<T>::type num_type;
1540 return is_integer_impl(v, num_type);
1543 template <typename T, unsigned int N>
1544 struct fast_exp
1546 static inline T result(T v)
1548 unsigned int k = N;
1549 T l = T(1);
1551 while (k)
1553 if (k & 1)
1555 l *= v;
1556 --k;
1559 v *= v;
1560 k >>= 1;
1563 return l;
1567 template <typename T> struct fast_exp<T,10> { static inline T result(T v) { T v_5 = fast_exp<T,5>::result(v); return v_5 * v_5; } };
1568 template <typename T> struct fast_exp<T, 9> { static inline T result(T v) { return fast_exp<T,8>::result(v) * v; } };
1569 template <typename T> struct fast_exp<T, 8> { static inline T result(T v) { T v_4 = fast_exp<T,4>::result(v); return v_4 * v_4; } };
1570 template <typename T> struct fast_exp<T, 7> { static inline T result(T v) { return fast_exp<T,6>::result(v) * v; } };
1571 template <typename T> struct fast_exp<T, 6> { static inline T result(T v) { T v_3 = fast_exp<T,3>::result(v); return v_3 * v_3; } };
1572 template <typename T> struct fast_exp<T, 5> { static inline T result(T v) { return fast_exp<T,4>::result(v) * v; } };
1573 template <typename T> struct fast_exp<T, 4> { static inline T result(T v) { T v_2 = v * v; return v_2 * v_2; } };
1574 template <typename T> struct fast_exp<T, 3> { static inline T result(T v) { return v * v * v; } };
1575 template <typename T> struct fast_exp<T, 2> { static inline T result(T v) { return v * v; } };
1576 template <typename T> struct fast_exp<T, 1> { static inline T result(T v) { return v; } };
1577 template <typename T> struct fast_exp<T, 0> { static inline T result(T ) { return T(1); } };
1579 #define exprtk_define_unary_function(FunctionName) \
1580 template <typename T> \
1581 inline T FunctionName (const T v) \
1583 const typename details::number_type<T>::type num_type; \
1584 return FunctionName##_impl(v,num_type); \
1587 exprtk_define_unary_function(abs )
1588 exprtk_define_unary_function(acos )
1589 exprtk_define_unary_function(acosh)
1590 exprtk_define_unary_function(asin )
1591 exprtk_define_unary_function(asinh)
1592 exprtk_define_unary_function(atan )
1593 exprtk_define_unary_function(atanh)
1594 exprtk_define_unary_function(ceil )
1595 exprtk_define_unary_function(cos )
1596 exprtk_define_unary_function(cosh )
1597 exprtk_define_unary_function(exp )
1598 exprtk_define_unary_function(expm1)
1599 exprtk_define_unary_function(floor)
1600 exprtk_define_unary_function(log )
1601 exprtk_define_unary_function(log10)
1602 exprtk_define_unary_function(log2 )
1603 exprtk_define_unary_function(log1p)
1604 exprtk_define_unary_function(neg )
1605 exprtk_define_unary_function(pos )
1606 exprtk_define_unary_function(round)
1607 exprtk_define_unary_function(sin )
1608 exprtk_define_unary_function(sinc )
1609 exprtk_define_unary_function(sinh )
1610 exprtk_define_unary_function(sqrt )
1611 exprtk_define_unary_function(tan )
1612 exprtk_define_unary_function(tanh )
1613 exprtk_define_unary_function(cot )
1614 exprtk_define_unary_function(sec )
1615 exprtk_define_unary_function(csc )
1616 exprtk_define_unary_function(r2d )
1617 exprtk_define_unary_function(d2r )
1618 exprtk_define_unary_function(d2g )
1619 exprtk_define_unary_function(g2d )
1620 exprtk_define_unary_function(notl )
1621 exprtk_define_unary_function(sgn )
1622 exprtk_define_unary_function(erf )
1623 exprtk_define_unary_function(erfc )
1624 exprtk_define_unary_function(ncdf )
1625 exprtk_define_unary_function(frac )
1626 exprtk_define_unary_function(trunc)
1627 #undef exprtk_define_unary_function
1630 template <typename T>
1631 inline T compute_pow10(T d, const int exponent)
1633 static const double fract10[] =
1635 0.0,
1636 1.0E+001, 1.0E+002, 1.0E+003, 1.0E+004, 1.0E+005, 1.0E+006, 1.0E+007, 1.0E+008, 1.0E+009, 1.0E+010,
1637 1.0E+011, 1.0E+012, 1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016, 1.0E+017, 1.0E+018, 1.0E+019, 1.0E+020,
1638 1.0E+021, 1.0E+022, 1.0E+023, 1.0E+024, 1.0E+025, 1.0E+026, 1.0E+027, 1.0E+028, 1.0E+029, 1.0E+030,
1639 1.0E+031, 1.0E+032, 1.0E+033, 1.0E+034, 1.0E+035, 1.0E+036, 1.0E+037, 1.0E+038, 1.0E+039, 1.0E+040,
1640 1.0E+041, 1.0E+042, 1.0E+043, 1.0E+044, 1.0E+045, 1.0E+046, 1.0E+047, 1.0E+048, 1.0E+049, 1.0E+050,
1641 1.0E+051, 1.0E+052, 1.0E+053, 1.0E+054, 1.0E+055, 1.0E+056, 1.0E+057, 1.0E+058, 1.0E+059, 1.0E+060,
1642 1.0E+061, 1.0E+062, 1.0E+063, 1.0E+064, 1.0E+065, 1.0E+066, 1.0E+067, 1.0E+068, 1.0E+069, 1.0E+070,
1643 1.0E+071, 1.0E+072, 1.0E+073, 1.0E+074, 1.0E+075, 1.0E+076, 1.0E+077, 1.0E+078, 1.0E+079, 1.0E+080,
1644 1.0E+081, 1.0E+082, 1.0E+083, 1.0E+084, 1.0E+085, 1.0E+086, 1.0E+087, 1.0E+088, 1.0E+089, 1.0E+090,
1645 1.0E+091, 1.0E+092, 1.0E+093, 1.0E+094, 1.0E+095, 1.0E+096, 1.0E+097, 1.0E+098, 1.0E+099, 1.0E+100,
1646 1.0E+101, 1.0E+102, 1.0E+103, 1.0E+104, 1.0E+105, 1.0E+106, 1.0E+107, 1.0E+108, 1.0E+109, 1.0E+110,
1647 1.0E+111, 1.0E+112, 1.0E+113, 1.0E+114, 1.0E+115, 1.0E+116, 1.0E+117, 1.0E+118, 1.0E+119, 1.0E+120,
1648 1.0E+121, 1.0E+122, 1.0E+123, 1.0E+124, 1.0E+125, 1.0E+126, 1.0E+127, 1.0E+128, 1.0E+129, 1.0E+130,
1649 1.0E+131, 1.0E+132, 1.0E+133, 1.0E+134, 1.0E+135, 1.0E+136, 1.0E+137, 1.0E+138, 1.0E+139, 1.0E+140,
1650 1.0E+141, 1.0E+142, 1.0E+143, 1.0E+144, 1.0E+145, 1.0E+146, 1.0E+147, 1.0E+148, 1.0E+149, 1.0E+150,
1651 1.0E+151, 1.0E+152, 1.0E+153, 1.0E+154, 1.0E+155, 1.0E+156, 1.0E+157, 1.0E+158, 1.0E+159, 1.0E+160,
1652 1.0E+161, 1.0E+162, 1.0E+163, 1.0E+164, 1.0E+165, 1.0E+166, 1.0E+167, 1.0E+168, 1.0E+169, 1.0E+170,
1653 1.0E+171, 1.0E+172, 1.0E+173, 1.0E+174, 1.0E+175, 1.0E+176, 1.0E+177, 1.0E+178, 1.0E+179, 1.0E+180,
1654 1.0E+181, 1.0E+182, 1.0E+183, 1.0E+184, 1.0E+185, 1.0E+186, 1.0E+187, 1.0E+188, 1.0E+189, 1.0E+190,
1655 1.0E+191, 1.0E+192, 1.0E+193, 1.0E+194, 1.0E+195, 1.0E+196, 1.0E+197, 1.0E+198, 1.0E+199, 1.0E+200,
1656 1.0E+201, 1.0E+202, 1.0E+203, 1.0E+204, 1.0E+205, 1.0E+206, 1.0E+207, 1.0E+208, 1.0E+209, 1.0E+210,
1657 1.0E+211, 1.0E+212, 1.0E+213, 1.0E+214, 1.0E+215, 1.0E+216, 1.0E+217, 1.0E+218, 1.0E+219, 1.0E+220,
1658 1.0E+221, 1.0E+222, 1.0E+223, 1.0E+224, 1.0E+225, 1.0E+226, 1.0E+227, 1.0E+228, 1.0E+229, 1.0E+230,
1659 1.0E+231, 1.0E+232, 1.0E+233, 1.0E+234, 1.0E+235, 1.0E+236, 1.0E+237, 1.0E+238, 1.0E+239, 1.0E+240,
1660 1.0E+241, 1.0E+242, 1.0E+243, 1.0E+244, 1.0E+245, 1.0E+246, 1.0E+247, 1.0E+248, 1.0E+249, 1.0E+250,
1661 1.0E+251, 1.0E+252, 1.0E+253, 1.0E+254, 1.0E+255, 1.0E+256, 1.0E+257, 1.0E+258, 1.0E+259, 1.0E+260,
1662 1.0E+261, 1.0E+262, 1.0E+263, 1.0E+264, 1.0E+265, 1.0E+266, 1.0E+267, 1.0E+268, 1.0E+269, 1.0E+270,
1663 1.0E+271, 1.0E+272, 1.0E+273, 1.0E+274, 1.0E+275, 1.0E+276, 1.0E+277, 1.0E+278, 1.0E+279, 1.0E+280,
1664 1.0E+281, 1.0E+282, 1.0E+283, 1.0E+284, 1.0E+285, 1.0E+286, 1.0E+287, 1.0E+288, 1.0E+289, 1.0E+290,
1665 1.0E+291, 1.0E+292, 1.0E+293, 1.0E+294, 1.0E+295, 1.0E+296, 1.0E+297, 1.0E+298, 1.0E+299, 1.0E+300,
1666 1.0E+301, 1.0E+302, 1.0E+303, 1.0E+304, 1.0E+305, 1.0E+306, 1.0E+307, 1.0E+308
1669 static const int fract10_size = static_cast<int>(sizeof(fract10) / sizeof(double));
1671 const int e = std::abs(exponent);
1673 if (exponent >= std::numeric_limits<T>::min_exponent10)
1675 if (e < fract10_size)
1677 if (exponent > 0)
1678 return T(d * fract10[e]);
1679 else
1680 return T(d / fract10[e]);
1682 else
1683 return T(d * std::pow(10.0, 10.0 * exponent));
1685 else
1687 d /= T(fract10[ -std::numeric_limits<T>::min_exponent10]);
1688 return T(d / fract10[-exponent + std::numeric_limits<T>::min_exponent10]);
1692 template <typename Iterator, typename T>
1693 inline bool string_to_type_converter_impl_ref(Iterator& itr, const Iterator end, T& result)
1695 if (itr == end)
1696 return false;
1698 const bool negative = ('-' == (*itr));
1700 if (negative || ('+' == (*itr)))
1702 if (end == ++itr)
1703 return false;
1706 static const uchar_t zero = static_cast<uchar_t>('0');
1708 while ((end != itr) && (zero == (*itr))) ++itr;
1710 bool return_result = true;
1711 unsigned int digit = 0;
1712 const std::size_t length = static_cast<std::size_t>(std::distance(itr,end));
1714 if (length <= 4)
1716 exprtk_disable_fallthrough_begin
1717 switch (length)
1719 #ifdef exprtk_use_lut
1721 #define exprtk_process_digit \
1722 if ((digit = details::digit_table[(int)*itr++]) < 10) \
1723 result = result * 10 + (digit); \
1724 else \
1726 return_result = false; \
1727 break; \
1730 #else
1732 #define exprtk_process_digit \
1733 if ((digit = (*itr++ - zero)) < 10) \
1734 result = result * T(10) + digit; \
1735 else \
1737 return_result = false; \
1738 break; \
1741 #endif
1743 case 4 : exprtk_process_digit
1744 case 3 : exprtk_process_digit
1745 case 2 : exprtk_process_digit
1746 case 1 : if ((digit = (*itr - zero))>= 10) { digit = 0; return_result = false; }
1748 #undef exprtk_process_digit
1750 exprtk_disable_fallthrough_end
1752 else
1753 return_result = false;
1755 if (length && return_result)
1757 result = result * 10 + static_cast<T>(digit);
1758 ++itr;
1761 result = negative ? -result : result;
1762 return return_result;
1765 template <typename Iterator, typename T>
1766 static inline bool parse_nan(Iterator& itr, const Iterator end, T& t)
1768 typedef typename std::iterator_traits<Iterator>::value_type type;
1770 static const std::size_t nan_length = 3;
1772 if (std::distance(itr,end) != static_cast<int>(nan_length))
1773 return false;
1775 if (static_cast<type>('n') == (*itr))
1777 if (
1778 (static_cast<type>('a') != *(itr + 1)) ||
1779 (static_cast<type>('n') != *(itr + 2))
1782 return false;
1785 else if (
1786 (static_cast<type>('A') != *(itr + 1)) ||
1787 (static_cast<type>('N') != *(itr + 2))
1790 return false;
1793 t = std::numeric_limits<T>::quiet_NaN();
1795 return true;
1798 template <typename Iterator, typename T>
1799 static inline bool parse_inf(Iterator& itr, const Iterator end, T& t, bool negative)
1801 static const char_t inf_uc[] = "INFINITY";
1802 static const char_t inf_lc[] = "infinity";
1803 static const std::size_t inf_length = 8;
1805 const std::size_t length = static_cast<std::size_t>(std::distance(itr,end));
1807 if ((3 != length) && (inf_length != length))
1808 return false;
1810 char_cptr inf_itr = ('i' == (*itr)) ? inf_lc : inf_uc;
1812 while (end != itr)
1814 if (*inf_itr == static_cast<char>(*itr))
1816 ++itr;
1817 ++inf_itr;
1818 continue;
1820 else
1821 return false;
1824 if (negative)
1825 t = -std::numeric_limits<T>::infinity();
1826 else
1827 t = std::numeric_limits<T>::infinity();
1829 return true;
1832 template <typename Iterator, typename T>
1833 inline bool string_to_real(Iterator& itr_external, const Iterator end, T& t, numeric::details::real_type_tag)
1835 if (end == itr_external) return false;
1837 Iterator itr = itr_external;
1839 T d = T(0);
1841 const bool negative = ('-' == (*itr));
1843 if (negative || '+' == (*itr))
1845 if (end == ++itr)
1846 return false;
1849 bool instate = false;
1851 static const char_t zero = static_cast<uchar_t>('0');
1853 #define parse_digit_1(d) \
1854 if ((digit = (*itr - zero)) < 10) \
1855 { d = d * T(10) + digit; } \
1856 else \
1857 { break; } \
1858 if (end == ++itr) break; \
1860 #define parse_digit_2(d) \
1861 if ((digit = (*itr - zero)) < 10) \
1862 { d = d * T(10) + digit; } \
1863 else { break; } \
1864 ++itr; \
1866 if ('.' != (*itr))
1868 const Iterator curr = itr;
1870 while ((end != itr) && (zero == (*itr))) ++itr;
1872 unsigned int digit;
1874 while (end != itr)
1876 // Note: For 'physical' superscalar architectures it
1877 // is advised that the following loop be: 4xPD1 and 1xPD2
1878 #ifdef exprtk_enable_superscalar
1879 parse_digit_1(d)
1880 parse_digit_1(d)
1881 #endif
1882 parse_digit_1(d)
1883 parse_digit_1(d)
1884 parse_digit_2(d)
1887 if (curr != itr) instate = true;
1890 int exponent = 0;
1892 if (end != itr)
1894 if ('.' == (*itr))
1896 const Iterator curr = ++itr;
1897 unsigned int digit;
1898 T tmp_d = T(0);
1900 while (end != itr)
1902 #ifdef exprtk_enable_superscalar
1903 parse_digit_1(tmp_d)
1904 parse_digit_1(tmp_d)
1905 parse_digit_1(tmp_d)
1906 #endif
1907 parse_digit_1(tmp_d)
1908 parse_digit_1(tmp_d)
1909 parse_digit_2(tmp_d)
1912 if (curr != itr)
1914 instate = true;
1915 d += compute_pow10(tmp_d,static_cast<int>(-std::distance(curr,itr)));
1918 #undef parse_digit_1
1919 #undef parse_digit_2
1922 if (end != itr)
1924 typename std::iterator_traits<Iterator>::value_type c = (*itr);
1926 if (('e' == c) || ('E' == c))
1928 int exp = 0;
1930 if (!details::string_to_type_converter_impl_ref(++itr, end, exp))
1932 if (end == itr)
1933 return false;
1934 else
1935 c = (*itr);
1938 exponent += exp;
1941 if (end != itr)
1943 if (('f' == c) || ('F' == c) || ('l' == c) || ('L' == c))
1944 ++itr;
1945 else if ('#' == c)
1947 if (end == ++itr)
1948 return false;
1949 else if (('I' <= (*itr)) && ((*itr) <= 'n'))
1951 if (('i' == (*itr)) || ('I' == (*itr)))
1953 return parse_inf(itr, end, t, negative);
1955 else if (('n' == (*itr)) || ('N' == (*itr)))
1957 return parse_nan(itr, end, t);
1959 else
1960 return false;
1962 else
1963 return false;
1965 else if (('I' <= (*itr)) && ((*itr) <= 'n'))
1967 if (('i' == (*itr)) || ('I' == (*itr)))
1969 return parse_inf(itr, end, t, negative);
1971 else if (('n' == (*itr)) || ('N' == (*itr)))
1973 return parse_nan(itr, end, t);
1975 else
1976 return false;
1978 else
1979 return false;
1984 if ((end != itr) || (!instate))
1985 return false;
1986 else if (exponent)
1987 d = compute_pow10(d,exponent);
1989 t = static_cast<T>((negative) ? -d : d);
1990 return true;
1993 template <typename T>
1994 inline bool string_to_real(const std::string& s, T& t)
1996 const typename numeric::details::number_type<T>::type num_type;
1998 char_cptr begin = s.data();
1999 char_cptr end = s.data() + s.size();
2001 return string_to_real(begin, end, t, num_type);
2004 template <typename T>
2005 struct functor_t
2008 Note: The following definitions for Type, may require tweaking
2009 based on the compiler and target architecture. The benchmark
2010 should provide enough information to make the right choice.
2012 //typedef T Type;
2013 //typedef const T Type;
2014 typedef const T& Type;
2015 typedef T& RefType;
2016 typedef T (*qfunc_t)(Type t0, Type t1, Type t2, Type t3);
2017 typedef T (*tfunc_t)(Type t0, Type t1, Type t2);
2018 typedef T (*bfunc_t)(Type t0, Type t1);
2019 typedef T (*ufunc_t)(Type t0);
2022 } // namespace details
2024 namespace lexer
2026 struct token
2028 enum token_type
2030 e_none = 0, e_error = 1, e_err_symbol = 2,
2031 e_err_number = 3, e_err_string = 4, e_err_sfunc = 5,
2032 e_eof = 6, e_number = 7, e_symbol = 8,
2033 e_string = 9, e_assign = 10, e_addass = 11,
2034 e_subass = 12, e_mulass = 13, e_divass = 14,
2035 e_modass = 15, e_shr = 16, e_shl = 17,
2036 e_lte = 18, e_ne = 19, e_gte = 20,
2037 e_swap = 21, e_lt = '<', e_gt = '>',
2038 e_eq = '=', e_rbracket = ')', e_lbracket = '(',
2039 e_rsqrbracket = ']', e_lsqrbracket = '[', e_rcrlbracket = '}',
2040 e_lcrlbracket = '{', e_comma = ',', e_add = '+',
2041 e_sub = '-', e_div = '/', e_mul = '*',
2042 e_mod = '%', e_pow = '^', e_colon = ':',
2043 e_ternary = '?'
2046 token()
2047 : type(e_none),
2048 value(""),
2049 position(std::numeric_limits<std::size_t>::max())
2052 void clear()
2054 type = e_none;
2055 value = "";
2056 position = std::numeric_limits<std::size_t>::max();
2059 template <typename Iterator>
2060 inline token& set_operator(const token_type tt,
2061 const Iterator begin, const Iterator end,
2062 const Iterator base_begin = Iterator(0))
2064 type = tt;
2065 value.assign(begin,end);
2066 if (base_begin)
2067 position = static_cast<std::size_t>(std::distance(base_begin,begin));
2068 return (*this);
2071 template <typename Iterator>
2072 inline token& set_symbol(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
2074 type = e_symbol;
2075 value.assign(begin,end);
2076 if (base_begin)
2077 position = static_cast<std::size_t>(std::distance(base_begin,begin));
2078 return (*this);
2081 template <typename Iterator>
2082 inline token& set_numeric(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
2084 type = e_number;
2085 value.assign(begin,end);
2086 if (base_begin)
2087 position = static_cast<std::size_t>(std::distance(base_begin,begin));
2088 return (*this);
2091 template <typename Iterator>
2092 inline token& set_string(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
2094 type = e_string;
2095 value.assign(begin,end);
2096 if (base_begin)
2097 position = static_cast<std::size_t>(std::distance(base_begin,begin));
2098 return (*this);
2101 inline token& set_string(const std::string& s, const std::size_t p)
2103 type = e_string;
2104 value = s;
2105 position = p;
2106 return (*this);
2109 template <typename Iterator>
2110 inline token& set_error(const token_type et,
2111 const Iterator begin, const Iterator end,
2112 const Iterator base_begin = Iterator(0))
2114 if (
2115 (e_error == et) ||
2116 (e_err_symbol == et) ||
2117 (e_err_number == et) ||
2118 (e_err_string == et) ||
2119 (e_err_sfunc == et)
2122 type = et;
2124 else
2125 type = e_error;
2127 value.assign(begin,end);
2129 if (base_begin)
2130 position = static_cast<std::size_t>(std::distance(base_begin,begin));
2132 return (*this);
2135 static inline std::string to_str(token_type t)
2137 switch (t)
2139 case e_none : return "NONE";
2140 case e_error : return "ERROR";
2141 case e_err_symbol : return "ERROR_SYMBOL";
2142 case e_err_number : return "ERROR_NUMBER";
2143 case e_err_string : return "ERROR_STRING";
2144 case e_eof : return "EOF";
2145 case e_number : return "NUMBER";
2146 case e_symbol : return "SYMBOL";
2147 case e_string : return "STRING";
2148 case e_assign : return ":=";
2149 case e_addass : return "+=";
2150 case e_subass : return "-=";
2151 case e_mulass : return "*=";
2152 case e_divass : return "/=";
2153 case e_modass : return "%=";
2154 case e_shr : return ">>";
2155 case e_shl : return "<<";
2156 case e_lte : return "<=";
2157 case e_ne : return "!=";
2158 case e_gte : return ">=";
2159 case e_lt : return "<";
2160 case e_gt : return ">";
2161 case e_eq : return "=";
2162 case e_rbracket : return ")";
2163 case e_lbracket : return "(";
2164 case e_rsqrbracket : return "]";
2165 case e_lsqrbracket : return "[";
2166 case e_rcrlbracket : return "}";
2167 case e_lcrlbracket : return "{";
2168 case e_comma : return ",";
2169 case e_add : return "+";
2170 case e_sub : return "-";
2171 case e_div : return "/";
2172 case e_mul : return "*";
2173 case e_mod : return "%";
2174 case e_pow : return "^";
2175 case e_colon : return ":";
2176 case e_ternary : return "?";
2177 case e_swap : return "<=>";
2178 default : return "UNKNOWN";
2182 inline bool is_error() const
2184 return (
2185 (e_error == type) ||
2186 (e_err_symbol == type) ||
2187 (e_err_number == type) ||
2188 (e_err_string == type) ||
2189 (e_err_sfunc == type)
2193 token_type type;
2194 std::string value;
2195 std::size_t position;
2198 class generator
2200 public:
2202 typedef token token_t;
2203 typedef std::vector<token_t> token_list_t;
2204 typedef std::vector<token_t>::iterator token_list_itr_t;
2205 typedef details::char_t char_t;
2207 generator()
2208 : base_itr_(0),
2209 s_itr_ (0),
2210 s_end_ (0)
2212 clear();
2215 inline void clear()
2217 base_itr_ = 0;
2218 s_itr_ = 0;
2219 s_end_ = 0;
2220 token_list_.clear();
2221 token_itr_ = token_list_.end();
2222 store_token_itr_ = token_list_.end();
2225 inline bool process(const std::string& str)
2227 base_itr_ = str.data();
2228 s_itr_ = str.data();
2229 s_end_ = str.data() + str.size();
2231 eof_token_.set_operator(token_t::e_eof,s_end_,s_end_,base_itr_);
2232 token_list_.clear();
2234 while (!is_end(s_itr_))
2236 scan_token();
2238 if (!token_list_.empty() && token_list_.back().is_error())
2239 return false;
2242 return true;
2245 inline bool empty() const
2247 return token_list_.empty();
2250 inline std::size_t size() const
2252 return token_list_.size();
2255 inline void begin()
2257 token_itr_ = token_list_.begin();
2258 store_token_itr_ = token_list_.begin();
2261 inline void store()
2263 store_token_itr_ = token_itr_;
2266 inline void restore()
2268 token_itr_ = store_token_itr_;
2271 inline token_t& next_token()
2273 if (token_list_.end() != token_itr_)
2275 return *token_itr_++;
2277 else
2278 return eof_token_;
2281 inline token_t& peek_next_token()
2283 if (token_list_.end() != token_itr_)
2285 return *token_itr_;
2287 else
2288 return eof_token_;
2291 inline token_t& operator[](const std::size_t& index)
2293 if (index < token_list_.size())
2294 return token_list_[index];
2295 else
2296 return eof_token_;
2299 inline token_t operator[](const std::size_t& index) const
2301 if (index < token_list_.size())
2302 return token_list_[index];
2303 else
2304 return eof_token_;
2307 inline bool finished() const
2309 return (token_list_.end() == token_itr_);
2312 inline void insert_front(token_t::token_type tk_type)
2314 if (
2315 !token_list_.empty() &&
2316 (token_list_.end() != token_itr_)
2319 token_t t = *token_itr_;
2321 t.type = tk_type;
2322 token_itr_ = token_list_.insert(token_itr_,t);
2326 inline std::string substr(const std::size_t& begin, const std::size_t& end)
2328 const details::char_cptr begin_itr = ((base_itr_ + begin) < s_end_) ? (base_itr_ + begin) : s_end_;
2329 const details::char_cptr end_itr = ((base_itr_ + end) < s_end_) ? (base_itr_ + end) : s_end_;
2331 return std::string(begin_itr,end_itr);
2334 inline std::string remaining() const
2336 if (finished())
2337 return "";
2338 else if (token_list_.begin() != token_itr_)
2339 return std::string(base_itr_ + (token_itr_ - 1)->position, s_end_);
2340 else
2341 return std::string(base_itr_ + token_itr_->position, s_end_);
2344 private:
2346 inline bool is_end(details::char_cptr itr)
2348 return (s_end_ == itr);
2351 inline bool is_comment_start(details::char_cptr itr)
2353 #ifndef exprtk_disable_comments
2354 const char_t c0 = *(itr + 0);
2355 const char_t c1 = *(itr + 1);
2357 if ('#' == c0)
2358 return true;
2359 else if (!is_end(itr + 1))
2361 if (('/' == c0) && ('/' == c1)) return true;
2362 if (('/' == c0) && ('*' == c1)) return true;
2364 #endif
2365 return false;
2368 inline void skip_whitespace()
2370 while (!is_end(s_itr_) && details::is_whitespace(*s_itr_))
2372 ++s_itr_;
2376 inline void skip_comments()
2378 #ifndef exprtk_disable_comments
2379 // The following comment styles are supported:
2380 // 1. // .... \n
2381 // 2. # .... \n
2382 // 3. /* .... */
2383 struct test
2385 static inline bool comment_start(const char_t c0, const char_t c1, int& mode, int& incr)
2387 mode = 0;
2388 if ('#' == c0) { mode = 1; incr = 1; }
2389 else if ('/' == c0)
2391 if ('/' == c1) { mode = 1; incr = 2; }
2392 else if ('*' == c1) { mode = 2; incr = 2; }
2394 return (0 != mode);
2397 static inline bool comment_end(const char_t c0, const char_t c1, int& mode)
2399 if (
2400 ((1 == mode) && ('\n' == c0)) ||
2401 ((2 == mode) && ( '*' == c0) && ('/' == c1))
2404 mode = 0;
2405 return true;
2407 else
2408 return false;
2412 int mode = 0;
2413 int increment = 0;
2415 if (is_end(s_itr_))
2416 return;
2417 else if (!test::comment_start(*s_itr_, *(s_itr_ + 1), mode, increment))
2418 return;
2420 details::char_cptr cmt_start = s_itr_;
2422 s_itr_ += increment;
2424 while (!is_end(s_itr_))
2426 if ((1 == mode) && test::comment_end(*s_itr_, 0, mode))
2428 ++s_itr_;
2429 return;
2432 if ((2 == mode))
2434 if (!is_end((s_itr_ + 1)) && test::comment_end(*s_itr_, *(s_itr_ + 1), mode))
2436 s_itr_ += 2;
2437 return;
2441 ++s_itr_;
2444 if (2 == mode)
2446 token_t t;
2447 t.set_error(token::e_error, cmt_start, cmt_start + mode, base_itr_);
2448 token_list_.push_back(t);
2450 #endif
2453 inline void scan_token()
2455 if (details::is_whitespace(*s_itr_))
2457 skip_whitespace();
2458 return;
2460 else if (is_comment_start(s_itr_))
2462 skip_comments();
2463 return;
2465 else if (details::is_operator_char(*s_itr_))
2467 scan_operator();
2468 return;
2470 else if (details::is_letter(*s_itr_))
2472 scan_symbol();
2473 return;
2475 else if (details::is_digit((*s_itr_)) || ('.' == (*s_itr_)))
2477 scan_number();
2478 return;
2480 else if ('$' == (*s_itr_))
2482 scan_special_function();
2483 return;
2485 #ifndef exprtk_disable_string_capabilities
2486 else if ('\'' == (*s_itr_))
2488 scan_string();
2489 return;
2491 #endif
2492 else if ('~' == (*s_itr_))
2494 token_t t;
2495 t.set_symbol(s_itr_, s_itr_ + 1, base_itr_);
2496 token_list_.push_back(t);
2497 ++s_itr_;
2498 return;
2500 else
2502 token_t t;
2503 t.set_error(token::e_error, s_itr_, s_itr_ + 2, base_itr_);
2504 token_list_.push_back(t);
2505 ++s_itr_;
2509 inline void scan_operator()
2511 token_t t;
2513 const char_t c0 = s_itr_[0];
2515 if (!is_end(s_itr_ + 1))
2517 const char_t c1 = s_itr_[1];
2519 if (!is_end(s_itr_ + 2))
2521 const char_t c2 = s_itr_[2];
2523 if ((c0 == '<') && (c1 == '=') && (c2 == '>'))
2525 t.set_operator(token_t::e_swap, s_itr_, s_itr_ + 3, base_itr_);
2526 token_list_.push_back(t);
2527 s_itr_ += 3;
2528 return;
2532 token_t::token_type ttype = token_t::e_none;
2534 if ((c0 == '<') && (c1 == '=')) ttype = token_t::e_lte;
2535 else if ((c0 == '>') && (c1 == '=')) ttype = token_t::e_gte;
2536 else if ((c0 == '<') && (c1 == '>')) ttype = token_t::e_ne;
2537 else if ((c0 == '!') && (c1 == '=')) ttype = token_t::e_ne;
2538 else if ((c0 == '=') && (c1 == '=')) ttype = token_t::e_eq;
2539 else if ((c0 == ':') && (c1 == '=')) ttype = token_t::e_assign;
2540 else if ((c0 == '<') && (c1 == '<')) ttype = token_t::e_shl;
2541 else if ((c0 == '>') && (c1 == '>')) ttype = token_t::e_shr;
2542 else if ((c0 == '+') && (c1 == '=')) ttype = token_t::e_addass;
2543 else if ((c0 == '-') && (c1 == '=')) ttype = token_t::e_subass;
2544 else if ((c0 == '*') && (c1 == '=')) ttype = token_t::e_mulass;
2545 else if ((c0 == '/') && (c1 == '=')) ttype = token_t::e_divass;
2546 else if ((c0 == '%') && (c1 == '=')) ttype = token_t::e_modass;
2548 if (token_t::e_none != ttype)
2550 t.set_operator(ttype, s_itr_, s_itr_ + 2, base_itr_);
2551 token_list_.push_back(t);
2552 s_itr_ += 2;
2553 return;
2557 if ('<' == c0)
2558 t.set_operator(token_t::e_lt , s_itr_, s_itr_ + 1, base_itr_);
2559 else if ('>' == c0)
2560 t.set_operator(token_t::e_gt , s_itr_, s_itr_ + 1, base_itr_);
2561 else if (';' == c0)
2562 t.set_operator(token_t::e_eof, s_itr_, s_itr_ + 1, base_itr_);
2563 else if ('&' == c0)
2564 t.set_symbol(s_itr_, s_itr_ + 1, base_itr_);
2565 else if ('|' == c0)
2566 t.set_symbol(s_itr_, s_itr_ + 1, base_itr_);
2567 else
2568 t.set_operator(token_t::token_type(c0), s_itr_, s_itr_ + 1, base_itr_);
2570 token_list_.push_back(t);
2571 ++s_itr_;
2574 inline void scan_symbol()
2576 details::char_cptr initial_itr = s_itr_;
2578 while (!is_end(s_itr_))
2580 if (!details::is_letter_or_digit(*s_itr_) && ('_' != (*s_itr_)))
2582 if ('.' != (*s_itr_))
2583 break;
2585 Permit symbols that contain a 'dot'
2586 Allowed : abc.xyz, a123.xyz, abc.123, abc_.xyz a123_.xyz abc._123
2587 Disallowed: .abc, abc.<white-space>, abc.<eof>, abc.<operator +,-,*,/...>
2589 if (
2590 (s_itr_ != initial_itr) &&
2591 !is_end(s_itr_ + 1) &&
2592 !details::is_letter_or_digit(*(s_itr_ + 1)) &&
2593 ('_' != (*(s_itr_ + 1)))
2595 break;
2598 ++s_itr_;
2601 token_t t;
2602 t.set_symbol(initial_itr,s_itr_,base_itr_);
2603 token_list_.push_back(t);
2606 inline void scan_number()
2609 Attempt to match a valid numeric value in one of the following formats:
2610 (01) 123456
2611 (02) 123456.
2612 (03) 123.456
2613 (04) 123.456e3
2614 (05) 123.456E3
2615 (06) 123.456e+3
2616 (07) 123.456E+3
2617 (08) 123.456e-3
2618 (09) 123.456E-3
2619 (00) .1234
2620 (11) .1234e3
2621 (12) .1234E+3
2622 (13) .1234e+3
2623 (14) .1234E-3
2624 (15) .1234e-3
2627 details::char_cptr initial_itr = s_itr_;
2628 bool dot_found = false;
2629 bool e_found = false;
2630 bool post_e_sign_found = false;
2631 bool post_e_digit_found = false;
2632 token_t t;
2634 while (!is_end(s_itr_))
2636 if ('.' == (*s_itr_))
2638 if (dot_found)
2640 t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
2641 token_list_.push_back(t);
2642 return;
2645 dot_found = true;
2646 ++s_itr_;
2648 continue;
2650 else if ('e' == std::tolower(*s_itr_))
2652 const char_t& c = *(s_itr_ + 1);
2654 if (is_end(s_itr_ + 1))
2656 t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
2657 token_list_.push_back(t);
2659 return;
2661 else if (
2662 ('+' != c) &&
2663 ('-' != c) &&
2664 !details::is_digit(c)
2667 t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
2668 token_list_.push_back(t);
2670 return;
2673 e_found = true;
2674 ++s_itr_;
2676 continue;
2678 else if (e_found && details::is_sign(*s_itr_) && !post_e_digit_found)
2680 if (post_e_sign_found)
2682 t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
2683 token_list_.push_back(t);
2685 return;
2688 post_e_sign_found = true;
2689 ++s_itr_;
2691 continue;
2693 else if (e_found && details::is_digit(*s_itr_))
2695 post_e_digit_found = true;
2696 ++s_itr_;
2698 continue;
2700 else if (('.' != (*s_itr_)) && !details::is_digit(*s_itr_))
2701 break;
2702 else
2703 ++s_itr_;
2706 t.set_numeric(initial_itr, s_itr_, base_itr_);
2707 token_list_.push_back(t);
2709 return;
2712 inline void scan_special_function()
2714 details::char_cptr initial_itr = s_itr_;
2715 token_t t;
2717 // $fdd(x,x,x) = at least 11 chars
2718 if (std::distance(s_itr_,s_end_) < 11)
2720 t.set_error(token::e_err_sfunc, initial_itr, s_itr_, base_itr_);
2721 token_list_.push_back(t);
2723 return;
2726 if (
2727 !(('$' == *s_itr_) &&
2728 (details::imatch ('f',*(s_itr_ + 1))) &&
2729 (details::is_digit(*(s_itr_ + 2))) &&
2730 (details::is_digit(*(s_itr_ + 3))))
2733 t.set_error(token::e_err_sfunc, initial_itr, s_itr_, base_itr_);
2734 token_list_.push_back(t);
2736 return;
2739 s_itr_ += 4; // $fdd = 4chars
2741 t.set_symbol(initial_itr, s_itr_, base_itr_);
2742 token_list_.push_back(t);
2744 return;
2747 #ifndef exprtk_disable_string_capabilities
2748 inline void scan_string()
2750 details::char_cptr initial_itr = s_itr_ + 1;
2751 token_t t;
2753 if (std::distance(s_itr_,s_end_) < 2)
2755 t.set_error(token::e_err_string, s_itr_, s_end_, base_itr_);
2756 token_list_.push_back(t);
2757 return;
2760 ++s_itr_;
2762 bool escaped_found = false;
2763 bool escaped = false;
2765 while (!is_end(s_itr_))
2767 if (!escaped && ('\\' == *s_itr_))
2769 escaped_found = true;
2770 escaped = true;
2771 ++s_itr_;
2773 continue;
2775 else if (!escaped)
2777 if ('\'' == *s_itr_)
2778 break;
2780 else if (escaped)
2782 if (!is_end(s_itr_) && ('0' == *(s_itr_)))
2785 Note: The following 'awkward' conditional is
2786 due to various broken msvc compilers.
2788 #if defined(_MSC_VER) && (_MSC_VER == 1600)
2789 const bool within_range = !is_end(s_itr_ + 2) &&
2790 !is_end(s_itr_ + 3) ;
2791 #else
2792 const bool within_range = !is_end(s_itr_ + 1) &&
2793 !is_end(s_itr_ + 2) &&
2794 !is_end(s_itr_ + 3) ;
2795 #endif
2797 const bool x_seperator = ('x' == *(s_itr_ + 1)) ||
2798 ('X' == *(s_itr_ + 1)) ;
2800 const bool both_digits = details::is_hex_digit(*(s_itr_ + 2)) &&
2801 details::is_hex_digit(*(s_itr_ + 3)) ;
2803 if (!within_range || !x_seperator || !both_digits)
2805 t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_);
2806 token_list_.push_back(t);
2808 return;
2810 else
2811 s_itr_ += 3;
2814 escaped = false;
2817 ++s_itr_;
2820 if (is_end(s_itr_))
2822 t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_);
2823 token_list_.push_back(t);
2825 return;
2828 if (!escaped_found)
2829 t.set_string(initial_itr, s_itr_, base_itr_);
2830 else
2832 std::string parsed_string(initial_itr,s_itr_);
2834 details::cleanup_escapes(parsed_string);
2836 t.set_string(
2837 parsed_string,
2838 static_cast<std::size_t>(std::distance(base_itr_,initial_itr)));
2841 token_list_.push_back(t);
2842 ++s_itr_;
2844 return;
2846 #endif
2848 private:
2850 token_list_t token_list_;
2851 token_list_itr_t token_itr_;
2852 token_list_itr_t store_token_itr_;
2853 token_t eof_token_;
2854 details::char_cptr base_itr_;
2855 details::char_cptr s_itr_;
2856 details::char_cptr s_end_;
2858 friend class token_scanner;
2859 friend class token_modifier;
2860 friend class token_inserter;
2861 friend class token_joiner;
2864 class helper_interface
2866 public:
2868 virtual void init() { }
2869 virtual void reset() { }
2870 virtual bool result() { return true; }
2871 virtual std::size_t process(generator&) { return 0; }
2872 virtual ~helper_interface() { }
2875 class token_scanner : public helper_interface
2877 public:
2879 virtual ~token_scanner()
2882 explicit token_scanner(const std::size_t& stride)
2883 : stride_(stride)
2885 if (stride > 4)
2887 throw std::invalid_argument("token_scanner() - Invalid stride value");
2891 inline std::size_t process(generator& g)
2893 if (g.token_list_.size() >= stride_)
2895 for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i)
2897 token t;
2899 switch (stride_)
2901 case 1 :
2903 const token& t0 = g.token_list_[i];
2905 if (!operator()(t0))
2907 return i;
2910 break;
2912 case 2 :
2914 const token& t0 = g.token_list_[i ];
2915 const token& t1 = g.token_list_[i + 1];
2917 if (!operator()(t0, t1))
2919 return i;
2922 break;
2924 case 3 :
2926 const token& t0 = g.token_list_[i ];
2927 const token& t1 = g.token_list_[i + 1];
2928 const token& t2 = g.token_list_[i + 2];
2930 if (!operator()(t0, t1, t2))
2932 return i;
2935 break;
2937 case 4 :
2939 const token& t0 = g.token_list_[i ];
2940 const token& t1 = g.token_list_[i + 1];
2941 const token& t2 = g.token_list_[i + 2];
2942 const token& t3 = g.token_list_[i + 3];
2944 if (!operator()(t0, t1, t2, t3))
2946 return i;
2949 break;
2954 return (g.token_list_.size() - stride_ + 1);
2957 virtual bool operator() (const token&)
2959 return false;
2962 virtual bool operator() (const token&, const token&)
2964 return false;
2967 virtual bool operator() (const token&, const token&, const token&)
2969 return false;
2972 virtual bool operator() (const token&, const token&, const token&, const token&)
2974 return false;
2977 private:
2979 const std::size_t stride_;
2982 class token_modifier : public helper_interface
2984 public:
2986 inline std::size_t process(generator& g)
2988 std::size_t changes = 0;
2990 for (std::size_t i = 0; i < g.token_list_.size(); ++i)
2992 if (modify(g.token_list_[i])) changes++;
2995 return changes;
2998 virtual bool modify(token& t) = 0;
3001 class token_inserter : public helper_interface
3003 public:
3005 explicit token_inserter(const std::size_t& stride)
3006 : stride_(stride)
3008 if (stride > 5)
3010 throw std::invalid_argument("token_inserter() - Invalid stride value");
3014 inline std::size_t process(generator& g)
3016 if (g.token_list_.empty())
3017 return 0;
3018 else if (g.token_list_.size() < stride_)
3019 return 0;
3021 std::size_t changes = 0;
3023 for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i)
3025 int insert_index = -1;
3026 token t;
3028 switch (stride_)
3030 case 1 : insert_index = insert(g.token_list_[i],t);
3031 break;
3033 case 2 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], t);
3034 break;
3036 case 3 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], g.token_list_[i + 2], t);
3037 break;
3039 case 4 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], g.token_list_[i + 2], g.token_list_[i + 3], t);
3040 break;
3042 case 5 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], g.token_list_[i + 2], g.token_list_[i + 3], g.token_list_[i + 4], t);
3043 break;
3046 typedef std::iterator_traits<generator::token_list_t::iterator>::difference_type diff_t;
3048 if ((insert_index >= 0) && (insert_index <= (static_cast<int>(stride_) + 1)))
3050 g.token_list_.insert(
3051 g.token_list_.begin() + static_cast<diff_t>(i + static_cast<std::size_t>(insert_index)), t);
3053 changes++;
3057 return changes;
3060 #define token_inserter_empty_body \
3062 return -1; \
3065 inline virtual int insert(const token&, token&)
3066 token_inserter_empty_body
3068 inline virtual int insert(const token&, const token&, token&)
3069 token_inserter_empty_body
3071 inline virtual int insert(const token&, const token&, const token&, token&)
3072 token_inserter_empty_body
3074 inline virtual int insert(const token&, const token&, const token&, const token&, token&)
3075 token_inserter_empty_body
3077 inline virtual int insert(const token&, const token&, const token&, const token&, const token&, token&)
3078 token_inserter_empty_body
3080 #undef token_inserter_empty_body
3082 private:
3084 const std::size_t stride_;
3087 class token_joiner : public helper_interface
3089 public:
3091 explicit token_joiner(const std::size_t& stride)
3092 : stride_(stride)
3095 inline std::size_t process(generator& g)
3097 if (g.token_list_.empty())
3098 return 0;
3100 switch (stride_)
3102 case 2 : return process_stride_2(g);
3103 case 3 : return process_stride_3(g);
3104 default : return 0;
3108 virtual bool join(const token&, const token&, token&) { return false; }
3109 virtual bool join(const token&, const token&, const token&, token&) { return false; }
3111 private:
3113 inline std::size_t process_stride_2(generator& g)
3115 typedef std::iterator_traits<generator::token_list_t::iterator>::difference_type diff_t;
3117 if (g.token_list_.size() < 2)
3118 return 0;
3120 std::size_t changes = 0;
3122 for (int i = 0; i < static_cast<int>(g.token_list_.size() - 1); ++i)
3124 token t;
3126 while (join(g[i], g[i + 1], t))
3128 g.token_list_[i] = t;
3130 g.token_list_.erase(g.token_list_.begin() + static_cast<diff_t>(i + 1));
3132 ++changes;
3134 if (static_cast<std::size_t>(i + 1) >= g.token_list_.size())
3135 break;
3139 return changes;
3142 inline std::size_t process_stride_3(generator& g)
3144 typedef std::iterator_traits<generator::token_list_t::iterator>::difference_type diff_t;
3146 if (g.token_list_.size() < 3)
3147 return 0;
3149 std::size_t changes = 0;
3151 for (int i = 0; i < static_cast<int>(g.token_list_.size() - 2); ++i)
3153 token t;
3155 while (join(g[i], g[i + 1], g[i + 2], t))
3157 g.token_list_[i] = t;
3159 g.token_list_.erase(g.token_list_.begin() + static_cast<diff_t>(i + 1),
3160 g.token_list_.begin() + static_cast<diff_t>(i + 3));
3161 ++changes;
3163 if (static_cast<std::size_t>(i + 2) >= g.token_list_.size())
3164 break;
3168 return changes;
3171 const std::size_t stride_;
3174 namespace helper
3177 inline void dump(lexer::generator& generator)
3179 for (std::size_t i = 0; i < generator.size(); ++i)
3181 lexer::token t = generator[i];
3182 printf("Token[%02d] @ %03d %6s --> '%s'\n",
3183 static_cast<int>(i),
3184 static_cast<int>(t.position),
3185 t.to_str(t.type).c_str(),
3186 t.value.c_str());
3190 class commutative_inserter : public lexer::token_inserter
3192 public:
3194 using lexer::token_inserter::insert;
3196 commutative_inserter()
3197 : lexer::token_inserter(2)
3200 inline void ignore_symbol(const std::string& symbol)
3202 ignore_set_.insert(symbol);
3205 inline int insert(const lexer::token& t0, const lexer::token& t1, lexer::token& new_token)
3207 bool match = false;
3208 new_token.type = lexer::token::e_mul;
3209 new_token.value = "*";
3210 new_token.position = t1.position;
3212 if (t0.type == lexer::token::e_symbol)
3214 if (ignore_set_.end() != ignore_set_.find(t0.value))
3216 return -1;
3218 else if (!t0.value.empty() && ('$' == t0.value[0]))
3220 return -1;
3224 if (t1.type == lexer::token::e_symbol)
3226 if (ignore_set_.end() != ignore_set_.find(t1.value))
3228 return -1;
3231 if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_symbol )) match = true;
3232 else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lbracket )) match = true;
3233 else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lcrlbracket)) match = true;
3234 else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lsqrbracket)) match = true;
3235 else if ((t0.type == lexer::token::e_symbol ) && (t1.type == lexer::token::e_number )) match = true;
3236 else if ((t0.type == lexer::token::e_rbracket ) && (t1.type == lexer::token::e_number )) match = true;
3237 else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_number )) match = true;
3238 else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_number )) match = true;
3239 else if ((t0.type == lexer::token::e_rbracket ) && (t1.type == lexer::token::e_symbol )) match = true;
3240 else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_symbol )) match = true;
3241 else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_symbol )) match = true;
3242 else if ((t0.type == lexer::token::e_symbol ) && (t1.type == lexer::token::e_symbol )) match = true;
3244 return (match) ? 1 : -1;
3247 private:
3249 std::set<std::string,details::ilesscompare> ignore_set_;
3252 class operator_joiner : public token_joiner
3254 public:
3256 explicit operator_joiner(const std::size_t& stride)
3257 : token_joiner(stride)
3260 inline bool join(const lexer::token& t0, const lexer::token& t1, lexer::token& t)
3262 // ': =' --> ':='
3263 if ((t0.type == lexer::token::e_colon) && (t1.type == lexer::token::e_eq))
3265 t.type = lexer::token::e_assign;
3266 t.value = ":=";
3267 t.position = t0.position;
3269 return true;
3271 // '+ =' --> '+='
3272 else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_eq))
3274 t.type = lexer::token::e_addass;
3275 t.value = "+=";
3276 t.position = t0.position;
3278 return true;
3280 // '- =' --> '-='
3281 else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_eq))
3283 t.type = lexer::token::e_subass;
3284 t.value = "-=";
3285 t.position = t0.position;
3287 return true;
3289 // '* =' --> '*='
3290 else if ((t0.type == lexer::token::e_mul) && (t1.type == lexer::token::e_eq))
3292 t.type = lexer::token::e_mulass;
3293 t.value = "*=";
3294 t.position = t0.position;
3296 return true;
3298 // '/ =' --> '/='
3299 else if ((t0.type == lexer::token::e_div) && (t1.type == lexer::token::e_eq))
3301 t.type = lexer::token::e_divass;
3302 t.value = "/=";
3303 t.position = t0.position;
3305 return true;
3307 // '% =' --> '%='
3308 else if ((t0.type == lexer::token::e_mod) && (t1.type == lexer::token::e_eq))
3310 t.type = lexer::token::e_modass;
3311 t.value = "%=";
3312 t.position = t0.position;
3314 return true;
3316 // '> =' --> '>='
3317 else if ((t0.type == lexer::token::e_gt) && (t1.type == lexer::token::e_eq))
3319 t.type = lexer::token::e_gte;
3320 t.value = ">=";
3321 t.position = t0.position;
3323 return true;
3325 // '< =' --> '<='
3326 else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_eq))
3328 t.type = lexer::token::e_lte;
3329 t.value = "<=";
3330 t.position = t0.position;
3332 return true;
3334 // '= =' --> '=='
3335 else if ((t0.type == lexer::token::e_eq) && (t1.type == lexer::token::e_eq))
3337 t.type = lexer::token::e_eq;
3338 t.value = "==";
3339 t.position = t0.position;
3341 return true;
3343 // '! =' --> '!='
3344 else if ((static_cast<char>(t0.type) == '!') && (t1.type == lexer::token::e_eq))
3346 t.type = lexer::token::e_ne;
3347 t.value = "!=";
3348 t.position = t0.position;
3350 return true;
3352 // '< >' --> '<>'
3353 else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_gt))
3355 t.type = lexer::token::e_ne;
3356 t.value = "<>";
3357 t.position = t0.position;
3359 return true;
3361 // '<= >' --> '<=>'
3362 else if ((t0.type == lexer::token::e_lte) && (t1.type == lexer::token::e_gt))
3364 t.type = lexer::token::e_swap;
3365 t.value = "<=>";
3366 t.position = t0.position;
3368 return true;
3370 // '+ -' --> '-'
3371 else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_sub))
3373 t.type = lexer::token::e_sub;
3374 t.value = "-";
3375 t.position = t0.position;
3377 return true;
3379 // '- +' --> '-'
3380 else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_add))
3382 t.type = lexer::token::e_sub;
3383 t.value = "-";
3384 t.position = t0.position;
3386 return true;
3388 // '- -' --> '+'
3389 else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_sub))
3392 Note: May need to reconsider this when wanting to implement
3393 pre/postfix decrement operator
3395 t.type = lexer::token::e_add;
3396 t.value = "+";
3397 t.position = t0.position;
3399 return true;
3401 else
3402 return false;
3405 inline bool join(const lexer::token& t0, const lexer::token& t1, const lexer::token& t2, lexer::token& t)
3407 // '[ * ]' --> '[*]'
3408 if (
3409 (t0.type == lexer::token::e_lsqrbracket) &&
3410 (t1.type == lexer::token::e_mul ) &&
3411 (t2.type == lexer::token::e_rsqrbracket)
3414 t.type = lexer::token::e_symbol;
3415 t.value = "[*]";
3416 t.position = t0.position;
3418 return true;
3420 else
3421 return false;
3425 class bracket_checker : public lexer::token_scanner
3427 public:
3429 using lexer::token_scanner::operator();
3431 bracket_checker()
3432 : token_scanner(1),
3433 state_(true)
3436 bool result()
3438 if (!stack_.empty())
3440 lexer::token t;
3441 t.value = stack_.top().first;
3442 t.position = stack_.top().second;
3443 error_token_ = t;
3444 state_ = false;
3446 return false;
3448 else
3449 return state_;
3452 lexer::token error_token()
3454 return error_token_;
3457 void reset()
3459 // Why? because msvc doesn't support swap properly.
3460 stack_ = std::stack<std::pair<char,std::size_t> >();
3461 state_ = true;
3462 error_token_.clear();
3465 bool operator() (const lexer::token& t)
3467 if (
3468 !t.value.empty() &&
3469 (lexer::token::e_string != t.type) &&
3470 (lexer::token::e_symbol != t.type) &&
3471 exprtk::details::is_bracket(t.value[0])
3474 details::char_t c = t.value[0];
3476 if (t.type == lexer::token::e_lbracket ) stack_.push(std::make_pair(')',t.position));
3477 else if (t.type == lexer::token::e_lcrlbracket) stack_.push(std::make_pair('}',t.position));
3478 else if (t.type == lexer::token::e_lsqrbracket) stack_.push(std::make_pair(']',t.position));
3479 else if (exprtk::details::is_right_bracket(c))
3481 if (stack_.empty())
3483 state_ = false;
3484 error_token_ = t;
3486 return false;
3488 else if (c != stack_.top().first)
3490 state_ = false;
3491 error_token_ = t;
3493 return false;
3495 else
3496 stack_.pop();
3500 return true;
3503 private:
3505 bool state_;
3506 std::stack<std::pair<char,std::size_t> > stack_;
3507 lexer::token error_token_;
3510 class numeric_checker : public lexer::token_scanner
3512 public:
3514 using lexer::token_scanner::operator();
3516 numeric_checker()
3517 : token_scanner (1),
3518 current_index_(0)
3521 bool result()
3523 return error_list_.empty();
3526 void reset()
3528 error_list_.clear();
3529 current_index_ = 0;
3532 bool operator() (const lexer::token& t)
3534 if (token::e_number == t.type)
3536 double v;
3538 if (!exprtk::details::string_to_real(t.value,v))
3540 error_list_.push_back(current_index_);
3544 ++current_index_;
3546 return true;
3549 std::size_t error_count() const
3551 return error_list_.size();
3554 std::size_t error_index(const std::size_t& i)
3556 if (i < error_list_.size())
3557 return error_list_[i];
3558 else
3559 return std::numeric_limits<std::size_t>::max();
3562 void clear_errors()
3564 error_list_.clear();
3567 private:
3569 std::size_t current_index_;
3570 std::vector<std::size_t> error_list_;
3573 class symbol_replacer : public lexer::token_modifier
3575 private:
3577 typedef std::map<std::string,std::pair<std::string,token::token_type>,details::ilesscompare> replace_map_t;
3579 public:
3581 bool remove(const std::string& target_symbol)
3583 const replace_map_t::iterator itr = replace_map_.find(target_symbol);
3585 if (replace_map_.end() == itr)
3586 return false;
3588 replace_map_.erase(itr);
3590 return true;
3593 bool add_replace(const std::string& target_symbol,
3594 const std::string& replace_symbol,
3595 const lexer::token::token_type token_type = lexer::token::e_symbol)
3597 const replace_map_t::iterator itr = replace_map_.find(target_symbol);
3599 if (replace_map_.end() != itr)
3601 return false;
3604 replace_map_[target_symbol] = std::make_pair(replace_symbol,token_type);
3606 return true;
3609 void clear()
3611 replace_map_.clear();
3614 private:
3616 bool modify(lexer::token& t)
3618 if (lexer::token::e_symbol == t.type)
3620 if (replace_map_.empty())
3621 return false;
3623 const replace_map_t::iterator itr = replace_map_.find(t.value);
3625 if (replace_map_.end() != itr)
3627 t.value = itr->second.first;
3628 t.type = itr->second.second;
3630 return true;
3634 return false;
3637 replace_map_t replace_map_;
3640 class sequence_validator : public lexer::token_scanner
3642 private:
3644 typedef std::pair<lexer::token::token_type,lexer::token::token_type> token_pair_t;
3645 typedef std::set<token_pair_t> set_t;
3647 public:
3649 using lexer::token_scanner::operator();
3651 sequence_validator()
3652 : lexer::token_scanner(2)
3654 add_invalid(lexer::token::e_number, lexer::token::e_number);
3655 add_invalid(lexer::token::e_string, lexer::token::e_string);
3656 add_invalid(lexer::token::e_number, lexer::token::e_string);
3657 add_invalid(lexer::token::e_string, lexer::token::e_number);
3659 add_invalid_set1(lexer::token::e_assign );
3660 add_invalid_set1(lexer::token::e_shr );
3661 add_invalid_set1(lexer::token::e_shl );
3662 add_invalid_set1(lexer::token::e_lte );
3663 add_invalid_set1(lexer::token::e_ne );
3664 add_invalid_set1(lexer::token::e_gte );
3665 add_invalid_set1(lexer::token::e_lt );
3666 add_invalid_set1(lexer::token::e_gt );
3667 add_invalid_set1(lexer::token::e_eq );
3668 add_invalid_set1(lexer::token::e_comma );
3669 add_invalid_set1(lexer::token::e_add );
3670 add_invalid_set1(lexer::token::e_sub );
3671 add_invalid_set1(lexer::token::e_div );
3672 add_invalid_set1(lexer::token::e_mul );
3673 add_invalid_set1(lexer::token::e_mod );
3674 add_invalid_set1(lexer::token::e_pow );
3675 add_invalid_set1(lexer::token::e_colon );
3676 add_invalid_set1(lexer::token::e_ternary);
3679 bool result()
3681 return error_list_.empty();
3684 bool operator() (const lexer::token& t0, const lexer::token& t1)
3686 const set_t::value_type p = std::make_pair(t0.type,t1.type);
3688 if (invalid_bracket_check(t0.type,t1.type))
3690 error_list_.push_back(std::make_pair(t0,t1));
3692 else if (invalid_comb_.find(p) != invalid_comb_.end())
3694 error_list_.push_back(std::make_pair(t0,t1));
3697 return true;
3700 std::size_t error_count() const
3702 return error_list_.size();
3705 std::pair<lexer::token,lexer::token> error(const std::size_t index)
3707 if (index < error_list_.size())
3709 return error_list_[index];
3711 else
3713 static const lexer::token error_token;
3714 return std::make_pair(error_token,error_token);
3718 void clear_errors()
3720 error_list_.clear();
3723 private:
3725 void add_invalid(lexer::token::token_type base, lexer::token::token_type t)
3727 invalid_comb_.insert(std::make_pair(base,t));
3730 void add_invalid_set1(lexer::token::token_type t)
3732 add_invalid(t, lexer::token::e_assign);
3733 add_invalid(t, lexer::token::e_shr );
3734 add_invalid(t, lexer::token::e_shl );
3735 add_invalid(t, lexer::token::e_lte );
3736 add_invalid(t, lexer::token::e_ne );
3737 add_invalid(t, lexer::token::e_gte );
3738 add_invalid(t, lexer::token::e_lt );
3739 add_invalid(t, lexer::token::e_gt );
3740 add_invalid(t, lexer::token::e_eq );
3741 add_invalid(t, lexer::token::e_comma );
3742 add_invalid(t, lexer::token::e_div );
3743 add_invalid(t, lexer::token::e_mul );
3744 add_invalid(t, lexer::token::e_mod );
3745 add_invalid(t, lexer::token::e_pow );
3746 add_invalid(t, lexer::token::e_colon );
3749 bool invalid_bracket_check(lexer::token::token_type base, lexer::token::token_type t)
3751 if (details::is_right_bracket(static_cast<char>(base)))
3753 switch (t)
3755 case lexer::token::e_assign : return (']' != base);
3756 case lexer::token::e_string : return (')' != base);
3757 default : return false;
3760 else if (details::is_left_bracket(static_cast<char>(base)))
3762 if (details::is_right_bracket(static_cast<char>(t)))
3763 return false;
3764 else if (details::is_left_bracket(static_cast<char>(t)))
3765 return false;
3766 else
3768 switch (t)
3770 case lexer::token::e_number : return false;
3771 case lexer::token::e_symbol : return false;
3772 case lexer::token::e_string : return false;
3773 case lexer::token::e_add : return false;
3774 case lexer::token::e_sub : return false;
3775 case lexer::token::e_colon : return false;
3776 case lexer::token::e_ternary : return false;
3777 default : return true ;
3781 else if (details::is_right_bracket(static_cast<char>(t)))
3783 switch (base)
3785 case lexer::token::e_number : return false;
3786 case lexer::token::e_symbol : return false;
3787 case lexer::token::e_string : return false;
3788 case lexer::token::e_eof : return false;
3789 case lexer::token::e_colon : return false;
3790 case lexer::token::e_ternary : return false;
3791 default : return true ;
3794 else if (details::is_left_bracket(static_cast<char>(t)))
3796 switch (base)
3798 case lexer::token::e_rbracket : return true;
3799 case lexer::token::e_rsqrbracket : return true;
3800 case lexer::token::e_rcrlbracket : return true;
3801 default : return false;
3805 return false;
3808 set_t invalid_comb_;
3809 std::vector<std::pair<lexer::token,lexer::token> > error_list_;
3812 class sequence_validator_3tokens : public lexer::token_scanner
3814 private:
3816 typedef lexer::token::token_type token_t;
3817 typedef std::pair<token_t,std::pair<token_t,token_t> > token_triplet_t;
3818 typedef std::set<token_triplet_t> set_t;
3820 public:
3822 using lexer::token_scanner::operator();
3824 sequence_validator_3tokens()
3825 : lexer::token_scanner(3)
3827 add_invalid(lexer::token::e_number, lexer::token::e_number, lexer::token::e_number);
3828 add_invalid(lexer::token::e_string, lexer::token::e_string, lexer::token::e_string);
3829 add_invalid(lexer::token::e_comma , lexer::token::e_comma , lexer::token::e_comma );
3831 add_invalid(lexer::token::e_add , lexer::token::e_add , lexer::token::e_add );
3832 add_invalid(lexer::token::e_sub , lexer::token::e_sub , lexer::token::e_sub );
3833 add_invalid(lexer::token::e_div , lexer::token::e_div , lexer::token::e_div );
3834 add_invalid(lexer::token::e_mul , lexer::token::e_mul , lexer::token::e_mul );
3835 add_invalid(lexer::token::e_mod , lexer::token::e_mod , lexer::token::e_mod );
3836 add_invalid(lexer::token::e_pow , lexer::token::e_pow , lexer::token::e_pow );
3838 add_invalid(lexer::token::e_add , lexer::token::e_sub , lexer::token::e_add );
3839 add_invalid(lexer::token::e_sub , lexer::token::e_add , lexer::token::e_sub );
3840 add_invalid(lexer::token::e_div , lexer::token::e_mul , lexer::token::e_div );
3841 add_invalid(lexer::token::e_mul , lexer::token::e_div , lexer::token::e_mul );
3842 add_invalid(lexer::token::e_mod , lexer::token::e_pow , lexer::token::e_mod );
3843 add_invalid(lexer::token::e_pow , lexer::token::e_mod , lexer::token::e_pow );
3846 bool result()
3848 return error_list_.empty();
3851 bool operator() (const lexer::token& t0, const lexer::token& t1, const lexer::token& t2)
3853 const set_t::value_type p = std::make_pair(t0.type,std::make_pair(t1.type,t2.type));
3855 if (invalid_comb_.find(p) != invalid_comb_.end())
3857 error_list_.push_back(std::make_pair(t0,t1));
3860 return true;
3863 std::size_t error_count() const
3865 return error_list_.size();
3868 std::pair<lexer::token,lexer::token> error(const std::size_t index)
3870 if (index < error_list_.size())
3872 return error_list_[index];
3874 else
3876 static const lexer::token error_token;
3877 return std::make_pair(error_token,error_token);
3881 void clear_errors()
3883 error_list_.clear();
3886 private:
3888 void add_invalid(token_t t0, token_t t1, token_t t2)
3890 invalid_comb_.insert(std::make_pair(t0,std::make_pair(t1,t2)));
3893 set_t invalid_comb_;
3894 std::vector<std::pair<lexer::token,lexer::token> > error_list_;
3897 struct helper_assembly
3899 inline bool register_scanner(lexer::token_scanner* scanner)
3901 if (token_scanner_list.end() != std::find(token_scanner_list.begin(),
3902 token_scanner_list.end (),
3903 scanner))
3905 return false;
3908 token_scanner_list.push_back(scanner);
3910 return true;
3913 inline bool register_modifier(lexer::token_modifier* modifier)
3915 if (token_modifier_list.end() != std::find(token_modifier_list.begin(),
3916 token_modifier_list.end (),
3917 modifier))
3919 return false;
3922 token_modifier_list.push_back(modifier);
3924 return true;
3927 inline bool register_joiner(lexer::token_joiner* joiner)
3929 if (token_joiner_list.end() != std::find(token_joiner_list.begin(),
3930 token_joiner_list.end (),
3931 joiner))
3933 return false;
3936 token_joiner_list.push_back(joiner);
3938 return true;
3941 inline bool register_inserter(lexer::token_inserter* inserter)
3943 if (token_inserter_list.end() != std::find(token_inserter_list.begin(),
3944 token_inserter_list.end (),
3945 inserter))
3947 return false;
3950 token_inserter_list.push_back(inserter);
3952 return true;
3955 inline bool run_modifiers(lexer::generator& g)
3957 error_token_modifier = reinterpret_cast<lexer::token_modifier*>(0);
3959 for (std::size_t i = 0; i < token_modifier_list.size(); ++i)
3961 lexer::token_modifier& modifier = (*token_modifier_list[i]);
3963 modifier.reset();
3964 modifier.process(g);
3966 if (!modifier.result())
3968 error_token_modifier = token_modifier_list[i];
3970 return false;
3974 return true;
3977 inline bool run_joiners(lexer::generator& g)
3979 error_token_joiner = reinterpret_cast<lexer::token_joiner*>(0);
3981 for (std::size_t i = 0; i < token_joiner_list.size(); ++i)
3983 lexer::token_joiner& joiner = (*token_joiner_list[i]);
3985 joiner.reset();
3986 joiner.process(g);
3988 if (!joiner.result())
3990 error_token_joiner = token_joiner_list[i];
3992 return false;
3996 return true;
3999 inline bool run_inserters(lexer::generator& g)
4001 error_token_inserter = reinterpret_cast<lexer::token_inserter*>(0);
4003 for (std::size_t i = 0; i < token_inserter_list.size(); ++i)
4005 lexer::token_inserter& inserter = (*token_inserter_list[i]);
4007 inserter.reset();
4008 inserter.process(g);
4010 if (!inserter.result())
4012 error_token_inserter = token_inserter_list[i];
4014 return false;
4018 return true;
4021 inline bool run_scanners(lexer::generator& g)
4023 error_token_scanner = reinterpret_cast<lexer::token_scanner*>(0);
4025 for (std::size_t i = 0; i < token_scanner_list.size(); ++i)
4027 lexer::token_scanner& scanner = (*token_scanner_list[i]);
4029 scanner.reset();
4030 scanner.process(g);
4032 if (!scanner.result())
4034 error_token_scanner = token_scanner_list[i];
4036 return false;
4040 return true;
4043 std::vector<lexer::token_scanner*> token_scanner_list;
4044 std::vector<lexer::token_modifier*> token_modifier_list;
4045 std::vector<lexer::token_joiner*> token_joiner_list;
4046 std::vector<lexer::token_inserter*> token_inserter_list;
4048 lexer::token_scanner* error_token_scanner;
4049 lexer::token_modifier* error_token_modifier;
4050 lexer::token_joiner* error_token_joiner;
4051 lexer::token_inserter* error_token_inserter;
4055 class parser_helper
4057 public:
4059 typedef token token_t;
4060 typedef generator generator_t;
4062 inline bool init(const std::string& str)
4064 if (!lexer_.process(str))
4066 return false;
4069 lexer_.begin();
4071 next_token();
4073 return true;
4076 inline generator_t& lexer()
4078 return lexer_;
4081 inline const generator_t& lexer() const
4083 return lexer_;
4086 inline void store_token()
4088 lexer_.store();
4089 store_current_token_ = current_token_;
4092 inline void restore_token()
4094 lexer_.restore();
4095 current_token_ = store_current_token_;
4098 inline void next_token()
4100 current_token_ = lexer_.next_token();
4103 inline const token_t& current_token() const
4105 return current_token_;
4108 enum token_advance_mode
4110 e_hold = 0,
4111 e_advance = 1
4114 inline void advance_token(const token_advance_mode mode)
4116 if (e_advance == mode)
4118 next_token();
4122 inline bool token_is(const token_t::token_type& ttype, const token_advance_mode mode = e_advance)
4124 if (current_token().type != ttype)
4126 return false;
4129 advance_token(mode);
4131 return true;
4134 inline bool token_is(const token_t::token_type& ttype,
4135 const std::string& value,
4136 const token_advance_mode mode = e_advance)
4138 if (
4139 (current_token().type != ttype) ||
4140 !exprtk::details::imatch(value,current_token().value)
4143 return false;
4146 advance_token(mode);
4148 return true;
4151 inline bool peek_token_is(const token_t::token_type& ttype)
4153 return (lexer_.peek_next_token().type == ttype);
4156 inline bool peek_token_is(const std::string& s)
4158 return (exprtk::details::imatch(lexer_.peek_next_token().value,s));
4161 private:
4163 generator_t lexer_;
4164 token_t current_token_;
4165 token_t store_current_token_;
4169 template <typename T>
4170 class vector_view
4172 public:
4174 typedef T* data_ptr_t;
4176 vector_view(data_ptr_t data, const std::size_t& size)
4177 : size_(size),
4178 data_(data),
4179 data_ref_(0)
4182 vector_view(const vector_view<T>& vv)
4183 : size_(vv.size_),
4184 data_(vv.data_),
4185 data_ref_(0)
4188 inline void rebase(data_ptr_t data)
4190 data_ = data;
4192 if (!data_ref_.empty())
4194 for (std::size_t i = 0; i < data_ref_.size(); ++i)
4196 (*data_ref_[i]) = data;
4201 inline data_ptr_t data() const
4203 return data_;
4206 inline std::size_t size() const
4208 return size_;
4211 inline const T& operator[](const std::size_t index) const
4213 return data_[index];
4216 inline T& operator[](const std::size_t index)
4218 return data_[index];
4221 void set_ref(data_ptr_t* data_ref)
4223 data_ref_.push_back(data_ref);
4226 private:
4228 const std::size_t size_;
4229 data_ptr_t data_;
4230 std::vector<data_ptr_t*> data_ref_;
4233 template <typename T>
4234 inline vector_view<T> make_vector_view(T* data,
4235 const std::size_t size, const std::size_t offset = 0)
4237 return vector_view<T>(data + offset, size);
4240 template <typename T>
4241 inline vector_view<T> make_vector_view(std::vector<T>& v,
4242 const std::size_t size, const std::size_t offset = 0)
4244 return vector_view<T>(v.data() + offset, size);
4247 template <typename T> class results_context;
4249 template <typename T>
4250 struct type_store
4252 enum store_type
4254 e_unknown,
4255 e_scalar ,
4256 e_vector ,
4257 e_string
4260 type_store()
4261 : data(0),
4262 size(0),
4263 type(e_unknown)
4266 union
4268 void* data;
4269 T* vec_data;
4272 std::size_t size;
4273 store_type type;
4275 class parameter_list
4277 public:
4279 parameter_list(std::vector<type_store>& pl)
4280 : parameter_list_(pl)
4283 inline bool empty() const
4285 return parameter_list_.empty();
4288 inline std::size_t size() const
4290 return parameter_list_.size();
4293 inline type_store& operator[](const std::size_t& index)
4295 return parameter_list_[index];
4298 inline const type_store& operator[](const std::size_t& index) const
4300 return parameter_list_[index];
4303 inline type_store& front()
4305 return parameter_list_[0];
4308 inline const type_store& front() const
4310 return parameter_list_[0];
4313 inline type_store& back()
4315 return parameter_list_.back();
4318 inline const type_store& back() const
4320 return parameter_list_.back();
4323 private:
4325 std::vector<type_store>& parameter_list_;
4327 friend class results_context<T>;
4330 template <typename ViewType>
4331 struct type_view
4333 typedef type_store<T> type_store_t;
4334 typedef ViewType value_t;
4336 type_view(type_store_t& ts)
4337 : ts_(ts),
4338 data_(reinterpret_cast<value_t*>(ts_.data))
4341 type_view(const type_store_t& ts)
4342 : ts_(const_cast<type_store_t&>(ts)),
4343 data_(reinterpret_cast<value_t*>(ts_.data))
4346 inline std::size_t size() const
4348 return ts_.size;
4351 inline value_t& operator[](const std::size_t& i)
4353 return data_[i];
4356 inline const value_t& operator[](const std::size_t& i) const
4358 return data_[i];
4361 inline const value_t* begin() const { return data_; }
4362 inline value_t* begin() { return data_; }
4364 inline const value_t* end() const
4366 return static_cast<value_t*>(data_ + ts_.size);
4369 inline value_t* end()
4371 return static_cast<value_t*>(data_ + ts_.size);
4374 type_store_t& ts_;
4375 value_t* data_;
4378 typedef type_view<T> vector_view;
4379 typedef type_view<char> string_view;
4381 struct scalar_view
4383 typedef type_store<T> type_store_t;
4384 typedef T value_t;
4386 scalar_view(type_store_t& ts)
4387 : v_(*reinterpret_cast<value_t*>(ts.data))
4390 scalar_view(const type_store_t& ts)
4391 : v_(*reinterpret_cast<value_t*>(const_cast<type_store_t&>(ts).data))
4394 inline value_t& operator() ()
4396 return v_;
4399 inline const value_t& operator() () const
4401 return v_;
4404 template <typename IntType>
4405 inline bool to_int(IntType& i) const
4407 if (!exprtk::details::numeric::is_integer(v_))
4408 return false;
4410 i = static_cast<IntType>(v_);
4412 return true;
4415 template <typename UIntType>
4416 inline bool to_uint(UIntType& u) const
4418 if (v_ < T(0))
4419 return false;
4420 else if (!exprtk::details::numeric::is_integer(v_))
4421 return false;
4423 u = static_cast<UIntType>(v_);
4425 return true;
4428 T& v_;
4432 template <typename StringView>
4433 inline std::string to_str(const StringView& view)
4435 return std::string(view.begin(),view.size());
4438 #ifndef exprtk_disable_return_statement
4439 namespace details
4441 template <typename T> class return_node;
4442 template <typename T> class return_envelope_node;
4444 #endif
4446 template <typename T>
4447 class results_context
4449 public:
4451 typedef type_store<T> type_store_t;
4453 results_context()
4454 : results_available_(false)
4457 inline std::size_t count() const
4459 if (results_available_)
4460 return parameter_list_.size();
4461 else
4462 return 0;
4465 inline type_store_t& operator[](const std::size_t& index)
4467 return parameter_list_[index];
4470 inline const type_store_t& operator[](const std::size_t& index) const
4472 return parameter_list_[index];
4475 private:
4477 inline void clear()
4479 results_available_ = false;
4482 typedef std::vector<type_store_t> ts_list_t;
4483 typedef typename type_store_t::parameter_list parameter_list_t;
4485 inline void assign(const parameter_list_t& pl)
4487 parameter_list_ = pl.parameter_list_;
4488 results_available_ = true;
4491 bool results_available_;
4492 ts_list_t parameter_list_;
4494 #ifndef exprtk_disable_return_statement
4495 friend class details::return_node<T>;
4496 friend class details::return_envelope_node<T>;
4497 #endif
4500 namespace details
4502 enum operator_type
4504 e_default , e_null , e_add , e_sub ,
4505 e_mul , e_div , e_mod , e_pow ,
4506 e_atan2 , e_min , e_max , e_avg ,
4507 e_sum , e_prod , e_lt , e_lte ,
4508 e_eq , e_equal , e_ne , e_nequal ,
4509 e_gte , e_gt , e_and , e_nand ,
4510 e_or , e_nor , e_xor , e_xnor ,
4511 e_mand , e_mor , e_scand , e_scor ,
4512 e_shr , e_shl , e_abs , e_acos ,
4513 e_acosh , e_asin , e_asinh , e_atan ,
4514 e_atanh , e_ceil , e_cos , e_cosh ,
4515 e_exp , e_expm1 , e_floor , e_log ,
4516 e_log10 , e_log2 , e_log1p , e_logn ,
4517 e_neg , e_pos , e_round , e_roundn ,
4518 e_root , e_sqrt , e_sin , e_sinc ,
4519 e_sinh , e_sec , e_csc , e_tan ,
4520 e_tanh , e_cot , e_clamp , e_iclamp ,
4521 e_inrange , e_sgn , e_r2d , e_d2r ,
4522 e_d2g , e_g2d , e_hypot , e_notl ,
4523 e_erf , e_erfc , e_ncdf , e_frac ,
4524 e_trunc , e_assign , e_addass , e_subass ,
4525 e_mulass , e_divass , e_modass , e_in ,
4526 e_like , e_ilike , e_multi , e_smulti ,
4527 e_swap ,
4529 // Do not add new functions/operators after this point.
4530 e_sf00 = 1000, e_sf01 = 1001, e_sf02 = 1002, e_sf03 = 1003,
4531 e_sf04 = 1004, e_sf05 = 1005, e_sf06 = 1006, e_sf07 = 1007,
4532 e_sf08 = 1008, e_sf09 = 1009, e_sf10 = 1010, e_sf11 = 1011,
4533 e_sf12 = 1012, e_sf13 = 1013, e_sf14 = 1014, e_sf15 = 1015,
4534 e_sf16 = 1016, e_sf17 = 1017, e_sf18 = 1018, e_sf19 = 1019,
4535 e_sf20 = 1020, e_sf21 = 1021, e_sf22 = 1022, e_sf23 = 1023,
4536 e_sf24 = 1024, e_sf25 = 1025, e_sf26 = 1026, e_sf27 = 1027,
4537 e_sf28 = 1028, e_sf29 = 1029, e_sf30 = 1030, e_sf31 = 1031,
4538 e_sf32 = 1032, e_sf33 = 1033, e_sf34 = 1034, e_sf35 = 1035,
4539 e_sf36 = 1036, e_sf37 = 1037, e_sf38 = 1038, e_sf39 = 1039,
4540 e_sf40 = 1040, e_sf41 = 1041, e_sf42 = 1042, e_sf43 = 1043,
4541 e_sf44 = 1044, e_sf45 = 1045, e_sf46 = 1046, e_sf47 = 1047,
4542 e_sf48 = 1048, e_sf49 = 1049, e_sf50 = 1050, e_sf51 = 1051,
4543 e_sf52 = 1052, e_sf53 = 1053, e_sf54 = 1054, e_sf55 = 1055,
4544 e_sf56 = 1056, e_sf57 = 1057, e_sf58 = 1058, e_sf59 = 1059,
4545 e_sf60 = 1060, e_sf61 = 1061, e_sf62 = 1062, e_sf63 = 1063,
4546 e_sf64 = 1064, e_sf65 = 1065, e_sf66 = 1066, e_sf67 = 1067,
4547 e_sf68 = 1068, e_sf69 = 1069, e_sf70 = 1070, e_sf71 = 1071,
4548 e_sf72 = 1072, e_sf73 = 1073, e_sf74 = 1074, e_sf75 = 1075,
4549 e_sf76 = 1076, e_sf77 = 1077, e_sf78 = 1078, e_sf79 = 1079,
4550 e_sf80 = 1080, e_sf81 = 1081, e_sf82 = 1082, e_sf83 = 1083,
4551 e_sf84 = 1084, e_sf85 = 1085, e_sf86 = 1086, e_sf87 = 1087,
4552 e_sf88 = 1088, e_sf89 = 1089, e_sf90 = 1090, e_sf91 = 1091,
4553 e_sf92 = 1092, e_sf93 = 1093, e_sf94 = 1094, e_sf95 = 1095,
4554 e_sf96 = 1096, e_sf97 = 1097, e_sf98 = 1098, e_sf99 = 1099,
4555 e_sffinal = 1100,
4556 e_sf4ext00 = 2000, e_sf4ext01 = 2001, e_sf4ext02 = 2002, e_sf4ext03 = 2003,
4557 e_sf4ext04 = 2004, e_sf4ext05 = 2005, e_sf4ext06 = 2006, e_sf4ext07 = 2007,
4558 e_sf4ext08 = 2008, e_sf4ext09 = 2009, e_sf4ext10 = 2010, e_sf4ext11 = 2011,
4559 e_sf4ext12 = 2012, e_sf4ext13 = 2013, e_sf4ext14 = 2014, e_sf4ext15 = 2015,
4560 e_sf4ext16 = 2016, e_sf4ext17 = 2017, e_sf4ext18 = 2018, e_sf4ext19 = 2019,
4561 e_sf4ext20 = 2020, e_sf4ext21 = 2021, e_sf4ext22 = 2022, e_sf4ext23 = 2023,
4562 e_sf4ext24 = 2024, e_sf4ext25 = 2025, e_sf4ext26 = 2026, e_sf4ext27 = 2027,
4563 e_sf4ext28 = 2028, e_sf4ext29 = 2029, e_sf4ext30 = 2030, e_sf4ext31 = 2031,
4564 e_sf4ext32 = 2032, e_sf4ext33 = 2033, e_sf4ext34 = 2034, e_sf4ext35 = 2035,
4565 e_sf4ext36 = 2036, e_sf4ext37 = 2037, e_sf4ext38 = 2038, e_sf4ext39 = 2039,
4566 e_sf4ext40 = 2040, e_sf4ext41 = 2041, e_sf4ext42 = 2042, e_sf4ext43 = 2043,
4567 e_sf4ext44 = 2044, e_sf4ext45 = 2045, e_sf4ext46 = 2046, e_sf4ext47 = 2047,
4568 e_sf4ext48 = 2048, e_sf4ext49 = 2049, e_sf4ext50 = 2050, e_sf4ext51 = 2051,
4569 e_sf4ext52 = 2052, e_sf4ext53 = 2053, e_sf4ext54 = 2054, e_sf4ext55 = 2055,
4570 e_sf4ext56 = 2056, e_sf4ext57 = 2057, e_sf4ext58 = 2058, e_sf4ext59 = 2059,
4571 e_sf4ext60 = 2060, e_sf4ext61 = 2061
4574 inline std::string to_str(const operator_type opr)
4576 switch (opr)
4578 case e_add : return "+" ;
4579 case e_sub : return "-" ;
4580 case e_mul : return "*" ;
4581 case e_div : return "/" ;
4582 case e_mod : return "%" ;
4583 case e_pow : return "^" ;
4584 case e_assign : return ":=" ;
4585 case e_addass : return "+=" ;
4586 case e_subass : return "-=" ;
4587 case e_mulass : return "*=" ;
4588 case e_divass : return "/=" ;
4589 case e_modass : return "%=" ;
4590 case e_lt : return "<" ;
4591 case e_lte : return "<=" ;
4592 case e_eq : return "==" ;
4593 case e_equal : return "=" ;
4594 case e_ne : return "!=" ;
4595 case e_nequal : return "<>" ;
4596 case e_gte : return ">=" ;
4597 case e_gt : return ">" ;
4598 case e_and : return "and" ;
4599 case e_or : return "or" ;
4600 case e_xor : return "xor" ;
4601 case e_nand : return "nand";
4602 case e_nor : return "nor" ;
4603 case e_xnor : return "xnor";
4604 default : return "N/A" ;
4608 struct base_operation_t
4610 base_operation_t(const operator_type t, const unsigned int& np)
4611 : type(t),
4612 num_params(np)
4615 operator_type type;
4616 unsigned int num_params;
4619 namespace loop_unroll
4621 #ifndef exprtk_disable_superscalar_unroll
4622 const unsigned int global_loop_batch_size = 16;
4623 #else
4624 const unsigned int global_loop_batch_size = 4;
4625 #endif
4627 struct details
4629 details(const std::size_t& vsize,
4630 const unsigned int loop_batch_size = global_loop_batch_size)
4631 : batch_size(loop_batch_size ),
4632 remainder (vsize % batch_size),
4633 upper_bound(static_cast<int>(vsize - (remainder ? loop_batch_size : 0)))
4636 unsigned int batch_size;
4637 int remainder;
4638 int upper_bound;
4642 #ifdef exprtk_enable_debugging
4643 inline void dump_ptr(const std::string& s, const void* ptr, const std::size_t size = 0)
4645 if (size)
4646 exprtk_debug(("%s - addr: %p\n",s.c_str(),ptr));
4647 else
4648 exprtk_debug(("%s - addr: %p size: %d\n",
4649 s.c_str(),
4650 ptr,
4651 static_cast<unsigned int>(size)));
4653 #else
4654 inline void dump_ptr(const std::string&, const void*) {}
4655 inline void dump_ptr(const std::string&, const void*, const std::size_t) {}
4656 #endif
4658 template <typename T>
4659 class vec_data_store
4661 public:
4663 typedef vec_data_store<T> type;
4664 typedef T* data_t;
4666 private:
4668 struct control_block
4670 control_block()
4671 : ref_count(1),
4672 size (0),
4673 data (0),
4674 destruct (true)
4677 control_block(const std::size_t& dsize)
4678 : ref_count(1 ),
4679 size (dsize),
4680 data (0 ),
4681 destruct (true )
4682 { create_data(); }
4684 control_block(const std::size_t& dsize, data_t dptr, bool dstrct = false)
4685 : ref_count(1 ),
4686 size (dsize ),
4687 data (dptr ),
4688 destruct (dstrct)
4691 ~control_block()
4693 if (data && destruct && (0 == ref_count))
4695 dump_ptr("~control_block() data",data);
4696 delete[] data;
4697 data = reinterpret_cast<data_t>(0);
4701 static inline control_block* create(const std::size_t& dsize, data_t data_ptr = data_t(0), bool dstrct = false)
4703 if (dsize)
4705 if (0 == data_ptr)
4706 return (new control_block(dsize));
4707 else
4708 return (new control_block(dsize, data_ptr, dstrct));
4710 else
4711 return (new control_block);
4714 static inline void destroy(control_block*& cntrl_blck)
4716 if (cntrl_blck)
4718 if (
4719 (0 != cntrl_blck->ref_count) &&
4720 (0 == --cntrl_blck->ref_count)
4723 delete cntrl_blck;
4726 cntrl_blck = 0;
4730 std::size_t ref_count;
4731 std::size_t size;
4732 data_t data;
4733 bool destruct;
4735 private:
4737 control_block(const control_block&);
4738 control_block& operator=(const control_block&);
4740 inline void create_data()
4742 destruct = true;
4743 data = new T[size];
4744 std::fill_n(data,size,T(0));
4745 dump_ptr("control_block::create_data() - data",data,size);
4749 public:
4751 vec_data_store()
4752 : control_block_(control_block::create(0))
4755 vec_data_store(const std::size_t& size)
4756 : control_block_(control_block::create(size,(data_t)(0),true))
4759 vec_data_store(const std::size_t& size, data_t data, bool dstrct = false)
4760 : control_block_(control_block::create(size, data, dstrct))
4763 vec_data_store(const type& vds)
4765 control_block_ = vds.control_block_;
4766 control_block_->ref_count++;
4769 ~vec_data_store()
4771 control_block::destroy(control_block_);
4774 type& operator=(const type& vds)
4776 if (this != &vds)
4778 std::size_t final_size = min_size(control_block_, vds.control_block_);
4780 vds.control_block_->size = final_size;
4781 control_block_->size = final_size;
4783 if (control_block_->destruct || (0 == control_block_->data))
4785 control_block::destroy(control_block_);
4787 control_block_ = vds.control_block_;
4788 control_block_->ref_count++;
4792 return (*this);
4795 inline data_t data()
4797 return control_block_->data;
4800 inline data_t data() const
4802 return control_block_->data;
4805 inline std::size_t size()
4807 return control_block_->size;
4810 inline std::size_t size() const
4812 return control_block_->size;
4815 inline data_t& ref()
4817 return control_block_->data;
4820 inline void dump() const
4822 #ifdef exprtk_enable_debugging
4823 exprtk_debug(("size: %d\taddress:%p\tdestruct:%c\n",
4824 size(),
4825 data(),
4826 (control_block_->destruct ? 'T' : 'F')));
4828 for (std::size_t i = 0; i < size(); ++i)
4830 if (5 == i)
4831 exprtk_debug(("\n"));
4833 exprtk_debug(("%15.10f ",data()[i]));
4835 exprtk_debug(("\n"));
4836 #endif
4839 static inline void match_sizes(type& vds0, type& vds1)
4841 std::size_t size = min_size(vds0.control_block_,vds1.control_block_);
4842 vds0.control_block_->size = size;
4843 vds1.control_block_->size = size;
4846 private:
4848 static inline std::size_t min_size(control_block* cb0, control_block* cb1)
4850 const std::size_t size0 = cb0->size;
4851 const std::size_t size1 = cb1->size;
4853 if (size0 && size1)
4854 return std::min(size0,size1);
4855 else
4856 return (size0) ? size0 : size1;
4859 control_block* control_block_;
4862 namespace numeric
4864 namespace details
4866 template <typename T>
4867 inline T process_impl(const operator_type operation, const T arg)
4869 switch (operation)
4871 case e_abs : return numeric::abs (arg);
4872 case e_acos : return numeric::acos (arg);
4873 case e_acosh : return numeric::acosh(arg);
4874 case e_asin : return numeric::asin (arg);
4875 case e_asinh : return numeric::asinh(arg);
4876 case e_atan : return numeric::atan (arg);
4877 case e_atanh : return numeric::atanh(arg);
4878 case e_ceil : return numeric::ceil (arg);
4879 case e_cos : return numeric::cos (arg);
4880 case e_cosh : return numeric::cosh (arg);
4881 case e_exp : return numeric::exp (arg);
4882 case e_expm1 : return numeric::expm1(arg);
4883 case e_floor : return numeric::floor(arg);
4884 case e_log : return numeric::log (arg);
4885 case e_log10 : return numeric::log10(arg);
4886 case e_log2 : return numeric::log2 (arg);
4887 case e_log1p : return numeric::log1p(arg);
4888 case e_neg : return numeric::neg (arg);
4889 case e_pos : return numeric::pos (arg);
4890 case e_round : return numeric::round(arg);
4891 case e_sin : return numeric::sin (arg);
4892 case e_sinc : return numeric::sinc (arg);
4893 case e_sinh : return numeric::sinh (arg);
4894 case e_sqrt : return numeric::sqrt (arg);
4895 case e_tan : return numeric::tan (arg);
4896 case e_tanh : return numeric::tanh (arg);
4897 case e_cot : return numeric::cot (arg);
4898 case e_sec : return numeric::sec (arg);
4899 case e_csc : return numeric::csc (arg);
4900 case e_r2d : return numeric::r2d (arg);
4901 case e_d2r : return numeric::d2r (arg);
4902 case e_d2g : return numeric::d2g (arg);
4903 case e_g2d : return numeric::g2d (arg);
4904 case e_notl : return numeric::notl (arg);
4905 case e_sgn : return numeric::sgn (arg);
4906 case e_erf : return numeric::erf (arg);
4907 case e_erfc : return numeric::erfc (arg);
4908 case e_ncdf : return numeric::ncdf (arg);
4909 case e_frac : return numeric::frac (arg);
4910 case e_trunc : return numeric::trunc(arg);
4912 default : exprtk_debug(("numeric::details::process_impl<T> - Invalid unary operation.\n"));
4913 return std::numeric_limits<T>::quiet_NaN();
4917 template <typename T>
4918 inline T process_impl(const operator_type operation, const T arg0, const T arg1)
4920 switch (operation)
4922 case e_add : return (arg0 + arg1);
4923 case e_sub : return (arg0 - arg1);
4924 case e_mul : return (arg0 * arg1);
4925 case e_div : return (arg0 / arg1);
4926 case e_mod : return modulus<T>(arg0,arg1);
4927 case e_pow : return pow<T>(arg0,arg1);
4928 case e_atan2 : return atan2<T>(arg0,arg1);
4929 case e_min : return std::min<T>(arg0,arg1);
4930 case e_max : return std::max<T>(arg0,arg1);
4931 case e_logn : return logn<T>(arg0,arg1);
4932 case e_lt : return (arg0 < arg1) ? T(1) : T(0);
4933 case e_lte : return (arg0 <= arg1) ? T(1) : T(0);
4934 case e_eq : return std::equal_to<T>()(arg0,arg1) ? T(1) : T(0);
4935 case e_ne : return std::not_equal_to<T>()(arg0,arg1) ? T(1) : T(0);
4936 case e_gte : return (arg0 >= arg1) ? T(1) : T(0);
4937 case e_gt : return (arg0 > arg1) ? T(1) : T(0);
4938 case e_and : return and_opr <T>(arg0,arg1);
4939 case e_nand : return nand_opr<T>(arg0,arg1);
4940 case e_or : return or_opr <T>(arg0,arg1);
4941 case e_nor : return nor_opr <T>(arg0,arg1);
4942 case e_xor : return xor_opr <T>(arg0,arg1);
4943 case e_xnor : return xnor_opr<T>(arg0,arg1);
4944 case e_root : return root <T>(arg0,arg1);
4945 case e_roundn : return roundn <T>(arg0,arg1);
4946 case e_equal : return equal (arg0,arg1);
4947 case e_nequal : return nequal (arg0,arg1);
4948 case e_hypot : return hypot <T>(arg0,arg1);
4949 case e_shr : return shr <T>(arg0,arg1);
4950 case e_shl : return shl <T>(arg0,arg1);
4952 default : exprtk_debug(("numeric::details::process_impl<T> - Invalid binary operation.\n"));
4953 return std::numeric_limits<T>::quiet_NaN();
4957 template <typename T>
4958 inline T process_impl(const operator_type operation, const T arg0, const T arg1, int_type_tag)
4960 switch (operation)
4962 case e_add : return (arg0 + arg1);
4963 case e_sub : return (arg0 - arg1);
4964 case e_mul : return (arg0 * arg1);
4965 case e_div : return (arg0 / arg1);
4966 case e_mod : return arg0 % arg1;
4967 case e_pow : return pow<T>(arg0,arg1);
4968 case e_min : return std::min<T>(arg0,arg1);
4969 case e_max : return std::max<T>(arg0,arg1);
4970 case e_logn : return logn<T>(arg0,arg1);
4971 case e_lt : return (arg0 < arg1) ? T(1) : T(0);
4972 case e_lte : return (arg0 <= arg1) ? T(1) : T(0);
4973 case e_eq : return (arg0 == arg1) ? T(1) : T(0);
4974 case e_ne : return (arg0 != arg1) ? T(1) : T(0);
4975 case e_gte : return (arg0 >= arg1) ? T(1) : T(0);
4976 case e_gt : return (arg0 > arg1) ? T(1) : T(0);
4977 case e_and : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(1) : T(0);
4978 case e_nand : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(0) : T(1);
4979 case e_or : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(1) : T(0);
4980 case e_nor : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(0) : T(1);
4981 case e_xor : return arg0 ^ arg1;
4982 case e_xnor : return !(arg0 ^ arg1);
4983 case e_root : return root<T>(arg0,arg1);
4984 case e_equal : return arg0 == arg1;
4985 case e_nequal : return arg0 != arg1;
4986 case e_hypot : return hypot<T>(arg0,arg1);
4987 case e_shr : return arg0 >> arg1;
4988 case e_shl : return arg0 << arg1;
4990 default : exprtk_debug(("numeric::details::process_impl<IntType> - Invalid binary operation.\n"));
4991 return std::numeric_limits<T>::quiet_NaN();
4996 template <typename T>
4997 inline T process(const operator_type operation, const T arg)
4999 return exprtk::details::numeric::details::process_impl(operation,arg);
5002 template <typename T>
5003 inline T process(const operator_type operation, const T arg0, const T arg1)
5005 return exprtk::details::numeric::details::process_impl(operation, arg0, arg1);
5009 template <typename T>
5010 class expression_node
5012 public:
5014 enum node_type
5016 e_none , e_null , e_constant , e_unary ,
5017 e_binary , e_binary_ext , e_trinary , e_quaternary ,
5018 e_vararg , e_conditional , e_while , e_repeat ,
5019 e_for , e_switch , e_mswitch , e_return ,
5020 e_retenv , e_variable , e_stringvar , e_stringconst ,
5021 e_stringvarrng , e_cstringvarrng , e_strgenrange , e_strconcat ,
5022 e_stringvarsize , e_strswap , e_stringsize , e_stringvararg ,
5023 e_function , e_vafunction , e_genfunction , e_strfunction ,
5024 e_strcondition , e_strccondition , e_add , e_sub ,
5025 e_mul , e_div , e_mod , e_pow ,
5026 e_lt , e_lte , e_gt , e_gte ,
5027 e_eq , e_ne , e_and , e_nand ,
5028 e_or , e_nor , e_xor , e_xnor ,
5029 e_in , e_like , e_ilike , e_inranges ,
5030 e_ipow , e_ipowinv , e_abs , e_acos ,
5031 e_acosh , e_asin , e_asinh , e_atan ,
5032 e_atanh , e_ceil , e_cos , e_cosh ,
5033 e_exp , e_expm1 , e_floor , e_log ,
5034 e_log10 , e_log2 , e_log1p , e_neg ,
5035 e_pos , e_round , e_sin , e_sinc ,
5036 e_sinh , e_sqrt , e_tan , e_tanh ,
5037 e_cot , e_sec , e_csc , e_r2d ,
5038 e_d2r , e_d2g , e_g2d , e_notl ,
5039 e_sgn , e_erf , e_erfc , e_ncdf ,
5040 e_frac , e_trunc , e_uvouv , e_vov ,
5041 e_cov , e_voc , e_vob , e_bov ,
5042 e_cob , e_boc , e_vovov , e_vovoc ,
5043 e_vocov , e_covov , e_covoc , e_vovovov ,
5044 e_vovovoc , e_vovocov , e_vocovov , e_covovov ,
5045 e_covocov , e_vocovoc , e_covovoc , e_vococov ,
5046 e_sf3ext , e_sf4ext , e_nulleq , e_strass ,
5047 e_vector , e_vecelem , e_rbvecelem , e_rbveccelem ,
5048 e_vecdefass , e_vecvalass , e_vecvecass , e_vecopvalass ,
5049 e_vecopvecass , e_vecfunc , e_vecvecswap , e_vecvecineq ,
5050 e_vecvalineq , e_valvecineq , e_vecvecarith , e_vecvalarith ,
5051 e_valvecarith , e_vecunaryop , e_break , e_continue ,
5052 e_swap
5055 typedef T value_type;
5056 typedef expression_node<T>* expression_ptr;
5058 virtual ~expression_node()
5061 inline virtual T value() const
5063 return std::numeric_limits<T>::quiet_NaN();
5066 inline virtual expression_node<T>* branch(const std::size_t& index = 0) const
5068 return reinterpret_cast<expression_ptr>(index * 0);
5071 inline virtual node_type type() const
5073 return e_none;
5077 template <typename T>
5078 inline bool is_generally_string_node(const expression_node<T>* node);
5080 inline bool is_true(const double v)
5082 return std::not_equal_to<double>()(0.0,v);
5085 inline bool is_true(const long double v)
5087 return std::not_equal_to<long double>()(0.0L,v);
5090 inline bool is_true(const float v)
5092 return std::not_equal_to<float>()(0.0f,v);
5095 template <typename T>
5096 inline bool is_true(const std::complex<T>& v)
5098 return std::not_equal_to<std::complex<T> >()(std::complex<T>(0),v);
5101 template <typename T>
5102 inline bool is_true(const expression_node<T>* node)
5104 return std::not_equal_to<T>()(T(0),node->value());
5107 template <typename T>
5108 inline bool is_false(const expression_node<T>* node)
5110 return std::equal_to<T>()(T(0),node->value());
5113 template <typename T>
5114 inline bool is_unary_node(const expression_node<T>* node)
5116 return node && (details::expression_node<T>::e_unary == node->type());
5119 template <typename T>
5120 inline bool is_neg_unary_node(const expression_node<T>* node)
5122 return node && (details::expression_node<T>::e_neg == node->type());
5125 template <typename T>
5126 inline bool is_binary_node(const expression_node<T>* node)
5128 return node && (details::expression_node<T>::e_binary == node->type());
5131 template <typename T>
5132 inline bool is_variable_node(const expression_node<T>* node)
5134 return node && (details::expression_node<T>::e_variable == node->type());
5137 template <typename T>
5138 inline bool is_ivariable_node(const expression_node<T>* node)
5140 return node &&
5142 details::expression_node<T>::e_variable == node->type() ||
5143 details::expression_node<T>::e_vecelem == node->type() ||
5144 details::expression_node<T>::e_rbvecelem == node->type() ||
5145 details::expression_node<T>::e_rbveccelem == node->type()
5149 template <typename T>
5150 inline bool is_vector_elem_node(const expression_node<T>* node)
5152 return node && (details::expression_node<T>::e_vecelem == node->type());
5155 template <typename T>
5156 inline bool is_rebasevector_elem_node(const expression_node<T>* node)
5158 return node && (details::expression_node<T>::e_rbvecelem == node->type());
5161 template <typename T>
5162 inline bool is_rebasevector_celem_node(const expression_node<T>* node)
5164 return node && (details::expression_node<T>::e_rbveccelem == node->type());
5167 template <typename T>
5168 inline bool is_vector_node(const expression_node<T>* node)
5170 return node && (details::expression_node<T>::e_vector == node->type());
5173 template <typename T>
5174 inline bool is_ivector_node(const expression_node<T>* node)
5176 if (node)
5178 switch (node->type())
5180 case details::expression_node<T>::e_vector :
5181 case details::expression_node<T>::e_vecvalass :
5182 case details::expression_node<T>::e_vecvecass :
5183 case details::expression_node<T>::e_vecopvalass :
5184 case details::expression_node<T>::e_vecopvecass :
5185 case details::expression_node<T>::e_vecvecswap :
5186 case details::expression_node<T>::e_vecvecarith :
5187 case details::expression_node<T>::e_vecvalarith :
5188 case details::expression_node<T>::e_valvecarith :
5189 case details::expression_node<T>::e_vecunaryop : return true;
5190 default : return false;
5193 else
5194 return false;
5197 template <typename T>
5198 inline bool is_constant_node(const expression_node<T>* node)
5200 return node && (details::expression_node<T>::e_constant == node->type());
5203 template <typename T>
5204 inline bool is_null_node(const expression_node<T>* node)
5206 return node && (details::expression_node<T>::e_null == node->type());
5209 template <typename T>
5210 inline bool is_break_node(const expression_node<T>* node)
5212 return node && (details::expression_node<T>::e_break == node->type());
5215 template <typename T>
5216 inline bool is_continue_node(const expression_node<T>* node)
5218 return node && (details::expression_node<T>::e_continue == node->type());
5221 template <typename T>
5222 inline bool is_swap_node(const expression_node<T>* node)
5224 return node && (details::expression_node<T>::e_swap == node->type());
5227 template <typename T>
5228 inline bool is_function(const expression_node<T>* node)
5230 return node && (details::expression_node<T>::e_function == node->type());
5233 template <typename T>
5234 inline bool is_return_node(const expression_node<T>* node)
5236 return node && (details::expression_node<T>::e_return == node->type());
5239 template <typename T> class unary_node;
5241 template <typename T>
5242 inline bool is_negate_node(const expression_node<T>* node)
5244 if (node && is_unary_node(node))
5246 return (details::e_neg == static_cast<const unary_node<T>*>(node)->operation());
5248 else
5249 return false;
5252 template <typename T>
5253 inline bool branch_deletable(expression_node<T>* node)
5255 return !is_variable_node(node) &&
5256 !is_string_node (node) ;
5259 template <std::size_t N, typename T>
5260 inline bool all_nodes_valid(expression_node<T>* (&b)[N])
5262 for (std::size_t i = 0; i < N; ++i)
5264 if (0 == b[i]) return false;
5267 return true;
5270 template <typename T,
5271 typename Allocator,
5272 template <typename, typename> class Sequence>
5273 inline bool all_nodes_valid(const Sequence<expression_node<T>*,Allocator>& b)
5275 for (std::size_t i = 0; i < b.size(); ++i)
5277 if (0 == b[i]) return false;
5280 return true;
5283 template <std::size_t N, typename T>
5284 inline bool all_nodes_variables(expression_node<T>* (&b)[N])
5286 for (std::size_t i = 0; i < N; ++i)
5288 if (0 == b[i])
5289 return false;
5290 else if (!is_variable_node(b[i]))
5291 return false;
5294 return true;
5297 template <typename T,
5298 typename Allocator,
5299 template <typename, typename> class Sequence>
5300 inline bool all_nodes_variables(Sequence<expression_node<T>*,Allocator>& b)
5302 for (std::size_t i = 0; i < b.size(); ++i)
5304 if (0 == b[i])
5305 return false;
5306 else if (!is_variable_node(b[i]))
5307 return false;
5310 return true;
5313 template <typename NodeAllocator, typename T, std::size_t N>
5314 inline void free_all_nodes(NodeAllocator& node_allocator, expression_node<T>* (&b)[N])
5316 for (std::size_t i = 0; i < N; ++i)
5318 free_node(node_allocator,b[i]);
5322 template <typename NodeAllocator,
5323 typename T,
5324 typename Allocator,
5325 template <typename, typename> class Sequence>
5326 inline void free_all_nodes(NodeAllocator& node_allocator, Sequence<expression_node<T>*,Allocator>& b)
5328 for (std::size_t i = 0; i < b.size(); ++i)
5330 free_node(node_allocator,b[i]);
5333 b.clear();
5336 template <typename NodeAllocator, typename T>
5337 inline void free_node(NodeAllocator& node_allocator, expression_node<T>*& node, const bool force_delete = false)
5339 if (0 != node)
5341 if (
5342 (is_variable_node(node) || is_string_node(node)) ||
5343 force_delete
5345 return;
5347 node_allocator.free(node);
5348 node = reinterpret_cast<expression_node<T>*>(0);
5352 template <typename T>
5353 inline void destroy_node(expression_node<T>*& node)
5355 delete node;
5356 node = reinterpret_cast<expression_node<T>*>(0);
5359 template <typename Type>
5360 class vector_holder
5362 private:
5364 typedef Type value_type;
5365 typedef value_type* value_ptr;
5366 typedef const value_ptr const_value_ptr;
5368 class vector_holder_base
5370 public:
5372 virtual ~vector_holder_base() {}
5374 inline value_ptr operator[](const std::size_t& index) const
5376 return value_at(index);
5379 inline std::size_t size() const
5381 return vector_size();
5384 inline value_ptr data() const
5386 return value_at(0);
5389 virtual inline bool rebaseable() const
5391 return false;
5394 virtual void set_ref(value_ptr*) {}
5396 protected:
5398 virtual value_ptr value_at(const std::size_t&) const = 0;
5399 virtual std::size_t vector_size() const = 0;
5402 class array_vector_impl : public vector_holder_base
5404 public:
5406 array_vector_impl(const Type* vec, const std::size_t& vec_size)
5407 : vec_(vec),
5408 size_(vec_size)
5411 protected:
5413 value_ptr value_at(const std::size_t& index) const
5415 if (index < size_)
5416 return const_cast<const_value_ptr>(vec_ + index);
5417 else
5418 return const_value_ptr(0);
5421 std::size_t vector_size() const
5423 return size_;
5426 private:
5428 array_vector_impl operator=(const array_vector_impl&);
5430 const Type* vec_;
5431 const std::size_t size_;
5434 template <typename Allocator,
5435 template <typename, typename> class Sequence>
5436 class sequence_vector_impl : public vector_holder_base
5438 public:
5440 typedef Sequence<Type,Allocator> sequence_t;
5442 sequence_vector_impl(sequence_t& seq)
5443 : sequence_(seq)
5446 protected:
5448 value_ptr value_at(const std::size_t& index) const
5450 return (index < sequence_.size()) ? (&sequence_[index]) : const_value_ptr(0);
5453 std::size_t vector_size() const
5455 return sequence_.size();
5458 private:
5460 sequence_vector_impl operator=(const sequence_vector_impl&);
5462 sequence_t& sequence_;
5465 class vector_view_impl : public vector_holder_base
5467 public:
5469 typedef exprtk::vector_view<Type> vector_view_t;
5471 vector_view_impl(vector_view_t& vec_view)
5472 : vec_view_(vec_view)
5475 void set_ref(value_ptr* ref)
5477 vec_view_.set_ref(ref);
5480 virtual inline bool rebaseable() const
5482 return true;
5485 protected:
5487 value_ptr value_at(const std::size_t& index) const
5489 return (index < vec_view_.size()) ? (&vec_view_[index]) : const_value_ptr(0);
5492 std::size_t vector_size() const
5494 return vec_view_.size();
5497 private:
5499 vector_view_impl operator=(const vector_view_impl&);
5501 vector_view_t& vec_view_;
5504 public:
5506 typedef typename details::vec_data_store<Type> vds_t;
5508 vector_holder(Type* vec, const std::size_t& vec_size)
5509 : vector_holder_base_(new(buffer)array_vector_impl(vec,vec_size))
5512 vector_holder(const vds_t& vds)
5513 : vector_holder_base_(new(buffer)array_vector_impl(vds.data(),vds.size()))
5516 template <typename Allocator>
5517 vector_holder(std::vector<Type,Allocator>& vec)
5518 : vector_holder_base_(new(buffer)sequence_vector_impl<Allocator,std::vector>(vec))
5521 vector_holder(exprtk::vector_view<Type>& vec)
5522 : vector_holder_base_(new(buffer)vector_view_impl(vec))
5525 inline value_ptr operator[](const std::size_t& index) const
5527 return (*vector_holder_base_)[index];
5530 inline std::size_t size() const
5532 return vector_holder_base_->size();
5535 inline value_ptr data() const
5537 return vector_holder_base_->data();
5540 void set_ref(value_ptr* ref)
5542 vector_holder_base_->set_ref(ref);
5545 bool rebaseable() const
5547 return vector_holder_base_->rebaseable();
5550 private:
5552 mutable vector_holder_base* vector_holder_base_;
5553 uchar_t buffer[64];
5556 template <typename T>
5557 class null_node : public expression_node<T>
5559 public:
5561 inline T value() const
5563 return std::numeric_limits<T>::quiet_NaN();
5566 inline typename expression_node<T>::node_type type() const
5568 return expression_node<T>::e_null;
5572 template <typename T>
5573 class null_eq_node : public expression_node<T>
5575 public:
5577 typedef expression_node<T>* expression_ptr;
5579 null_eq_node(expression_ptr brnch, const bool equality = true)
5580 : branch_(brnch),
5581 branch_deletable_(branch_deletable(branch_)),
5582 equality_(equality)
5585 ~null_eq_node()
5587 if (branch_ && branch_deletable_)
5589 destroy_node(branch_);
5593 inline T value() const
5595 const T v = branch_->value();
5596 const bool result = details::numeric::is_nan(v);
5598 if (result)
5599 return (equality_) ? T(1) : T(0);
5600 else
5601 return (equality_) ? T(0) : T(1);
5604 inline typename expression_node<T>::node_type type() const
5606 return expression_node<T>::e_nulleq;
5609 inline operator_type operation() const
5611 return details::e_eq;
5614 inline expression_node<T>* branch(const std::size_t&) const
5616 return branch_;
5619 private:
5621 expression_ptr branch_;
5622 const bool branch_deletable_;
5623 bool equality_;
5626 template <typename T>
5627 class literal_node : public expression_node<T>
5629 public:
5631 explicit literal_node(const T& v)
5632 : value_(v)
5635 inline T value() const
5637 return value_;
5640 inline typename expression_node<T>::node_type type() const
5642 return expression_node<T>::e_constant;
5645 inline expression_node<T>* branch(const std::size_t&) const
5647 return reinterpret_cast<expression_node<T>*>(0);
5650 private:
5652 literal_node(literal_node<T>&) {}
5653 literal_node<T>& operator=(literal_node<T>&) { return (*this); }
5655 const T value_;
5658 template <typename T>
5659 struct range_pack;
5661 template <typename T>
5662 struct range_data_type;
5664 template <typename T>
5665 class range_interface
5667 public:
5669 typedef range_pack<T> range_t;
5671 virtual ~range_interface()
5674 virtual range_t& range_ref() = 0;
5676 virtual const range_t& range_ref() const = 0;
5679 #ifndef exprtk_disable_string_capabilities
5680 template <typename T>
5681 class string_base_node
5683 public:
5685 typedef range_data_type<T> range_data_type_t;
5687 virtual ~string_base_node()
5690 virtual std::string str () const = 0;
5692 virtual char_cptr base() const = 0;
5694 virtual std::size_t size() const = 0;
5697 template <typename T>
5698 class string_literal_node : public expression_node <T>,
5699 public string_base_node<T>,
5700 public range_interface <T>
5702 public:
5704 typedef range_pack<T> range_t;
5706 explicit string_literal_node(const std::string& v)
5707 : value_(v)
5709 rp_.n0_c = std::make_pair<bool,std::size_t>(true,0);
5710 rp_.n1_c = std::make_pair<bool,std::size_t>(true,v.size() - 1);
5711 rp_.cache.first = rp_.n0_c.second;
5712 rp_.cache.second = rp_.n1_c.second;
5715 inline T value() const
5717 return std::numeric_limits<T>::quiet_NaN();
5720 inline typename expression_node<T>::node_type type() const
5722 return expression_node<T>::e_stringconst;
5725 inline expression_node<T>* branch(const std::size_t&) const
5727 return reinterpret_cast<expression_node<T>*>(0);
5730 std::string str() const
5732 return value_;
5735 char_cptr base() const
5737 return value_.data();
5740 std::size_t size() const
5742 return value_.size();
5745 range_t& range_ref()
5747 return rp_;
5750 const range_t& range_ref() const
5752 return rp_;
5755 private:
5757 string_literal_node(const string_literal_node<T>&);
5758 string_literal_node<T>& operator=(const string_literal_node<T>&);
5760 const std::string value_;
5761 range_t rp_;
5763 #endif
5765 template <typename T>
5766 class unary_node : public expression_node<T>
5768 public:
5770 typedef expression_node<T>* expression_ptr;
5772 unary_node(const operator_type& opr,
5773 expression_ptr brnch)
5774 : operation_(opr),
5775 branch_(brnch),
5776 branch_deletable_(branch_deletable(branch_))
5779 ~unary_node()
5781 if (branch_ && branch_deletable_)
5783 destroy_node(branch_);
5787 inline T value() const
5789 const T arg = branch_->value();
5791 return numeric::process<T>(operation_,arg);
5794 inline typename expression_node<T>::node_type type() const
5796 return expression_node<T>::e_unary;
5799 inline operator_type operation() const
5801 return operation_;
5804 inline expression_node<T>* branch(const std::size_t&) const
5806 return branch_;
5809 inline void release()
5811 branch_deletable_ = false;
5814 protected:
5816 operator_type operation_;
5817 expression_ptr branch_;
5818 bool branch_deletable_;
5821 template <typename T, std::size_t D, bool B>
5822 struct construct_branch_pair
5824 template <std::size_t N>
5825 static inline void process(std::pair<expression_node<T>*,bool> (&)[N], expression_node<T>*)
5829 template <typename T, std::size_t D>
5830 struct construct_branch_pair<T,D,true>
5832 template <std::size_t N>
5833 static inline void process(std::pair<expression_node<T>*,bool> (&branch)[N], expression_node<T>* b)
5835 if (b)
5837 branch[D] = std::make_pair(b,branch_deletable(b));
5842 template <std::size_t N, typename T>
5843 inline void init_branches(std::pair<expression_node<T>*,bool> (&branch)[N],
5844 expression_node<T>* b0,
5845 expression_node<T>* b1 = reinterpret_cast<expression_node<T>*>(0),
5846 expression_node<T>* b2 = reinterpret_cast<expression_node<T>*>(0),
5847 expression_node<T>* b3 = reinterpret_cast<expression_node<T>*>(0),
5848 expression_node<T>* b4 = reinterpret_cast<expression_node<T>*>(0),
5849 expression_node<T>* b5 = reinterpret_cast<expression_node<T>*>(0),
5850 expression_node<T>* b6 = reinterpret_cast<expression_node<T>*>(0),
5851 expression_node<T>* b7 = reinterpret_cast<expression_node<T>*>(0),
5852 expression_node<T>* b8 = reinterpret_cast<expression_node<T>*>(0),
5853 expression_node<T>* b9 = reinterpret_cast<expression_node<T>*>(0))
5855 construct_branch_pair<T,0,(N > 0)>::process(branch,b0);
5856 construct_branch_pair<T,1,(N > 1)>::process(branch,b1);
5857 construct_branch_pair<T,2,(N > 2)>::process(branch,b2);
5858 construct_branch_pair<T,3,(N > 3)>::process(branch,b3);
5859 construct_branch_pair<T,4,(N > 4)>::process(branch,b4);
5860 construct_branch_pair<T,5,(N > 5)>::process(branch,b5);
5861 construct_branch_pair<T,6,(N > 6)>::process(branch,b6);
5862 construct_branch_pair<T,7,(N > 7)>::process(branch,b7);
5863 construct_branch_pair<T,8,(N > 8)>::process(branch,b8);
5864 construct_branch_pair<T,9,(N > 9)>::process(branch,b9);
5867 struct cleanup_branches
5869 template <typename T, std::size_t N>
5870 static inline void execute(std::pair<expression_node<T>*,bool> (&branch)[N])
5872 for (std::size_t i = 0; i < N; ++i)
5874 if (branch[i].first && branch[i].second)
5876 destroy_node(branch[i].first);
5881 template <typename T,
5882 typename Allocator,
5883 template <typename, typename> class Sequence>
5884 static inline void execute(Sequence<std::pair<expression_node<T>*,bool>,Allocator>& branch)
5886 for (std::size_t i = 0; i < branch.size(); ++i)
5888 if (branch[i].first && branch[i].second)
5890 destroy_node(branch[i].first);
5896 template <typename T>
5897 class binary_node : public expression_node<T>
5899 public:
5901 typedef expression_node<T>* expression_ptr;
5902 typedef std::pair<expression_ptr,bool> branch_t;
5904 binary_node(const operator_type& opr,
5905 expression_ptr branch0,
5906 expression_ptr branch1)
5907 : operation_(opr)
5909 init_branches<2>(branch_, branch0, branch1);
5912 ~binary_node()
5914 cleanup_branches::execute<T,2>(branch_);
5917 inline T value() const
5919 const T arg0 = branch_[0].first->value();
5920 const T arg1 = branch_[1].first->value();
5922 return numeric::process<T>(operation_,arg0,arg1);
5925 inline typename expression_node<T>::node_type type() const
5927 return expression_node<T>::e_binary;
5930 inline operator_type operation()
5932 return operation_;
5935 inline expression_node<T>* branch(const std::size_t& index = 0) const
5937 if (0 == index)
5938 return branch_[0].first;
5939 else if (1 == index)
5940 return branch_[1].first;
5941 else
5942 return reinterpret_cast<expression_ptr>(0);
5945 protected:
5947 operator_type operation_;
5948 branch_t branch_[2];
5951 template <typename T, typename Operation>
5952 class binary_ext_node : public expression_node<T>
5954 public:
5956 typedef expression_node<T>* expression_ptr;
5957 typedef std::pair<expression_ptr,bool> branch_t;
5959 binary_ext_node(expression_ptr branch0, expression_ptr branch1)
5961 init_branches<2>(branch_, branch0, branch1);
5964 ~binary_ext_node()
5966 cleanup_branches::execute<T,2>(branch_);
5969 inline T value() const
5971 const T arg0 = branch_[0].first->value();
5972 const T arg1 = branch_[1].first->value();
5974 return Operation::process(arg0,arg1);
5977 inline typename expression_node<T>::node_type type() const
5979 return expression_node<T>::e_binary_ext;
5982 inline operator_type operation()
5984 return Operation::operation();
5987 inline expression_node<T>* branch(const std::size_t& index = 0) const
5989 if (0 == index)
5990 return branch_[0].first;
5991 else if (1 == index)
5992 return branch_[1].first;
5993 else
5994 return reinterpret_cast<expression_ptr>(0);
5997 protected:
5999 branch_t branch_[2];
6002 template <typename T>
6003 class trinary_node : public expression_node<T>
6005 public:
6007 typedef expression_node<T>* expression_ptr;
6008 typedef std::pair<expression_ptr,bool> branch_t;
6010 trinary_node(const operator_type& opr,
6011 expression_ptr branch0,
6012 expression_ptr branch1,
6013 expression_ptr branch2)
6014 : operation_(opr)
6016 init_branches<3>(branch_, branch0, branch1, branch2);
6019 ~trinary_node()
6021 cleanup_branches::execute<T,3>(branch_);
6024 inline T value() const
6026 const T arg0 = branch_[0].first->value();
6027 const T arg1 = branch_[1].first->value();
6028 const T arg2 = branch_[2].first->value();
6030 switch (operation_)
6032 case e_inrange : return (arg1 < arg0) ? T(0) : ((arg1 > arg2) ? T(0) : T(1));
6034 case e_clamp : return (arg1 < arg0) ? arg0 : (arg1 > arg2 ? arg2 : arg1);
6036 case e_iclamp : if ((arg1 <= arg0) || (arg1 >= arg2))
6037 return arg1;
6038 else
6039 return ((T(2) * arg1 <= (arg2 + arg0)) ? arg0 : arg2);
6041 default : exprtk_debug(("trinary_node::value() - Error: Invalid operation\n"));
6042 return std::numeric_limits<T>::quiet_NaN();
6046 inline typename expression_node<T>::node_type type() const
6048 return expression_node<T>::e_trinary;
6051 protected:
6053 operator_type operation_;
6054 branch_t branch_[3];
6057 template <typename T>
6058 class quaternary_node : public expression_node<T>
6060 public:
6062 typedef expression_node<T>* expression_ptr;
6063 typedef std::pair<expression_ptr,bool> branch_t;
6065 quaternary_node(const operator_type& opr,
6066 expression_ptr branch0,
6067 expression_ptr branch1,
6068 expression_ptr branch2,
6069 expression_ptr branch3)
6070 : operation_(opr)
6072 init_branches<4>(branch_, branch0, branch1, branch2, branch3);
6075 ~quaternary_node()
6077 cleanup_branches::execute<T,4>(branch_);
6080 inline T value() const
6082 return std::numeric_limits<T>::quiet_NaN();
6085 inline typename expression_node<T>::node_type type() const
6087 return expression_node<T>::e_quaternary;
6090 protected:
6092 operator_type operation_;
6093 branch_t branch_[4];
6096 template <typename T>
6097 class conditional_node : public expression_node<T>
6099 public:
6101 typedef expression_node<T>* expression_ptr;
6103 conditional_node(expression_ptr test,
6104 expression_ptr consequent,
6105 expression_ptr alternative)
6106 : test_(test),
6107 consequent_(consequent),
6108 alternative_(alternative),
6109 test_deletable_(branch_deletable(test_)),
6110 consequent_deletable_(branch_deletable(consequent_)),
6111 alternative_deletable_(branch_deletable(alternative_))
6114 ~conditional_node()
6116 if (test_ && test_deletable_)
6118 destroy_node(test_);
6121 if (consequent_ && consequent_deletable_ )
6123 destroy_node(consequent_);
6126 if (alternative_ && alternative_deletable_)
6128 destroy_node(alternative_);
6132 inline T value() const
6134 if (is_true(test_))
6135 return consequent_->value();
6136 else
6137 return alternative_->value();
6140 inline typename expression_node<T>::node_type type() const
6142 return expression_node<T>::e_conditional;
6145 private:
6147 expression_ptr test_;
6148 expression_ptr consequent_;
6149 expression_ptr alternative_;
6150 const bool test_deletable_;
6151 const bool consequent_deletable_;
6152 const bool alternative_deletable_;
6155 template <typename T>
6156 class cons_conditional_node : public expression_node<T>
6158 public:
6160 // Consequent only conditional statement node
6161 typedef expression_node<T>* expression_ptr;
6163 cons_conditional_node(expression_ptr test,
6164 expression_ptr consequent)
6165 : test_(test),
6166 consequent_(consequent),
6167 test_deletable_(branch_deletable(test_)),
6168 consequent_deletable_(branch_deletable(consequent_))
6171 ~cons_conditional_node()
6173 if (test_ && test_deletable_)
6175 destroy_node(test_);
6178 if (consequent_ && consequent_deletable_)
6180 destroy_node(consequent_);
6184 inline T value() const
6186 if (is_true(test_))
6187 return consequent_->value();
6188 else
6189 return std::numeric_limits<T>::quiet_NaN();
6192 inline typename expression_node<T>::node_type type() const
6194 return expression_node<T>::e_conditional;
6197 private:
6199 expression_ptr test_;
6200 expression_ptr consequent_;
6201 const bool test_deletable_;
6202 const bool consequent_deletable_;
6205 #ifndef exprtk_disable_break_continue
6206 template <typename T>
6207 class break_exception
6209 public:
6211 break_exception(const T& v)
6212 : value(v)
6215 T value;
6218 class continue_exception
6221 template <typename T>
6222 class break_node : public expression_node<T>
6224 public:
6226 typedef expression_node<T>* expression_ptr;
6228 break_node(expression_ptr ret = expression_ptr(0))
6229 : return_(ret),
6230 return_deletable_(branch_deletable(return_))
6233 ~break_node()
6235 if (return_deletable_)
6237 destroy_node(return_);
6241 inline T value() const
6243 throw break_exception<T>(return_ ? return_->value() : std::numeric_limits<T>::quiet_NaN());
6244 #ifndef _MSC_VER
6245 return std::numeric_limits<T>::quiet_NaN();
6246 #endif
6249 inline typename expression_node<T>::node_type type() const
6251 return expression_node<T>::e_break;
6254 private:
6256 expression_ptr return_;
6257 const bool return_deletable_;
6260 template <typename T>
6261 class continue_node : public expression_node<T>
6263 public:
6265 inline T value() const
6267 throw continue_exception();
6268 #ifndef _MSC_VER
6269 return std::numeric_limits<T>::quiet_NaN();
6270 #endif
6273 inline typename expression_node<T>::node_type type() const
6275 return expression_node<T>::e_break;
6278 #endif
6280 template <typename T>
6281 class while_loop_node : public expression_node<T>
6283 public:
6285 typedef expression_node<T>* expression_ptr;
6287 while_loop_node(expression_ptr condition, expression_ptr loop_body)
6288 : condition_(condition),
6289 loop_body_(loop_body),
6290 condition_deletable_(branch_deletable(condition_)),
6291 loop_body_deletable_(branch_deletable(loop_body_))
6294 ~while_loop_node()
6296 if (condition_ && condition_deletable_)
6298 destroy_node(condition_);
6301 if (loop_body_ && loop_body_deletable_)
6303 destroy_node(loop_body_);
6307 inline T value() const
6309 T result = T(0);
6311 while (is_true(condition_))
6313 result = loop_body_->value();
6316 return result;
6319 inline typename expression_node<T>::node_type type() const
6321 return expression_node<T>::e_while;
6324 private:
6326 expression_ptr condition_;
6327 expression_ptr loop_body_;
6328 const bool condition_deletable_;
6329 const bool loop_body_deletable_;
6332 template <typename T>
6333 class repeat_until_loop_node : public expression_node<T>
6335 public:
6337 typedef expression_node<T>* expression_ptr;
6339 repeat_until_loop_node(expression_ptr condition, expression_ptr loop_body)
6340 : condition_(condition),
6341 loop_body_(loop_body),
6342 condition_deletable_(branch_deletable(condition_)),
6343 loop_body_deletable_(branch_deletable(loop_body_))
6346 ~repeat_until_loop_node()
6348 if (condition_ && condition_deletable_)
6350 destroy_node(condition_);
6353 if (loop_body_ && loop_body_deletable_)
6355 destroy_node(loop_body_);
6359 inline T value() const
6361 T result = T(0);
6365 result = loop_body_->value();
6367 while (is_false(condition_));
6369 return result;
6372 inline typename expression_node<T>::node_type type() const
6374 return expression_node<T>::e_repeat;
6377 private:
6379 expression_ptr condition_;
6380 expression_ptr loop_body_;
6381 const bool condition_deletable_;
6382 const bool loop_body_deletable_;
6385 template <typename T>
6386 class for_loop_node : public expression_node<T>
6388 public:
6390 typedef expression_node<T>* expression_ptr;
6392 for_loop_node(expression_ptr initialiser,
6393 expression_ptr condition,
6394 expression_ptr incrementor,
6395 expression_ptr loop_body)
6396 : initialiser_(initialiser),
6397 condition_ (condition ),
6398 incrementor_(incrementor),
6399 loop_body_ (loop_body ),
6400 initialiser_deletable_(branch_deletable(initialiser_)),
6401 condition_deletable_ (branch_deletable(condition_ )),
6402 incrementor_deletable_(branch_deletable(incrementor_)),
6403 loop_body_deletable_ (branch_deletable(loop_body_ ))
6406 ~for_loop_node()
6408 if (initialiser_ && initialiser_deletable_)
6410 destroy_node(initialiser_);
6413 if (condition_ && condition_deletable_)
6415 destroy_node(condition_);
6418 if (incrementor_ && incrementor_deletable_)
6420 destroy_node(incrementor_);
6423 if (loop_body_ && loop_body_deletable_)
6425 destroy_node(loop_body_);
6429 inline T value() const
6431 T result = T(0);
6433 if (initialiser_)
6434 initialiser_->value();
6436 if (incrementor_)
6438 while (is_true(condition_))
6440 result = loop_body_->value();
6441 incrementor_->value();
6444 else
6446 while (is_true(condition_))
6448 result = loop_body_->value();
6452 return result;
6455 inline typename expression_node<T>::node_type type() const
6457 return expression_node<T>::e_for;
6460 private:
6462 expression_ptr initialiser_ ;
6463 expression_ptr condition_ ;
6464 expression_ptr incrementor_ ;
6465 expression_ptr loop_body_ ;
6466 const bool initialiser_deletable_;
6467 const bool condition_deletable_ ;
6468 const bool incrementor_deletable_;
6469 const bool loop_body_deletable_ ;
6472 #ifndef exprtk_disable_break_continue
6473 template <typename T>
6474 class while_loop_bc_node : public expression_node<T>
6476 public:
6478 typedef expression_node<T>* expression_ptr;
6480 while_loop_bc_node(expression_ptr condition, expression_ptr loop_body)
6481 : condition_(condition),
6482 loop_body_(loop_body),
6483 condition_deletable_(branch_deletable(condition_)),
6484 loop_body_deletable_(branch_deletable(loop_body_))
6487 ~while_loop_bc_node()
6489 if (condition_ && condition_deletable_)
6491 destroy_node(condition_);
6494 if (loop_body_ && loop_body_deletable_)
6496 destroy_node(loop_body_);
6500 inline T value() const
6502 T result = T(0);
6504 while (is_true(condition_))
6508 result = loop_body_->value();
6510 catch(const break_exception<T>& e)
6512 return e.value;
6514 catch(const continue_exception&)
6518 return result;
6521 inline typename expression_node<T>::node_type type() const
6523 return expression_node<T>::e_while;
6526 private:
6528 expression_ptr condition_;
6529 expression_ptr loop_body_;
6530 const bool condition_deletable_;
6531 const bool loop_body_deletable_;
6534 template <typename T>
6535 class repeat_until_loop_bc_node : public expression_node<T>
6537 public:
6539 typedef expression_node<T>* expression_ptr;
6541 repeat_until_loop_bc_node(expression_ptr condition, expression_ptr loop_body)
6542 : condition_(condition),
6543 loop_body_(loop_body),
6544 condition_deletable_(branch_deletable(condition_)),
6545 loop_body_deletable_(branch_deletable(loop_body_))
6548 ~repeat_until_loop_bc_node()
6550 if (condition_ && condition_deletable_)
6552 destroy_node(condition_);
6555 if (loop_body_ && loop_body_deletable_)
6557 destroy_node(loop_body_);
6561 inline T value() const
6563 T result = T(0);
6569 result = loop_body_->value();
6571 catch(const break_exception<T>& e)
6573 return e.value;
6575 catch(const continue_exception&)
6578 while (is_false(condition_));
6580 return result;
6583 inline typename expression_node<T>::node_type type() const
6585 return expression_node<T>::e_repeat;
6588 private:
6590 expression_ptr condition_;
6591 expression_ptr loop_body_;
6592 const bool condition_deletable_;
6593 const bool loop_body_deletable_;
6596 template <typename T>
6597 class for_loop_bc_node : public expression_node<T>
6599 public:
6601 typedef expression_node<T>* expression_ptr;
6603 for_loop_bc_node(expression_ptr initialiser,
6604 expression_ptr condition,
6605 expression_ptr incrementor,
6606 expression_ptr loop_body)
6607 : initialiser_(initialiser),
6608 condition_ (condition ),
6609 incrementor_(incrementor),
6610 loop_body_ (loop_body ),
6611 initialiser_deletable_(branch_deletable(initialiser_)),
6612 condition_deletable_ (branch_deletable(condition_ )),
6613 incrementor_deletable_(branch_deletable(incrementor_)),
6614 loop_body_deletable_ (branch_deletable(loop_body_ ))
6617 ~for_loop_bc_node()
6619 if (initialiser_ && initialiser_deletable_)
6621 destroy_node(initialiser_);
6624 if (condition_ && condition_deletable_)
6626 destroy_node(condition_);
6629 if (incrementor_ && incrementor_deletable_)
6631 destroy_node(incrementor_);
6634 if (loop_body_ && loop_body_deletable_)
6636 destroy_node(loop_body_);
6640 inline T value() const
6642 T result = T(0);
6644 if (initialiser_)
6645 initialiser_->value();
6647 if (incrementor_)
6649 while (is_true(condition_))
6653 result = loop_body_->value();
6655 catch(const break_exception<T>& e)
6657 return e.value;
6659 catch(const continue_exception&)
6662 incrementor_->value();
6665 else
6667 while (is_true(condition_))
6671 result = loop_body_->value();
6673 catch(const break_exception<T>& e)
6675 return e.value;
6677 catch(const continue_exception&)
6682 return result;
6685 inline typename expression_node<T>::node_type type() const
6687 return expression_node<T>::e_for;
6690 private:
6692 expression_ptr initialiser_;
6693 expression_ptr condition_ ;
6694 expression_ptr incrementor_;
6695 expression_ptr loop_body_ ;
6696 const bool initialiser_deletable_;
6697 const bool condition_deletable_ ;
6698 const bool incrementor_deletable_;
6699 const bool loop_body_deletable_ ;
6701 #endif
6703 template <typename T>
6704 class switch_node : public expression_node<T>
6706 public:
6708 typedef expression_node<T>* expression_ptr;
6710 template <typename Allocator,
6711 template <typename, typename> class Sequence>
6712 explicit switch_node(const Sequence<expression_ptr,Allocator>& arg_list)
6714 if (1 != (arg_list.size() & 1))
6715 return;
6717 arg_list_.resize(arg_list.size());
6718 delete_branch_.resize(arg_list.size());
6720 for (std::size_t i = 0; i < arg_list.size(); ++i)
6722 if (arg_list[i])
6724 arg_list_[i] = arg_list[i];
6725 delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0);
6727 else
6729 arg_list_.clear();
6730 delete_branch_.clear();
6731 return;
6736 ~switch_node()
6738 for (std::size_t i = 0; i < arg_list_.size(); ++i)
6740 if (arg_list_[i] && delete_branch_[i])
6742 destroy_node(arg_list_[i]);
6747 inline T value() const
6749 if (!arg_list_.empty())
6751 const std::size_t upper_bound = (arg_list_.size() - 1);
6753 for (std::size_t i = 0; i < upper_bound; i += 2)
6755 expression_ptr condition = arg_list_[i ];
6756 expression_ptr consequent = arg_list_[i + 1];
6758 if (is_true(condition))
6760 return consequent->value();
6764 return arg_list_[upper_bound]->value();
6766 else
6767 return std::numeric_limits<T>::quiet_NaN();
6770 inline typename expression_node<T>::node_type type() const
6772 return expression_node<T>::e_switch;
6775 protected:
6777 std::vector<expression_ptr> arg_list_;
6778 std::vector<unsigned char> delete_branch_;
6781 template <typename T, typename Switch_N>
6782 class switch_n_node : public switch_node<T>
6784 public:
6786 typedef expression_node<T>* expression_ptr;
6788 template <typename Allocator,
6789 template <typename, typename> class Sequence>
6790 explicit switch_n_node(const Sequence<expression_ptr,Allocator>& arg_list)
6791 : switch_node<T>(arg_list)
6794 inline T value() const
6796 return Switch_N::process(switch_node<T>::arg_list_);
6800 template <typename T>
6801 class multi_switch_node : public expression_node<T>
6803 public:
6805 typedef expression_node<T>* expression_ptr;
6807 template <typename Allocator,
6808 template <typename, typename> class Sequence>
6809 explicit multi_switch_node(const Sequence<expression_ptr,Allocator>& arg_list)
6811 if (0 != (arg_list.size() & 1))
6812 return;
6814 arg_list_.resize(arg_list.size());
6815 delete_branch_.resize(arg_list.size());
6817 for (std::size_t i = 0; i < arg_list.size(); ++i)
6819 if (arg_list[i])
6821 arg_list_[i] = arg_list[i];
6822 delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0);
6824 else
6826 arg_list_.clear();
6827 delete_branch_.clear();
6828 return;
6833 ~multi_switch_node()
6835 for (std::size_t i = 0; i < arg_list_.size(); ++i)
6837 if (arg_list_[i] && delete_branch_[i])
6839 destroy_node(arg_list_[i]);
6844 inline T value() const
6846 T result = T(0);
6848 if (arg_list_.empty())
6850 return std::numeric_limits<T>::quiet_NaN();
6853 const std::size_t upper_bound = (arg_list_.size() - 1);
6855 for (std::size_t i = 0; i < upper_bound; i += 2)
6857 expression_ptr condition = arg_list_[i ];
6858 expression_ptr consequent = arg_list_[i + 1];
6860 if (is_true(condition))
6862 result = consequent->value();
6866 return result;
6869 inline typename expression_node<T>::node_type type() const
6871 return expression_node<T>::e_mswitch;
6874 private:
6876 std::vector<expression_ptr> arg_list_;
6877 std::vector<unsigned char> delete_branch_;
6880 template <typename T>
6881 class ivariable
6883 public:
6885 virtual ~ivariable()
6888 virtual T& ref() = 0;
6889 virtual const T& ref() const = 0;
6892 template <typename T>
6893 class variable_node : public expression_node<T>,
6894 public ivariable <T>
6896 public:
6898 static T null_value;
6900 explicit variable_node()
6901 : value_(&null_value)
6904 explicit variable_node(T& v)
6905 : value_(&v)
6908 inline bool operator <(const variable_node<T>& v) const
6910 return this < (&v);
6913 inline T value() const
6915 return (*value_);
6918 inline T& ref()
6920 return (*value_);
6923 inline const T& ref() const
6925 return (*value_);
6928 inline typename expression_node<T>::node_type type() const
6930 return expression_node<T>::e_variable;
6933 private:
6935 T* value_;
6938 template <typename T>
6939 T variable_node<T>::null_value = T(std::numeric_limits<T>::quiet_NaN());
6941 template <typename T>
6942 struct range_pack
6944 typedef expression_node<T>* expression_node_ptr;
6945 typedef std::pair<std::size_t,std::size_t> cached_range_t;
6947 range_pack()
6948 : n0_e (std::make_pair(false,expression_node_ptr(0))),
6949 n1_e (std::make_pair(false,expression_node_ptr(0))),
6950 n0_c (std::make_pair(false,0)),
6951 n1_c (std::make_pair(false,0)),
6952 cache(std::make_pair(0,0))
6955 void clear()
6957 n0_e = std::make_pair(false,expression_node_ptr(0));
6958 n1_e = std::make_pair(false,expression_node_ptr(0));
6959 n0_c = std::make_pair(false,0);
6960 n1_c = std::make_pair(false,0);
6961 cache = std::make_pair(0,0);
6964 void free()
6966 if (n0_e.first && n0_e.second)
6968 n0_e.first = false;
6970 if (
6971 !is_variable_node(n0_e.second) &&
6972 !is_string_node (n0_e.second)
6975 destroy_node(n0_e.second);
6979 if (n1_e.first && n1_e.second)
6981 n1_e.first = false;
6983 if (
6984 !is_variable_node(n1_e.second) &&
6985 !is_string_node (n1_e.second)
6988 destroy_node(n1_e.second);
6993 bool const_range()
6995 return ( n0_c.first && n1_c.first) &&
6996 (!n0_e.first && !n1_e.first);
6999 bool var_range()
7001 return ( n0_e.first && n1_e.first) &&
7002 (!n0_c.first && !n1_c.first);
7005 bool operator() (std::size_t& r0, std::size_t& r1,
7006 const std::size_t& size = std::numeric_limits<std::size_t>::max()) const
7008 if (n0_c.first)
7009 r0 = n0_c.second;
7010 else if (n0_e.first)
7012 const T r0_value = n0_e.second->value();
7014 if (r0_value < 0)
7015 return false;
7016 else
7017 r0 = static_cast<std::size_t>(details::numeric::to_int64(r0_value));
7019 else
7020 return false;
7022 if (n1_c.first)
7023 r1 = n1_c.second;
7024 else if (n1_e.first)
7026 const T r1_value = n1_e.second->value();
7028 if (r1_value < 0)
7029 return false;
7030 else
7031 r1 = static_cast<std::size_t>(details::numeric::to_int64(r1_value));
7033 else
7034 return false;
7036 if (
7037 (std::numeric_limits<std::size_t>::max() != size) &&
7038 (std::numeric_limits<std::size_t>::max() == r1 )
7041 r1 = size - 1;
7044 cache.first = r0;
7045 cache.second = r1;
7047 return (r0 <= r1);
7050 inline std::size_t const_size() const
7052 return (n1_c.second - n0_c.second + 1);
7055 inline std::size_t cache_size() const
7057 return (cache.second - cache.first + 1);
7060 std::pair<bool,expression_node_ptr> n0_e;
7061 std::pair<bool,expression_node_ptr> n1_e;
7062 std::pair<bool,std::size_t > n0_c;
7063 std::pair<bool,std::size_t > n1_c;
7064 mutable cached_range_t cache;
7067 template <typename T>
7068 class string_base_node;
7070 template <typename T>
7071 struct range_data_type
7073 typedef range_pack<T> range_t;
7074 typedef string_base_node<T>* strbase_ptr_t;
7076 range_data_type()
7077 : range(0),
7078 data (0),
7079 size (0),
7080 type_size(0),
7081 str_node (0)
7084 range_t* range;
7085 void* data;
7086 std::size_t size;
7087 std::size_t type_size;
7088 strbase_ptr_t str_node;
7091 template <typename T> class vector_node;
7093 template <typename T>
7094 class vector_interface
7096 public:
7098 typedef vector_node<T>* vector_node_ptr;
7099 typedef vec_data_store<T> vds_t;
7101 virtual ~vector_interface()
7104 virtual std::size_t size () const = 0;
7106 virtual vector_node_ptr vec() const = 0;
7108 virtual vector_node_ptr vec() = 0;
7110 virtual vds_t& vds () = 0;
7112 virtual const vds_t& vds () const = 0;
7114 virtual bool side_effect () const { return false; }
7117 template <typename T>
7118 class vector_node : public expression_node <T>,
7119 public vector_interface<T>
7121 public:
7123 typedef expression_node<T>* expression_ptr;
7124 typedef vector_holder<T> vector_holder_t;
7125 typedef vector_node<T>* vector_node_ptr;
7126 typedef vec_data_store<T> vds_t;
7128 explicit vector_node(vector_holder_t* vh)
7129 : vector_holder_(vh),
7130 vds_((*vector_holder_).size(),(*vector_holder_)[0])
7132 vector_holder_->set_ref(&vds_.ref());
7135 vector_node(const vds_t& vds, vector_holder_t* vh)
7136 : vector_holder_(vh),
7137 vds_(vds)
7140 inline T value() const
7142 return vds().data()[0];
7145 vector_node_ptr vec() const
7147 return const_cast<vector_node_ptr>(this);
7150 vector_node_ptr vec()
7152 return this;
7155 inline typename expression_node<T>::node_type type() const
7157 return expression_node<T>::e_vector;
7160 std::size_t size() const
7162 return vds().size();
7165 vds_t& vds()
7167 return vds_;
7170 const vds_t& vds() const
7172 return vds_;
7175 inline vector_holder_t& vec_holder()
7177 return (*vector_holder_);
7180 private:
7182 vector_holder_t* vector_holder_;
7183 vds_t vds_;
7186 template <typename T>
7187 class vector_elem_node : public expression_node<T>,
7188 public ivariable <T>
7190 public:
7192 typedef expression_node<T>* expression_ptr;
7193 typedef vector_holder<T> vector_holder_t;
7194 typedef vector_holder_t* vector_holder_ptr;
7196 vector_elem_node(expression_ptr index, vector_holder_ptr vec_holder)
7197 : index_(index),
7198 vec_holder_(vec_holder),
7199 vector_base_((*vec_holder)[0]),
7200 index_deletable_(branch_deletable(index_))
7203 ~vector_elem_node()
7205 if (index_ && index_deletable_)
7207 destroy_node(index_);
7211 inline T value() const
7213 return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
7216 inline T& ref()
7218 return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
7221 inline const T& ref() const
7223 return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
7226 inline typename expression_node<T>::node_type type() const
7228 return expression_node<T>::e_vecelem;
7231 inline vector_holder_t& vec_holder()
7233 return (*vec_holder_);
7236 private:
7238 expression_ptr index_;
7239 vector_holder_ptr vec_holder_;
7240 T* vector_base_;
7241 const bool index_deletable_;
7244 template <typename T>
7245 class rebasevector_elem_node : public expression_node<T>,
7246 public ivariable <T>
7248 public:
7250 typedef expression_node<T>* expression_ptr;
7251 typedef vector_holder<T> vector_holder_t;
7252 typedef vector_holder_t* vector_holder_ptr;
7253 typedef vec_data_store<T> vds_t;
7255 rebasevector_elem_node(expression_ptr index, vector_holder_ptr vec_holder)
7256 : index_(index),
7257 index_deletable_(branch_deletable(index_)),
7258 vector_holder_(vec_holder),
7259 vds_((*vector_holder_).size(),(*vector_holder_)[0])
7261 vector_holder_->set_ref(&vds_.ref());
7264 ~rebasevector_elem_node()
7266 if (index_ && index_deletable_)
7268 destroy_node(index_);
7272 inline T value() const
7274 return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
7277 inline T& ref()
7279 return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
7282 inline const T& ref() const
7284 return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
7287 inline typename expression_node<T>::node_type type() const
7289 return expression_node<T>::e_rbvecelem;
7292 inline vector_holder_t& vec_holder()
7294 return (*vector_holder_);
7297 private:
7299 expression_ptr index_;
7300 const bool index_deletable_;
7301 vector_holder_ptr vector_holder_;
7302 vds_t vds_;
7305 template <typename T>
7306 class rebasevector_celem_node : public expression_node<T>,
7307 public ivariable <T>
7309 public:
7311 typedef expression_node<T>* expression_ptr;
7312 typedef vector_holder<T> vector_holder_t;
7313 typedef vector_holder_t* vector_holder_ptr;
7314 typedef vec_data_store<T> vds_t;
7316 rebasevector_celem_node(const std::size_t index, vector_holder_ptr vec_holder)
7317 : index_(index),
7318 vector_holder_(vec_holder),
7319 vds_((*vector_holder_).size(),(*vector_holder_)[0])
7321 vector_holder_->set_ref(&vds_.ref());
7324 inline T value() const
7326 return *(vds_.data() + index_);
7329 inline T& ref()
7331 return *(vds_.data() + index_);
7334 inline const T& ref() const
7336 return *(vds_.data() + index_);
7339 inline typename expression_node<T>::node_type type() const
7341 return expression_node<T>::e_rbveccelem;
7344 inline vector_holder_t& vec_holder()
7346 return (*vector_holder_);
7349 private:
7351 const std::size_t index_;
7352 vector_holder_ptr vector_holder_;
7353 vds_t vds_;
7356 template <typename T>
7357 class vector_assignment_node : public expression_node<T>
7359 public:
7361 typedef expression_node<T>* expression_ptr;
7363 vector_assignment_node(T* vector_base,
7364 const std::size_t& size,
7365 const std::vector<expression_ptr>& initialiser_list,
7366 const bool single_value_initialse)
7367 : vector_base_(vector_base),
7368 initialiser_list_(initialiser_list),
7369 size_(size),
7370 single_value_initialse_(single_value_initialse)
7373 ~vector_assignment_node()
7375 for (std::size_t i = 0; i < initialiser_list_.size(); ++i)
7377 if (branch_deletable(initialiser_list_[i]))
7379 destroy_node(initialiser_list_[i]);
7384 inline T value() const
7386 if (single_value_initialse_)
7388 for (std::size_t i = 0; i < size_; ++i)
7390 *(vector_base_ + i) = initialiser_list_[0]->value();
7393 else
7395 std::size_t il_size = initialiser_list_.size();
7397 for (std::size_t i = 0; i < il_size; ++i)
7399 *(vector_base_ + i) = initialiser_list_[i]->value();
7402 if (il_size < size_)
7404 for (std::size_t i = il_size; i < size_; ++i)
7406 *(vector_base_ + i) = T(0);
7411 return *(vector_base_);
7414 inline typename expression_node<T>::node_type type() const
7416 return expression_node<T>::e_vecdefass;
7419 private:
7421 vector_assignment_node<T>& operator=(const vector_assignment_node<T>&);
7423 mutable T* vector_base_;
7424 std::vector<expression_ptr> initialiser_list_;
7425 const std::size_t size_;
7426 const bool single_value_initialse_;
7429 template <typename T>
7430 class swap_node : public expression_node<T>
7432 public:
7434 typedef expression_node<T>* expression_ptr;
7435 typedef variable_node<T>* variable_node_ptr;
7437 swap_node(variable_node_ptr var0, variable_node_ptr var1)
7438 : var0_(var0),
7439 var1_(var1)
7442 inline T value() const
7444 std::swap(var0_->ref(),var1_->ref());
7445 return var1_->ref();
7448 inline typename expression_node<T>::node_type type() const
7450 return expression_node<T>::e_swap;
7453 private:
7455 variable_node_ptr var0_;
7456 variable_node_ptr var1_;
7459 template <typename T>
7460 class swap_generic_node : public binary_node<T>
7462 public:
7464 typedef expression_node<T>* expression_ptr;
7465 typedef ivariable<T>* ivariable_ptr;
7467 swap_generic_node(expression_ptr var0, expression_ptr var1)
7468 : binary_node<T>(details::e_swap, var0, var1),
7469 var0_(dynamic_cast<ivariable_ptr>(var0)),
7470 var1_(dynamic_cast<ivariable_ptr>(var1))
7473 inline T value() const
7475 std::swap(var0_->ref(),var1_->ref());
7476 return var1_->ref();
7479 inline typename expression_node<T>::node_type type() const
7481 return expression_node<T>::e_swap;
7484 private:
7486 ivariable_ptr var0_;
7487 ivariable_ptr var1_;
7490 template <typename T>
7491 class swap_vecvec_node : public binary_node <T>,
7492 public vector_interface<T>
7494 public:
7496 typedef expression_node<T>* expression_ptr;
7497 typedef vector_node<T>* vector_node_ptr;
7498 typedef vec_data_store<T> vds_t;
7500 swap_vecvec_node(expression_ptr branch0,
7501 expression_ptr branch1)
7502 : binary_node<T>(details::e_swap, branch0, branch1),
7503 vec0_node_ptr_(0),
7504 vec1_node_ptr_(0),
7505 vec_size_ (0),
7506 initialised_ (false)
7508 if (is_ivector_node(binary_node<T>::branch_[0].first))
7510 vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
7512 if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
7514 vec0_node_ptr_ = vi->vec();
7515 vds() = vi->vds();
7519 if (is_ivector_node(binary_node<T>::branch_[1].first))
7521 vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
7523 if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
7525 vec1_node_ptr_ = vi->vec();
7529 if (vec0_node_ptr_ && vec1_node_ptr_)
7531 vec_size_ = std::min(vec0_node_ptr_->vds().size(),
7532 vec1_node_ptr_->vds().size());
7534 initialised_ = true;
7538 inline T value() const
7540 if (initialised_)
7542 binary_node<T>::branch_[0].first->value();
7543 binary_node<T>::branch_[1].first->value();
7545 T* vec0 = vec0_node_ptr_->vds().data();
7546 T* vec1 = vec1_node_ptr_->vds().data();
7548 for (std::size_t i = 0; i < vec_size_; ++i)
7550 std::swap(vec0[i],vec1[i]);
7553 return vec1_node_ptr_->value();
7555 else
7556 return std::numeric_limits<T>::quiet_NaN();
7559 vector_node_ptr vec() const
7561 return vec0_node_ptr_;
7564 vector_node_ptr vec()
7566 return vec0_node_ptr_;
7569 inline typename expression_node<T>::node_type type() const
7571 return expression_node<T>::e_vecvecswap;
7574 std::size_t size() const
7576 return vec_size_;
7579 vds_t& vds()
7581 return vds_;
7584 const vds_t& vds() const
7586 return vds_;
7589 private:
7591 vector_node<T>* vec0_node_ptr_;
7592 vector_node<T>* vec1_node_ptr_;
7593 std::size_t vec_size_;
7594 bool initialised_;
7595 vds_t vds_;
7598 #ifndef exprtk_disable_string_capabilities
7599 template <typename T>
7600 class stringvar_node : public expression_node <T>,
7601 public string_base_node<T>,
7602 public range_interface <T>
7604 public:
7606 typedef range_pack<T> range_t;
7608 static std::string null_value;
7610 explicit stringvar_node()
7611 : value_(&null_value)
7614 explicit stringvar_node(std::string& v)
7615 : value_(&v)
7617 rp_.n0_c = std::make_pair<bool,std::size_t>(true,0);
7618 rp_.n1_c = std::make_pair<bool,std::size_t>(true,v.size() - 1);
7619 rp_.cache.first = rp_.n0_c.second;
7620 rp_.cache.second = rp_.n1_c.second;
7623 inline bool operator <(const stringvar_node<T>& v) const
7625 return this < (&v);
7628 inline T value() const
7630 rp_.n1_c.second = (*value_).size() - 1;
7631 rp_.cache.second = rp_.n1_c.second;
7633 return std::numeric_limits<T>::quiet_NaN();
7636 std::string str() const
7638 return ref();
7641 char_cptr base() const
7643 return &(*value_)[0];
7646 std::size_t size() const
7648 return ref().size();
7651 std::string& ref()
7653 return (*value_);
7656 const std::string& ref() const
7658 return (*value_);
7661 range_t& range_ref()
7663 return rp_;
7666 const range_t& range_ref() const
7668 return rp_;
7671 inline typename expression_node<T>::node_type type() const
7673 return expression_node<T>::e_stringvar;
7676 private:
7678 std::string* value_;
7679 mutable range_t rp_;
7682 template <typename T>
7683 std::string stringvar_node<T>::null_value = std::string("");
7685 template <typename T>
7686 class string_range_node : public expression_node <T>,
7687 public string_base_node<T>,
7688 public range_interface <T>
7690 public:
7692 typedef range_pack<T> range_t;
7694 static std::string null_value;
7696 explicit string_range_node(std::string& v, const range_t& rp)
7697 : value_(&v),
7698 rp_(rp)
7701 virtual ~string_range_node()
7703 rp_.free();
7706 inline bool operator <(const string_range_node<T>& v) const
7708 return this < (&v);
7711 inline T value() const
7713 return std::numeric_limits<T>::quiet_NaN();
7716 inline std::string str() const
7718 return (*value_);
7721 char_cptr base() const
7723 return &(*value_)[0];
7726 std::size_t size() const
7728 return ref().size();
7731 inline range_t range() const
7733 return rp_;
7736 inline virtual std::string& ref()
7738 return (*value_);
7741 inline virtual const std::string& ref() const
7743 return (*value_);
7746 inline range_t& range_ref()
7748 return rp_;
7751 inline const range_t& range_ref() const
7753 return rp_;
7756 inline typename expression_node<T>::node_type type() const
7758 return expression_node<T>::e_stringvarrng;
7761 private:
7763 std::string* value_;
7764 range_t rp_;
7767 template <typename T>
7768 std::string string_range_node<T>::null_value = std::string("");
7770 template <typename T>
7771 class const_string_range_node : public expression_node <T>,
7772 public string_base_node<T>,
7773 public range_interface <T>
7775 public:
7777 typedef range_pack<T> range_t;
7779 explicit const_string_range_node(const std::string& v, const range_t& rp)
7780 : value_(v),
7781 rp_(rp)
7784 ~const_string_range_node()
7786 rp_.free();
7789 inline T value() const
7791 return std::numeric_limits<T>::quiet_NaN();
7794 std::string str() const
7796 return value_;
7799 char_cptr base() const
7801 return value_.data();
7804 std::size_t size() const
7806 return value_.size();
7809 range_t range() const
7811 return rp_;
7814 range_t& range_ref()
7816 return rp_;
7819 const range_t& range_ref() const
7821 return rp_;
7824 inline typename expression_node<T>::node_type type() const
7826 return expression_node<T>::e_cstringvarrng;
7829 private:
7831 const_string_range_node<T>& operator=(const const_string_range_node<T>&);
7833 const std::string value_;
7834 range_t rp_;
7837 template <typename T>
7838 class generic_string_range_node : public expression_node <T>,
7839 public string_base_node<T>,
7840 public range_interface <T>
7842 public:
7844 typedef expression_node <T>* expression_ptr;
7845 typedef stringvar_node <T>* strvar_node_ptr;
7846 typedef string_base_node<T>* str_base_ptr;
7847 typedef range_pack <T> range_t;
7848 typedef range_t* range_ptr;
7849 typedef range_interface<T> irange_t;
7850 typedef irange_t* irange_ptr;
7852 generic_string_range_node(expression_ptr str_branch, const range_t& brange)
7853 : initialised_(false),
7854 branch_(str_branch),
7855 branch_deletable_(branch_deletable(branch_)),
7856 str_base_ptr_ (0),
7857 str_range_ptr_(0),
7858 base_range_(brange)
7860 range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
7861 range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
7862 range_.cache.first = range_.n0_c.second;
7863 range_.cache.second = range_.n1_c.second;
7865 if (is_generally_string_node(branch_))
7867 str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_);
7869 if (0 == str_base_ptr_)
7870 return;
7872 str_range_ptr_ = dynamic_cast<irange_ptr>(branch_);
7874 if (0 == str_range_ptr_)
7875 return;
7878 initialised_ = (str_base_ptr_ && str_range_ptr_);
7881 ~generic_string_range_node()
7883 base_range_.free();
7885 if (branch_ && branch_deletable_)
7887 destroy_node(branch_);
7891 inline T value() const
7893 if (initialised_)
7895 branch_->value();
7897 std::size_t str_r0 = 0;
7898 std::size_t str_r1 = 0;
7900 std::size_t r0 = 0;
7901 std::size_t r1 = 0;
7903 range_t& range = str_range_ptr_->range_ref();
7905 const std::size_t base_str_size = str_base_ptr_->size();
7907 if (
7908 range (str_r0, str_r1, base_str_size) &&
7909 base_range_( r0, r1, base_str_size)
7912 const std::size_t size = (r1 - r0) + 1;
7914 range_.n1_c.second = size - 1;
7915 range_.cache.second = range_.n1_c.second;
7917 value_.assign(str_base_ptr_->base() + str_r0 + r0, size);
7921 return std::numeric_limits<T>::quiet_NaN();
7924 std::string str() const
7926 return value_;
7929 char_cptr base() const
7931 return &value_[0];
7934 std::size_t size() const
7936 return value_.size();
7939 range_t& range_ref()
7941 return range_;
7944 const range_t& range_ref() const
7946 return range_;
7949 inline typename expression_node<T>::node_type type() const
7951 return expression_node<T>::e_strgenrange;
7954 private:
7956 bool initialised_;
7957 expression_ptr branch_;
7958 const bool branch_deletable_;
7959 str_base_ptr str_base_ptr_;
7960 irange_ptr str_range_ptr_;
7961 mutable range_t base_range_;
7962 mutable range_t range_;
7963 mutable std::string value_;
7966 template <typename T>
7967 class string_concat_node : public binary_node <T>,
7968 public string_base_node<T>,
7969 public range_interface <T>
7971 public:
7973 typedef expression_node <T>* expression_ptr;
7974 typedef string_base_node<T>* str_base_ptr;
7975 typedef range_pack <T> range_t;
7976 typedef range_t* range_ptr;
7977 typedef range_interface<T> irange_t;
7978 typedef irange_t* irange_ptr;
7980 string_concat_node(const operator_type& opr,
7981 expression_ptr branch0,
7982 expression_ptr branch1)
7983 : binary_node<T>(opr, branch0, branch1),
7984 initialised_(false),
7985 str0_base_ptr_ (0),
7986 str1_base_ptr_ (0),
7987 str0_range_ptr_(0),
7988 str1_range_ptr_(0)
7990 range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
7991 range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
7993 range_.cache.first = range_.n0_c.second;
7994 range_.cache.second = range_.n1_c.second;
7996 if (is_generally_string_node(binary_node<T>::branch_[0].first))
7998 str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
8000 if (0 == str0_base_ptr_)
8001 return;
8003 str0_range_ptr_ = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
8005 if (0 == str0_range_ptr_)
8006 return;
8009 if (is_generally_string_node(binary_node<T>::branch_[1].first))
8011 str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
8013 if (0 == str1_base_ptr_)
8014 return;
8016 str1_range_ptr_ = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
8018 if (0 == str1_range_ptr_)
8019 return;
8022 initialised_ = str0_base_ptr_ &&
8023 str1_base_ptr_ &&
8024 str0_range_ptr_ &&
8025 str1_range_ptr_ ;
8028 inline T value() const
8030 if (initialised_)
8032 binary_node<T>::branch_[0].first->value();
8033 binary_node<T>::branch_[1].first->value();
8035 std::size_t str0_r0 = 0;
8036 std::size_t str0_r1 = 0;
8038 std::size_t str1_r0 = 0;
8039 std::size_t str1_r1 = 0;
8041 range_t& range0 = str0_range_ptr_->range_ref();
8042 range_t& range1 = str1_range_ptr_->range_ref();
8044 if (
8045 range0(str0_r0, str0_r1, str0_base_ptr_->size()) &&
8046 range1(str1_r0, str1_r1, str1_base_ptr_->size())
8049 const std::size_t size0 = (str0_r1 - str0_r0) + 1;
8050 const std::size_t size1 = (str1_r1 - str1_r0) + 1;
8052 value_.assign(str0_base_ptr_->base() + str0_r0, size0);
8053 value_.append(str1_base_ptr_->base() + str1_r0, size1);
8055 range_.n1_c.second = value_.size() - 1;
8056 range_.cache.second = range_.n1_c.second;
8060 return std::numeric_limits<T>::quiet_NaN();
8063 std::string str() const
8065 return value_;
8068 char_cptr base() const
8070 return &value_[0];
8073 std::size_t size() const
8075 return value_.size();
8078 range_t& range_ref()
8080 return range_;
8083 const range_t& range_ref() const
8085 return range_;
8088 inline typename expression_node<T>::node_type type() const
8090 return expression_node<T>::e_strconcat;
8093 private:
8095 bool initialised_;
8096 str_base_ptr str0_base_ptr_;
8097 str_base_ptr str1_base_ptr_;
8098 irange_ptr str0_range_ptr_;
8099 irange_ptr str1_range_ptr_;
8100 mutable range_t range_;
8101 mutable std::string value_;
8104 template <typename T>
8105 class swap_string_node : public binary_node <T>,
8106 public string_base_node<T>,
8107 public range_interface <T>
8109 public:
8111 typedef expression_node <T>* expression_ptr;
8112 typedef stringvar_node <T>* strvar_node_ptr;
8113 typedef string_base_node<T>* str_base_ptr;
8114 typedef range_pack <T> range_t;
8115 typedef range_t* range_ptr;
8116 typedef range_interface<T> irange_t;
8117 typedef irange_t* irange_ptr;
8119 swap_string_node(expression_ptr branch0, expression_ptr branch1)
8120 : binary_node<T>(details::e_swap, branch0, branch1),
8121 initialised_(false),
8122 str0_node_ptr_(0),
8123 str1_node_ptr_(0)
8125 if (is_string_node(binary_node<T>::branch_[0].first))
8127 str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first);
8130 if (is_string_node(binary_node<T>::branch_[1].first))
8132 str1_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[1].first);
8135 initialised_ = (str0_node_ptr_ && str1_node_ptr_);
8138 inline T value() const
8140 if (initialised_)
8142 binary_node<T>::branch_[0].first->value();
8143 binary_node<T>::branch_[1].first->value();
8145 std::swap(str0_node_ptr_->ref(), str1_node_ptr_->ref());
8148 return std::numeric_limits<T>::quiet_NaN();
8151 std::string str() const
8153 return str0_node_ptr_->str();
8156 char_cptr base() const
8158 return str0_node_ptr_->base();
8161 std::size_t size() const
8163 return str0_node_ptr_->size();
8166 range_t& range_ref()
8168 return str0_node_ptr_->range_ref();
8171 const range_t& range_ref() const
8173 return str0_node_ptr_->range_ref();
8176 inline typename expression_node<T>::node_type type() const
8178 return expression_node<T>::e_strswap;
8181 private:
8183 bool initialised_;
8184 strvar_node_ptr str0_node_ptr_;
8185 strvar_node_ptr str1_node_ptr_;
8188 template <typename T>
8189 class swap_genstrings_node : public binary_node<T>
8191 public:
8193 typedef expression_node <T>* expression_ptr;
8194 typedef string_base_node<T>* str_base_ptr;
8195 typedef range_pack <T> range_t;
8196 typedef range_t* range_ptr;
8197 typedef range_interface<T> irange_t;
8198 typedef irange_t* irange_ptr;
8200 swap_genstrings_node(expression_ptr branch0,
8201 expression_ptr branch1)
8202 : binary_node<T>(details::e_default, branch0, branch1),
8203 str0_base_ptr_ (0),
8204 str1_base_ptr_ (0),
8205 str0_range_ptr_(0),
8206 str1_range_ptr_(0),
8207 initialised_(false)
8209 if (is_generally_string_node(binary_node<T>::branch_[0].first))
8211 str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
8213 if (0 == str0_base_ptr_)
8214 return;
8216 irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
8218 if (0 == range)
8219 return;
8221 str0_range_ptr_ = &(range->range_ref());
8224 if (is_generally_string_node(binary_node<T>::branch_[1].first))
8226 str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
8228 if (0 == str1_base_ptr_)
8229 return;
8231 irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
8233 if (0 == range)
8234 return;
8236 str1_range_ptr_ = &(range->range_ref());
8239 initialised_ = str0_base_ptr_ &&
8240 str1_base_ptr_ &&
8241 str0_range_ptr_ &&
8242 str1_range_ptr_ ;
8245 inline T value() const
8247 if (initialised_)
8249 binary_node<T>::branch_[0].first->value();
8250 binary_node<T>::branch_[1].first->value();
8252 std::size_t str0_r0 = 0;
8253 std::size_t str0_r1 = 0;
8255 std::size_t str1_r0 = 0;
8256 std::size_t str1_r1 = 0;
8258 range_t& range0 = (*str0_range_ptr_);
8259 range_t& range1 = (*str1_range_ptr_);
8261 if (
8262 range0(str0_r0, str0_r1, str0_base_ptr_->size()) &&
8263 range1(str1_r0, str1_r1, str1_base_ptr_->size())
8266 const std::size_t size0 = range0.cache_size();
8267 const std::size_t size1 = range1.cache_size();
8268 const std::size_t max_size = std::min(size0,size1);
8270 char_ptr s0 = const_cast<char_ptr>(str0_base_ptr_->base() + str0_r0);
8271 char_ptr s1 = const_cast<char_ptr>(str1_base_ptr_->base() + str1_r0);
8273 loop_unroll::details lud(max_size);
8274 char_cptr upper_bound = s0 + lud.upper_bound;
8276 while (s0 < upper_bound)
8278 #define exprtk_loop(N) \
8279 std::swap(s0[N], s1[N]); \
8281 exprtk_loop( 0) exprtk_loop( 1)
8282 exprtk_loop( 2) exprtk_loop( 3)
8283 #ifndef exprtk_disable_superscalar_unroll
8284 exprtk_loop( 4) exprtk_loop( 5)
8285 exprtk_loop( 6) exprtk_loop( 7)
8286 exprtk_loop( 8) exprtk_loop( 9)
8287 exprtk_loop(10) exprtk_loop(11)
8288 exprtk_loop(12) exprtk_loop(13)
8289 exprtk_loop(14) exprtk_loop(15)
8290 #endif
8292 s0 += lud.batch_size;
8293 s1 += lud.batch_size;
8296 int i = 0;
8298 exprtk_disable_fallthrough_begin
8299 switch (lud.remainder)
8301 #define case_stmt(N) \
8302 case N : { std::swap(s0[i], s1[i]); ++i; } \
8304 #ifndef exprtk_disable_superscalar_unroll
8305 case_stmt(15) case_stmt(14)
8306 case_stmt(13) case_stmt(12)
8307 case_stmt(11) case_stmt(10)
8308 case_stmt( 9) case_stmt( 8)
8309 case_stmt( 7) case_stmt( 6)
8310 case_stmt( 5) case_stmt( 4)
8311 #endif
8312 case_stmt( 3) case_stmt( 2)
8313 case_stmt( 1)
8315 exprtk_disable_fallthrough_end
8317 #undef exprtk_loop
8318 #undef case_stmt
8322 return std::numeric_limits<T>::quiet_NaN();
8325 inline typename expression_node<T>::node_type type() const
8327 return expression_node<T>::e_strswap;
8330 private:
8332 swap_genstrings_node(swap_genstrings_node<T>&);
8333 swap_genstrings_node<T>& operator=(swap_genstrings_node<T>&);
8335 str_base_ptr str0_base_ptr_;
8336 str_base_ptr str1_base_ptr_;
8337 range_ptr str0_range_ptr_;
8338 range_ptr str1_range_ptr_;
8339 bool initialised_;
8342 template <typename T>
8343 class stringvar_size_node : public expression_node<T>
8345 public:
8347 static std::string null_value;
8349 explicit stringvar_size_node()
8350 : value_(&null_value)
8353 explicit stringvar_size_node(std::string& v)
8354 : value_(&v)
8357 inline T value() const
8359 return T((*value_).size());
8362 inline typename expression_node<T>::node_type type() const
8364 return expression_node<T>::e_stringvarsize;
8367 private:
8369 std::string* value_;
8372 template <typename T>
8373 std::string stringvar_size_node<T>::null_value = std::string("");
8375 template <typename T>
8376 class string_size_node : public expression_node<T>
8378 public:
8380 typedef expression_node <T>* expression_ptr;
8381 typedef string_base_node<T>* str_base_ptr;
8383 explicit string_size_node(expression_ptr brnch)
8384 : branch_(brnch),
8385 branch_deletable_(branch_deletable(branch_)),
8386 str_base_ptr_(0)
8388 if (is_generally_string_node(branch_))
8390 str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_);
8392 if (0 == str_base_ptr_)
8393 return;
8397 ~string_size_node()
8399 if (branch_ && branch_deletable_)
8401 destroy_node(branch_);
8405 inline T value() const
8407 T result = std::numeric_limits<T>::quiet_NaN();
8409 if (str_base_ptr_)
8411 branch_->value();
8412 result = T(str_base_ptr_->size());
8415 return result;
8418 inline typename expression_node<T>::node_type type() const
8420 return expression_node<T>::e_stringsize;
8423 private:
8425 expression_ptr branch_;
8426 const bool branch_deletable_;
8427 str_base_ptr str_base_ptr_;
8430 struct asn_assignment
8432 static inline void execute(std::string& s, char_cptr data, const std::size_t size)
8433 { s.assign(data,size); }
8436 struct asn_addassignment
8438 static inline void execute(std::string& s, char_cptr data, const std::size_t size)
8439 { s.append(data,size); }
8442 template <typename T, typename AssignmentProcess = asn_assignment>
8443 class assignment_string_node : public binary_node <T>,
8444 public string_base_node<T>,
8445 public range_interface <T>
8447 public:
8449 typedef expression_node <T>* expression_ptr;
8450 typedef stringvar_node <T>* strvar_node_ptr;
8451 typedef string_base_node<T>* str_base_ptr;
8452 typedef range_pack <T> range_t;
8453 typedef range_t* range_ptr;
8454 typedef range_interface<T> irange_t;
8455 typedef irange_t* irange_ptr;
8457 assignment_string_node(const operator_type& opr,
8458 expression_ptr branch0,
8459 expression_ptr branch1)
8460 : binary_node<T>(opr, branch0, branch1),
8461 initialised_(false),
8462 str0_base_ptr_ (0),
8463 str1_base_ptr_ (0),
8464 str0_node_ptr_ (0),
8465 str1_range_ptr_(0)
8467 if (is_string_node(binary_node<T>::branch_[0].first))
8469 str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first);
8471 str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
8474 if (is_generally_string_node(binary_node<T>::branch_[1].first))
8476 str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
8478 if (0 == str1_base_ptr_)
8479 return;
8481 irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
8483 if (0 == range)
8484 return;
8486 str1_range_ptr_ = &(range->range_ref());
8489 initialised_ = str0_base_ptr_ &&
8490 str1_base_ptr_ &&
8491 str0_node_ptr_ &&
8492 str1_range_ptr_ ;
8495 inline T value() const
8497 if (initialised_)
8499 binary_node<T>::branch_[1].first->value();
8501 std::size_t r0 = 0;
8502 std::size_t r1 = 0;
8504 range_t& range = (*str1_range_ptr_);
8506 if (range(r0, r1, str1_base_ptr_->size()))
8508 AssignmentProcess::execute(str0_node_ptr_->ref(),
8509 str1_base_ptr_->base() + r0,
8510 (r1 - r0) + 1);
8512 binary_node<T>::branch_[0].first->value();
8516 return std::numeric_limits<T>::quiet_NaN();
8519 std::string str() const
8521 return str0_node_ptr_->str();
8524 char_cptr base() const
8526 return str0_node_ptr_->base();
8529 std::size_t size() const
8531 return str0_node_ptr_->size();
8534 range_t& range_ref()
8536 return str0_node_ptr_->range_ref();
8539 const range_t& range_ref() const
8541 return str0_node_ptr_->range_ref();
8544 inline typename expression_node<T>::node_type type() const
8546 return expression_node<T>::e_strass;
8549 private:
8551 bool initialised_;
8552 str_base_ptr str0_base_ptr_;
8553 str_base_ptr str1_base_ptr_;
8554 strvar_node_ptr str0_node_ptr_;
8555 range_ptr str1_range_ptr_;
8558 template <typename T, typename AssignmentProcess = asn_assignment>
8559 class assignment_string_range_node : public binary_node <T>,
8560 public string_base_node<T>,
8561 public range_interface <T>
8563 public:
8565 typedef expression_node <T>* expression_ptr;
8566 typedef stringvar_node <T>* strvar_node_ptr;
8567 typedef string_base_node<T>* str_base_ptr;
8568 typedef range_pack <T> range_t;
8569 typedef range_t* range_ptr;
8570 typedef range_interface<T> irange_t;
8571 typedef irange_t* irange_ptr;
8573 assignment_string_range_node(const operator_type& opr,
8574 expression_ptr branch0,
8575 expression_ptr branch1)
8576 : binary_node<T>(opr, branch0, branch1),
8577 initialised_(false),
8578 str0_base_ptr_ (0),
8579 str1_base_ptr_ (0),
8580 str0_node_ptr_ (0),
8581 str0_range_ptr_(0),
8582 str1_range_ptr_(0)
8584 if (is_string_range_node(binary_node<T>::branch_[0].first))
8586 str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first);
8588 str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
8590 irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
8592 if (0 == range)
8593 return;
8595 str0_range_ptr_ = &(range->range_ref());
8598 if (is_generally_string_node(binary_node<T>::branch_[1].first))
8600 str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
8602 if (0 == str1_base_ptr_)
8603 return;
8605 irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
8607 if (0 == range)
8608 return;
8610 str1_range_ptr_ = &(range->range_ref());
8613 initialised_ = str0_base_ptr_ &&
8614 str1_base_ptr_ &&
8615 str0_node_ptr_ &&
8616 str0_range_ptr_ &&
8617 str1_range_ptr_ ;
8620 inline T value() const
8622 if (initialised_)
8624 binary_node<T>::branch_[0].first->value();
8625 binary_node<T>::branch_[1].first->value();
8627 std::size_t s0_r0 = 0;
8628 std::size_t s0_r1 = 0;
8630 std::size_t s1_r0 = 0;
8631 std::size_t s1_r1 = 0;
8633 range_t& range0 = (*str0_range_ptr_);
8634 range_t& range1 = (*str1_range_ptr_);
8636 if (
8637 range0(s0_r0, s0_r1, str0_base_ptr_->size()) &&
8638 range1(s1_r0, s1_r1, str1_base_ptr_->size())
8641 std::size_t size = std::min((s0_r1 - s0_r0), (s1_r1 - s1_r0)) + 1;
8643 std::copy(str1_base_ptr_->base() + s1_r0,
8644 str1_base_ptr_->base() + s1_r0 + size,
8645 const_cast<char_ptr>(base() + s0_r0));
8649 return std::numeric_limits<T>::quiet_NaN();
8652 std::string str() const
8654 return str0_node_ptr_->str();
8657 char_cptr base() const
8659 return str0_node_ptr_->base();
8662 std::size_t size() const
8664 return str0_node_ptr_->size();
8667 range_t& range_ref()
8669 return str0_node_ptr_->range_ref();
8672 const range_t& range_ref() const
8674 return str0_node_ptr_->range_ref();
8677 inline typename expression_node<T>::node_type type() const
8679 return expression_node<T>::e_strass;
8682 private:
8684 bool initialised_;
8685 str_base_ptr str0_base_ptr_;
8686 str_base_ptr str1_base_ptr_;
8687 strvar_node_ptr str0_node_ptr_;
8688 range_ptr str0_range_ptr_;
8689 range_ptr str1_range_ptr_;
8692 template <typename T>
8693 class conditional_string_node : public trinary_node <T>,
8694 public string_base_node<T>,
8695 public range_interface <T>
8697 public:
8699 typedef expression_node <T>* expression_ptr;
8700 typedef string_base_node<T>* str_base_ptr;
8701 typedef range_pack <T> range_t;
8702 typedef range_t* range_ptr;
8703 typedef range_interface<T> irange_t;
8704 typedef irange_t* irange_ptr;
8706 conditional_string_node(expression_ptr test,
8707 expression_ptr consequent,
8708 expression_ptr alternative)
8709 : trinary_node<T>(details::e_default,consequent,alternative,test),
8710 initialised_(false),
8711 str0_base_ptr_ (0),
8712 str1_base_ptr_ (0),
8713 str0_range_ptr_(0),
8714 str1_range_ptr_(0),
8715 test_ (test),
8716 consequent_ (consequent),
8717 alternative_(alternative)
8719 range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
8720 range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
8722 range_.cache.first = range_.n0_c.second;
8723 range_.cache.second = range_.n1_c.second;
8725 if (is_generally_string_node(trinary_node<T>::branch_[0].first))
8727 str0_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[0].first);
8729 if (0 == str0_base_ptr_)
8730 return;
8732 str0_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[0].first);
8734 if (0 == str0_range_ptr_)
8735 return;
8738 if (is_generally_string_node(trinary_node<T>::branch_[1].first))
8740 str1_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[1].first);
8742 if (0 == str1_base_ptr_)
8743 return;
8745 str1_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[1].first);
8747 if (0 == str1_range_ptr_)
8748 return;
8751 initialised_ = str0_base_ptr_ &&
8752 str1_base_ptr_ &&
8753 str0_range_ptr_ &&
8754 str1_range_ptr_ ;
8758 inline T value() const
8760 if (initialised_)
8762 std::size_t r0 = 0;
8763 std::size_t r1 = 0;
8765 if (is_true(test_))
8767 consequent_->value();
8769 range_t& range = str0_range_ptr_->range_ref();
8771 if (range(r0, r1, str0_base_ptr_->size()))
8773 const std::size_t size = (r1 - r0) + 1;
8775 value_.assign(str0_base_ptr_->base() + r0, size);
8777 range_.n1_c.second = value_.size() - 1;
8778 range_.cache.second = range_.n1_c.second;
8780 return T(1);
8783 else
8785 alternative_->value();
8787 range_t& range = str1_range_ptr_->range_ref();
8789 if (range(r0, r1, str1_base_ptr_->size()))
8791 const std::size_t size = (r1 - r0) + 1;
8793 value_.assign(str1_base_ptr_->base() + r0, size);
8795 range_.n1_c.second = value_.size() - 1;
8796 range_.cache.second = range_.n1_c.second;
8798 return T(0);
8803 return std::numeric_limits<T>::quiet_NaN();
8806 std::string str() const
8808 return value_;
8811 char_cptr base() const
8813 return &value_[0];
8816 std::size_t size() const
8818 return value_.size();
8821 range_t& range_ref()
8823 return range_;
8826 const range_t& range_ref() const
8828 return range_;
8831 inline typename expression_node<T>::node_type type() const
8833 return expression_node<T>::e_strcondition;
8836 private:
8838 bool initialised_;
8839 str_base_ptr str0_base_ptr_;
8840 str_base_ptr str1_base_ptr_;
8841 irange_ptr str0_range_ptr_;
8842 irange_ptr str1_range_ptr_;
8843 mutable range_t range_;
8844 mutable std::string value_;
8846 expression_ptr test_;
8847 expression_ptr consequent_;
8848 expression_ptr alternative_;
8851 template <typename T>
8852 class cons_conditional_str_node : public binary_node <T>,
8853 public string_base_node<T>,
8854 public range_interface <T>
8856 public:
8858 typedef expression_node <T>* expression_ptr;
8859 typedef string_base_node<T>* str_base_ptr;
8860 typedef range_pack <T> range_t;
8861 typedef range_t* range_ptr;
8862 typedef range_interface<T> irange_t;
8863 typedef irange_t* irange_ptr;
8865 cons_conditional_str_node(expression_ptr test,
8866 expression_ptr consequent)
8867 : binary_node<T>(details::e_default, consequent, test),
8868 initialised_(false),
8869 str0_base_ptr_ (0),
8870 str0_range_ptr_(0),
8871 test_ (test),
8872 consequent_(consequent)
8874 range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
8875 range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
8877 range_.cache.first = range_.n0_c.second;
8878 range_.cache.second = range_.n1_c.second;
8880 if (is_generally_string_node(binary_node<T>::branch_[0].first))
8882 str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
8884 if (0 == str0_base_ptr_)
8885 return;
8887 str0_range_ptr_ = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
8889 if (0 == str0_range_ptr_)
8890 return;
8893 initialised_ = str0_base_ptr_ && str0_range_ptr_ ;
8896 inline T value() const
8898 if (initialised_)
8900 if (is_true(test_))
8902 consequent_->value();
8904 range_t& range = str0_range_ptr_->range_ref();
8906 std::size_t r0 = 0;
8907 std::size_t r1 = 0;
8909 if (range(r0, r1, str0_base_ptr_->size()))
8911 const std::size_t size = (r1 - r0) + 1;
8913 value_.assign(str0_base_ptr_->base() + r0, size);
8915 range_.n1_c.second = value_.size() - 1;
8916 range_.cache.second = range_.n1_c.second;
8918 return T(1);
8923 return std::numeric_limits<T>::quiet_NaN();
8926 std::string str() const
8928 return value_;
8931 char_cptr base() const
8933 return &value_[0];
8936 std::size_t size() const
8938 return value_.size();
8941 range_t& range_ref()
8943 return range_;
8946 const range_t& range_ref() const
8948 return range_;
8951 inline typename expression_node<T>::node_type type() const
8953 return expression_node<T>::e_strccondition;
8956 private:
8958 bool initialised_;
8959 str_base_ptr str0_base_ptr_;
8960 irange_ptr str0_range_ptr_;
8961 mutable range_t range_;
8962 mutable std::string value_;
8964 expression_ptr test_;
8965 expression_ptr consequent_;
8968 template <typename T, typename VarArgFunction>
8969 class str_vararg_node : public expression_node <T>,
8970 public string_base_node<T>,
8971 public range_interface <T>
8973 public:
8975 typedef expression_node <T>* expression_ptr;
8976 typedef string_base_node<T>* str_base_ptr;
8977 typedef range_pack <T> range_t;
8978 typedef range_t* range_ptr;
8979 typedef range_interface<T> irange_t;
8980 typedef irange_t* irange_ptr;
8982 template <typename Allocator,
8983 template <typename, typename> class Sequence>
8984 explicit str_vararg_node(const Sequence<expression_ptr,Allocator>& arg_list)
8985 : final_node_(arg_list.back()),
8986 final_deletable_(branch_deletable(final_node_)),
8987 initialised_(false),
8988 str_base_ptr_ (0),
8989 str_range_ptr_(0)
8991 if (0 == final_node_)
8992 return;
8993 else if (!is_generally_string_node(final_node_))
8994 return;
8996 str_base_ptr_ = dynamic_cast<str_base_ptr>(final_node_);
8998 if (0 == str_base_ptr_)
8999 return;
9001 str_range_ptr_ = dynamic_cast<irange_ptr>(final_node_);
9003 if (0 == str_range_ptr_)
9004 return;
9006 initialised_ = str_base_ptr_ && str_range_ptr_;
9008 if (arg_list.size() > 1)
9010 const std::size_t arg_list_size = arg_list.size() - 1;
9012 arg_list_.resize(arg_list_size);
9013 delete_branch_.resize(arg_list_size);
9015 for (std::size_t i = 0; i < arg_list_size; ++i)
9017 if (arg_list[i])
9019 arg_list_[i] = arg_list[i];
9020 delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0);
9022 else
9024 arg_list_ .clear();
9025 delete_branch_.clear();
9026 return;
9032 ~str_vararg_node()
9034 if (final_node_ && final_deletable_)
9036 destroy_node(final_node_);
9039 for (std::size_t i = 0; i < arg_list_.size(); ++i)
9041 if (arg_list_[i] && delete_branch_[i])
9043 destroy_node(arg_list_[i]);
9048 inline T value() const
9050 if (!arg_list_.empty())
9052 VarArgFunction::process(arg_list_);
9055 final_node_->value();
9057 return std::numeric_limits<T>::quiet_NaN();
9060 std::string str() const
9062 return str_base_ptr_->str();
9065 char_cptr base() const
9067 return str_base_ptr_->base();
9070 std::size_t size() const
9072 return str_base_ptr_->size();
9075 range_t& range_ref()
9077 return str_range_ptr_->range_ref();
9080 const range_t& range_ref() const
9082 return str_range_ptr_->range_ref();
9085 inline typename expression_node<T>::node_type type() const
9087 return expression_node<T>::e_stringvararg;
9090 private:
9092 expression_ptr final_node_;
9093 bool final_deletable_;
9094 bool initialised_;
9095 str_base_ptr str_base_ptr_;
9096 irange_ptr str_range_ptr_;
9097 std::vector<expression_ptr> arg_list_;
9098 std::vector<unsigned char> delete_branch_;
9100 #endif
9102 template <typename T, std::size_t N>
9103 inline T axn(T a, T x)
9105 // a*x^n
9106 return a * exprtk::details::numeric::fast_exp<T,N>::result(x);
9109 template <typename T, std::size_t N>
9110 inline T axnb(T a, T x, T b)
9112 // a*x^n+b
9113 return a * exprtk::details::numeric::fast_exp<T,N>::result(x) + b;
9116 template <typename T>
9117 struct sf_base
9119 typedef typename details::functor_t<T>::Type Type;
9120 typedef typename details::functor_t<T> functor_t;
9121 typedef typename functor_t::qfunc_t quaternary_functor_t;
9122 typedef typename functor_t::tfunc_t trinary_functor_t;
9123 typedef typename functor_t::bfunc_t binary_functor_t;
9124 typedef typename functor_t::ufunc_t unary_functor_t;
9127 #define define_sfop3(NN,OP0,OP1) \
9128 template <typename T> \
9129 struct sf##NN##_op : public sf_base<T> \
9131 typedef typename sf_base<T>::Type const Type; \
9132 static inline T process(Type x, Type y, Type z) \
9134 return (OP0); \
9136 static inline std::string id() \
9138 return OP1; \
9140 }; \
9142 define_sfop3(00,(x + y) / z ,"(t+t)/t")
9143 define_sfop3(01,(x + y) * z ,"(t+t)*t")
9144 define_sfop3(02,(x + y) - z ,"(t+t)-t")
9145 define_sfop3(03,(x + y) + z ,"(t+t)+t")
9146 define_sfop3(04,(x - y) + z ,"(t-t)+t")
9147 define_sfop3(05,(x - y) / z ,"(t-t)/t")
9148 define_sfop3(06,(x - y) * z ,"(t-t)*t")
9149 define_sfop3(07,(x * y) + z ,"(t*t)+t")
9150 define_sfop3(08,(x * y) - z ,"(t*t)-t")
9151 define_sfop3(09,(x * y) / z ,"(t*t)/t")
9152 define_sfop3(10,(x * y) * z ,"(t*t)*t")
9153 define_sfop3(11,(x / y) + z ,"(t/t)+t")
9154 define_sfop3(12,(x / y) - z ,"(t/t)-t")
9155 define_sfop3(13,(x / y) / z ,"(t/t)/t")
9156 define_sfop3(14,(x / y) * z ,"(t/t)*t")
9157 define_sfop3(15,x / (y + z) ,"t/(t+t)")
9158 define_sfop3(16,x / (y - z) ,"t/(t-t)")
9159 define_sfop3(17,x / (y * z) ,"t/(t*t)")
9160 define_sfop3(18,x / (y / z) ,"t/(t/t)")
9161 define_sfop3(19,x * (y + z) ,"t*(t+t)")
9162 define_sfop3(20,x * (y - z) ,"t*(t-t)")
9163 define_sfop3(21,x * (y * z) ,"t*(t*t)")
9164 define_sfop3(22,x * (y / z) ,"t*(t/t)")
9165 define_sfop3(23,x - (y + z) ,"t-(t+t)")
9166 define_sfop3(24,x - (y - z) ,"t-(t-t)")
9167 define_sfop3(25,x - (y / z) ,"t-(t/t)")
9168 define_sfop3(26,x - (y * z) ,"t-(t*t)")
9169 define_sfop3(27,x + (y * z) ,"t+(t*t)")
9170 define_sfop3(28,x + (y / z) ,"t+(t/t)")
9171 define_sfop3(29,x + (y + z) ,"t+(t+t)")
9172 define_sfop3(30,x + (y - z) ,"t+(t-t)")
9173 define_sfop3(31,(axnb<T,2>(x,y,z))," ")
9174 define_sfop3(32,(axnb<T,3>(x,y,z))," ")
9175 define_sfop3(33,(axnb<T,4>(x,y,z))," ")
9176 define_sfop3(34,(axnb<T,5>(x,y,z))," ")
9177 define_sfop3(35,(axnb<T,6>(x,y,z))," ")
9178 define_sfop3(36,(axnb<T,7>(x,y,z))," ")
9179 define_sfop3(37,(axnb<T,8>(x,y,z))," ")
9180 define_sfop3(38,(axnb<T,9>(x,y,z))," ")
9181 define_sfop3(39,x * numeric::log(y) + z,"")
9182 define_sfop3(40,x * numeric::log(y) - z,"")
9183 define_sfop3(41,x * numeric::log10(y) + z,"")
9184 define_sfop3(42,x * numeric::log10(y) - z,"")
9185 define_sfop3(43,x * numeric::sin(y) + z ,"")
9186 define_sfop3(44,x * numeric::sin(y) - z ,"")
9187 define_sfop3(45,x * numeric::cos(y) + z ,"")
9188 define_sfop3(46,x * numeric::cos(y) - z ,"")
9189 define_sfop3(47,details::is_true(x) ? y : z,"")
9191 #define define_sfop4(NN,OP0,OP1) \
9192 template <typename T> \
9193 struct sf##NN##_op : public sf_base<T> \
9195 typedef typename sf_base<T>::Type const Type; \
9196 static inline T process(Type x, Type y, Type z, Type w) \
9198 return (OP0); \
9200 static inline std::string id() { return OP1; } \
9201 }; \
9203 define_sfop4(48,(x + ((y + z) / w)),"t+((t+t)/t)")
9204 define_sfop4(49,(x + ((y + z) * w)),"t+((t+t)*t)")
9205 define_sfop4(50,(x + ((y - z) / w)),"t+((t-t)/t)")
9206 define_sfop4(51,(x + ((y - z) * w)),"t+((t-t)*t)")
9207 define_sfop4(52,(x + ((y * z) / w)),"t+((t*t)/t)")
9208 define_sfop4(53,(x + ((y * z) * w)),"t+((t*t)*t)")
9209 define_sfop4(54,(x + ((y / z) + w)),"t+((t/t)+t)")
9210 define_sfop4(55,(x + ((y / z) / w)),"t+((t/t)/t)")
9211 define_sfop4(56,(x + ((y / z) * w)),"t+((t/t)*t)")
9212 define_sfop4(57,(x - ((y + z) / w)),"t-((t+t)/t)")
9213 define_sfop4(58,(x - ((y + z) * w)),"t-((t+t)*t)")
9214 define_sfop4(59,(x - ((y - z) / w)),"t-((t-t)/t)")
9215 define_sfop4(60,(x - ((y - z) * w)),"t-((t-t)*t)")
9216 define_sfop4(61,(x - ((y * z) / w)),"t-((t*t)/t)")
9217 define_sfop4(62,(x - ((y * z) * w)),"t-((t*t)*t)")
9218 define_sfop4(63,(x - ((y / z) / w)),"t-((t/t)/t)")
9219 define_sfop4(64,(x - ((y / z) * w)),"t-((t/t)*t)")
9220 define_sfop4(65,(((x + y) * z) - w),"((t+t)*t)-t")
9221 define_sfop4(66,(((x - y) * z) - w),"((t-t)*t)-t")
9222 define_sfop4(67,(((x * y) * z) - w),"((t*t)*t)-t")
9223 define_sfop4(68,(((x / y) * z) - w),"((t/t)*t)-t")
9224 define_sfop4(69,(((x + y) / z) - w),"((t+t)/t)-t")
9225 define_sfop4(70,(((x - y) / z) - w),"((t-t)/t)-t")
9226 define_sfop4(71,(((x * y) / z) - w),"((t*t)/t)-t")
9227 define_sfop4(72,(((x / y) / z) - w),"((t/t)/t)-t")
9228 define_sfop4(73,((x * y) + (z * w)),"(t*t)+(t*t)")
9229 define_sfop4(74,((x * y) - (z * w)),"(t*t)-(t*t)")
9230 define_sfop4(75,((x * y) + (z / w)),"(t*t)+(t/t)")
9231 define_sfop4(76,((x * y) - (z / w)),"(t*t)-(t/t)")
9232 define_sfop4(77,((x / y) + (z / w)),"(t/t)+(t/t)")
9233 define_sfop4(78,((x / y) - (z / w)),"(t/t)-(t/t)")
9234 define_sfop4(79,((x / y) - (z * w)),"(t/t)-(t*t)")
9235 define_sfop4(80,(x / (y + (z * w))),"t/(t+(t*t))")
9236 define_sfop4(81,(x / (y - (z * w))),"t/(t-(t*t))")
9237 define_sfop4(82,(x * (y + (z * w))),"t*(t+(t*t))")
9238 define_sfop4(83,(x * (y - (z * w))),"t*(t-(t*t))")
9240 define_sfop4(84,(axn<T,2>(x,y) + axn<T,2>(z,w)),"")
9241 define_sfop4(85,(axn<T,3>(x,y) + axn<T,3>(z,w)),"")
9242 define_sfop4(86,(axn<T,4>(x,y) + axn<T,4>(z,w)),"")
9243 define_sfop4(87,(axn<T,5>(x,y) + axn<T,5>(z,w)),"")
9244 define_sfop4(88,(axn<T,6>(x,y) + axn<T,6>(z,w)),"")
9245 define_sfop4(89,(axn<T,7>(x,y) + axn<T,7>(z,w)),"")
9246 define_sfop4(90,(axn<T,8>(x,y) + axn<T,8>(z,w)),"")
9247 define_sfop4(91,(axn<T,9>(x,y) + axn<T,9>(z,w)),"")
9248 define_sfop4(92,((details::is_true(x) && details::is_true(y)) ? z : w),"")
9249 define_sfop4(93,((details::is_true(x) || details::is_true(y)) ? z : w),"")
9250 define_sfop4(94,((x < y) ? z : w),"")
9251 define_sfop4(95,((x <= y) ? z : w),"")
9252 define_sfop4(96,((x > y) ? z : w),"")
9253 define_sfop4(97,((x >= y) ? z : w),"")
9254 define_sfop4(98,(details::is_true(numeric::equal(x,y)) ? z : w),"")
9255 define_sfop4(99,(x * numeric::sin(y) + z * numeric::cos(w)),"")
9257 define_sfop4(ext00,((x + y) - (z * w)),"(t+t)-(t*t)")
9258 define_sfop4(ext01,((x + y) - (z / w)),"(t+t)-(t/t)")
9259 define_sfop4(ext02,((x + y) + (z * w)),"(t+t)+(t*t)")
9260 define_sfop4(ext03,((x + y) + (z / w)),"(t+t)+(t/t)")
9261 define_sfop4(ext04,((x - y) + (z * w)),"(t-t)+(t*t)")
9262 define_sfop4(ext05,((x - y) + (z / w)),"(t-t)+(t/t)")
9263 define_sfop4(ext06,((x - y) - (z * w)),"(t-t)-(t*t)")
9264 define_sfop4(ext07,((x - y) - (z / w)),"(t-t)-(t/t)")
9265 define_sfop4(ext08,((x + y) - (z - w)),"(t+t)-(t-t)")
9266 define_sfop4(ext09,((x + y) + (z - w)),"(t+t)+(t-t)")
9267 define_sfop4(ext10,((x + y) + (z + w)),"(t+t)+(t+t)")
9268 define_sfop4(ext11,((x + y) * (z - w)),"(t+t)*(t-t)")
9269 define_sfop4(ext12,((x + y) / (z - w)),"(t+t)/(t-t)")
9270 define_sfop4(ext13,((x - y) - (z + w)),"(t-t)-(t+t)")
9271 define_sfop4(ext14,((x - y) + (z + w)),"(t-t)+(t+t)")
9272 define_sfop4(ext15,((x - y) * (z + w)),"(t-t)*(t+t)")
9273 define_sfop4(ext16,((x - y) / (z + w)),"(t-t)/(t+t)")
9274 define_sfop4(ext17,((x * y) - (z + w)),"(t*t)-(t+t)")
9275 define_sfop4(ext18,((x / y) - (z + w)),"(t/t)-(t+t)")
9276 define_sfop4(ext19,((x * y) + (z + w)),"(t*t)+(t+t)")
9277 define_sfop4(ext20,((x / y) + (z + w)),"(t/t)+(t+t)")
9278 define_sfop4(ext21,((x * y) + (z - w)),"(t*t)+(t-t)")
9279 define_sfop4(ext22,((x / y) + (z - w)),"(t/t)+(t-t)")
9280 define_sfop4(ext23,((x * y) - (z - w)),"(t*t)-(t-t)")
9281 define_sfop4(ext24,((x / y) - (z - w)),"(t/t)-(t-t)")
9282 define_sfop4(ext25,((x + y) * (z * w)),"(t+t)*(t*t)")
9283 define_sfop4(ext26,((x + y) * (z / w)),"(t+t)*(t/t)")
9284 define_sfop4(ext27,((x + y) / (z * w)),"(t+t)/(t*t)")
9285 define_sfop4(ext28,((x + y) / (z / w)),"(t+t)/(t/t)")
9286 define_sfop4(ext29,((x - y) / (z * w)),"(t-t)/(t*t)")
9287 define_sfop4(ext30,((x - y) / (z / w)),"(t-t)/(t/t)")
9288 define_sfop4(ext31,((x - y) * (z * w)),"(t-t)*(t*t)")
9289 define_sfop4(ext32,((x - y) * (z / w)),"(t-t)*(t/t)")
9290 define_sfop4(ext33,((x * y) * (z + w)),"(t*t)*(t+t)")
9291 define_sfop4(ext34,((x / y) * (z + w)),"(t/t)*(t+t)")
9292 define_sfop4(ext35,((x * y) / (z + w)),"(t*t)/(t+t)")
9293 define_sfop4(ext36,((x / y) / (z + w)),"(t/t)/(t+t)")
9294 define_sfop4(ext37,((x * y) / (z - w)),"(t*t)/(t-t)")
9295 define_sfop4(ext38,((x / y) / (z - w)),"(t/t)/(t-t)")
9296 define_sfop4(ext39,((x * y) * (z - w)),"(t*t)*(t-t)")
9297 define_sfop4(ext40,((x * y) / (z * w)),"(t*t)/(t*t)")
9298 define_sfop4(ext41,((x / y) * (z / w)),"(t/t)*(t/t)")
9299 define_sfop4(ext42,((x / y) * (z - w)),"(t/t)*(t-t)")
9300 define_sfop4(ext43,((x * y) * (z * w)),"(t*t)*(t*t)")
9301 define_sfop4(ext44,(x + (y * (z / w))),"t+(t*(t/t))")
9302 define_sfop4(ext45,(x - (y * (z / w))),"t-(t*(t/t))")
9303 define_sfop4(ext46,(x + (y / (z * w))),"t+(t/(t*t))")
9304 define_sfop4(ext47,(x - (y / (z * w))),"t-(t/(t*t))")
9305 define_sfop4(ext48,(((x - y) - z) * w),"((t-t)-t)*t")
9306 define_sfop4(ext49,(((x - y) - z) / w),"((t-t)-t)/t")
9307 define_sfop4(ext50,(((x - y) + z) * w),"((t-t)+t)*t")
9308 define_sfop4(ext51,(((x - y) + z) / w),"((t-t)+t)/t")
9309 define_sfop4(ext52,((x + (y - z)) * w),"(t+(t-t))*t")
9310 define_sfop4(ext53,((x + (y - z)) / w),"(t+(t-t))/t")
9311 define_sfop4(ext54,((x + y) / (z + w)),"(t+t)/(t+t)")
9312 define_sfop4(ext55,((x - y) / (z - w)),"(t-t)/(t-t)")
9313 define_sfop4(ext56,((x + y) * (z + w)),"(t+t)*(t+t)")
9314 define_sfop4(ext57,((x - y) * (z - w)),"(t-t)*(t-t)")
9315 define_sfop4(ext58,((x - y) + (z - w)),"(t-t)+(t-t)")
9316 define_sfop4(ext59,((x - y) - (z - w)),"(t-t)-(t-t)")
9317 define_sfop4(ext60,((x / y) + (z * w)),"(t/t)+(t*t)")
9318 define_sfop4(ext61,(((x * y) * z) / w),"((t*t)*t)/t")
9320 #undef define_sfop3
9321 #undef define_sfop4
9323 template <typename T, typename SpecialFunction>
9324 class sf3_node : public trinary_node<T>
9326 public:
9328 typedef expression_node<T>* expression_ptr;
9330 sf3_node(const operator_type& opr,
9331 expression_ptr branch0,
9332 expression_ptr branch1,
9333 expression_ptr branch2)
9334 : trinary_node<T>(opr, branch0, branch1, branch2)
9337 inline T value() const
9339 const T x = trinary_node<T>::branch_[0].first->value();
9340 const T y = trinary_node<T>::branch_[1].first->value();
9341 const T z = trinary_node<T>::branch_[2].first->value();
9343 return SpecialFunction::process(x, y, z);
9347 template <typename T, typename SpecialFunction>
9348 class sf4_node : public quaternary_node<T>
9350 public:
9352 typedef expression_node<T>* expression_ptr;
9354 sf4_node(const operator_type& opr,
9355 expression_ptr branch0,
9356 expression_ptr branch1,
9357 expression_ptr branch2,
9358 expression_ptr branch3)
9359 : quaternary_node<T>(opr, branch0, branch1, branch2, branch3)
9362 inline T value() const
9364 const T x = quaternary_node<T>::branch_[0].first->value();
9365 const T y = quaternary_node<T>::branch_[1].first->value();
9366 const T z = quaternary_node<T>::branch_[2].first->value();
9367 const T w = quaternary_node<T>::branch_[3].first->value();
9369 return SpecialFunction::process(x, y, z, w);
9373 template <typename T, typename SpecialFunction>
9374 class sf3_var_node : public expression_node<T>
9376 public:
9378 typedef expression_node<T>* expression_ptr;
9380 sf3_var_node(const T& v0, const T& v1, const T& v2)
9381 : v0_(v0),
9382 v1_(v1),
9383 v2_(v2)
9386 inline T value() const
9388 return SpecialFunction::process(v0_, v1_, v2_);
9391 inline typename expression_node<T>::node_type type() const
9393 return expression_node<T>::e_trinary;
9396 private:
9398 sf3_var_node(sf3_var_node<T,SpecialFunction>&);
9399 sf3_var_node<T,SpecialFunction>& operator=(sf3_var_node<T,SpecialFunction>&);
9401 const T& v0_;
9402 const T& v1_;
9403 const T& v2_;
9406 template <typename T, typename SpecialFunction>
9407 class sf4_var_node : public expression_node<T>
9409 public:
9411 typedef expression_node<T>* expression_ptr;
9413 sf4_var_node(const T& v0, const T& v1, const T& v2, const T& v3)
9414 : v0_(v0),
9415 v1_(v1),
9416 v2_(v2),
9417 v3_(v3)
9420 inline T value() const
9422 return SpecialFunction::process(v0_, v1_, v2_, v3_);
9425 inline typename expression_node<T>::node_type type() const
9427 return expression_node<T>::e_trinary;
9430 private:
9432 sf4_var_node(sf4_var_node<T,SpecialFunction>&);
9433 sf4_var_node<T,SpecialFunction>& operator=(sf4_var_node<T,SpecialFunction>&);
9435 const T& v0_;
9436 const T& v1_;
9437 const T& v2_;
9438 const T& v3_;
9441 template <typename T, typename VarArgFunction>
9442 class vararg_node : public expression_node<T>
9444 public:
9446 typedef expression_node<T>* expression_ptr;
9448 template <typename Allocator,
9449 template <typename, typename> class Sequence>
9450 explicit vararg_node(const Sequence<expression_ptr,Allocator>& arg_list)
9452 arg_list_ .resize(arg_list.size());
9453 delete_branch_.resize(arg_list.size());
9455 for (std::size_t i = 0; i < arg_list.size(); ++i)
9457 if (arg_list[i])
9459 arg_list_[i] = arg_list[i];
9460 delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0);
9462 else
9464 arg_list_.clear();
9465 delete_branch_.clear();
9466 return;
9471 ~vararg_node()
9473 for (std::size_t i = 0; i < arg_list_.size(); ++i)
9475 if (arg_list_[i] && delete_branch_[i])
9477 destroy_node(arg_list_[i]);
9482 inline T value() const
9484 return VarArgFunction::process(arg_list_);
9487 inline typename expression_node<T>::node_type type() const
9489 return expression_node<T>::e_vararg;
9492 private:
9494 std::vector<expression_ptr> arg_list_;
9495 std::vector<unsigned char> delete_branch_;
9498 template <typename T, typename VarArgFunction>
9499 class vararg_varnode : public expression_node<T>
9501 public:
9503 typedef expression_node<T>* expression_ptr;
9505 template <typename Allocator,
9506 template <typename, typename> class Sequence>
9507 explicit vararg_varnode(const Sequence<expression_ptr,Allocator>& arg_list)
9509 arg_list_.resize(arg_list.size());
9511 for (std::size_t i = 0; i < arg_list.size(); ++i)
9513 if (arg_list[i] && is_variable_node(arg_list[i]))
9515 variable_node<T>* var_node_ptr = static_cast<variable_node<T>*>(arg_list[i]);
9516 arg_list_[i] = (&var_node_ptr->ref());
9518 else
9520 arg_list_.clear();
9521 return;
9526 inline T value() const
9528 if (!arg_list_.empty())
9529 return VarArgFunction::process(arg_list_);
9530 else
9531 return std::numeric_limits<T>::quiet_NaN();
9534 inline typename expression_node<T>::node_type type() const
9536 return expression_node<T>::e_vararg;
9539 private:
9541 std::vector<const T*> arg_list_;
9544 template <typename T, typename VecFunction>
9545 class vectorize_node : public expression_node<T>
9547 public:
9549 typedef expression_node<T>* expression_ptr;
9551 explicit vectorize_node(const expression_ptr v)
9552 : ivec_ptr_(0),
9553 v_(v),
9554 v_deletable_(branch_deletable(v_))
9556 if (is_ivector_node(v))
9558 ivec_ptr_ = dynamic_cast<vector_interface<T>*>(v);
9560 else
9561 ivec_ptr_ = 0;
9564 ~vectorize_node()
9566 if (v_ && v_deletable_)
9568 destroy_node(v_);
9572 inline T value() const
9574 if (ivec_ptr_)
9576 v_->value();
9577 return VecFunction::process(ivec_ptr_);
9579 else
9580 return std::numeric_limits<T>::quiet_NaN();
9583 inline typename expression_node<T>::node_type type() const
9585 return expression_node<T>::e_vecfunc;
9588 private:
9590 vector_interface<T>* ivec_ptr_;
9591 expression_ptr v_;
9592 const bool v_deletable_;
9595 template <typename T>
9596 class assignment_node : public binary_node<T>
9598 public:
9600 typedef expression_node<T>* expression_ptr;
9602 assignment_node(const operator_type& opr,
9603 expression_ptr branch0,
9604 expression_ptr branch1)
9605 : binary_node<T>(opr, branch0, branch1),
9606 var_node_ptr_(0)
9608 if (is_variable_node(binary_node<T>::branch_[0].first))
9610 var_node_ptr_ = static_cast<variable_node<T>*>(binary_node<T>::branch_[0].first);
9614 inline T value() const
9616 if (var_node_ptr_)
9618 T& result = var_node_ptr_->ref();
9620 result = binary_node<T>::branch_[1].first->value();
9622 return result;
9624 else
9625 return std::numeric_limits<T>::quiet_NaN();
9628 private:
9630 variable_node<T>* var_node_ptr_;
9633 template <typename T>
9634 class assignment_vec_elem_node : public binary_node<T>
9636 public:
9638 typedef expression_node<T>* expression_ptr;
9640 assignment_vec_elem_node(const operator_type& opr,
9641 expression_ptr branch0,
9642 expression_ptr branch1)
9643 : binary_node<T>(opr, branch0, branch1),
9644 vec_node_ptr_(0)
9646 if (is_vector_elem_node(binary_node<T>::branch_[0].first))
9648 vec_node_ptr_ = static_cast<vector_elem_node<T>*>(binary_node<T>::branch_[0].first);
9652 inline T value() const
9654 if (vec_node_ptr_)
9656 T& result = vec_node_ptr_->ref();
9658 result = binary_node<T>::branch_[1].first->value();
9660 return result;
9662 else
9663 return std::numeric_limits<T>::quiet_NaN();
9666 private:
9668 vector_elem_node<T>* vec_node_ptr_;
9671 template <typename T>
9672 class assignment_rebasevec_elem_node : public binary_node<T>
9674 public:
9676 typedef expression_node<T>* expression_ptr;
9678 assignment_rebasevec_elem_node(const operator_type& opr,
9679 expression_ptr branch0,
9680 expression_ptr branch1)
9681 : binary_node<T>(opr, branch0, branch1),
9682 rbvec_node_ptr_(0)
9684 if (is_rebasevector_elem_node(binary_node<T>::branch_[0].first))
9686 rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(binary_node<T>::branch_[0].first);
9690 inline T value() const
9692 if (rbvec_node_ptr_)
9694 T& result = rbvec_node_ptr_->ref();
9696 result = binary_node<T>::branch_[1].first->value();
9698 return result;
9700 else
9701 return std::numeric_limits<T>::quiet_NaN();
9704 private:
9706 rebasevector_elem_node<T>* rbvec_node_ptr_;
9709 template <typename T>
9710 class assignment_rebasevec_celem_node : public binary_node<T>
9712 public:
9714 typedef expression_node<T>* expression_ptr;
9716 assignment_rebasevec_celem_node(const operator_type& opr,
9717 expression_ptr branch0,
9718 expression_ptr branch1)
9719 : binary_node<T>(opr, branch0, branch1),
9720 rbvec_node_ptr_(0)
9722 if (is_rebasevector_celem_node(binary_node<T>::branch_[0].first))
9724 rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(binary_node<T>::branch_[0].first);
9728 inline T value() const
9730 if (rbvec_node_ptr_)
9732 T& result = rbvec_node_ptr_->ref();
9734 result = binary_node<T>::branch_[1].first->value();
9736 return result;
9738 else
9739 return std::numeric_limits<T>::quiet_NaN();
9742 private:
9744 rebasevector_celem_node<T>* rbvec_node_ptr_;
9747 template <typename T>
9748 class assignment_vec_node : public binary_node <T>,
9749 public vector_interface<T>
9751 public:
9753 typedef expression_node<T>* expression_ptr;
9754 typedef vector_node<T>* vector_node_ptr;
9755 typedef vec_data_store<T> vds_t;
9757 assignment_vec_node(const operator_type& opr,
9758 expression_ptr branch0,
9759 expression_ptr branch1)
9760 : binary_node<T>(opr, branch0, branch1),
9761 vec_node_ptr_(0)
9763 if (is_vector_node(binary_node<T>::branch_[0].first))
9765 vec_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
9766 vds() = vec_node_ptr_->vds();
9770 inline T value() const
9772 if (vec_node_ptr_)
9774 const T v = binary_node<T>::branch_[1].first->value();
9776 T* vec = vds().data();
9778 loop_unroll::details lud(size());
9779 const T* upper_bound = vec + lud.upper_bound;
9781 while (vec < upper_bound)
9783 #define exprtk_loop(N) \
9784 vec[N] = v; \
9786 exprtk_loop( 0) exprtk_loop( 1)
9787 exprtk_loop( 2) exprtk_loop( 3)
9788 #ifndef exprtk_disable_superscalar_unroll
9789 exprtk_loop( 4) exprtk_loop( 5)
9790 exprtk_loop( 6) exprtk_loop( 7)
9791 exprtk_loop( 8) exprtk_loop( 9)
9792 exprtk_loop(10) exprtk_loop(11)
9793 exprtk_loop(12) exprtk_loop(13)
9794 exprtk_loop(14) exprtk_loop(15)
9795 #endif
9797 vec += lud.batch_size;
9800 exprtk_disable_fallthrough_begin
9801 switch (lud.remainder)
9803 #define case_stmt(N) \
9804 case N : *vec++ = v; \
9806 #ifndef exprtk_disable_superscalar_unroll
9807 case_stmt(15) case_stmt(14)
9808 case_stmt(13) case_stmt(12)
9809 case_stmt(11) case_stmt(10)
9810 case_stmt( 9) case_stmt( 8)
9811 case_stmt( 7) case_stmt( 6)
9812 case_stmt( 5) case_stmt( 4)
9813 #endif
9814 case_stmt( 3) case_stmt( 2)
9815 case_stmt( 1)
9817 exprtk_disable_fallthrough_end
9819 #undef exprtk_loop
9820 #undef case_stmt
9822 return vec_node_ptr_->value();
9824 else
9825 return std::numeric_limits<T>::quiet_NaN();
9828 vector_node_ptr vec() const
9830 return vec_node_ptr_;
9833 vector_node_ptr vec()
9835 return vec_node_ptr_;
9838 inline typename expression_node<T>::node_type type() const
9840 return expression_node<T>::e_vecvalass;
9843 std::size_t size() const
9845 return vds().size();
9848 vds_t& vds()
9850 return vds_;
9853 const vds_t& vds() const
9855 return vds_;
9858 private:
9860 vector_node<T>* vec_node_ptr_;
9861 vds_t vds_;
9864 template <typename T>
9865 class assignment_vecvec_node : public binary_node <T>,
9866 public vector_interface<T>
9868 public:
9870 typedef expression_node<T>* expression_ptr;
9871 typedef vector_node<T>* vector_node_ptr;
9872 typedef vec_data_store<T> vds_t;
9874 assignment_vecvec_node(const operator_type& opr,
9875 expression_ptr branch0,
9876 expression_ptr branch1)
9877 : binary_node<T>(opr, branch0, branch1),
9878 vec0_node_ptr_(0),
9879 vec1_node_ptr_(0),
9880 initialised_(false),
9881 src_is_ivec_(false)
9883 if (is_vector_node(binary_node<T>::branch_[0].first))
9885 vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
9886 vds() = vec0_node_ptr_->vds();
9889 if (is_vector_node(binary_node<T>::branch_[1].first))
9891 vec1_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first);
9892 vds_t::match_sizes(vds(),vec1_node_ptr_->vds());
9894 else if (is_ivector_node(binary_node<T>::branch_[1].first))
9896 vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
9898 if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
9900 vec1_node_ptr_ = vi->vec();
9902 if (!vi->side_effect())
9904 vi->vds() = vds();
9905 src_is_ivec_ = true;
9907 else
9908 vds_t::match_sizes(vds(),vi->vds());
9912 initialised_ = (vec0_node_ptr_ && vec1_node_ptr_);
9915 inline T value() const
9917 if (initialised_)
9919 binary_node<T>::branch_[1].first->value();
9921 if (src_is_ivec_)
9922 return vec0_node_ptr_->value();
9924 T* vec0 = vec0_node_ptr_->vds().data();
9925 T* vec1 = vec1_node_ptr_->vds().data();
9927 loop_unroll::details lud(size());
9928 const T* upper_bound = vec0 + lud.upper_bound;
9930 while (vec0 < upper_bound)
9932 #define exprtk_loop(N) \
9933 vec0[N] = vec1[N]; \
9935 exprtk_loop( 0) exprtk_loop( 1)
9936 exprtk_loop( 2) exprtk_loop( 3)
9937 #ifndef exprtk_disable_superscalar_unroll
9938 exprtk_loop( 4) exprtk_loop( 5)
9939 exprtk_loop( 6) exprtk_loop( 7)
9940 exprtk_loop( 8) exprtk_loop( 9)
9941 exprtk_loop(10) exprtk_loop(11)
9942 exprtk_loop(12) exprtk_loop(13)
9943 exprtk_loop(14) exprtk_loop(15)
9944 #endif
9946 vec0 += lud.batch_size;
9947 vec1 += lud.batch_size;
9950 exprtk_disable_fallthrough_begin
9951 switch (lud.remainder)
9953 #define case_stmt(N) \
9954 case N : *vec0++ = *vec1++; \
9956 #ifndef exprtk_disable_superscalar_unroll
9957 case_stmt(15) case_stmt(14)
9958 case_stmt(13) case_stmt(12)
9959 case_stmt(11) case_stmt(10)
9960 case_stmt( 9) case_stmt( 8)
9961 case_stmt( 7) case_stmt( 6)
9962 case_stmt( 5) case_stmt( 4)
9963 #endif
9964 case_stmt( 3) case_stmt( 2)
9965 case_stmt( 1)
9967 exprtk_disable_fallthrough_end
9969 #undef exprtk_loop
9970 #undef case_stmt
9972 return vec0_node_ptr_->value();
9974 else
9975 return std::numeric_limits<T>::quiet_NaN();
9978 vector_node_ptr vec() const
9980 return vec0_node_ptr_;
9983 vector_node_ptr vec()
9985 return vec0_node_ptr_;
9988 inline typename expression_node<T>::node_type type() const
9990 return expression_node<T>::e_vecvecass;
9993 std::size_t size() const
9995 return vds().size();
9998 vds_t& vds()
10000 return vds_;
10003 const vds_t& vds() const
10005 return vds_;
10008 private:
10010 vector_node<T>* vec0_node_ptr_;
10011 vector_node<T>* vec1_node_ptr_;
10012 bool initialised_;
10013 bool src_is_ivec_;
10014 vds_t vds_;
10017 template <typename T, typename Operation>
10018 class assignment_op_node : public binary_node<T>
10020 public:
10022 typedef expression_node<T>* expression_ptr;
10024 assignment_op_node(const operator_type& opr,
10025 expression_ptr branch0,
10026 expression_ptr branch1)
10027 : binary_node<T>(opr, branch0, branch1),
10028 var_node_ptr_(0)
10030 if (is_variable_node(binary_node<T>::branch_[0].first))
10032 var_node_ptr_ = static_cast<variable_node<T>*>(binary_node<T>::branch_[0].first);
10036 inline T value() const
10038 if (var_node_ptr_)
10040 T& v = var_node_ptr_->ref();
10041 v = Operation::process(v,binary_node<T>::branch_[1].first->value());
10043 return v;
10045 else
10046 return std::numeric_limits<T>::quiet_NaN();
10049 private:
10051 variable_node<T>* var_node_ptr_;
10054 template <typename T, typename Operation>
10055 class assignment_vec_elem_op_node : public binary_node<T>
10057 public:
10059 typedef expression_node<T>* expression_ptr;
10061 assignment_vec_elem_op_node(const operator_type& opr,
10062 expression_ptr branch0,
10063 expression_ptr branch1)
10064 : binary_node<T>(opr, branch0, branch1),
10065 vec_node_ptr_(0)
10067 if (is_vector_elem_node(binary_node<T>::branch_[0].first))
10069 vec_node_ptr_ = static_cast<vector_elem_node<T>*>(binary_node<T>::branch_[0].first);
10073 inline T value() const
10075 if (vec_node_ptr_)
10077 T& v = vec_node_ptr_->ref();
10078 v = Operation::process(v,binary_node<T>::branch_[1].first->value());
10080 return v;
10082 else
10083 return std::numeric_limits<T>::quiet_NaN();
10086 private:
10088 vector_elem_node<T>* vec_node_ptr_;
10091 template <typename T, typename Operation>
10092 class assignment_rebasevec_elem_op_node : public binary_node<T>
10094 public:
10096 typedef expression_node<T>* expression_ptr;
10098 assignment_rebasevec_elem_op_node(const operator_type& opr,
10099 expression_ptr branch0,
10100 expression_ptr branch1)
10101 : binary_node<T>(opr, branch0, branch1),
10102 rbvec_node_ptr_(0)
10104 if (is_rebasevector_elem_node(binary_node<T>::branch_[0].first))
10106 rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(binary_node<T>::branch_[0].first);
10110 inline T value() const
10112 if (rbvec_node_ptr_)
10114 T& v = rbvec_node_ptr_->ref();
10115 v = Operation::process(v,binary_node<T>::branch_[1].first->value());
10117 return v;
10119 else
10120 return std::numeric_limits<T>::quiet_NaN();
10123 private:
10125 rebasevector_elem_node<T>* rbvec_node_ptr_;
10128 template <typename T, typename Operation>
10129 class assignment_rebasevec_celem_op_node : public binary_node<T>
10131 public:
10133 typedef expression_node<T>* expression_ptr;
10135 assignment_rebasevec_celem_op_node(const operator_type& opr,
10136 expression_ptr branch0,
10137 expression_ptr branch1)
10138 : binary_node<T>(opr, branch0, branch1),
10139 rbvec_node_ptr_(0)
10141 if (is_rebasevector_celem_node(binary_node<T>::branch_[0].first))
10143 rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(binary_node<T>::branch_[0].first);
10147 inline T value() const
10149 if (rbvec_node_ptr_)
10151 T& v = rbvec_node_ptr_->ref();
10152 v = Operation::process(v,binary_node<T>::branch_[1].first->value());
10154 return v;
10156 else
10157 return std::numeric_limits<T>::quiet_NaN();
10160 private:
10162 rebasevector_celem_node<T>* rbvec_node_ptr_;
10165 template <typename T, typename Operation>
10166 class assignment_vec_op_node : public binary_node <T>,
10167 public vector_interface<T>
10169 public:
10171 typedef expression_node<T>* expression_ptr;
10172 typedef vector_node<T>* vector_node_ptr;
10173 typedef vec_data_store<T> vds_t;
10175 assignment_vec_op_node(const operator_type& opr,
10176 expression_ptr branch0,
10177 expression_ptr branch1)
10178 : binary_node<T>(opr, branch0, branch1),
10179 vec_node_ptr_(0)
10181 if (is_vector_node(binary_node<T>::branch_[0].first))
10183 vec_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
10184 vds() = vec_node_ptr_->vds();
10188 inline T value() const
10190 if (vec_node_ptr_)
10192 const T v = binary_node<T>::branch_[1].first->value();
10194 T* vec = vds().data();
10196 loop_unroll::details lud(size());
10197 const T* upper_bound = vec + lud.upper_bound;
10199 while (vec < upper_bound)
10201 #define exprtk_loop(N) \
10202 Operation::assign(vec[N],v); \
10204 exprtk_loop( 0) exprtk_loop( 1)
10205 exprtk_loop( 2) exprtk_loop( 3)
10206 #ifndef exprtk_disable_superscalar_unroll
10207 exprtk_loop( 4) exprtk_loop( 5)
10208 exprtk_loop( 6) exprtk_loop( 7)
10209 exprtk_loop( 8) exprtk_loop( 9)
10210 exprtk_loop(10) exprtk_loop(11)
10211 exprtk_loop(12) exprtk_loop(13)
10212 exprtk_loop(14) exprtk_loop(15)
10213 #endif
10215 vec += lud.batch_size;
10218 exprtk_disable_fallthrough_begin
10219 switch (lud.remainder)
10221 #define case_stmt(N) \
10222 case N : Operation::assign(*vec++,v); \
10224 #ifndef exprtk_disable_superscalar_unroll
10225 case_stmt(15) case_stmt(14)
10226 case_stmt(13) case_stmt(12)
10227 case_stmt(11) case_stmt(10)
10228 case_stmt( 9) case_stmt( 8)
10229 case_stmt( 7) case_stmt( 6)
10230 case_stmt( 5) case_stmt( 4)
10231 #endif
10232 case_stmt( 3) case_stmt( 2)
10233 case_stmt( 1)
10235 exprtk_disable_fallthrough_end
10238 #undef exprtk_loop
10239 #undef case_stmt
10241 return vec_node_ptr_->value();
10243 else
10244 return std::numeric_limits<T>::quiet_NaN();
10247 vector_node_ptr vec() const
10249 return vec_node_ptr_;
10252 vector_node_ptr vec()
10254 return vec_node_ptr_;
10257 inline typename expression_node<T>::node_type type() const
10259 return expression_node<T>::e_vecopvalass;
10262 std::size_t size() const
10264 return vds().size();
10267 vds_t& vds()
10269 return vds_;
10272 const vds_t& vds() const
10274 return vds_;
10277 bool side_effect() const
10279 return true;
10282 private:
10284 vector_node<T>* vec_node_ptr_;
10285 vds_t vds_;
10288 template <typename T, typename Operation>
10289 class assignment_vecvec_op_node : public binary_node <T>,
10290 public vector_interface<T>
10292 public:
10294 typedef expression_node<T>* expression_ptr;
10295 typedef vector_node<T>* vector_node_ptr;
10296 typedef vec_data_store<T> vds_t;
10298 assignment_vecvec_op_node(const operator_type& opr,
10299 expression_ptr branch0,
10300 expression_ptr branch1)
10301 : binary_node<T>(opr, branch0, branch1),
10302 vec0_node_ptr_(0),
10303 vec1_node_ptr_(0),
10304 initialised_(false)
10306 if (is_vector_node(binary_node<T>::branch_[0].first))
10308 vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
10309 vds() = vec0_node_ptr_->vds();
10312 if (is_vector_node(binary_node<T>::branch_[1].first))
10314 vec1_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first);
10315 vec1_node_ptr_->vds() = vds();
10317 else if (is_ivector_node(binary_node<T>::branch_[1].first))
10319 vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
10321 if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
10323 vec1_node_ptr_ = vi->vec();
10324 vec1_node_ptr_->vds() = vds();
10326 else
10327 vds_t::match_sizes(vds(),vec1_node_ptr_->vds());
10330 initialised_ = (vec0_node_ptr_ && vec1_node_ptr_);
10333 inline T value() const
10335 if (initialised_)
10337 binary_node<T>::branch_[0].first->value();
10338 binary_node<T>::branch_[1].first->value();
10340 T* vec0 = vec0_node_ptr_->vds().data();
10341 const T* vec1 = vec1_node_ptr_->vds().data();
10343 loop_unroll::details lud(size());
10344 const T* upper_bound = vec0 + lud.upper_bound;
10346 while (vec0 < upper_bound)
10348 #define exprtk_loop(N) \
10349 vec0[N] = Operation::process(vec0[N], vec1[N]); \
10351 exprtk_loop( 0) exprtk_loop( 1)
10352 exprtk_loop( 2) exprtk_loop( 3)
10353 #ifndef exprtk_disable_superscalar_unroll
10354 exprtk_loop( 4) exprtk_loop( 5)
10355 exprtk_loop( 6) exprtk_loop( 7)
10356 exprtk_loop( 8) exprtk_loop( 9)
10357 exprtk_loop(10) exprtk_loop(11)
10358 exprtk_loop(12) exprtk_loop(13)
10359 exprtk_loop(14) exprtk_loop(15)
10360 #endif
10362 vec0 += lud.batch_size;
10363 vec1 += lud.batch_size;
10366 int i = 0;
10368 exprtk_disable_fallthrough_begin
10369 switch (lud.remainder)
10371 #define case_stmt(N) \
10372 case N : { vec0[i] = Operation::process(vec0[i], vec1[i]); ++i; } \
10374 #ifndef exprtk_disable_superscalar_unroll
10375 case_stmt(15) case_stmt(14)
10376 case_stmt(13) case_stmt(12)
10377 case_stmt(11) case_stmt(10)
10378 case_stmt( 9) case_stmt( 8)
10379 case_stmt( 7) case_stmt( 6)
10380 case_stmt( 5) case_stmt( 4)
10381 #endif
10382 case_stmt( 3) case_stmt( 2)
10383 case_stmt( 1)
10385 exprtk_disable_fallthrough_end
10387 #undef exprtk_loop
10388 #undef case_stmt
10390 return vec0_node_ptr_->value();
10392 else
10393 return std::numeric_limits<T>::quiet_NaN();
10396 vector_node_ptr vec() const
10398 return vec0_node_ptr_;
10401 vector_node_ptr vec()
10403 return vec0_node_ptr_;
10406 inline typename expression_node<T>::node_type type() const
10408 return expression_node<T>::e_vecopvecass;
10411 std::size_t size() const
10413 return vds().size();
10416 vds_t& vds()
10418 return vds_;
10421 const vds_t& vds() const
10423 return vds_;
10426 bool side_effect() const
10428 return true;
10431 private:
10433 vector_node<T>* vec0_node_ptr_;
10434 vector_node<T>* vec1_node_ptr_;
10435 bool initialised_;
10436 vds_t vds_;
10439 template <typename T, typename Operation>
10440 class vec_binop_vecvec_node : public binary_node <T>,
10441 public vector_interface<T>
10443 public:
10445 typedef expression_node<T>* expression_ptr;
10446 typedef vector_node<T>* vector_node_ptr;
10447 typedef vector_holder<T>* vector_holder_ptr;
10448 typedef vec_data_store<T> vds_t;
10450 vec_binop_vecvec_node(const operator_type& opr,
10451 expression_ptr branch0,
10452 expression_ptr branch1)
10453 : binary_node<T>(opr, branch0, branch1),
10454 vec0_node_ptr_(0),
10455 vec1_node_ptr_(0),
10456 temp_ (0),
10457 temp_vec_node_(0),
10458 initialised_(false)
10460 bool v0_is_ivec = false;
10461 bool v1_is_ivec = false;
10463 if (is_vector_node(binary_node<T>::branch_[0].first))
10465 vec0_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[0].first);
10467 else if (is_ivector_node(binary_node<T>::branch_[0].first))
10469 vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
10471 if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
10473 vec0_node_ptr_ = vi->vec();
10474 v0_is_ivec = true;
10478 if (is_vector_node(binary_node<T>::branch_[1].first))
10480 vec1_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[1].first);
10482 else if (is_ivector_node(binary_node<T>::branch_[1].first))
10484 vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
10486 if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
10488 vec1_node_ptr_ = vi->vec();
10489 v1_is_ivec = true;
10493 if (vec0_node_ptr_ && vec1_node_ptr_)
10495 vector_holder<T>& vec0 = vec0_node_ptr_->vec_holder();
10496 vector_holder<T>& vec1 = vec1_node_ptr_->vec_holder();
10498 if (v0_is_ivec && (vec0.size() <= vec1.size()))
10499 vds_ = vds_t(vec0_node_ptr_->vds());
10500 else if (v1_is_ivec && (vec1.size() <= vec0.size()))
10501 vds_ = vds_t(vec1_node_ptr_->vds());
10502 else
10503 vds_ = vds_t(std::min(vec0.size(),vec1.size()));
10505 temp_ = new vector_holder<T>(vds().data(),vds().size());
10506 temp_vec_node_ = new vector_node<T> (vds(),temp_);
10508 initialised_ = true;
10512 ~vec_binop_vecvec_node()
10514 delete temp_;
10515 delete temp_vec_node_;
10518 inline T value() const
10520 if (initialised_)
10522 binary_node<T>::branch_[0].first->value();
10523 binary_node<T>::branch_[1].first->value();
10525 const T* vec0 = vec0_node_ptr_->vds().data();
10526 const T* vec1 = vec1_node_ptr_->vds().data();
10527 T* vec2 = vds().data();
10529 loop_unroll::details lud(size());
10530 const T* upper_bound = vec2 + lud.upper_bound;
10532 while (vec2 < upper_bound)
10534 #define exprtk_loop(N) \
10535 vec2[N] = Operation::process(vec0[N], vec1[N]); \
10537 exprtk_loop( 0) exprtk_loop( 1)
10538 exprtk_loop( 2) exprtk_loop( 3)
10539 #ifndef exprtk_disable_superscalar_unroll
10540 exprtk_loop( 4) exprtk_loop( 5)
10541 exprtk_loop( 6) exprtk_loop( 7)
10542 exprtk_loop( 8) exprtk_loop( 9)
10543 exprtk_loop(10) exprtk_loop(11)
10544 exprtk_loop(12) exprtk_loop(13)
10545 exprtk_loop(14) exprtk_loop(15)
10546 #endif
10548 vec0 += lud.batch_size;
10549 vec1 += lud.batch_size;
10550 vec2 += lud.batch_size;
10553 int i = 0;
10555 exprtk_disable_fallthrough_begin
10556 switch (lud.remainder)
10558 #define case_stmt(N) \
10559 case N : { vec2[i] = Operation::process(vec0[i], vec1[i]); ++i; } \
10561 #ifndef exprtk_disable_superscalar_unroll
10562 case_stmt(15) case_stmt(14)
10563 case_stmt(13) case_stmt(12)
10564 case_stmt(11) case_stmt(10)
10565 case_stmt( 9) case_stmt( 8)
10566 case_stmt( 7) case_stmt( 6)
10567 case_stmt( 5) case_stmt( 4)
10568 #endif
10569 case_stmt( 3) case_stmt( 2)
10570 case_stmt( 1)
10572 exprtk_disable_fallthrough_end
10574 #undef exprtk_loop
10575 #undef case_stmt
10577 return (vds().data())[0];
10579 else
10580 return std::numeric_limits<T>::quiet_NaN();
10583 vector_node_ptr vec() const
10585 return temp_vec_node_;
10588 vector_node_ptr vec()
10590 return temp_vec_node_;
10593 inline typename expression_node<T>::node_type type() const
10595 return expression_node<T>::e_vecvecarith;
10598 std::size_t size() const
10600 return vds_.size();
10603 vds_t& vds()
10605 return vds_;
10608 const vds_t& vds() const
10610 return vds_;
10613 private:
10615 vector_node_ptr vec0_node_ptr_;
10616 vector_node_ptr vec1_node_ptr_;
10617 vector_holder_ptr temp_;
10618 vector_node_ptr temp_vec_node_;
10619 bool initialised_;
10620 vds_t vds_;
10623 template <typename T, typename Operation>
10624 class vec_binop_vecval_node : public binary_node <T>,
10625 public vector_interface<T>
10627 public:
10629 typedef expression_node<T>* expression_ptr;
10630 typedef vector_node<T>* vector_node_ptr;
10631 typedef vector_holder<T>* vector_holder_ptr;
10632 typedef vec_data_store<T> vds_t;
10634 vec_binop_vecval_node(const operator_type& opr,
10635 expression_ptr branch0,
10636 expression_ptr branch1)
10637 : binary_node<T>(opr, branch0, branch1),
10638 vec0_node_ptr_(0),
10639 temp_ (0),
10640 temp_vec_node_(0)
10642 bool v0_is_ivec = false;
10644 if (is_vector_node(binary_node<T>::branch_[0].first))
10646 vec0_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[0].first);
10648 else if (is_ivector_node(binary_node<T>::branch_[0].first))
10650 vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
10652 if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
10654 vec0_node_ptr_ = vi->vec();
10655 v0_is_ivec = true;
10659 if (vec0_node_ptr_)
10661 if (v0_is_ivec)
10662 vds() = vec0_node_ptr_->vds();
10663 else
10664 vds() = vds_t(vec0_node_ptr_->size());
10666 temp_ = new vector_holder<T>(vds());
10667 temp_vec_node_ = new vector_node<T> (vds(),temp_);
10671 ~vec_binop_vecval_node()
10673 delete temp_;
10674 delete temp_vec_node_;
10677 inline T value() const
10679 if (vec0_node_ptr_)
10681 binary_node<T>::branch_[0].first->value();
10682 const T v = binary_node<T>::branch_[1].first->value();
10684 const T* vec0 = vec0_node_ptr_->vds().data();
10685 T* vec1 = vds().data();
10687 loop_unroll::details lud(size());
10688 const T* upper_bound = vec0 + lud.upper_bound;
10690 while (vec0 < upper_bound)
10692 #define exprtk_loop(N) \
10693 vec1[N] = Operation::process(vec0[N], v); \
10695 exprtk_loop( 0) exprtk_loop( 1)
10696 exprtk_loop( 2) exprtk_loop( 3)
10697 #ifndef exprtk_disable_superscalar_unroll
10698 exprtk_loop( 4) exprtk_loop( 5)
10699 exprtk_loop( 6) exprtk_loop( 7)
10700 exprtk_loop( 8) exprtk_loop( 9)
10701 exprtk_loop(10) exprtk_loop(11)
10702 exprtk_loop(12) exprtk_loop(13)
10703 exprtk_loop(14) exprtk_loop(15)
10704 #endif
10706 vec0 += lud.batch_size;
10707 vec1 += lud.batch_size;
10710 int i = 0;
10712 exprtk_disable_fallthrough_begin
10713 switch (lud.remainder)
10715 #define case_stmt(N) \
10716 case N : { vec1[i] = Operation::process(vec0[i], v); ++i; } \
10718 #ifndef exprtk_disable_superscalar_unroll
10719 case_stmt(15) case_stmt(14)
10720 case_stmt(13) case_stmt(12)
10721 case_stmt(11) case_stmt(10)
10722 case_stmt( 9) case_stmt( 8)
10723 case_stmt( 7) case_stmt( 6)
10724 case_stmt( 5) case_stmt( 4)
10725 #endif
10726 case_stmt( 3) case_stmt( 2)
10727 case_stmt( 1)
10729 exprtk_disable_fallthrough_end
10731 #undef exprtk_loop
10732 #undef case_stmt
10734 return (vds().data())[0];
10736 else
10737 return std::numeric_limits<T>::quiet_NaN();
10740 vector_node_ptr vec() const
10742 return temp_vec_node_;
10745 vector_node_ptr vec()
10747 return temp_vec_node_;
10750 inline typename expression_node<T>::node_type type() const
10752 return expression_node<T>::e_vecvalarith;
10755 std::size_t size() const
10757 return vds().size();
10760 vds_t& vds()
10762 return vds_;
10765 const vds_t& vds() const
10767 return vds_;
10770 private:
10772 vector_node_ptr vec0_node_ptr_;
10773 vector_holder_ptr temp_;
10774 vector_node_ptr temp_vec_node_;
10775 vds_t vds_;
10778 template <typename T, typename Operation>
10779 class vec_binop_valvec_node : public binary_node <T>,
10780 public vector_interface<T>
10782 public:
10784 typedef expression_node<T>* expression_ptr;
10785 typedef vector_node<T>* vector_node_ptr;
10786 typedef vector_holder<T>* vector_holder_ptr;
10787 typedef vec_data_store<T> vds_t;
10789 vec_binop_valvec_node(const operator_type& opr,
10790 expression_ptr branch0,
10791 expression_ptr branch1)
10792 : binary_node<T>(opr, branch0, branch1),
10793 vec1_node_ptr_(0),
10794 temp_ (0),
10795 temp_vec_node_(0)
10797 bool v1_is_ivec = false;
10799 if (is_vector_node(binary_node<T>::branch_[1].first))
10801 vec1_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[1].first);
10803 else if (is_ivector_node(binary_node<T>::branch_[1].first))
10805 vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
10807 if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
10809 vec1_node_ptr_ = vi->vec();
10810 v1_is_ivec = true;
10814 if (vec1_node_ptr_)
10816 if (v1_is_ivec)
10817 vds() = vec1_node_ptr_->vds();
10818 else
10819 vds() = vds_t(vec1_node_ptr_->size());
10821 temp_ = new vector_holder<T>(vds());
10822 temp_vec_node_ = new vector_node<T> (vds(),temp_);
10826 ~vec_binop_valvec_node()
10828 delete temp_;
10829 delete temp_vec_node_;
10832 inline T value() const
10834 if (vec1_node_ptr_)
10836 const T v = binary_node<T>::branch_[0].first->value();
10837 binary_node<T>::branch_[1].first->value();
10839 T* vec0 = vds().data();
10840 const T* vec1 = vec1_node_ptr_->vds().data();
10842 loop_unroll::details lud(size());
10843 const T* upper_bound = vec0 + lud.upper_bound;
10845 while (vec0 < upper_bound)
10847 #define exprtk_loop(N) \
10848 vec0[N] = Operation::process(v, vec1[N]); \
10850 exprtk_loop( 0) exprtk_loop( 1)
10851 exprtk_loop( 2) exprtk_loop( 3)
10852 #ifndef exprtk_disable_superscalar_unroll
10853 exprtk_loop( 4) exprtk_loop( 5)
10854 exprtk_loop( 6) exprtk_loop( 7)
10855 exprtk_loop( 8) exprtk_loop( 9)
10856 exprtk_loop(10) exprtk_loop(11)
10857 exprtk_loop(12) exprtk_loop(13)
10858 exprtk_loop(14) exprtk_loop(15)
10859 #endif
10861 vec0 += lud.batch_size;
10862 vec1 += lud.batch_size;
10865 int i = 0;
10867 exprtk_disable_fallthrough_begin
10868 switch (lud.remainder)
10870 #define case_stmt(N) \
10871 case N : { vec0[i] = Operation::process(v, vec1[i]); ++i; } \
10873 #ifndef exprtk_disable_superscalar_unroll
10874 case_stmt(15) case_stmt(14)
10875 case_stmt(13) case_stmt(12)
10876 case_stmt(11) case_stmt(10)
10877 case_stmt( 9) case_stmt( 8)
10878 case_stmt( 7) case_stmt( 6)
10879 case_stmt( 5) case_stmt( 4)
10880 #endif
10881 case_stmt( 3) case_stmt( 2)
10882 case_stmt( 1)
10884 exprtk_disable_fallthrough_end
10886 #undef exprtk_loop
10887 #undef case_stmt
10889 return (vds().data())[0];
10891 else
10892 return std::numeric_limits<T>::quiet_NaN();
10895 vector_node_ptr vec() const
10897 return temp_vec_node_;
10900 vector_node_ptr vec()
10902 return temp_vec_node_;
10905 inline typename expression_node<T>::node_type type() const
10907 return expression_node<T>::e_vecvalarith;
10910 std::size_t size() const
10912 return vds().size();
10915 vds_t& vds()
10917 return vds_;
10920 const vds_t& vds() const
10922 return vds_;
10925 private:
10927 vector_node_ptr vec1_node_ptr_;
10928 vector_holder_ptr temp_;
10929 vector_node_ptr temp_vec_node_;
10930 vds_t vds_;
10933 template <typename T, typename Operation>
10934 class unary_vector_node : public unary_node <T>,
10935 public vector_interface<T>
10937 public:
10939 typedef expression_node<T>* expression_ptr;
10940 typedef vector_node<T>* vector_node_ptr;
10941 typedef vector_holder<T>* vector_holder_ptr;
10942 typedef vec_data_store<T> vds_t;
10944 unary_vector_node(const operator_type& opr, expression_ptr branch0)
10945 : unary_node<T>(opr, branch0),
10946 vec0_node_ptr_(0),
10947 temp_ (0),
10948 temp_vec_node_(0)
10950 bool vec0_is_ivec = false;
10952 if (is_vector_node(unary_node<T>::branch_))
10954 vec0_node_ptr_ = static_cast<vector_node_ptr>(unary_node<T>::branch_);
10956 else if (is_ivector_node(unary_node<T>::branch_))
10958 vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
10960 if (0 != (vi = dynamic_cast<vector_interface<T>*>(unary_node<T>::branch_)))
10962 vec0_node_ptr_ = vi->vec();
10963 vec0_is_ivec = true;
10967 if (vec0_node_ptr_)
10969 if (vec0_is_ivec)
10970 vds_ = vec0_node_ptr_->vds();
10971 else
10972 vds_ = vds_t(vec0_node_ptr_->size());
10974 temp_ = new vector_holder<T>(vds());
10975 temp_vec_node_ = new vector_node<T> (vds(),temp_);
10979 ~unary_vector_node()
10981 delete temp_;
10982 delete temp_vec_node_;
10985 inline T value() const
10987 unary_node<T>::branch_->value();
10989 if (vec0_node_ptr_)
10991 const T* vec0 = vec0_node_ptr_->vds().data();
10992 T* vec1 = vds().data();
10994 loop_unroll::details lud(size());
10995 const T* upper_bound = vec0 + lud.upper_bound;
10997 while (vec0 < upper_bound)
10999 #define exprtk_loop(N) \
11000 vec1[N] = Operation::process(vec0[N]); \
11002 exprtk_loop( 0) exprtk_loop( 1)
11003 exprtk_loop( 2) exprtk_loop( 3)
11004 #ifndef exprtk_disable_superscalar_unroll
11005 exprtk_loop( 4) exprtk_loop( 5)
11006 exprtk_loop( 6) exprtk_loop( 7)
11007 exprtk_loop( 8) exprtk_loop( 9)
11008 exprtk_loop(10) exprtk_loop(11)
11009 exprtk_loop(12) exprtk_loop(13)
11010 exprtk_loop(14) exprtk_loop(15)
11011 #endif
11013 vec0 += lud.batch_size;
11014 vec1 += lud.batch_size;
11017 int i = 0;
11019 exprtk_disable_fallthrough_begin
11020 switch (lud.remainder)
11022 #define case_stmt(N) \
11023 case N : { vec1[i] = Operation::process(vec0[i]); ++i; } \
11025 #ifndef exprtk_disable_superscalar_unroll
11026 case_stmt(15) case_stmt(14)
11027 case_stmt(13) case_stmt(12)
11028 case_stmt(11) case_stmt(10)
11029 case_stmt( 9) case_stmt( 8)
11030 case_stmt( 7) case_stmt( 6)
11031 case_stmt( 5) case_stmt( 4)
11032 #endif
11033 case_stmt( 3) case_stmt( 2)
11034 case_stmt( 1)
11036 exprtk_disable_fallthrough_end
11038 #undef exprtk_loop
11039 #undef case_stmt
11041 return (vds().data())[0];
11043 else
11044 return std::numeric_limits<T>::quiet_NaN();
11047 vector_node_ptr vec() const
11049 return temp_vec_node_;
11052 vector_node_ptr vec()
11054 return temp_vec_node_;
11057 inline typename expression_node<T>::node_type type() const
11059 return expression_node<T>::e_vecunaryop;
11062 std::size_t size() const
11064 return vds().size();
11067 vds_t& vds()
11069 return vds_;
11072 const vds_t& vds() const
11074 return vds_;
11077 private:
11079 vector_node_ptr vec0_node_ptr_;
11080 vector_holder_ptr temp_;
11081 vector_node_ptr temp_vec_node_;
11082 vds_t vds_;
11085 template <typename T>
11086 class scand_node : public binary_node<T>
11088 public:
11090 typedef expression_node<T>* expression_ptr;
11092 scand_node(const operator_type& opr,
11093 expression_ptr branch0,
11094 expression_ptr branch1)
11095 : binary_node<T>(opr, branch0, branch1)
11098 inline T value() const
11100 return (
11101 std::not_equal_to<T>()
11102 (T(0),binary_node<T>::branch_[0].first->value()) &&
11103 std::not_equal_to<T>()
11104 (T(0),binary_node<T>::branch_[1].first->value())
11105 ) ? T(1) : T(0);
11109 template <typename T>
11110 class scor_node : public binary_node<T>
11112 public:
11114 typedef expression_node<T>* expression_ptr;
11116 scor_node(const operator_type& opr,
11117 expression_ptr branch0,
11118 expression_ptr branch1)
11119 : binary_node<T>(opr, branch0, branch1)
11122 inline T value() const
11124 return (
11125 std::not_equal_to<T>()
11126 (T(0),binary_node<T>::branch_[0].first->value()) ||
11127 std::not_equal_to<T>()
11128 (T(0),binary_node<T>::branch_[1].first->value())
11129 ) ? T(1) : T(0);
11133 template <typename T, typename IFunction, std::size_t N>
11134 class function_N_node : public expression_node<T>
11136 public:
11138 // Function of N paramters.
11139 typedef expression_node<T>* expression_ptr;
11140 typedef std::pair<expression_ptr,bool> branch_t;
11141 typedef IFunction ifunction;
11143 explicit function_N_node(ifunction* func)
11144 : function_((N == func->param_count) ? func : reinterpret_cast<ifunction*>(0)),
11145 parameter_count_(func->param_count)
11148 ~function_N_node()
11150 cleanup_branches::execute<T,N>(branch_);
11153 template <std::size_t NumBranches>
11154 bool init_branches(expression_ptr (&b)[NumBranches])
11156 // Needed for incompetent and broken msvc compiler versions
11157 #ifdef _MSC_VER
11158 #pragma warning(push)
11159 #pragma warning(disable: 4127)
11160 #endif
11161 if (N != NumBranches)
11162 return false;
11163 else
11165 for (std::size_t i = 0; i < NumBranches; ++i)
11167 if (b[i])
11168 branch_[i] = std::make_pair(b[i],branch_deletable(b[i]));
11169 else
11170 return false;
11172 return true;
11174 #ifdef _MSC_VER
11175 #pragma warning(pop)
11176 #endif
11179 inline bool operator <(const function_N_node<T,IFunction,N>& fn) const
11181 return this < (&fn);
11184 inline T value() const
11186 // Needed for incompetent and broken msvc compiler versions
11187 #ifdef _MSC_VER
11188 #pragma warning(push)
11189 #pragma warning(disable: 4127)
11190 #endif
11191 if ((0 == function_) || (0 == N))
11192 return std::numeric_limits<T>::quiet_NaN();
11193 else
11195 T v[N];
11196 evaluate_branches<T,N>::execute(v,branch_);
11197 return invoke<T,N>::execute(*function_,v);
11199 #ifdef _MSC_VER
11200 #pragma warning(pop)
11201 #endif
11204 template <typename T_, std::size_t BranchCount>
11205 struct evaluate_branches
11207 static inline void execute(T_ (&v)[BranchCount], const branch_t (&b)[BranchCount])
11209 for (std::size_t i = 0; i < BranchCount; ++i)
11211 v[i] = b[i].first->value();
11216 template <typename T_>
11217 struct evaluate_branches <T_,5>
11219 static inline void execute(T_ (&v)[5], const branch_t (&b)[5])
11221 v[0] = b[0].first->value();
11222 v[1] = b[1].first->value();
11223 v[2] = b[2].first->value();
11224 v[3] = b[3].first->value();
11225 v[4] = b[4].first->value();
11229 template <typename T_>
11230 struct evaluate_branches <T_,4>
11232 static inline void execute(T_ (&v)[4], const branch_t (&b)[4])
11234 v[0] = b[0].first->value();
11235 v[1] = b[1].first->value();
11236 v[2] = b[2].first->value();
11237 v[3] = b[3].first->value();
11241 template <typename T_>
11242 struct evaluate_branches <T_,3>
11244 static inline void execute(T_ (&v)[3], const branch_t (&b)[3])
11246 v[0] = b[0].first->value();
11247 v[1] = b[1].first->value();
11248 v[2] = b[2].first->value();
11252 template <typename T_>
11253 struct evaluate_branches <T_,2>
11255 static inline void execute(T_ (&v)[2], const branch_t (&b)[2])
11257 v[0] = b[0].first->value();
11258 v[1] = b[1].first->value();
11262 template <typename T_>
11263 struct evaluate_branches <T_,1>
11265 static inline void execute(T_ (&v)[1], const branch_t (&b)[1])
11267 v[0] = b[0].first->value();
11271 template <typename T_, std::size_t ParamCount>
11272 struct invoke { static inline T execute(ifunction&, branch_t (&)[ParamCount]) { return std::numeric_limits<T_>::quiet_NaN(); } };
11274 template <typename T_>
11275 struct invoke<T_,20>
11277 static inline T_ execute(ifunction& f, T_ (&v)[20])
11278 { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16],v[17],v[18],v[19]); }
11281 template <typename T_>
11282 struct invoke<T_,19>
11284 static inline T_ execute(ifunction& f, T_ (&v)[19])
11285 { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16],v[17],v[18]); }
11288 template <typename T_>
11289 struct invoke<T_,18>
11291 static inline T_ execute(ifunction& f, T_ (&v)[18])
11292 { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16],v[17]); }
11295 template <typename T_>
11296 struct invoke<T_,17>
11298 static inline T_ execute(ifunction& f, T_ (&v)[17])
11299 { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16]); }
11302 template <typename T_>
11303 struct invoke<T_,16>
11305 static inline T_ execute(ifunction& f, T_ (&v)[16])
11306 { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15]); }
11309 template <typename T_>
11310 struct invoke<T_,15>
11312 static inline T_ execute(ifunction& f, T_ (&v)[15])
11313 { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14]); }
11316 template <typename T_>
11317 struct invoke<T_,14>
11319 static inline T_ execute(ifunction& f, T_ (&v)[14])
11320 { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13]); }
11323 template <typename T_>
11324 struct invoke<T_,13>
11326 static inline T_ execute(ifunction& f, T_ (&v)[13])
11327 { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12]); }
11330 template <typename T_>
11331 struct invoke<T_,12>
11333 static inline T_ execute(ifunction& f, T_ (&v)[12])
11334 { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11]); }
11337 template <typename T_>
11338 struct invoke<T_,11>
11340 static inline T_ execute(ifunction& f, T_ (&v)[11])
11341 { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10]); }
11344 template <typename T_>
11345 struct invoke<T_,10>
11347 static inline T_ execute(ifunction& f, T_ (&v)[10])
11348 { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9]); }
11351 template <typename T_>
11352 struct invoke<T_,9>
11354 static inline T_ execute(ifunction& f, T_ (&v)[9])
11355 { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8]); }
11358 template <typename T_>
11359 struct invoke<T_,8>
11361 static inline T_ execute(ifunction& f, T_ (&v)[8])
11362 { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]); }
11365 template <typename T_>
11366 struct invoke<T_,7>
11368 static inline T_ execute(ifunction& f, T_ (&v)[7])
11369 { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6]); }
11372 template <typename T_>
11373 struct invoke<T_,6>
11375 static inline T_ execute(ifunction& f, T_ (&v)[6])
11376 { return f(v[0],v[1],v[2],v[3],v[4],v[5]); }
11379 template <typename T_>
11380 struct invoke<T_,5>
11382 static inline T_ execute(ifunction& f, T_ (&v)[5])
11383 { return f(v[0],v[1],v[2],v[3],v[4]); }
11386 template <typename T_>
11387 struct invoke<T_,4>
11389 static inline T_ execute(ifunction& f, T_ (&v)[4])
11390 { return f(v[0],v[1],v[2],v[3]); }
11393 template <typename T_>
11394 struct invoke<T_,3>
11396 static inline T_ execute(ifunction& f, T_ (&v)[3])
11397 { return f(v[0],v[1],v[2]); }
11400 template <typename T_>
11401 struct invoke<T_,2>
11403 static inline T_ execute(ifunction& f, T_ (&v)[2])
11404 { return f(v[0],v[1]); }
11407 template <typename T_>
11408 struct invoke<T_,1>
11410 static inline T_ execute(ifunction& f, T_ (&v)[1])
11411 { return f(v[0]); }
11414 inline typename expression_node<T>::node_type type() const
11416 return expression_node<T>::e_function;
11419 private:
11421 ifunction* function_;
11422 std::size_t parameter_count_;
11423 branch_t branch_[N];
11426 template <typename T, typename IFunction>
11427 class function_N_node<T,IFunction,0> : public expression_node<T>
11429 public:
11431 typedef expression_node<T>* expression_ptr;
11432 typedef IFunction ifunction;
11434 explicit function_N_node(ifunction* func)
11435 : function_((0 == func->param_count) ? func : reinterpret_cast<ifunction*>(0))
11438 inline bool operator <(const function_N_node<T,IFunction,0>& fn) const
11440 return this < (&fn);
11443 inline T value() const
11445 if (function_)
11446 return (*function_)();
11447 else
11448 return std::numeric_limits<T>::quiet_NaN();
11451 inline typename expression_node<T>::node_type type() const
11453 return expression_node<T>::e_function;
11456 private:
11458 ifunction* function_;
11461 template <typename T, typename VarArgFunction>
11462 class vararg_function_node : public expression_node<T>
11464 public:
11466 typedef expression_node<T>* expression_ptr;
11468 vararg_function_node(VarArgFunction* func,
11469 const std::vector<expression_ptr>& arg_list)
11470 : function_(func),
11471 arg_list_(arg_list)
11473 value_list_.resize(arg_list.size(),std::numeric_limits<T>::quiet_NaN());
11476 ~vararg_function_node()
11478 for (std::size_t i = 0; i < arg_list_.size(); ++i)
11480 if (arg_list_[i] && !details::is_variable_node(arg_list_[i]))
11482 destroy_node(arg_list_[i]);
11487 inline bool operator <(const vararg_function_node<T,VarArgFunction>& fn) const
11489 return this < (&fn);
11492 inline T value() const
11494 if (function_)
11496 populate_value_list();
11497 return (*function_)(value_list_);
11499 else
11500 return std::numeric_limits<T>::quiet_NaN();
11503 inline typename expression_node<T>::node_type type() const
11505 return expression_node<T>::e_vafunction;
11508 private:
11510 inline void populate_value_list() const
11512 for (std::size_t i = 0; i < arg_list_.size(); ++i)
11514 value_list_[i] = arg_list_[i]->value();
11518 VarArgFunction* function_;
11519 std::vector<expression_ptr> arg_list_;
11520 mutable std::vector<T> value_list_;
11523 template <typename T, typename GenericFunction>
11524 class generic_function_node : public expression_node<T>
11526 public:
11528 typedef type_store<T> type_store_t;
11529 typedef expression_node<T>* expression_ptr;
11530 typedef variable_node<T> variable_node_t;
11531 typedef vector_node<T> vector_node_t;
11532 typedef variable_node_t* variable_node_ptr_t;
11533 typedef vector_node_t* vector_node_ptr_t;
11534 typedef range_interface<T> range_interface_t;
11535 typedef range_data_type<T> range_data_type_t;
11536 typedef range_pack<T> range_t;
11537 typedef std::pair<expression_ptr,bool> branch_t;
11538 typedef std::pair<void*,std::size_t> void_t;
11539 typedef std::vector<T> tmp_vs_t;
11540 typedef std::vector<type_store_t> typestore_list_t;
11541 typedef std::vector<range_data_type_t> range_list_t;
11543 generic_function_node(const std::vector<expression_ptr>& arg_list,
11544 GenericFunction* func = (GenericFunction*)(0))
11545 : function_(func),
11546 arg_list_(arg_list)
11549 virtual ~generic_function_node()
11551 cleanup_branches::execute(branch_);
11554 virtual bool init_branches()
11556 expr_as_vec1_store_.resize(arg_list_.size(),T(0) );
11557 typestore_list_ .resize(arg_list_.size(),type_store_t() );
11558 range_list_ .resize(arg_list_.size(),range_data_type_t());
11559 branch_ .resize(arg_list_.size(),branch_t((expression_ptr)0,false));
11561 for (std::size_t i = 0; i < arg_list_.size(); ++i)
11563 type_store_t& ts = typestore_list_[i];
11565 if (0 == arg_list_[i])
11566 return false;
11567 else if (is_ivector_node(arg_list_[i]))
11569 vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
11571 if (0 == (vi = dynamic_cast<vector_interface<T>*>(arg_list_[i])))
11572 return false;
11574 ts.size = vi->size();
11575 ts.data = vi->vds().data();
11576 ts.type = type_store_t::e_vector;
11577 vi->vec()->vec_holder().set_ref(&ts.vec_data);
11579 #ifndef exprtk_disable_string_capabilities
11580 else if (is_generally_string_node(arg_list_[i]))
11582 string_base_node<T>* sbn = reinterpret_cast<string_base_node<T>*>(0);
11584 if (0 == (sbn = dynamic_cast<string_base_node<T>*>(arg_list_[i])))
11585 return false;
11587 ts.size = sbn->size();
11588 ts.data = reinterpret_cast<void*>(const_cast<char_ptr>(sbn->base()));
11589 ts.type = type_store_t::e_string;
11591 range_list_[i].data = ts.data;
11592 range_list_[i].size = ts.size;
11593 range_list_[i].type_size = sizeof(char);
11594 range_list_[i].str_node = sbn;
11596 range_interface_t* ri = reinterpret_cast<range_interface_t*>(0);
11598 if (0 == (ri = dynamic_cast<range_interface_t*>(arg_list_[i])))
11599 return false;
11601 range_t& rp = ri->range_ref();
11603 if (
11604 rp.const_range() &&
11605 is_const_string_range_node(arg_list_[i])
11608 ts.size = rp.const_size();
11609 ts.data = static_cast<char_ptr>(ts.data) + rp.n0_c.second;
11610 range_list_[i].range = reinterpret_cast<range_t*>(0);
11612 else
11613 range_list_[i].range = &(ri->range_ref());
11615 #endif
11616 else if (is_variable_node(arg_list_[i]))
11618 variable_node_ptr_t var = variable_node_ptr_t(0);
11620 if (0 == (var = dynamic_cast<variable_node_ptr_t>(arg_list_[i])))
11621 return false;
11623 ts.size = 1;
11624 ts.data = &var->ref();
11625 ts.type = type_store_t::e_scalar;
11627 else
11629 ts.size = 1;
11630 ts.data = reinterpret_cast<void*>(&expr_as_vec1_store_[i]);
11631 ts.type = type_store_t::e_scalar;
11634 branch_[i] = std::make_pair(arg_list_[i],branch_deletable(arg_list_[i]));
11637 return true;
11640 inline bool operator <(const generic_function_node<T,GenericFunction>& fn) const
11642 return this < (&fn);
11645 inline T value() const
11647 if (function_)
11649 if (populate_value_list())
11651 typedef typename GenericFunction::parameter_list_t parameter_list_t;
11653 return (*function_)(parameter_list_t(typestore_list_));
11657 return std::numeric_limits<T>::quiet_NaN();
11660 inline typename expression_node<T>::node_type type() const
11662 return expression_node<T>::e_genfunction;
11665 protected:
11667 inline virtual bool populate_value_list() const
11669 for (std::size_t i = 0; i < branch_.size(); ++i)
11671 expr_as_vec1_store_[i] = branch_[i].first->value();
11674 for (std::size_t i = 0; i < branch_.size(); ++i)
11676 range_data_type_t& rdt = range_list_[i];
11678 if (rdt.range)
11680 range_t& rp = (*rdt.range);
11681 std::size_t r0 = 0;
11682 std::size_t r1 = 0;
11684 if (rp(r0,r1,rdt.size))
11686 type_store_t& ts = typestore_list_[i];
11688 ts.size = rp.cache_size();
11689 #ifndef exprtk_disable_string_capabilities
11690 if (ts.type == type_store_t::e_string)
11691 ts.data = const_cast<char_ptr>(rdt.str_node->base()) + rp.cache.first;
11692 else
11693 #endif
11694 ts.data = static_cast<char_ptr>(rdt.data) + (rp.cache.first * rdt.type_size);
11696 else
11697 return false;
11701 return true;
11704 GenericFunction* function_;
11705 mutable typestore_list_t typestore_list_;
11707 private:
11709 std::vector<expression_ptr> arg_list_;
11710 std::vector<branch_t> branch_;
11711 mutable tmp_vs_t expr_as_vec1_store_;
11712 mutable range_list_t range_list_;
11715 #ifndef exprtk_disable_string_capabilities
11716 template <typename T, typename StringFunction>
11717 class string_function_node : public generic_function_node<T,StringFunction>,
11718 public string_base_node<T>,
11719 public range_interface <T>
11721 public:
11723 typedef generic_function_node<T,StringFunction> gen_function_t;
11724 typedef range_pack<T> range_t;
11726 string_function_node(StringFunction* func,
11727 const std::vector<typename gen_function_t::expression_ptr>& arg_list)
11728 : gen_function_t(arg_list,func)
11730 range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
11731 range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
11732 range_.cache.first = range_.n0_c.second;
11733 range_.cache.second = range_.n1_c.second;
11736 inline bool operator <(const string_function_node<T,StringFunction>& fn) const
11738 return this < (&fn);
11741 inline T value() const
11743 if (gen_function_t::function_)
11745 if (gen_function_t::populate_value_list())
11747 typedef typename StringFunction::parameter_list_t parameter_list_t;
11749 const T result = (*gen_function_t::function_)
11751 ret_string_,
11752 parameter_list_t(gen_function_t::typestore_list_)
11755 range_.n1_c.second = ret_string_.size() - 1;
11756 range_.cache.second = range_.n1_c.second;
11758 return result;
11762 return std::numeric_limits<T>::quiet_NaN();
11765 inline typename expression_node<T>::node_type type() const
11767 return expression_node<T>::e_strfunction;
11770 std::string str() const
11772 return ret_string_;
11775 char_cptr base() const
11777 return &ret_string_[0];
11780 std::size_t size() const
11782 return ret_string_.size();
11785 range_t& range_ref()
11787 return range_;
11790 const range_t& range_ref() const
11792 return range_;
11795 protected:
11797 mutable range_t range_;
11798 mutable std::string ret_string_;
11800 #endif
11802 template <typename T, typename GenericFunction>
11803 class multimode_genfunction_node : public generic_function_node<T,GenericFunction>
11805 public:
11807 typedef generic_function_node<T,GenericFunction> gen_function_t;
11808 typedef range_pack<T> range_t;
11810 multimode_genfunction_node(GenericFunction* func,
11811 const std::size_t& param_seq_index,
11812 const std::vector<typename gen_function_t::expression_ptr>& arg_list)
11813 : gen_function_t(arg_list,func),
11814 param_seq_index_(param_seq_index)
11817 inline T value() const
11819 if (gen_function_t::function_)
11821 if (gen_function_t::populate_value_list())
11823 typedef typename GenericFunction::parameter_list_t parameter_list_t;
11825 return (*gen_function_t::function_)
11827 param_seq_index_,
11828 parameter_list_t(gen_function_t::typestore_list_)
11833 return std::numeric_limits<T>::quiet_NaN();
11836 inline typename expression_node<T>::node_type type() const
11838 return expression_node<T>::e_genfunction;
11841 private:
11843 std::size_t param_seq_index_;
11846 #ifndef exprtk_disable_string_capabilities
11847 template <typename T, typename StringFunction>
11848 class multimode_strfunction_node : public string_function_node<T,StringFunction>
11850 public:
11852 typedef string_function_node<T,StringFunction> str_function_t;
11853 typedef range_pack<T> range_t;
11855 multimode_strfunction_node(StringFunction* func,
11856 const std::size_t& param_seq_index,
11857 const std::vector<typename str_function_t::expression_ptr>& arg_list)
11858 : str_function_t(func,arg_list),
11859 param_seq_index_(param_seq_index)
11862 inline T value() const
11864 if (str_function_t::function_)
11866 if (str_function_t::populate_value_list())
11868 typedef typename StringFunction::parameter_list_t parameter_list_t;
11870 const T result = (*str_function_t::function_)
11872 param_seq_index_,
11873 str_function_t::ret_string_,
11874 parameter_list_t(str_function_t::typestore_list_)
11877 str_function_t::range_.n1_c.second = str_function_t::ret_string_.size() - 1;
11878 str_function_t::range_.cache.second = str_function_t::range_.n1_c.second;
11880 return result;
11884 return std::numeric_limits<T>::quiet_NaN();
11887 inline typename expression_node<T>::node_type type() const
11889 return expression_node<T>::e_strfunction;
11892 private:
11894 const std::size_t param_seq_index_;
11896 #endif
11898 class return_exception
11901 template <typename T>
11902 class null_igenfunc
11904 public:
11906 virtual ~null_igenfunc()
11909 typedef type_store<T> generic_type;
11910 typedef typename generic_type::parameter_list parameter_list_t;
11912 inline virtual T operator() (parameter_list_t)
11914 return std::numeric_limits<T>::quiet_NaN();
11918 #ifndef exprtk_disable_return_statement
11919 template <typename T>
11920 class return_node : public generic_function_node<T,null_igenfunc<T> >
11922 public:
11924 typedef null_igenfunc<T> igeneric_function_t;
11925 typedef igeneric_function_t* igeneric_function_ptr;
11926 typedef generic_function_node<T,igeneric_function_t> gen_function_t;
11927 typedef results_context<T> results_context_t;
11929 return_node(const std::vector<typename gen_function_t::expression_ptr>& arg_list,
11930 results_context_t& rc)
11931 : gen_function_t (arg_list),
11932 results_context_(&rc)
11935 inline T value() const
11937 if (
11938 (0 != results_context_) &&
11939 gen_function_t::populate_value_list()
11942 typedef typename type_store<T>::parameter_list parameter_list_t;
11944 results_context_->
11945 assign(parameter_list_t(gen_function_t::typestore_list_));
11947 throw return_exception();
11950 return std::numeric_limits<T>::quiet_NaN();
11953 inline typename expression_node<T>::node_type type() const
11955 return expression_node<T>::e_return;
11958 private:
11960 results_context_t* results_context_;
11963 template <typename T>
11964 class return_envelope_node : public expression_node<T>
11966 public:
11968 typedef expression_node<T>* expression_ptr;
11969 typedef results_context<T> results_context_t;
11971 return_envelope_node(expression_ptr body, results_context_t& rc)
11972 : results_context_(&rc ),
11973 return_invoked_ (false),
11974 body_ (body ),
11975 body_deletable_ (branch_deletable(body_))
11978 ~return_envelope_node()
11980 if (body_ && body_deletable_)
11982 destroy_node(body_);
11986 inline T value() const
11990 return_invoked_ = false;
11991 results_context_->clear();
11993 return body_->value();
11995 catch(const return_exception&)
11997 return_invoked_ = true;
11998 return std::numeric_limits<T>::quiet_NaN();
12002 inline typename expression_node<T>::node_type type() const
12004 return expression_node<T>::e_retenv;
12007 inline bool* retinvk_ptr()
12009 return &return_invoked_;
12012 private:
12014 results_context_t* results_context_;
12015 mutable bool return_invoked_;
12016 expression_ptr body_;
12017 const bool body_deletable_;
12019 #endif
12021 #define exprtk_define_unary_op(OpName) \
12022 template <typename T> \
12023 struct OpName##_op \
12025 typedef typename functor_t<T>::Type Type; \
12026 typedef typename expression_node<T>::node_type node_t; \
12028 static inline T process(Type v) \
12030 return numeric:: OpName (v); \
12033 static inline node_t type() \
12035 return expression_node<T>::e_##OpName; \
12038 static inline details::operator_type operation() \
12040 return details::e_##OpName; \
12042 }; \
12044 exprtk_define_unary_op(abs )
12045 exprtk_define_unary_op(acos )
12046 exprtk_define_unary_op(acosh)
12047 exprtk_define_unary_op(asin )
12048 exprtk_define_unary_op(asinh)
12049 exprtk_define_unary_op(atan )
12050 exprtk_define_unary_op(atanh)
12051 exprtk_define_unary_op(ceil )
12052 exprtk_define_unary_op(cos )
12053 exprtk_define_unary_op(cosh )
12054 exprtk_define_unary_op(cot )
12055 exprtk_define_unary_op(csc )
12056 exprtk_define_unary_op(d2g )
12057 exprtk_define_unary_op(d2r )
12058 exprtk_define_unary_op(erf )
12059 exprtk_define_unary_op(erfc )
12060 exprtk_define_unary_op(exp )
12061 exprtk_define_unary_op(expm1)
12062 exprtk_define_unary_op(floor)
12063 exprtk_define_unary_op(frac )
12064 exprtk_define_unary_op(g2d )
12065 exprtk_define_unary_op(log )
12066 exprtk_define_unary_op(log10)
12067 exprtk_define_unary_op(log2 )
12068 exprtk_define_unary_op(log1p)
12069 exprtk_define_unary_op(ncdf )
12070 exprtk_define_unary_op(neg )
12071 exprtk_define_unary_op(notl )
12072 exprtk_define_unary_op(pos )
12073 exprtk_define_unary_op(r2d )
12074 exprtk_define_unary_op(round)
12075 exprtk_define_unary_op(sec )
12076 exprtk_define_unary_op(sgn )
12077 exprtk_define_unary_op(sin )
12078 exprtk_define_unary_op(sinc )
12079 exprtk_define_unary_op(sinh )
12080 exprtk_define_unary_op(sqrt )
12081 exprtk_define_unary_op(tan )
12082 exprtk_define_unary_op(tanh )
12083 exprtk_define_unary_op(trunc)
12084 #undef exprtk_define_unary_op
12086 template <typename T>
12087 struct opr_base
12089 typedef typename details::functor_t<T>::Type Type;
12090 typedef typename details::functor_t<T>::RefType RefType;
12091 typedef typename details::functor_t<T> functor_t;
12092 typedef typename functor_t::qfunc_t quaternary_functor_t;
12093 typedef typename functor_t::tfunc_t trinary_functor_t;
12094 typedef typename functor_t::bfunc_t binary_functor_t;
12095 typedef typename functor_t::ufunc_t unary_functor_t;
12098 template <typename T>
12099 struct add_op : public opr_base<T>
12101 typedef typename opr_base<T>::Type Type;
12102 typedef typename opr_base<T>::RefType RefType;
12104 static inline T process(Type t1, Type t2) { return t1 + t2; }
12105 static inline T process(Type t1, Type t2, Type t3) { return t1 + t2 + t3; }
12106 static inline void assign(RefType t1, Type t2) { t1 += t2; }
12107 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_add; }
12108 static inline details::operator_type operation() { return details::e_add; }
12111 template <typename T>
12112 struct mul_op : public opr_base<T>
12114 typedef typename opr_base<T>::Type Type;
12115 typedef typename opr_base<T>::RefType RefType;
12117 static inline T process(Type t1, Type t2) { return t1 * t2; }
12118 static inline T process(Type t1, Type t2, Type t3) { return t1 * t2 * t3; }
12119 static inline void assign(RefType t1, Type t2) { t1 *= t2; }
12120 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mul; }
12121 static inline details::operator_type operation() { return details::e_mul; }
12124 template <typename T>
12125 struct sub_op : public opr_base<T>
12127 typedef typename opr_base<T>::Type Type;
12128 typedef typename opr_base<T>::RefType RefType;
12130 static inline T process(Type t1, Type t2) { return t1 - t2; }
12131 static inline T process(Type t1, Type t2, Type t3) { return t1 - t2 - t3; }
12132 static inline void assign(RefType t1, Type t2) { t1 -= t2; }
12133 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_sub; }
12134 static inline details::operator_type operation() { return details::e_sub; }
12137 template <typename T>
12138 struct div_op : public opr_base<T>
12140 typedef typename opr_base<T>::Type Type;
12141 typedef typename opr_base<T>::RefType RefType;
12143 static inline T process(Type t1, Type t2) { return t1 / t2; }
12144 static inline T process(Type t1, Type t2, Type t3) { return t1 / t2 / t3; }
12145 static inline void assign(RefType t1, Type t2) { t1 /= t2; }
12146 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_div; }
12147 static inline details::operator_type operation() { return details::e_div; }
12150 template <typename T>
12151 struct mod_op : public opr_base<T>
12153 typedef typename opr_base<T>::Type Type;
12154 typedef typename opr_base<T>::RefType RefType;
12156 static inline T process(Type t1, Type t2) { return numeric::modulus<T>(t1,t2); }
12157 static inline void assign(RefType t1, Type t2) { t1 = numeric::modulus<T>(t1,t2); }
12158 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mod; }
12159 static inline details::operator_type operation() { return details::e_mod; }
12162 template <typename T>
12163 struct pow_op : public opr_base<T>
12165 typedef typename opr_base<T>::Type Type;
12166 typedef typename opr_base<T>::RefType RefType;
12168 static inline T process(Type t1, Type t2) { return numeric::pow<T>(t1,t2); }
12169 static inline void assign(RefType t1, Type t2) { t1 = numeric::pow<T>(t1,t2); }
12170 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_pow; }
12171 static inline details::operator_type operation() { return details::e_pow; }
12174 template <typename T>
12175 struct lt_op : public opr_base<T>
12177 typedef typename opr_base<T>::Type Type;
12179 static inline T process(Type t1, Type t2) { return ((t1 < t2) ? T(1) : T(0)); }
12180 static inline T process(const std::string& t1, const std::string& t2) { return ((t1 < t2) ? T(1) : T(0)); }
12181 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lt; }
12182 static inline details::operator_type operation() { return details::e_lt; }
12185 template <typename T>
12186 struct lte_op : public opr_base<T>
12188 typedef typename opr_base<T>::Type Type;
12190 static inline T process(Type t1, Type t2) { return ((t1 <= t2) ? T(1) : T(0)); }
12191 static inline T process(const std::string& t1, const std::string& t2) { return ((t1 <= t2) ? T(1) : T(0)); }
12192 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lte; }
12193 static inline details::operator_type operation() { return details::e_lte; }
12196 template <typename T>
12197 struct gt_op : public opr_base<T>
12199 typedef typename opr_base<T>::Type Type;
12201 static inline T process(Type t1, Type t2) { return ((t1 > t2) ? T(1) : T(0)); }
12202 static inline T process(const std::string& t1, const std::string& t2) { return ((t1 > t2) ? T(1) : T(0)); }
12203 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gt; }
12204 static inline details::operator_type operation() { return details::e_gt; }
12207 template <typename T>
12208 struct gte_op : public opr_base<T>
12210 typedef typename opr_base<T>::Type Type;
12212 static inline T process(Type t1, Type t2) { return ((t1 >= t2) ? T(1) : T(0)); }
12213 static inline T process(const std::string& t1, const std::string& t2) { return ((t1 >= t2) ? T(1) : T(0)); }
12214 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gte; }
12215 static inline details::operator_type operation() { return details::e_gte; }
12218 template <typename T>
12219 struct eq_op : public opr_base<T>
12221 typedef typename opr_base<T>::Type Type;
12222 static inline T process(Type t1, Type t2) { return (std::equal_to<T>()(t1,t2) ? T(1) : T(0)); }
12223 static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); }
12224 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_eq; }
12225 static inline details::operator_type operation() { return details::e_eq; }
12228 template <typename T>
12229 struct equal_op : public opr_base<T>
12231 typedef typename opr_base<T>::Type Type;
12233 static inline T process(Type t1, Type t2) { return numeric::equal(t1,t2); }
12234 static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); }
12235 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_eq; }
12236 static inline details::operator_type operation() { return details::e_equal; }
12239 template <typename T>
12240 struct ne_op : public opr_base<T>
12242 typedef typename opr_base<T>::Type Type;
12244 static inline T process(Type t1, Type t2) { return (std::not_equal_to<T>()(t1,t2) ? T(1) : T(0)); }
12245 static inline T process(const std::string& t1, const std::string& t2) { return ((t1 != t2) ? T(1) : T(0)); }
12246 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ne; }
12247 static inline details::operator_type operation() { return details::e_ne; }
12250 template <typename T>
12251 struct and_op : public opr_base<T>
12253 typedef typename opr_base<T>::Type Type;
12255 static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(1) : T(0); }
12256 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_and; }
12257 static inline details::operator_type operation() { return details::e_and; }
12260 template <typename T>
12261 struct nand_op : public opr_base<T>
12263 typedef typename opr_base<T>::Type Type;
12265 static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(0) : T(1); }
12266 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nand; }
12267 static inline details::operator_type operation() { return details::e_nand; }
12270 template <typename T>
12271 struct or_op : public opr_base<T>
12273 typedef typename opr_base<T>::Type Type;
12275 static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(1) : T(0); }
12276 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_or; }
12277 static inline details::operator_type operation() { return details::e_or; }
12280 template <typename T>
12281 struct nor_op : public opr_base<T>
12283 typedef typename opr_base<T>::Type Type;
12285 static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(0) : T(1); }
12286 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
12287 static inline details::operator_type operation() { return details::e_nor; }
12290 template <typename T>
12291 struct xor_op : public opr_base<T>
12293 typedef typename opr_base<T>::Type Type;
12295 static inline T process(Type t1, Type t2) { return numeric::xor_opr<T>(t1,t2); }
12296 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
12297 static inline details::operator_type operation() { return details::e_xor; }
12300 template <typename T>
12301 struct xnor_op : public opr_base<T>
12303 typedef typename opr_base<T>::Type Type;
12305 static inline T process(Type t1, Type t2) { return numeric::xnor_opr<T>(t1,t2); }
12306 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
12307 static inline details::operator_type operation() { return details::e_xnor; }
12310 template <typename T>
12311 struct in_op : public opr_base<T>
12313 typedef typename opr_base<T>::Type Type;
12315 static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
12316 static inline T process(const std::string& t1, const std::string& t2) { return ((std::string::npos != t2.find(t1)) ? T(1) : T(0)); }
12317 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_in; }
12318 static inline details::operator_type operation() { return details::e_in; }
12321 template <typename T>
12322 struct like_op : public opr_base<T>
12324 typedef typename opr_base<T>::Type Type;
12326 static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
12327 static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_match(t2,t1) ? T(1) : T(0)); }
12328 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_like; }
12329 static inline details::operator_type operation() { return details::e_like; }
12332 template <typename T>
12333 struct ilike_op : public opr_base<T>
12335 typedef typename opr_base<T>::Type Type;
12337 static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
12338 static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_imatch(t2,t1) ? T(1) : T(0)); }
12339 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ilike; }
12340 static inline details::operator_type operation() { return details::e_ilike; }
12343 template <typename T>
12344 struct inrange_op : public opr_base<T>
12346 typedef typename opr_base<T>::Type Type;
12348 static inline T process(const T& t0, const T& t1, const T& t2) { return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); }
12349 static inline T process(const std::string& t0, const std::string& t1, const std::string& t2)
12351 return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0);
12353 static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_inranges; }
12354 static inline details::operator_type operation() { return details::e_inrange; }
12357 template <typename T>
12358 inline T value(details::expression_node<T>* n)
12360 return n->value();
12363 template <typename T>
12364 inline T value(T* t)
12366 return (*t);
12369 template <typename T>
12370 struct vararg_add_op : public opr_base<T>
12372 typedef typename opr_base<T>::Type Type;
12374 template <typename Type,
12375 typename Allocator,
12376 template <typename, typename> class Sequence>
12377 static inline T process(const Sequence<Type,Allocator>& arg_list)
12379 switch (arg_list.size())
12381 case 0 : return T(0);
12382 case 1 : return process_1(arg_list);
12383 case 2 : return process_2(arg_list);
12384 case 3 : return process_3(arg_list);
12385 case 4 : return process_4(arg_list);
12386 case 5 : return process_5(arg_list);
12387 default :
12389 T result = T(0);
12391 for (std::size_t i = 0; i < arg_list.size(); ++i)
12393 result += value(arg_list[i]);
12396 return result;
12401 template <typename Sequence>
12402 static inline T process_1(const Sequence& arg_list)
12404 return value(arg_list[0]);
12407 template <typename Sequence>
12408 static inline T process_2(const Sequence& arg_list)
12410 return value(arg_list[0]) + value(arg_list[1]);
12413 template <typename Sequence>
12414 static inline T process_3(const Sequence& arg_list)
12416 return value(arg_list[0]) + value(arg_list[1]) +
12417 value(arg_list[2]) ;
12420 template <typename Sequence>
12421 static inline T process_4(const Sequence& arg_list)
12423 return value(arg_list[0]) + value(arg_list[1]) +
12424 value(arg_list[2]) + value(arg_list[3]) ;
12427 template <typename Sequence>
12428 static inline T process_5(const Sequence& arg_list)
12430 return value(arg_list[0]) + value(arg_list[1]) +
12431 value(arg_list[2]) + value(arg_list[3]) +
12432 value(arg_list[4]) ;
12436 template <typename T>
12437 struct vararg_mul_op : public opr_base<T>
12439 typedef typename opr_base<T>::Type Type;
12441 template <typename Type,
12442 typename Allocator,
12443 template <typename, typename> class Sequence>
12444 static inline T process(const Sequence<Type,Allocator>& arg_list)
12446 switch (arg_list.size())
12448 case 0 : return T(0);
12449 case 1 : return process_1(arg_list);
12450 case 2 : return process_2(arg_list);
12451 case 3 : return process_3(arg_list);
12452 case 4 : return process_4(arg_list);
12453 case 5 : return process_5(arg_list);
12454 default :
12456 T result = T(value(arg_list[0]));
12458 for (std::size_t i = 1; i < arg_list.size(); ++i)
12460 result *= value(arg_list[i]);
12463 return result;
12468 template <typename Sequence>
12469 static inline T process_1(const Sequence& arg_list)
12471 return value(arg_list[0]);
12474 template <typename Sequence>
12475 static inline T process_2(const Sequence& arg_list)
12477 return value(arg_list[0]) * value(arg_list[1]);
12480 template <typename Sequence>
12481 static inline T process_3(const Sequence& arg_list)
12483 return value(arg_list[0]) * value(arg_list[1]) *
12484 value(arg_list[2]) ;
12487 template <typename Sequence>
12488 static inline T process_4(const Sequence& arg_list)
12490 return value(arg_list[0]) * value(arg_list[1]) *
12491 value(arg_list[2]) * value(arg_list[3]) ;
12494 template <typename Sequence>
12495 static inline T process_5(const Sequence& arg_list)
12497 return value(arg_list[0]) * value(arg_list[1]) *
12498 value(arg_list[2]) * value(arg_list[3]) *
12499 value(arg_list[4]) ;
12503 template <typename T>
12504 struct vararg_avg_op : public opr_base<T>
12506 typedef typename opr_base<T>::Type Type;
12508 template <typename Type,
12509 typename Allocator,
12510 template <typename, typename> class Sequence>
12511 static inline T process(const Sequence<Type,Allocator>& arg_list)
12513 switch (arg_list.size())
12515 case 0 : return T(0);
12516 case 1 : return process_1(arg_list);
12517 case 2 : return process_2(arg_list);
12518 case 3 : return process_3(arg_list);
12519 case 4 : return process_4(arg_list);
12520 case 5 : return process_5(arg_list);
12521 default : return vararg_add_op<T>::process(arg_list) / arg_list.size();
12525 template <typename Sequence>
12526 static inline T process_1(const Sequence& arg_list)
12528 return value(arg_list[0]);
12531 template <typename Sequence>
12532 static inline T process_2(const Sequence& arg_list)
12534 return (value(arg_list[0]) + value(arg_list[1])) / T(2);
12537 template <typename Sequence>
12538 static inline T process_3(const Sequence& arg_list)
12540 return (value(arg_list[0]) + value(arg_list[1]) + value(arg_list[2])) / T(3);
12543 template <typename Sequence>
12544 static inline T process_4(const Sequence& arg_list)
12546 return (value(arg_list[0]) + value(arg_list[1]) +
12547 value(arg_list[2]) + value(arg_list[3])) / T(4);
12550 template <typename Sequence>
12551 static inline T process_5(const Sequence& arg_list)
12553 return (value(arg_list[0]) + value(arg_list[1]) +
12554 value(arg_list[2]) + value(arg_list[3]) +
12555 value(arg_list[4])) / T(5);
12559 template <typename T>
12560 struct vararg_min_op : public opr_base<T>
12562 typedef typename opr_base<T>::Type Type;
12564 template <typename Type,
12565 typename Allocator,
12566 template <typename, typename> class Sequence>
12567 static inline T process(const Sequence<Type,Allocator>& arg_list)
12569 switch (arg_list.size())
12571 case 0 : return T(0);
12572 case 1 : return process_1(arg_list);
12573 case 2 : return process_2(arg_list);
12574 case 3 : return process_3(arg_list);
12575 case 4 : return process_4(arg_list);
12576 case 5 : return process_5(arg_list);
12577 default :
12579 T result = T(value(arg_list[0]));
12581 for (std::size_t i = 1; i < arg_list.size(); ++i)
12583 const T v = value(arg_list[i]);
12585 if (v < result)
12586 result = v;
12589 return result;
12594 template <typename Sequence>
12595 static inline T process_1(const Sequence& arg_list)
12597 return value(arg_list[0]);
12600 template <typename Sequence>
12601 static inline T process_2(const Sequence& arg_list)
12603 return std::min<T>(value(arg_list[0]),value(arg_list[1]));
12606 template <typename Sequence>
12607 static inline T process_3(const Sequence& arg_list)
12609 return std::min<T>(std::min<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2]));
12612 template <typename Sequence>
12613 static inline T process_4(const Sequence& arg_list)
12615 return std::min<T>(
12616 std::min<T>(value(arg_list[0]), value(arg_list[1])),
12617 std::min<T>(value(arg_list[2]), value(arg_list[3])));
12620 template <typename Sequence>
12621 static inline T process_5(const Sequence& arg_list)
12623 return std::min<T>(
12624 std::min<T>(std::min<T>(value(arg_list[0]), value(arg_list[1])),
12625 std::min<T>(value(arg_list[2]), value(arg_list[3]))),
12626 value(arg_list[4]));
12630 template <typename T>
12631 struct vararg_max_op : public opr_base<T>
12633 typedef typename opr_base<T>::Type Type;
12635 template <typename Type,
12636 typename Allocator,
12637 template <typename, typename> class Sequence>
12638 static inline T process(const Sequence<Type,Allocator>& arg_list)
12640 switch (arg_list.size())
12642 case 0 : return T(0);
12643 case 1 : return process_1(arg_list);
12644 case 2 : return process_2(arg_list);
12645 case 3 : return process_3(arg_list);
12646 case 4 : return process_4(arg_list);
12647 case 5 : return process_5(arg_list);
12648 default :
12650 T result = T(value(arg_list[0]));
12652 for (std::size_t i = 1; i < arg_list.size(); ++i)
12654 const T v = value(arg_list[i]);
12656 if (v > result)
12657 result = v;
12660 return result;
12665 template <typename Sequence>
12666 static inline T process_1(const Sequence& arg_list)
12668 return value(arg_list[0]);
12671 template <typename Sequence>
12672 static inline T process_2(const Sequence& arg_list)
12674 return std::max<T>(value(arg_list[0]),value(arg_list[1]));
12677 template <typename Sequence>
12678 static inline T process_3(const Sequence& arg_list)
12680 return std::max<T>(std::max<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2]));
12683 template <typename Sequence>
12684 static inline T process_4(const Sequence& arg_list)
12686 return std::max<T>(
12687 std::max<T>(value(arg_list[0]), value(arg_list[1])),
12688 std::max<T>(value(arg_list[2]), value(arg_list[3])));
12691 template <typename Sequence>
12692 static inline T process_5(const Sequence& arg_list)
12694 return std::max<T>(
12695 std::max<T>(std::max<T>(value(arg_list[0]), value(arg_list[1])),
12696 std::max<T>(value(arg_list[2]), value(arg_list[3]))),
12697 value(arg_list[4]));
12701 template <typename T>
12702 struct vararg_mand_op : public opr_base<T>
12704 typedef typename opr_base<T>::Type Type;
12706 template <typename Type,
12707 typename Allocator,
12708 template <typename, typename> class Sequence>
12709 static inline T process(const Sequence<Type,Allocator>& arg_list)
12711 switch (arg_list.size())
12713 case 1 : return process_1(arg_list);
12714 case 2 : return process_2(arg_list);
12715 case 3 : return process_3(arg_list);
12716 case 4 : return process_4(arg_list);
12717 case 5 : return process_5(arg_list);
12718 default :
12720 for (std::size_t i = 0; i < arg_list.size(); ++i)
12722 if (std::equal_to<T>()(T(0), value(arg_list[i])))
12723 return T(0);
12726 return T(1);
12731 template <typename Sequence>
12732 static inline T process_1(const Sequence& arg_list)
12734 return std::not_equal_to<T>()
12735 (T(0), value(arg_list[0])) ? T(1) : T(0);
12738 template <typename Sequence>
12739 static inline T process_2(const Sequence& arg_list)
12741 return (
12742 std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
12743 std::not_equal_to<T>()(T(0), value(arg_list[1]))
12744 ) ? T(1) : T(0);
12747 template <typename Sequence>
12748 static inline T process_3(const Sequence& arg_list)
12750 return (
12751 std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
12752 std::not_equal_to<T>()(T(0), value(arg_list[1])) &&
12753 std::not_equal_to<T>()(T(0), value(arg_list[2]))
12754 ) ? T(1) : T(0);
12757 template <typename Sequence>
12758 static inline T process_4(const Sequence& arg_list)
12760 return (
12761 std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
12762 std::not_equal_to<T>()(T(0), value(arg_list[1])) &&
12763 std::not_equal_to<T>()(T(0), value(arg_list[2])) &&
12764 std::not_equal_to<T>()(T(0), value(arg_list[3]))
12765 ) ? T(1) : T(0);
12768 template <typename Sequence>
12769 static inline T process_5(const Sequence& arg_list)
12771 return (
12772 std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
12773 std::not_equal_to<T>()(T(0), value(arg_list[1])) &&
12774 std::not_equal_to<T>()(T(0), value(arg_list[2])) &&
12775 std::not_equal_to<T>()(T(0), value(arg_list[3])) &&
12776 std::not_equal_to<T>()(T(0), value(arg_list[4]))
12777 ) ? T(1) : T(0);
12781 template <typename T>
12782 struct vararg_mor_op : public opr_base<T>
12784 typedef typename opr_base<T>::Type Type;
12786 template <typename Type,
12787 typename Allocator,
12788 template <typename, typename> class Sequence>
12789 static inline T process(const Sequence<Type,Allocator>& arg_list)
12791 switch (arg_list.size())
12793 case 1 : return process_1(arg_list);
12794 case 2 : return process_2(arg_list);
12795 case 3 : return process_3(arg_list);
12796 case 4 : return process_4(arg_list);
12797 case 5 : return process_5(arg_list);
12798 default :
12800 for (std::size_t i = 0; i < arg_list.size(); ++i)
12802 if (std::not_equal_to<T>()(T(0), value(arg_list[i])))
12803 return T(1);
12806 return T(0);
12811 template <typename Sequence>
12812 static inline T process_1(const Sequence& arg_list)
12814 return std::not_equal_to<T>()
12815 (T(0), value(arg_list[0])) ? T(1) : T(0);
12818 template <typename Sequence>
12819 static inline T process_2(const Sequence& arg_list)
12821 return (
12822 std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
12823 std::not_equal_to<T>()(T(0), value(arg_list[1]))
12824 ) ? T(1) : T(0);
12827 template <typename Sequence>
12828 static inline T process_3(const Sequence& arg_list)
12830 return (
12831 std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
12832 std::not_equal_to<T>()(T(0), value(arg_list[1])) ||
12833 std::not_equal_to<T>()(T(0), value(arg_list[2]))
12834 ) ? T(1) : T(0);
12837 template <typename Sequence>
12838 static inline T process_4(const Sequence& arg_list)
12840 return (
12841 std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
12842 std::not_equal_to<T>()(T(0), value(arg_list[1])) ||
12843 std::not_equal_to<T>()(T(0), value(arg_list[2])) ||
12844 std::not_equal_to<T>()(T(0), value(arg_list[3]))
12845 ) ? T(1) : T(0);
12848 template <typename Sequence>
12849 static inline T process_5(const Sequence& arg_list)
12851 return (
12852 std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
12853 std::not_equal_to<T>()(T(0), value(arg_list[1])) ||
12854 std::not_equal_to<T>()(T(0), value(arg_list[2])) ||
12855 std::not_equal_to<T>()(T(0), value(arg_list[3])) ||
12856 std::not_equal_to<T>()(T(0), value(arg_list[4]))
12857 ) ? T(1) : T(0);
12861 template <typename T>
12862 struct vararg_multi_op : public opr_base<T>
12864 typedef typename opr_base<T>::Type Type;
12866 template <typename Type,
12867 typename Allocator,
12868 template <typename, typename> class Sequence>
12869 static inline T process(const Sequence<Type,Allocator>& arg_list)
12871 switch (arg_list.size())
12873 case 0 : return std::numeric_limits<T>::quiet_NaN();
12874 case 1 : return process_1(arg_list);
12875 case 2 : return process_2(arg_list);
12876 case 3 : return process_3(arg_list);
12877 case 4 : return process_4(arg_list);
12878 case 5 : return process_5(arg_list);
12879 case 6 : return process_6(arg_list);
12880 case 7 : return process_7(arg_list);
12881 case 8 : return process_8(arg_list);
12882 default :
12884 for (std::size_t i = 0; i < (arg_list.size() - 1); ++i)
12886 value(arg_list[i]);
12889 return value(arg_list.back());
12894 template <typename Sequence>
12895 static inline T process_1(const Sequence& arg_list)
12897 return value(arg_list[0]);
12900 template <typename Sequence>
12901 static inline T process_2(const Sequence& arg_list)
12903 value(arg_list[0]);
12904 return value(arg_list[1]);
12907 template <typename Sequence>
12908 static inline T process_3(const Sequence& arg_list)
12910 value(arg_list[0]);
12911 value(arg_list[1]);
12912 return value(arg_list[2]);
12915 template <typename Sequence>
12916 static inline T process_4(const Sequence& arg_list)
12918 value(arg_list[0]);
12919 value(arg_list[1]);
12920 value(arg_list[2]);
12921 return value(arg_list[3]);
12924 template <typename Sequence>
12925 static inline T process_5(const Sequence& arg_list)
12927 value(arg_list[0]);
12928 value(arg_list[1]);
12929 value(arg_list[2]);
12930 value(arg_list[3]);
12931 return value(arg_list[4]);
12934 template <typename Sequence>
12935 static inline T process_6(const Sequence& arg_list)
12937 value(arg_list[0]);
12938 value(arg_list[1]);
12939 value(arg_list[2]);
12940 value(arg_list[3]);
12941 value(arg_list[4]);
12942 return value(arg_list[5]);
12945 template <typename Sequence>
12946 static inline T process_7(const Sequence& arg_list)
12948 value(arg_list[0]);
12949 value(arg_list[1]);
12950 value(arg_list[2]);
12951 value(arg_list[3]);
12952 value(arg_list[4]);
12953 value(arg_list[5]);
12954 return value(arg_list[6]);
12957 template <typename Sequence>
12958 static inline T process_8(const Sequence& arg_list)
12960 value(arg_list[0]);
12961 value(arg_list[1]);
12962 value(arg_list[2]);
12963 value(arg_list[3]);
12964 value(arg_list[4]);
12965 value(arg_list[5]);
12966 value(arg_list[6]);
12967 return value(arg_list[7]);
12971 template <typename T>
12972 struct vec_add_op
12974 typedef vector_interface<T>* ivector_ptr;
12976 static inline T process(const ivector_ptr v)
12978 const T* vec = v->vec()->vds().data();
12979 const std::size_t vec_size = v->vec()->vds().size();
12981 loop_unroll::details lud(vec_size);
12983 if (vec_size <= static_cast<std::size_t>(lud.batch_size))
12985 T result = T(0);
12986 int i = 0;
12988 exprtk_disable_fallthrough_begin
12989 switch (vec_size)
12991 #define case_stmt(N) \
12992 case N : result += vec[i++]; \
12994 #ifndef exprtk_disable_superscalar_unroll
12995 case_stmt(16) case_stmt(15)
12996 case_stmt(14) case_stmt(13)
12997 case_stmt(12) case_stmt(11)
12998 case_stmt(10) case_stmt( 9)
12999 case_stmt( 8) case_stmt( 7)
13000 case_stmt( 6) case_stmt( 5)
13001 #endif
13002 case_stmt( 4) case_stmt( 3)
13003 case_stmt( 2) case_stmt( 1)
13005 exprtk_disable_fallthrough_end
13007 #undef case_stmt
13009 return result;
13012 T r[] = {
13013 T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0),
13014 T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0)
13017 const T* upper_bound = vec + lud.upper_bound;
13019 while (vec < upper_bound)
13021 #define exprtk_loop(N) \
13022 r[N] += vec[N]; \
13024 exprtk_loop( 0) exprtk_loop( 1)
13025 exprtk_loop( 2) exprtk_loop( 3)
13026 #ifndef exprtk_disable_superscalar_unroll
13027 exprtk_loop( 4) exprtk_loop( 5)
13028 exprtk_loop( 6) exprtk_loop( 7)
13029 exprtk_loop( 8) exprtk_loop( 9)
13030 exprtk_loop(10) exprtk_loop(11)
13031 exprtk_loop(12) exprtk_loop(13)
13032 exprtk_loop(14) exprtk_loop(15)
13033 #endif
13035 vec += lud.batch_size;
13038 int i = 0;
13040 exprtk_disable_fallthrough_begin
13041 switch (lud.remainder)
13043 #define case_stmt(N) \
13044 case N : r[0] += vec[i++]; \
13046 #ifndef exprtk_disable_superscalar_unroll
13047 case_stmt(15) case_stmt(14)
13048 case_stmt(13) case_stmt(12)
13049 case_stmt(11) case_stmt(10)
13050 case_stmt( 9) case_stmt( 8)
13051 case_stmt( 7) case_stmt( 6)
13052 case_stmt( 5) case_stmt( 4)
13053 #endif
13054 case_stmt( 3) case_stmt( 2)
13055 case_stmt( 1)
13057 exprtk_disable_fallthrough_end
13059 #undef exprtk_loop
13060 #undef case_stmt
13062 return (r[ 0] + r[ 1] + r[ 2] + r[ 3])
13063 #ifndef exprtk_disable_superscalar_unroll
13064 + (r[ 4] + r[ 5] + r[ 6] + r[ 7])
13065 + (r[ 8] + r[ 9] + r[10] + r[11])
13066 + (r[12] + r[13] + r[14] + r[15])
13067 #endif
13072 template <typename T>
13073 struct vec_mul_op
13075 typedef vector_interface<T>* ivector_ptr;
13077 static inline T process(const ivector_ptr v)
13079 const T* vec = v->vec()->vds().data();
13080 const std::size_t vec_size = v->vec()->vds().size();
13082 loop_unroll::details lud(vec_size);
13084 if (vec_size <= static_cast<std::size_t>(lud.batch_size))
13086 T result = T(1);
13087 int i = 0;
13089 exprtk_disable_fallthrough_begin
13090 switch (vec_size)
13092 #define case_stmt(N) \
13093 case N : result *= vec[i++]; \
13095 #ifndef exprtk_disable_superscalar_unroll
13096 case_stmt(16) case_stmt(15)
13097 case_stmt(14) case_stmt(13)
13098 case_stmt(12) case_stmt(11)
13099 case_stmt(10) case_stmt( 9)
13100 case_stmt( 8) case_stmt( 7)
13101 case_stmt( 6) case_stmt( 5)
13102 #endif
13103 case_stmt( 4) case_stmt( 3)
13104 case_stmt( 2) case_stmt( 1)
13106 exprtk_disable_fallthrough_end
13108 #undef case_stmt
13110 return result;
13113 T r[] = {
13114 T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1),
13115 T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1)
13118 const T* upper_bound = vec + lud.upper_bound;
13120 while (vec < upper_bound)
13122 #define exprtk_loop(N) \
13123 r[N] *= vec[N]; \
13125 exprtk_loop( 0) exprtk_loop( 1)
13126 exprtk_loop( 2) exprtk_loop( 3)
13127 #ifndef exprtk_disable_superscalar_unroll
13128 exprtk_loop( 4) exprtk_loop( 5)
13129 exprtk_loop( 6) exprtk_loop( 7)
13130 exprtk_loop( 8) exprtk_loop( 9)
13131 exprtk_loop(10) exprtk_loop(11)
13132 exprtk_loop(12) exprtk_loop(13)
13133 exprtk_loop(14) exprtk_loop(15)
13134 #endif
13136 vec += lud.batch_size;
13139 int i = 0;
13141 exprtk_disable_fallthrough_begin
13142 switch (lud.remainder)
13144 #define case_stmt(N) \
13145 case N : r[0] *= vec[i++]; \
13147 #ifndef exprtk_disable_superscalar_unroll
13148 case_stmt(15) case_stmt(14)
13149 case_stmt(13) case_stmt(12)
13150 case_stmt(11) case_stmt(10)
13151 case_stmt( 9) case_stmt( 8)
13152 case_stmt( 7) case_stmt( 6)
13153 case_stmt( 5) case_stmt( 4)
13154 #endif
13155 case_stmt( 3) case_stmt( 2)
13156 case_stmt( 1)
13158 exprtk_disable_fallthrough_end
13160 #undef exprtk_loop
13161 #undef case_stmt
13163 return (r[ 0] * r[ 1] * r[ 2] * r[ 3])
13164 #ifndef exprtk_disable_superscalar_unroll
13165 + (r[ 4] * r[ 5] * r[ 6] * r[ 7])
13166 + (r[ 8] * r[ 9] * r[10] * r[11])
13167 + (r[12] * r[13] * r[14] * r[15])
13168 #endif
13173 template <typename T>
13174 struct vec_avg_op
13176 typedef vector_interface<T>* ivector_ptr;
13178 static inline T process(const ivector_ptr v)
13180 const std::size_t vec_size = v->vec()->vds().size();
13182 return vec_add_op<T>::process(v) / vec_size;
13186 template <typename T>
13187 struct vec_min_op
13189 typedef vector_interface<T>* ivector_ptr;
13191 static inline T process(const ivector_ptr v)
13193 const T* vec = v->vec()->vds().data();
13194 const std::size_t vec_size = v->vec()->vds().size();
13196 T result = vec[0];
13198 for (std::size_t i = 1; i < vec_size; ++i)
13200 T v_i = vec[i];
13202 if (v_i < result)
13203 result = v_i;
13206 return result;
13210 template <typename T>
13211 struct vec_max_op
13213 typedef vector_interface<T>* ivector_ptr;
13215 static inline T process(const ivector_ptr v)
13217 const T* vec = v->vec()->vds().data();
13218 const std::size_t vec_size = v->vec()->vds().size();
13220 T result = vec[0];
13222 for (std::size_t i = 1; i < vec_size; ++i)
13224 T v_i = vec[i];
13226 if (v_i > result)
13227 result = v_i;
13230 return result;
13234 template <typename T>
13235 class vov_base_node : public expression_node<T>
13237 public:
13239 virtual ~vov_base_node()
13242 inline virtual operator_type operation() const
13244 return details::e_default;
13247 virtual const T& v0() const = 0;
13249 virtual const T& v1() const = 0;
13252 template <typename T>
13253 class cov_base_node : public expression_node<T>
13255 public:
13257 virtual ~cov_base_node()
13260 inline virtual operator_type operation() const
13262 return details::e_default;
13265 virtual const T c() const = 0;
13267 virtual const T& v() const = 0;
13270 template <typename T>
13271 class voc_base_node : public expression_node<T>
13273 public:
13275 virtual ~voc_base_node()
13278 inline virtual operator_type operation() const
13280 return details::e_default;
13283 virtual const T c() const = 0;
13285 virtual const T& v() const = 0;
13288 template <typename T>
13289 class vob_base_node : public expression_node<T>
13291 public:
13293 virtual ~vob_base_node()
13296 virtual const T& v() const = 0;
13299 template <typename T>
13300 class bov_base_node : public expression_node<T>
13302 public:
13304 virtual ~bov_base_node()
13307 virtual const T& v() const = 0;
13310 template <typename T>
13311 class cob_base_node : public expression_node<T>
13313 public:
13315 virtual ~cob_base_node()
13318 inline virtual operator_type operation() const
13320 return details::e_default;
13323 virtual const T c() const = 0;
13325 virtual void set_c(const T) = 0;
13327 virtual expression_node<T>* move_branch(const std::size_t& index) = 0;
13330 template <typename T>
13331 class boc_base_node : public expression_node<T>
13333 public:
13335 virtual ~boc_base_node()
13338 inline virtual operator_type operation() const
13340 return details::e_default;
13343 virtual const T c() const = 0;
13345 virtual void set_c(const T) = 0;
13347 virtual expression_node<T>* move_branch(const std::size_t& index) = 0;
13350 template <typename T>
13351 class uv_base_node : public expression_node<T>
13353 public:
13355 virtual ~uv_base_node()
13358 inline virtual operator_type operation() const
13360 return details::e_default;
13363 virtual const T& v() const = 0;
13366 template <typename T>
13367 class sos_base_node : public expression_node<T>
13369 public:
13371 virtual ~sos_base_node()
13374 inline virtual operator_type operation() const
13376 return details::e_default;
13380 template <typename T>
13381 class sosos_base_node : public expression_node<T>
13383 public:
13385 virtual ~sosos_base_node()
13388 inline virtual operator_type operation() const
13390 return details::e_default;
13394 template <typename T>
13395 class T0oT1oT2_base_node : public expression_node<T>
13397 public:
13399 virtual ~T0oT1oT2_base_node()
13402 virtual std::string type_id() const = 0;
13405 template <typename T>
13406 class T0oT1oT2oT3_base_node : public expression_node<T>
13408 public:
13410 virtual ~T0oT1oT2oT3_base_node()
13413 virtual std::string type_id() const = 0;
13416 template <typename T, typename Operation>
13417 class unary_variable_node : public uv_base_node<T>
13419 public:
13421 typedef expression_node<T>* expression_ptr;
13422 typedef Operation operation_t;
13424 explicit unary_variable_node(const T& var)
13425 : v_(var)
13428 inline T value() const
13430 return Operation::process(v_);
13433 inline typename expression_node<T>::node_type type() const
13435 return Operation::type();
13438 inline operator_type operation() const
13440 return Operation::operation();
13443 inline const T& v() const
13445 return v_;
13448 private:
13450 unary_variable_node(unary_variable_node<T,Operation>&);
13451 unary_variable_node<T,Operation>& operator=(unary_variable_node<T,Operation>&);
13453 const T& v_;
13456 template <typename T>
13457 class uvouv_node : public expression_node<T>
13459 public:
13461 // UOpr1(v0) Op UOpr2(v1)
13463 typedef expression_node<T>* expression_ptr;
13464 typedef typename details::functor_t<T> functor_t;
13465 typedef typename functor_t::bfunc_t bfunc_t;
13466 typedef typename functor_t::ufunc_t ufunc_t;
13468 explicit uvouv_node(const T& var0,const T& var1,
13469 ufunc_t uf0, ufunc_t uf1, bfunc_t bf)
13470 : v0_(var0),
13471 v1_(var1),
13472 u0_(uf0 ),
13473 u1_(uf1 ),
13474 f_ (bf )
13477 inline T value() const
13479 return f_(u0_(v0_),u1_(v1_));
13482 inline typename expression_node<T>::node_type type() const
13484 return expression_node<T>::e_uvouv;
13487 inline operator_type operation() const
13489 return details::e_default;
13492 inline const T& v0()
13494 return v0_;
13497 inline const T& v1()
13499 return v1_;
13502 inline ufunc_t u0()
13504 return u0_;
13507 inline ufunc_t u1()
13509 return u1_;
13512 inline ufunc_t f()
13514 return f_;
13517 private:
13519 uvouv_node(uvouv_node<T>&);
13520 uvouv_node<T>& operator=(uvouv_node<T>&);
13522 const T& v0_;
13523 const T& v1_;
13524 const ufunc_t u0_;
13525 const ufunc_t u1_;
13526 const bfunc_t f_;
13529 template <typename T, typename Operation>
13530 class unary_branch_node : public expression_node<T>
13532 public:
13534 typedef expression_node<T>* expression_ptr;
13535 typedef Operation operation_t;
13537 explicit unary_branch_node(expression_ptr brnch)
13538 : branch_(brnch),
13539 branch_deletable_(branch_deletable(branch_))
13542 ~unary_branch_node()
13544 if (branch_ && branch_deletable_)
13546 destroy_node(branch_);
13550 inline T value() const
13552 return Operation::process(branch_->value());
13555 inline typename expression_node<T>::node_type type() const
13557 return Operation::type();
13560 inline operator_type operation() const
13562 return Operation::operation();
13565 inline expression_node<T>* branch(const std::size_t&) const
13567 return branch_;
13570 inline void release()
13572 branch_deletable_ = false;
13575 private:
13577 unary_branch_node(unary_branch_node<T,Operation>&);
13578 unary_branch_node<T,Operation>& operator=(unary_branch_node<T,Operation>&);
13580 expression_ptr branch_;
13581 bool branch_deletable_;
13584 template <typename T> struct is_const { enum {result = 0}; };
13585 template <typename T> struct is_const <const T> { enum {result = 1}; };
13586 template <typename T> struct is_const_ref { enum {result = 0}; };
13587 template <typename T> struct is_const_ref <const T&> { enum {result = 1}; };
13588 template <typename T> struct is_ref { enum {result = 0}; };
13589 template <typename T> struct is_ref<T&> { enum {result = 1}; };
13590 template <typename T> struct is_ref<const T&> { enum {result = 0}; };
13592 template <std::size_t State>
13593 struct param_to_str { static std::string result() { static const std::string r("v"); return r; } };
13595 template <>
13596 struct param_to_str<0> { static std::string result() { static const std::string r("c"); return r; } };
13598 #define exprtk_crtype(Type) \
13599 param_to_str<is_const_ref< Type >::result>::result() \
13601 template <typename T>
13602 struct T0oT1oT2process
13604 typedef typename details::functor_t<T> functor_t;
13605 typedef typename functor_t::bfunc_t bfunc_t;
13607 struct mode0
13609 static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1)
13611 // (T0 o0 T1) o1 T2
13612 return bf1(bf0(t0,t1),t2);
13615 template <typename T0, typename T1, typename T2>
13616 static inline std::string id()
13618 static const std::string result = "(" + exprtk_crtype(T0) + "o" +
13619 exprtk_crtype(T1) + ")o(" +
13620 exprtk_crtype(T2) + ")" ;
13621 return result;
13625 struct mode1
13627 static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1)
13629 // T0 o0 (T1 o1 T2)
13630 return bf0(t0,bf1(t1,t2));
13633 template <typename T0, typename T1, typename T2>
13634 static inline std::string id()
13636 static const std::string result = "(" + exprtk_crtype(T0) + ")o(" +
13637 exprtk_crtype(T1) + "o" +
13638 exprtk_crtype(T2) + ")" ;
13639 return result;
13644 template <typename T>
13645 struct T0oT1oT20T3process
13647 typedef typename details::functor_t<T> functor_t;
13648 typedef typename functor_t::bfunc_t bfunc_t;
13650 struct mode0
13652 static inline T process(const T& t0, const T& t1,
13653 const T& t2, const T& t3,
13654 const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
13656 // (T0 o0 T1) o1 (T2 o2 T3)
13657 return bf1(bf0(t0,t1),bf2(t2,t3));
13660 template <typename T0, typename T1, typename T2, typename T3>
13661 static inline std::string id()
13663 static const std::string result = "(" + exprtk_crtype(T0) + "o" +
13664 exprtk_crtype(T1) + ")o" +
13665 "(" + exprtk_crtype(T2) + "o" +
13666 exprtk_crtype(T3) + ")" ;
13667 return result;
13671 struct mode1
13673 static inline T process(const T& t0, const T& t1,
13674 const T& t2, const T& t3,
13675 const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
13677 // (T0 o0 (T1 o1 (T2 o2 T3))
13678 return bf0(t0,bf1(t1,bf2(t2,t3)));
13680 template <typename T0, typename T1, typename T2, typename T3>
13681 static inline std::string id()
13683 static const std::string result = "(" + exprtk_crtype(T0) + ")o((" +
13684 exprtk_crtype(T1) + ")o(" +
13685 exprtk_crtype(T2) + "o" +
13686 exprtk_crtype(T3) + "))" ;
13687 return result;
13691 struct mode2
13693 static inline T process(const T& t0, const T& t1,
13694 const T& t2, const T& t3,
13695 const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
13697 // (T0 o0 ((T1 o1 T2) o2 T3)
13698 return bf0(t0,bf2(bf1(t1,t2),t3));
13701 template <typename T0, typename T1, typename T2, typename T3>
13702 static inline std::string id()
13704 static const std::string result = "(" + exprtk_crtype(T0) + ")o((" +
13705 exprtk_crtype(T1) + "o" +
13706 exprtk_crtype(T2) + ")o(" +
13707 exprtk_crtype(T3) + "))" ;
13708 return result;
13712 struct mode3
13714 static inline T process(const T& t0, const T& t1,
13715 const T& t2, const T& t3,
13716 const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
13718 // (((T0 o0 T1) o1 T2) o2 T3)
13719 return bf2(bf1(bf0(t0,t1),t2),t3);
13722 template <typename T0, typename T1, typename T2, typename T3>
13723 static inline std::string id()
13725 static const std::string result = "((" + exprtk_crtype(T0) + "o" +
13726 exprtk_crtype(T1) + ")o(" +
13727 exprtk_crtype(T2) + "))o(" +
13728 exprtk_crtype(T3) + ")";
13729 return result;
13733 struct mode4
13735 static inline T process(const T& t0, const T& t1,
13736 const T& t2, const T& t3,
13737 const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
13739 // ((T0 o0 (T1 o1 T2)) o2 T3
13740 return bf2(bf0(t0,bf1(t1,t2)),t3);
13743 template <typename T0, typename T1, typename T2, typename T3>
13744 static inline std::string id()
13746 static const std::string result = "((" + exprtk_crtype(T0) + ")o(" +
13747 exprtk_crtype(T1) + "o" +
13748 exprtk_crtype(T2) + "))o(" +
13749 exprtk_crtype(T3) + ")" ;
13750 return result;
13755 #undef exprtk_crtype
13757 template <typename T, typename T0, typename T1>
13758 struct nodetype_T0oT1 { static const typename expression_node<T>::node_type result; };
13759 template <typename T, typename T0, typename T1>
13760 const typename expression_node<T>::node_type nodetype_T0oT1<T,T0,T1>::result = expression_node<T>::e_none;
13762 #define synthesis_node_type_define(T0_,T1_,v_) \
13763 template <typename T, typename T0, typename T1> \
13764 struct nodetype_T0oT1<T,T0_,T1_> { static const typename expression_node<T>::node_type result; }; \
13765 template <typename T, typename T0, typename T1> \
13766 const typename expression_node<T>::node_type nodetype_T0oT1<T,T0_,T1_>::result = expression_node<T>:: v_; \
13768 synthesis_node_type_define(const T0&, const T1&, e_vov)
13769 synthesis_node_type_define(const T0&, const T1 , e_voc)
13770 synthesis_node_type_define(const T0 , const T1&, e_cov)
13771 synthesis_node_type_define( T0&, T1&, e_none)
13772 synthesis_node_type_define(const T0 , const T1 , e_none)
13773 synthesis_node_type_define( T0&, const T1 , e_none)
13774 synthesis_node_type_define(const T0 , T1&, e_none)
13775 synthesis_node_type_define(const T0&, T1&, e_none)
13776 synthesis_node_type_define( T0&, const T1&, e_none)
13777 #undef synthesis_node_type_define
13779 template <typename T, typename T0, typename T1, typename T2>
13780 struct nodetype_T0oT1oT2 { static const typename expression_node<T>::node_type result; };
13781 template <typename T, typename T0, typename T1, typename T2>
13782 const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0,T1,T2>::result = expression_node<T>::e_none;
13784 #define synthesis_node_type_define(T0_,T1_,T2_,v_) \
13785 template <typename T, typename T0, typename T1, typename T2> \
13786 struct nodetype_T0oT1oT2<T,T0_,T1_,T2_> { static const typename expression_node<T>::node_type result; }; \
13787 template <typename T, typename T0, typename T1, typename T2> \
13788 const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0_,T1_,T2_>::result = expression_node<T>:: v_; \
13790 synthesis_node_type_define(const T0&, const T1&, const T2&, e_vovov)
13791 synthesis_node_type_define(const T0&, const T1&, const T2 , e_vovoc)
13792 synthesis_node_type_define(const T0&, const T1 , const T2&, e_vocov)
13793 synthesis_node_type_define(const T0 , const T1&, const T2&, e_covov)
13794 synthesis_node_type_define(const T0 , const T1&, const T2 , e_covoc)
13795 synthesis_node_type_define(const T0 , const T1 , const T2 , e_none )
13796 synthesis_node_type_define(const T0 , const T1 , const T2&, e_none )
13797 synthesis_node_type_define(const T0&, const T1 , const T2 , e_none )
13798 synthesis_node_type_define( T0&, T1&, T2&, e_none )
13799 #undef synthesis_node_type_define
13801 template <typename T, typename T0, typename T1, typename T2, typename T3>
13802 struct nodetype_T0oT1oT2oT3 { static const typename expression_node<T>::node_type result; };
13803 template <typename T, typename T0, typename T1, typename T2, typename T3>
13804 const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result = expression_node<T>::e_none;
13806 #define synthesis_node_type_define(T0_,T1_,T2_,T3_,v_) \
13807 template <typename T, typename T0, typename T1, typename T2, typename T3> \
13808 struct nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_> { static const typename expression_node<T>::node_type result; }; \
13809 template <typename T, typename T0, typename T1, typename T2, typename T3> \
13810 const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_>::result = expression_node<T>:: v_; \
13812 synthesis_node_type_define(const T0&, const T1&, const T2&, const T3&, e_vovovov)
13813 synthesis_node_type_define(const T0&, const T1&, const T2&, const T3 , e_vovovoc)
13814 synthesis_node_type_define(const T0&, const T1&, const T2 , const T3&, e_vovocov)
13815 synthesis_node_type_define(const T0&, const T1 , const T2&, const T3&, e_vocovov)
13816 synthesis_node_type_define(const T0 , const T1&, const T2&, const T3&, e_covovov)
13817 synthesis_node_type_define(const T0 , const T1&, const T2 , const T3&, e_covocov)
13818 synthesis_node_type_define(const T0&, const T1 , const T2&, const T3 , e_vocovoc)
13819 synthesis_node_type_define(const T0 , const T1&, const T2&, const T3 , e_covovoc)
13820 synthesis_node_type_define(const T0&, const T1 , const T2 , const T3&, e_vococov)
13821 synthesis_node_type_define(const T0 , const T1 , const T2 , const T3 , e_none )
13822 synthesis_node_type_define(const T0 , const T1 , const T2 , const T3&, e_none )
13823 synthesis_node_type_define(const T0 , const T1 , const T2&, const T3 , e_none )
13824 synthesis_node_type_define(const T0 , const T1&, const T2 , const T3 , e_none )
13825 synthesis_node_type_define(const T0&, const T1 , const T2 , const T3 , e_none )
13826 synthesis_node_type_define(const T0 , const T1 , const T2&, const T3&, e_none )
13827 synthesis_node_type_define(const T0&, const T1&, const T2 , const T3 , e_none )
13828 #undef synthesis_node_type_define
13830 template <typename T, typename T0, typename T1>
13831 class T0oT1 : public expression_node<T>
13833 public:
13835 typedef typename details::functor_t<T> functor_t;
13836 typedef typename functor_t::bfunc_t bfunc_t;
13837 typedef T value_type;
13838 typedef T0oT1<T,T0,T1> node_type;
13840 T0oT1(T0 p0, T1 p1, const bfunc_t p2)
13841 : t0_(p0),
13842 t1_(p1),
13843 f_ (p2)
13846 inline typename expression_node<T>::node_type type() const
13848 static const typename expression_node<T>::node_type result = nodetype_T0oT1<T,T0,T1>::result;
13849 return result;
13852 inline operator_type operation() const
13854 return e_default;
13857 inline T value() const
13859 return f_(t0_,t1_);
13862 inline T0 t0() const
13864 return t0_;
13867 inline T1 t1() const
13869 return t1_;
13872 inline bfunc_t f() const
13874 return f_;
13877 template <typename Allocator>
13878 static inline expression_node<T>* allocate(Allocator& allocator,
13879 T0 p0, T1 p1,
13880 bfunc_t p2)
13882 return allocator
13883 .template allocate_type<node_type, T0, T1, bfunc_t&>
13884 (p0, p1, p2);
13887 private:
13889 T0oT1(T0oT1<T,T0,T1>&) {}
13890 T0oT1<T,T0,T1>& operator=(T0oT1<T,T0,T1>&) { return (*this); }
13892 T0 t0_;
13893 T1 t1_;
13894 const bfunc_t f_;
13897 template <typename T, typename T0, typename T1, typename T2, typename ProcessMode>
13898 class T0oT1oT2 : public T0oT1oT2_base_node<T>
13900 public:
13902 typedef typename details::functor_t<T> functor_t;
13903 typedef typename functor_t::bfunc_t bfunc_t;
13904 typedef T value_type;
13905 typedef T0oT1oT2<T,T0,T1,T2,ProcessMode> node_type;
13906 typedef ProcessMode process_mode_t;
13908 T0oT1oT2(T0 p0, T1 p1, T2 p2, const bfunc_t p3, const bfunc_t p4)
13909 : t0_(p0),
13910 t1_(p1),
13911 t2_(p2),
13912 f0_(p3),
13913 f1_(p4)
13916 inline typename expression_node<T>::node_type type() const
13918 static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
13919 return result;
13922 inline operator_type operation() const
13924 return e_default;
13927 inline T value() const
13929 return ProcessMode::process(t0_, t1_, t2_, f0_, f1_);
13932 inline T0 t0() const
13934 return t0_;
13937 inline T1 t1() const
13939 return t1_;
13942 inline T2 t2() const
13944 return t2_;
13947 bfunc_t f0() const
13949 return f0_;
13952 bfunc_t f1() const
13954 return f1_;
13957 std::string type_id() const
13959 return id();
13962 static inline std::string id()
13964 return process_mode_t::template id<T0,T1,T2>();
13967 template <typename Allocator>
13968 static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, bfunc_t p3, bfunc_t p4)
13970 return allocator
13971 .template allocate_type<node_type, T0, T1, T2, bfunc_t, bfunc_t>
13972 (p0, p1, p2, p3, p4);
13975 private:
13977 T0oT1oT2(node_type&) {}
13978 node_type& operator=(node_type&) { return (*this); }
13980 T0 t0_;
13981 T1 t1_;
13982 T2 t2_;
13983 const bfunc_t f0_;
13984 const bfunc_t f1_;
13987 template <typename T, typename T0_, typename T1_, typename T2_, typename T3_, typename ProcessMode>
13988 class T0oT1oT2oT3 : public T0oT1oT2oT3_base_node<T>
13990 public:
13992 typedef typename details::functor_t<T> functor_t;
13993 typedef typename functor_t::bfunc_t bfunc_t;
13994 typedef T value_type;
13995 typedef T0_ T0;
13996 typedef T1_ T1;
13997 typedef T2_ T2;
13998 typedef T3_ T3;
13999 typedef T0oT1oT2oT3<T,T0,T1,T2,T3,ProcessMode> node_type;
14000 typedef ProcessMode process_mode_t;
14002 T0oT1oT2oT3(T0 p0, T1 p1, T2 p2, T3 p3, bfunc_t p4, bfunc_t p5, bfunc_t p6)
14003 : t0_(p0),
14004 t1_(p1),
14005 t2_(p2),
14006 t3_(p3),
14007 f0_(p4),
14008 f1_(p5),
14009 f2_(p6)
14012 inline T value() const
14014 return ProcessMode::process(t0_, t1_, t2_, t3_, f0_, f1_, f2_);
14017 inline T0 t0() const
14019 return t0_;
14022 inline T1 t1() const
14024 return t1_;
14027 inline T2 t2() const
14029 return t2_;
14032 inline T3 t3() const
14034 return t3_;
14037 inline bfunc_t f0() const
14039 return f0_;
14042 inline bfunc_t f1() const
14044 return f1_;
14047 inline bfunc_t f2() const
14049 return f2_;
14052 inline std::string type_id() const
14054 return id();
14057 static inline std::string id()
14059 return process_mode_t::template id<T0, T1, T2, T3>();
14062 template <typename Allocator>
14063 static inline expression_node<T>* allocate(Allocator& allocator,
14064 T0 p0, T1 p1, T2 p2, T3 p3,
14065 bfunc_t p4, bfunc_t p5, bfunc_t p6)
14067 return allocator
14068 .template allocate_type<node_type, T0, T1, T2, T3, bfunc_t, bfunc_t>
14069 (p0, p1, p2, p3, p4, p5, p6);
14072 private:
14074 T0oT1oT2oT3(node_type&) {}
14075 node_type& operator=(node_type&) { return (*this); }
14077 T0 t0_;
14078 T1 t1_;
14079 T2 t2_;
14080 T3 t3_;
14081 const bfunc_t f0_;
14082 const bfunc_t f1_;
14083 const bfunc_t f2_;
14086 template <typename T, typename T0, typename T1, typename T2>
14087 class T0oT1oT2_sf3 : public T0oT1oT2_base_node<T>
14089 public:
14091 typedef typename details::functor_t<T> functor_t;
14092 typedef typename functor_t::tfunc_t tfunc_t;
14093 typedef T value_type;
14094 typedef T0oT1oT2_sf3<T,T0,T1,T2> node_type;
14096 T0oT1oT2_sf3(T0 p0, T1 p1, T2 p2, const tfunc_t p3)
14097 : t0_(p0),
14098 t1_(p1),
14099 t2_(p2),
14100 f_ (p3)
14103 inline typename expression_node<T>::node_type type() const
14105 static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
14106 return result;
14109 inline operator_type operation() const
14111 return e_default;
14114 inline T value() const
14116 return f_(t0_, t1_, t2_);
14119 inline T0 t0() const
14121 return t0_;
14124 inline T1 t1() const
14126 return t1_;
14129 inline T2 t2() const
14131 return t2_;
14134 tfunc_t f() const
14136 return f_;
14139 std::string type_id() const
14141 return id();
14144 static inline std::string id()
14146 return "sf3";
14149 template <typename Allocator>
14150 static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, tfunc_t p3)
14152 return allocator
14153 .template allocate_type<node_type, T0, T1, T2, tfunc_t>
14154 (p0, p1, p2, p3);
14157 private:
14159 T0oT1oT2_sf3(node_type&) {}
14160 node_type& operator=(node_type&) { return (*this); }
14162 T0 t0_;
14163 T1 t1_;
14164 T2 t2_;
14165 const tfunc_t f_;
14168 template <typename T, typename T0, typename T1, typename T2>
14169 class sf3ext_type_node : public T0oT1oT2_base_node<T>
14171 public:
14173 virtual ~sf3ext_type_node()
14176 virtual T0 t0() const = 0;
14178 virtual T1 t1() const = 0;
14180 virtual T2 t2() const = 0;
14183 template <typename T, typename T0, typename T1, typename T2, typename SF3Operation>
14184 class T0oT1oT2_sf3ext : public sf3ext_type_node<T,T0,T1,T2>
14186 public:
14188 typedef typename details::functor_t<T> functor_t;
14189 typedef typename functor_t::tfunc_t tfunc_t;
14190 typedef T value_type;
14191 typedef T0oT1oT2_sf3ext<T,T0,T1,T2,SF3Operation> node_type;
14193 T0oT1oT2_sf3ext(T0 p0, T1 p1, T2 p2)
14194 : t0_(p0),
14195 t1_(p1),
14196 t2_(p2)
14199 inline typename expression_node<T>::node_type type() const
14201 static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
14202 return result;
14205 inline operator_type operation() const
14207 return e_default;
14210 inline T value() const
14212 return SF3Operation::process(t0_, t1_, t2_);
14215 T0 t0() const
14217 return t0_;
14220 T1 t1() const
14222 return t1_;
14225 T2 t2() const
14227 return t2_;
14230 std::string type_id() const
14232 return id();
14235 static inline std::string id()
14237 return SF3Operation::id();
14240 template <typename Allocator>
14241 static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2)
14243 return allocator
14244 .template allocate_type<node_type, T0, T1, T2>
14245 (p0, p1, p2);
14248 private:
14250 T0oT1oT2_sf3ext(node_type&) {}
14251 node_type& operator=(node_type&) { return (*this); }
14253 T0 t0_;
14254 T1 t1_;
14255 T2 t2_;
14258 template <typename T>
14259 inline bool is_sf3ext_node(const expression_node<T>* n)
14261 switch (n->type())
14263 case expression_node<T>::e_vovov : return true;
14264 case expression_node<T>::e_vovoc : return true;
14265 case expression_node<T>::e_vocov : return true;
14266 case expression_node<T>::e_covov : return true;
14267 case expression_node<T>::e_covoc : return true;
14268 default : return false;
14272 template <typename T, typename T0, typename T1, typename T2, typename T3>
14273 class T0oT1oT2oT3_sf4 : public T0oT1oT2_base_node<T>
14275 public:
14277 typedef typename details::functor_t<T> functor_t;
14278 typedef typename functor_t::qfunc_t qfunc_t;
14279 typedef T value_type;
14280 typedef T0oT1oT2oT3_sf4<T,T0,T1,T2,T3> node_type;
14282 T0oT1oT2oT3_sf4(T0 p0, T1 p1, T2 p2, T3 p3, const qfunc_t p4)
14283 : t0_(p0),
14284 t1_(p1),
14285 t2_(p2),
14286 t3_(p3),
14287 f_ (p4)
14290 inline typename expression_node<T>::node_type type() const
14292 static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result;
14293 return result;
14296 inline operator_type operation() const
14298 return e_default;
14301 inline T value() const
14303 return f_(t0_, t1_, t2_, t3_);
14306 inline T0 t0() const
14308 return t0_;
14311 inline T1 t1() const
14313 return t1_;
14316 inline T2 t2() const
14318 return t2_;
14321 inline T3 t3() const
14323 return t3_;
14326 qfunc_t f() const
14328 return f_;
14331 std::string type_id() const
14333 return id();
14336 static inline std::string id()
14338 return "sf4";
14341 template <typename Allocator>
14342 static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3, qfunc_t p4)
14344 return allocator
14345 .template allocate_type<node_type, T0, T1, T2, T3, qfunc_t>
14346 (p0, p1, p2, p3, p4);
14349 private:
14351 T0oT1oT2oT3_sf4(node_type&) {}
14352 node_type& operator=(node_type&) { return (*this); }
14354 T0 t0_;
14355 T1 t1_;
14356 T2 t2_;
14357 T3 t3_;
14358 const qfunc_t f_;
14361 template <typename T, typename T0, typename T1, typename T2, typename T3, typename SF4Operation>
14362 class T0oT1oT2oT3_sf4ext : public T0oT1oT2oT3_base_node<T>
14364 public:
14366 typedef typename details::functor_t<T> functor_t;
14367 typedef typename functor_t::tfunc_t tfunc_t;
14368 typedef T value_type;
14369 typedef T0oT1oT2oT3_sf4ext<T,T0,T1,T2,T3,SF4Operation> node_type;
14371 T0oT1oT2oT3_sf4ext(T0 p0, T1 p1, T2 p2, T3 p3)
14372 : t0_(p0),
14373 t1_(p1),
14374 t2_(p2),
14375 t3_(p3)
14378 inline typename expression_node<T>::node_type type() const
14380 static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result;
14381 return result;
14384 inline operator_type operation() const
14386 return e_default;
14389 inline T value() const
14391 return SF4Operation::process(t0_, t1_, t2_, t3_);
14394 inline T0 t0() const
14396 return t0_;
14399 inline T1 t1() const
14401 return t1_;
14404 inline T2 t2() const
14406 return t2_;
14409 inline T3 t3() const
14411 return t3_;
14414 std::string type_id() const
14416 return id();
14419 static inline std::string id()
14421 return SF4Operation::id();
14424 template <typename Allocator>
14425 static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3)
14427 return allocator
14428 .template allocate_type<node_type, T0, T1, T2, T3>
14429 (p0, p1, p2, p3);
14432 private:
14434 T0oT1oT2oT3_sf4ext(node_type&) {}
14435 node_type& operator=(node_type&) { return (*this); }
14437 T0 t0_;
14438 T1 t1_;
14439 T2 t2_;
14440 T3 t3_;
14443 template <typename T>
14444 inline bool is_sf4ext_node(const expression_node<T>* n)
14446 switch (n->type())
14448 case expression_node<T>::e_vovovov : return true;
14449 case expression_node<T>::e_vovovoc : return true;
14450 case expression_node<T>::e_vovocov : return true;
14451 case expression_node<T>::e_vocovov : return true;
14452 case expression_node<T>::e_covovov : return true;
14453 case expression_node<T>::e_covocov : return true;
14454 case expression_node<T>::e_vocovoc : return true;
14455 case expression_node<T>::e_covovoc : return true;
14456 case expression_node<T>::e_vococov : return true;
14457 default : return false;
14461 template <typename T, typename T0, typename T1>
14462 struct T0oT1_define
14464 typedef details::T0oT1<T, T0, T1> type0;
14467 template <typename T, typename T0, typename T1, typename T2>
14468 struct T0oT1oT2_define
14470 typedef details::T0oT1oT2<T, T0, T1, T2, typename T0oT1oT2process<T>::mode0> type0;
14471 typedef details::T0oT1oT2<T, T0, T1, T2, typename T0oT1oT2process<T>::mode1> type1;
14472 typedef details::T0oT1oT2_sf3<T, T0, T1, T2> sf3_type;
14473 typedef details::sf3ext_type_node<T, T0, T1, T2> sf3_type_node;
14476 template <typename T, typename T0, typename T1, typename T2, typename T3>
14477 struct T0oT1oT2oT3_define
14479 typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode0> type0;
14480 typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode1> type1;
14481 typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode2> type2;
14482 typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode3> type3;
14483 typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode4> type4;
14484 typedef details::T0oT1oT2oT3_sf4<T, T0, T1, T2, T3> sf4_type;
14487 template <typename T, typename Operation>
14488 class vov_node : public vov_base_node<T>
14490 public:
14492 typedef expression_node<T>* expression_ptr;
14493 typedef Operation operation_t;
14495 // variable op variable node
14496 explicit vov_node(const T& var0, const T& var1)
14497 : v0_(var0),
14498 v1_(var1)
14501 inline T value() const
14503 return Operation::process(v0_,v1_);
14506 inline typename expression_node<T>::node_type type() const
14508 return Operation::type();
14511 inline operator_type operation() const
14513 return Operation::operation();
14516 inline const T& v0() const
14518 return v0_;
14521 inline const T& v1() const
14523 return v1_;
14526 protected:
14528 const T& v0_;
14529 const T& v1_;
14531 private:
14533 vov_node(vov_node<T,Operation>&);
14534 vov_node<T,Operation>& operator=(vov_node<T,Operation>&);
14537 template <typename T, typename Operation>
14538 class cov_node : public cov_base_node<T>
14540 public:
14542 typedef expression_node<T>* expression_ptr;
14543 typedef Operation operation_t;
14545 // constant op variable node
14546 explicit cov_node(const T& const_var, const T& var)
14547 : c_(const_var),
14548 v_(var)
14551 inline T value() const
14553 return Operation::process(c_,v_);
14556 inline typename expression_node<T>::node_type type() const
14558 return Operation::type();
14561 inline operator_type operation() const
14563 return Operation::operation();
14566 inline const T c() const
14568 return c_;
14571 inline const T& v() const
14573 return v_;
14576 protected:
14578 const T c_;
14579 const T& v_;
14581 private:
14583 cov_node(const cov_node<T,Operation>&);
14584 cov_node<T,Operation>& operator=(const cov_node<T,Operation>&);
14587 template <typename T, typename Operation>
14588 class voc_node : public voc_base_node<T>
14590 public:
14592 typedef expression_node<T>* expression_ptr;
14593 typedef Operation operation_t;
14595 // variable op constant node
14596 explicit voc_node(const T& var, const T& const_var)
14597 : v_(var),
14598 c_(const_var)
14601 inline T value() const
14603 return Operation::process(v_,c_);
14606 inline operator_type operation() const
14608 return Operation::operation();
14611 inline const T c() const
14613 return c_;
14616 inline const T& v() const
14618 return v_;
14621 protected:
14623 const T& v_;
14624 const T c_;
14626 private:
14628 voc_node(const voc_node<T,Operation>&);
14629 voc_node<T,Operation>& operator=(const voc_node<T,Operation>&);
14632 template <typename T, typename Operation>
14633 class vob_node : public vob_base_node<T>
14635 public:
14637 typedef expression_node<T>* expression_ptr;
14638 typedef std::pair<expression_ptr,bool> branch_t;
14639 typedef Operation operation_t;
14641 // variable op constant node
14642 explicit vob_node(const T& var, const expression_ptr brnch)
14643 : v_(var)
14645 init_branches<1>(branch_,brnch);
14648 ~vob_node()
14650 cleanup_branches::execute<T,1>(branch_);
14653 inline T value() const
14655 return Operation::process(v_,branch_[0].first->value());
14658 inline operator_type operation() const
14660 return Operation::operation();
14663 inline const T& v() const
14665 return v_;
14668 inline expression_node<T>* branch(const std::size_t&) const
14670 return branch_[0].first;
14673 private:
14675 vob_node(const vob_node<T,Operation>&);
14676 vob_node<T,Operation>& operator=(const vob_node<T,Operation>&);
14678 const T& v_;
14679 branch_t branch_[1];
14682 template <typename T, typename Operation>
14683 class bov_node : public bov_base_node<T>
14685 public:
14687 typedef expression_node<T>* expression_ptr;
14688 typedef std::pair<expression_ptr,bool> branch_t;
14689 typedef Operation operation_t;
14691 // variable op constant node
14692 explicit bov_node(const expression_ptr brnch, const T& var)
14693 : v_(var)
14695 init_branches<1>(branch_,brnch);
14698 ~bov_node()
14700 cleanup_branches::execute<T,1>(branch_);
14703 inline T value() const
14705 return Operation::process(branch_[0].first->value(),v_);
14708 inline operator_type operation() const
14710 return Operation::operation();
14713 inline const T& v() const
14715 return v_;
14718 inline expression_node<T>* branch(const std::size_t&) const
14720 return branch_[0].first;
14723 private:
14725 bov_node(const bov_node<T,Operation>&);
14726 bov_node<T,Operation>& operator=(const bov_node<T,Operation>&);
14728 const T& v_;
14729 branch_t branch_[1];
14732 template <typename T, typename Operation>
14733 class cob_node : public cob_base_node<T>
14735 public:
14737 typedef expression_node<T>* expression_ptr;
14738 typedef std::pair<expression_ptr,bool> branch_t;
14739 typedef Operation operation_t;
14741 // variable op constant node
14742 explicit cob_node(const T const_var, const expression_ptr brnch)
14743 : c_(const_var)
14745 init_branches<1>(branch_,brnch);
14748 ~cob_node()
14750 cleanup_branches::execute<T,1>(branch_);
14753 inline T value() const
14755 return Operation::process(c_,branch_[0].first->value());
14758 inline operator_type operation() const
14760 return Operation::operation();
14763 inline const T c() const
14765 return c_;
14768 inline void set_c(const T new_c)
14770 (*const_cast<T*>(&c_)) = new_c;
14773 inline expression_node<T>* branch(const std::size_t&) const
14775 return branch_[0].first;
14778 inline expression_node<T>* move_branch(const std::size_t&)
14780 branch_[0].second = false;
14781 return branch_[0].first;
14784 private:
14786 cob_node(const cob_node<T,Operation>&);
14787 cob_node<T,Operation>& operator=(const cob_node<T,Operation>&);
14789 const T c_;
14790 branch_t branch_[1];
14793 template <typename T, typename Operation>
14794 class boc_node : public boc_base_node<T>
14796 public:
14798 typedef expression_node<T>* expression_ptr;
14799 typedef std::pair<expression_ptr,bool> branch_t;
14800 typedef Operation operation_t;
14802 // variable op constant node
14803 explicit boc_node(const expression_ptr brnch, const T const_var)
14804 : c_(const_var)
14806 init_branches<1>(branch_,brnch);
14809 ~boc_node()
14811 cleanup_branches::execute<T,1>(branch_);
14814 inline T value() const
14816 return Operation::process(branch_[0].first->value(),c_);
14819 inline operator_type operation() const
14821 return Operation::operation();
14824 inline const T c() const
14826 return c_;
14829 inline void set_c(const T new_c)
14831 (*const_cast<T*>(&c_)) = new_c;
14834 inline expression_node<T>* branch(const std::size_t&) const
14836 return branch_[0].first;
14839 inline expression_node<T>* move_branch(const std::size_t&)
14841 branch_[0].second = false;
14842 return branch_[0].first;
14845 private:
14847 boc_node(const boc_node<T,Operation>&);
14848 boc_node<T,Operation>& operator=(const boc_node<T,Operation>&);
14850 const T c_;
14851 branch_t branch_[1];
14854 #ifndef exprtk_disable_string_capabilities
14855 template <typename T, typename SType0, typename SType1, typename Operation>
14856 class sos_node : public sos_base_node<T>
14858 public:
14860 typedef expression_node<T>* expression_ptr;
14861 typedef Operation operation_t;
14863 // string op string node
14864 explicit sos_node(SType0 p0, SType1 p1)
14865 : s0_(p0),
14866 s1_(p1)
14869 inline T value() const
14871 return Operation::process(s0_,s1_);
14874 inline typename expression_node<T>::node_type type() const
14876 return Operation::type();
14879 inline operator_type operation() const
14881 return Operation::operation();
14884 inline std::string& s0()
14886 return s0_;
14889 inline std::string& s1()
14891 return s1_;
14894 protected:
14896 SType0 s0_;
14897 SType1 s1_;
14899 private:
14901 sos_node(sos_node<T,SType0,SType1,Operation>&);
14902 sos_node<T,SType0,SType1,Operation>& operator=(sos_node<T,SType0,SType1,Operation>&);
14905 template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
14906 class str_xrox_node : public sos_base_node<T>
14908 public:
14910 typedef expression_node<T>* expression_ptr;
14911 typedef Operation operation_t;
14913 // string-range op string node
14914 explicit str_xrox_node(SType0 p0, SType1 p1, RangePack rp0)
14915 : s0_ (p0 ),
14916 s1_ (p1 ),
14917 rp0_(rp0)
14920 ~str_xrox_node()
14922 rp0_.free();
14925 inline T value() const
14927 std::size_t r0 = 0;
14928 std::size_t r1 = 0;
14930 if (rp0_(r0, r1, s0_.size()))
14931 return Operation::process(s0_.substr(r0, (r1 - r0) + 1), s1_);
14932 else
14933 return T(0);
14936 inline typename expression_node<T>::node_type type() const
14938 return Operation::type();
14941 inline operator_type operation() const
14943 return Operation::operation();
14946 inline std::string& s0()
14948 return s0_;
14951 inline std::string& s1()
14953 return s1_;
14956 protected:
14958 SType0 s0_;
14959 SType1 s1_;
14960 RangePack rp0_;
14962 private:
14964 str_xrox_node(str_xrox_node<T,SType0,SType1,RangePack,Operation>&);
14965 str_xrox_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xrox_node<T,SType0,SType1,RangePack,Operation>&);
14968 template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
14969 class str_xoxr_node : public sos_base_node<T>
14971 public:
14973 typedef expression_node<T>* expression_ptr;
14974 typedef Operation operation_t;
14976 // string op string range node
14977 explicit str_xoxr_node(SType0 p0, SType1 p1, RangePack rp1)
14978 : s0_ (p0 ),
14979 s1_ (p1 ),
14980 rp1_(rp1)
14983 ~str_xoxr_node()
14985 rp1_.free();
14988 inline T value() const
14990 std::size_t r0 = 0;
14991 std::size_t r1 = 0;
14993 if (rp1_(r0, r1, s1_.size()))
14994 return Operation::process(s0_, s1_.substr(r0, (r1 - r0) + 1));
14995 else
14996 return T(0);
14999 inline typename expression_node<T>::node_type type() const
15001 return Operation::type();
15004 inline operator_type operation() const
15006 return Operation::operation();
15009 inline std::string& s0()
15011 return s0_;
15014 inline std::string& s1()
15016 return s1_;
15019 protected:
15021 SType0 s0_;
15022 SType1 s1_;
15023 RangePack rp1_;
15025 private:
15027 str_xoxr_node(str_xoxr_node<T,SType0,SType1,RangePack,Operation>&);
15028 str_xoxr_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xoxr_node<T,SType0,SType1,RangePack,Operation>&);
15031 template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
15032 class str_xroxr_node : public sos_base_node<T>
15034 public:
15036 typedef expression_node<T>* expression_ptr;
15037 typedef Operation operation_t;
15039 // string-range op string-range node
15040 explicit str_xroxr_node(SType0 p0, SType1 p1, RangePack rp0, RangePack rp1)
15041 : s0_ (p0 ),
15042 s1_ (p1 ),
15043 rp0_(rp0),
15044 rp1_(rp1)
15047 ~str_xroxr_node()
15049 rp0_.free();
15050 rp1_.free();
15053 inline T value() const
15055 std::size_t r0_0 = 0;
15056 std::size_t r0_1 = 0;
15057 std::size_t r1_0 = 0;
15058 std::size_t r1_1 = 0;
15060 if (
15061 rp0_(r0_0, r1_0, s0_.size()) &&
15062 rp1_(r0_1, r1_1, s1_.size())
15065 return Operation::process(
15066 s0_.substr(r0_0, (r1_0 - r0_0) + 1),
15067 s1_.substr(r0_1, (r1_1 - r0_1) + 1)
15070 else
15071 return T(0);
15074 inline typename expression_node<T>::node_type type() const
15076 return Operation::type();
15079 inline operator_type operation() const
15081 return Operation::operation();
15084 inline std::string& s0()
15086 return s0_;
15089 inline std::string& s1()
15091 return s1_;
15094 protected:
15096 SType0 s0_;
15097 SType1 s1_;
15098 RangePack rp0_;
15099 RangePack rp1_;
15101 private:
15103 str_xroxr_node(str_xroxr_node<T,SType0,SType1,RangePack,Operation>&);
15104 str_xroxr_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xroxr_node<T,SType0,SType1,RangePack,Operation>&);
15107 template <typename T, typename Operation>
15108 class str_sogens_node : public binary_node<T>
15110 public:
15112 typedef expression_node <T>* expression_ptr;
15113 typedef string_base_node<T>* str_base_ptr;
15114 typedef range_pack <T> range_t;
15115 typedef range_t* range_ptr;
15116 typedef range_interface<T> irange_t;
15117 typedef irange_t* irange_ptr;
15119 str_sogens_node(const operator_type& opr,
15120 expression_ptr branch0,
15121 expression_ptr branch1)
15122 : binary_node<T>(opr, branch0, branch1),
15123 str0_base_ptr_ (0),
15124 str1_base_ptr_ (0),
15125 str0_range_ptr_(0),
15126 str1_range_ptr_(0)
15128 if (is_generally_string_node(binary_node<T>::branch_[0].first))
15130 str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
15132 if (0 == str0_base_ptr_)
15133 return;
15135 irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
15137 if (0 == range)
15138 return;
15140 str0_range_ptr_ = &(range->range_ref());
15143 if (is_generally_string_node(binary_node<T>::branch_[1].first))
15145 str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
15147 if (0 == str1_base_ptr_)
15148 return;
15150 irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
15152 if (0 == range)
15153 return;
15155 str1_range_ptr_ = &(range->range_ref());
15159 inline T value() const
15161 if (
15162 str0_base_ptr_ &&
15163 str1_base_ptr_ &&
15164 str0_range_ptr_ &&
15165 str1_range_ptr_
15168 binary_node<T>::branch_[0].first->value();
15169 binary_node<T>::branch_[1].first->value();
15171 std::size_t str0_r0 = 0;
15172 std::size_t str0_r1 = 0;
15174 std::size_t str1_r0 = 0;
15175 std::size_t str1_r1 = 0;
15177 range_t& range0 = (*str0_range_ptr_);
15178 range_t& range1 = (*str1_range_ptr_);
15180 if (
15181 range0(str0_r0, str0_r1, str0_base_ptr_->size()) &&
15182 range1(str1_r0, str1_r1, str1_base_ptr_->size())
15185 return Operation::process(
15186 str0_base_ptr_->str().substr(str0_r0,(str0_r1 - str0_r0) + 1),
15187 str1_base_ptr_->str().substr(str1_r0,(str1_r1 - str1_r0) + 1)
15192 return std::numeric_limits<T>::quiet_NaN();
15195 inline typename expression_node<T>::node_type type() const
15197 return Operation::type();
15200 inline operator_type operation() const
15202 return Operation::operation();
15205 private:
15207 str_sogens_node(str_sogens_node<T,Operation>&);
15208 str_sogens_node<T,Operation>& operator=(str_sogens_node<T,Operation>&);
15210 str_base_ptr str0_base_ptr_;
15211 str_base_ptr str1_base_ptr_;
15212 range_ptr str0_range_ptr_;
15213 range_ptr str1_range_ptr_;
15216 template <typename T, typename SType0, typename SType1, typename SType2, typename Operation>
15217 class sosos_node : public sosos_base_node<T>
15219 public:
15221 typedef expression_node<T>* expression_ptr;
15222 typedef Operation operation_t;
15224 // variable op variable node
15225 explicit sosos_node(SType0 p0, SType1 p1, SType2 p2)
15226 : s0_(p0),
15227 s1_(p1),
15228 s2_(p2)
15231 inline T value() const
15233 return Operation::process(s0_,s1_,s2_);
15236 inline typename expression_node<T>::node_type type() const
15238 return Operation::type();
15241 inline operator_type operation() const
15243 return Operation::operation();
15246 inline std::string& s0()
15248 return s0_;
15251 inline std::string& s1()
15253 return s1_;
15256 inline std::string& s2()
15258 return s2_;
15261 protected:
15263 SType0 s0_;
15264 SType1 s1_;
15265 SType2 s2_;
15267 private:
15269 sosos_node(sosos_node<T,SType0,SType1,SType2,Operation>&);
15270 sosos_node<T,SType0,SType1,SType2,Operation>& operator=(sosos_node<T,SType0,SType1,SType2,Operation>&);
15272 #endif
15274 template <typename T, typename PowOp>
15275 class ipow_node : public expression_node<T>
15277 public:
15279 typedef expression_node<T>* expression_ptr;
15280 typedef PowOp operation_t;
15282 explicit ipow_node(const T& v)
15283 : v_(v)
15286 inline T value() const
15288 return PowOp::result(v_);
15291 inline typename expression_node<T>::node_type type() const
15293 return expression_node<T>::e_ipow;
15296 private:
15298 ipow_node(const ipow_node<T,PowOp>&);
15299 ipow_node<T,PowOp>& operator=(const ipow_node<T,PowOp>&);
15301 const T& v_;
15304 template <typename T, typename PowOp>
15305 class bipow_node : public expression_node<T>
15307 public:
15309 typedef expression_node<T>* expression_ptr;
15310 typedef std::pair<expression_ptr, bool> branch_t;
15311 typedef PowOp operation_t;
15313 explicit bipow_node(expression_ptr brnch)
15315 init_branches<1>(branch_, brnch);
15318 ~bipow_node()
15320 cleanup_branches::execute<T,1>(branch_);
15323 inline T value() const
15325 return PowOp::result(branch_[0].first->value());
15328 inline typename expression_node<T>::node_type type() const
15330 return expression_node<T>::e_ipow;
15333 private:
15335 bipow_node(const bipow_node<T,PowOp>&);
15336 bipow_node<T,PowOp>& operator=(const bipow_node<T,PowOp>&);
15338 branch_t branch_[1];
15341 template <typename T, typename PowOp>
15342 class ipowinv_node : public expression_node<T>
15344 public:
15346 typedef expression_node<T>* expression_ptr;
15347 typedef PowOp operation_t;
15349 explicit ipowinv_node(const T& v)
15350 : v_(v)
15353 inline T value() const
15355 return (T(1) / PowOp::result(v_));
15358 inline typename expression_node<T>::node_type type() const
15360 return expression_node<T>::e_ipowinv;
15363 private:
15365 ipowinv_node(const ipowinv_node<T,PowOp>&);
15366 ipowinv_node<T,PowOp>& operator=(const ipowinv_node<T,PowOp>&);
15368 const T& v_;
15371 template <typename T, typename PowOp>
15372 class bipowninv_node : public expression_node<T>
15374 public:
15376 typedef expression_node<T>* expression_ptr;
15377 typedef std::pair<expression_ptr, bool> branch_t;
15378 typedef PowOp operation_t;
15380 explicit bipowninv_node(expression_ptr brnch)
15382 init_branches<1>(branch_, brnch);
15385 ~bipowninv_node()
15387 cleanup_branches::execute<T,1>(branch_);
15390 inline T value() const
15392 return (T(1) / PowOp::result(branch_[0].first->value()));
15395 inline typename expression_node<T>::node_type type() const
15397 return expression_node<T>::e_ipowinv;
15400 private:
15402 bipowninv_node(const bipowninv_node<T,PowOp>&);
15403 bipowninv_node<T,PowOp>& operator=(const bipowninv_node<T,PowOp>&);
15405 branch_t branch_[1];
15408 template <typename T>
15409 inline bool is_vov_node(const expression_node<T>* node)
15411 return (0 != dynamic_cast<const vov_base_node<T>*>(node));
15414 template <typename T>
15415 inline bool is_cov_node(const expression_node<T>* node)
15417 return (0 != dynamic_cast<const cov_base_node<T>*>(node));
15420 template <typename T>
15421 inline bool is_voc_node(const expression_node<T>* node)
15423 return (0 != dynamic_cast<const voc_base_node<T>*>(node));
15426 template <typename T>
15427 inline bool is_cob_node(const expression_node<T>* node)
15429 return (0 != dynamic_cast<const cob_base_node<T>*>(node));
15432 template <typename T>
15433 inline bool is_boc_node(const expression_node<T>* node)
15435 return (0 != dynamic_cast<const boc_base_node<T>*>(node));
15438 template <typename T>
15439 inline bool is_t0ot1ot2_node(const expression_node<T>* node)
15441 return (0 != dynamic_cast<const T0oT1oT2_base_node<T>*>(node));
15444 template <typename T>
15445 inline bool is_t0ot1ot2ot3_node(const expression_node<T>* node)
15447 return (0 != dynamic_cast<const T0oT1oT2oT3_base_node<T>*>(node));
15450 template <typename T>
15451 inline bool is_uv_node(const expression_node<T>* node)
15453 return (0 != dynamic_cast<const uv_base_node<T>*>(node));
15456 template <typename T>
15457 inline bool is_string_node(const expression_node<T>* node)
15459 return node && (expression_node<T>::e_stringvar == node->type());
15462 template <typename T>
15463 inline bool is_string_range_node(const expression_node<T>* node)
15465 return node && (expression_node<T>::e_stringvarrng == node->type());
15468 template <typename T>
15469 inline bool is_const_string_node(const expression_node<T>* node)
15471 return node && (expression_node<T>::e_stringconst == node->type());
15474 template <typename T>
15475 inline bool is_const_string_range_node(const expression_node<T>* node)
15477 return node && (expression_node<T>::e_cstringvarrng == node->type());
15480 template <typename T>
15481 inline bool is_string_assignment_node(const expression_node<T>* node)
15483 return node && (expression_node<T>::e_strass == node->type());
15486 template <typename T>
15487 inline bool is_string_concat_node(const expression_node<T>* node)
15489 return node && (expression_node<T>::e_strconcat == node->type());
15492 template <typename T>
15493 inline bool is_string_function_node(const expression_node<T>* node)
15495 return node && (expression_node<T>::e_strfunction == node->type());
15498 template <typename T>
15499 inline bool is_string_condition_node(const expression_node<T>* node)
15501 return node && (expression_node<T>::e_strcondition == node->type());
15504 template <typename T>
15505 inline bool is_string_ccondition_node(const expression_node<T>* node)
15507 return node && (expression_node<T>::e_strccondition == node->type());
15510 template <typename T>
15511 inline bool is_string_vararg_node(const expression_node<T>* node)
15513 return node && (expression_node<T>::e_stringvararg == node->type());
15516 template <typename T>
15517 inline bool is_genricstring_range_node(const expression_node<T>* node)
15519 return node && (expression_node<T>::e_strgenrange == node->type());
15522 template <typename T>
15523 inline bool is_generally_string_node(const expression_node<T>* node)
15525 if (node)
15527 switch (node->type())
15529 case expression_node<T>::e_stringvar :
15530 case expression_node<T>::e_stringconst :
15531 case expression_node<T>::e_stringvarrng :
15532 case expression_node<T>::e_cstringvarrng :
15533 case expression_node<T>::e_strgenrange :
15534 case expression_node<T>::e_strass :
15535 case expression_node<T>::e_strconcat :
15536 case expression_node<T>::e_strfunction :
15537 case expression_node<T>::e_strcondition :
15538 case expression_node<T>::e_strccondition :
15539 case expression_node<T>::e_stringvararg : return true;
15540 default : return false;
15544 return false;
15547 class node_allocator
15549 public:
15551 template <typename ResultNode, typename OpType, typename ExprNode>
15552 inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[1])
15554 return allocate<ResultNode>(operation, branch[0]);
15557 template <typename ResultNode, typename OpType, typename ExprNode>
15558 inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[2])
15560 return allocate<ResultNode>(operation, branch[0], branch[1]);
15563 template <typename ResultNode, typename OpType, typename ExprNode>
15564 inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[3])
15566 return allocate<ResultNode>(operation, branch[0], branch[1], branch[2]);
15569 template <typename ResultNode, typename OpType, typename ExprNode>
15570 inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[4])
15572 return allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3]);
15575 template <typename ResultNode, typename OpType, typename ExprNode>
15576 inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[5])
15578 return allocate<ResultNode>(operation, branch[0],branch[1], branch[2], branch[3], branch[4]);
15581 template <typename ResultNode, typename OpType, typename ExprNode>
15582 inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[6])
15584 return allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3], branch[4], branch[5]);
15587 template <typename node_type>
15588 inline expression_node<typename node_type::value_type>* allocate() const
15590 return (new node_type());
15593 template <typename node_type,
15594 typename Type,
15595 typename Allocator,
15596 template <typename, typename> class Sequence>
15597 inline expression_node<typename node_type::value_type>* allocate(const Sequence<Type,Allocator>& seq) const
15599 return (new node_type(seq));
15602 template <typename node_type, typename T1>
15603 inline expression_node<typename node_type::value_type>* allocate(T1& t1) const
15605 return (new node_type(t1));
15608 template <typename node_type, typename T1>
15609 inline expression_node<typename node_type::value_type>* allocate_c(const T1& t1) const
15611 return (new node_type(t1));
15614 template <typename node_type,
15615 typename T1, typename T2>
15616 inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2) const
15618 return (new node_type(t1, t2));
15621 template <typename node_type,
15622 typename T1, typename T2>
15623 inline expression_node<typename node_type::value_type>* allocate_cr(const T1& t1, T2& t2) const
15625 return (new node_type(t1, t2));
15628 template <typename node_type,
15629 typename T1, typename T2>
15630 inline expression_node<typename node_type::value_type>* allocate_rc(T1& t1, const T2& t2) const
15632 return (new node_type(t1, t2));
15635 template <typename node_type,
15636 typename T1, typename T2>
15637 inline expression_node<typename node_type::value_type>* allocate_rr(T1& t1, T2& t2) const
15639 return (new node_type(t1, t2));
15642 template <typename node_type,
15643 typename T1, typename T2>
15644 inline expression_node<typename node_type::value_type>* allocate_tt(T1 t1, T2 t2) const
15646 return (new node_type(t1, t2));
15649 template <typename node_type,
15650 typename T1, typename T2, typename T3>
15651 inline expression_node<typename node_type::value_type>* allocate_ttt(T1 t1, T2 t2, T3 t3) const
15653 return (new node_type(t1, t2, t3));
15656 template <typename node_type,
15657 typename T1, typename T2, typename T3, typename T4>
15658 inline expression_node<typename node_type::value_type>* allocate_tttt(T1 t1, T2 t2, T3 t3, T4 t4) const
15660 return (new node_type(t1, t2, t3, t4));
15663 template <typename node_type,
15664 typename T1, typename T2, typename T3>
15665 inline expression_node<typename node_type::value_type>* allocate_rrr(T1& t1, T2& t2, T3& t3) const
15667 return (new node_type(t1, t2, t3));
15670 template <typename node_type,
15671 typename T1, typename T2, typename T3, typename T4>
15672 inline expression_node<typename node_type::value_type>* allocate_rrrr(T1& t1, T2& t2, T3& t3, T4& t4) const
15674 return (new node_type(t1, t2, t3, t4));
15677 template <typename node_type,
15678 typename T1, typename T2, typename T3, typename T4, typename T5>
15679 inline expression_node<typename node_type::value_type>* allocate_rrrrr(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5) const
15681 return (new node_type(t1, t2, t3, t4, t5));
15684 template <typename node_type,
15685 typename T1, typename T2, typename T3>
15686 inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
15687 const T3& t3) const
15689 return (new node_type(t1, t2, t3));
15692 template <typename node_type,
15693 typename T1, typename T2,
15694 typename T3, typename T4>
15695 inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
15696 const T3& t3, const T4& t4) const
15698 return (new node_type(t1, t2, t3, t4));
15701 template <typename node_type,
15702 typename T1, typename T2,
15703 typename T3, typename T4, typename T5>
15704 inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
15705 const T3& t3, const T4& t4,
15706 const T5& t5) const
15708 return (new node_type(t1, t2, t3, t4, t5));
15711 template <typename node_type,
15712 typename T1, typename T2,
15713 typename T3, typename T4, typename T5, typename T6>
15714 inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
15715 const T3& t3, const T4& t4,
15716 const T5& t5, const T6& t6) const
15718 return (new node_type(t1, t2, t3, t4, t5, t6));
15721 template <typename node_type,
15722 typename T1, typename T2,
15723 typename T3, typename T4,
15724 typename T5, typename T6, typename T7>
15725 inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
15726 const T3& t3, const T4& t4,
15727 const T5& t5, const T6& t6,
15728 const T7& t7) const
15730 return (new node_type(t1, t2, t3, t4, t5, t6, t7));
15733 template <typename node_type,
15734 typename T1, typename T2,
15735 typename T3, typename T4,
15736 typename T5, typename T6,
15737 typename T7, typename T8>
15738 inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
15739 const T3& t3, const T4& t4,
15740 const T5& t5, const T6& t6,
15741 const T7& t7, const T8& t8) const
15743 return (new node_type(t1, t2, t3, t4, t5, t6, t7, t8));
15746 template <typename node_type,
15747 typename T1, typename T2,
15748 typename T3, typename T4,
15749 typename T5, typename T6,
15750 typename T7, typename T8, typename T9>
15751 inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
15752 const T3& t3, const T4& t4,
15753 const T5& t5, const T6& t6,
15754 const T7& t7, const T8& t8,
15755 const T9& t9) const
15757 return (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9));
15760 template <typename node_type,
15761 typename T1, typename T2,
15762 typename T3, typename T4,
15763 typename T5, typename T6,
15764 typename T7, typename T8,
15765 typename T9, typename T10>
15766 inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
15767 const T3& t3, const T4& t4,
15768 const T5& t5, const T6& t6,
15769 const T7& t7, const T8& t8,
15770 const T9& t9, const T10& t10) const
15772 return (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10));
15775 template <typename node_type,
15776 typename T1, typename T2, typename T3>
15777 inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, T3 t3) const
15779 return (new node_type(t1, t2, t3));
15782 template <typename node_type,
15783 typename T1, typename T2,
15784 typename T3, typename T4>
15785 inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
15786 T3 t3, T4 t4) const
15788 return (new node_type(t1, t2, t3, t4));
15791 template <typename node_type,
15792 typename T1, typename T2,
15793 typename T3, typename T4,
15794 typename T5>
15795 inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
15796 T3 t3, T4 t4,
15797 T5 t5) const
15799 return (new node_type(t1, t2, t3, t4, t5));
15802 template <typename node_type,
15803 typename T1, typename T2,
15804 typename T3, typename T4,
15805 typename T5, typename T6>
15806 inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
15807 T3 t3, T4 t4,
15808 T5 t5, T6 t6) const
15810 return (new node_type(t1, t2, t3, t4, t5, t6));
15813 template <typename node_type,
15814 typename T1, typename T2,
15815 typename T3, typename T4,
15816 typename T5, typename T6, typename T7>
15817 inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
15818 T3 t3, T4 t4,
15819 T5 t5, T6 t6,
15820 T7 t7) const
15822 return (new node_type(t1, t2, t3, t4, t5, t6, t7));
15825 template <typename T>
15826 void inline free(expression_node<T>*& e) const
15828 delete e;
15829 e = 0;
15833 inline void load_operations_map(std::multimap<std::string,details::base_operation_t,details::ilesscompare>& m)
15835 #define register_op(Symbol,Type,Args) \
15836 m.insert(std::make_pair(std::string(Symbol),details::base_operation_t(Type,Args))); \
15838 register_op( "abs", e_abs , 1)
15839 register_op( "acos", e_acos , 1)
15840 register_op( "acosh", e_acosh , 1)
15841 register_op( "asin", e_asin , 1)
15842 register_op( "asinh", e_asinh , 1)
15843 register_op( "atan", e_atan , 1)
15844 register_op( "atanh", e_atanh , 1)
15845 register_op( "ceil", e_ceil , 1)
15846 register_op( "cos", e_cos , 1)
15847 register_op( "cosh", e_cosh , 1)
15848 register_op( "exp", e_exp , 1)
15849 register_op( "expm1", e_expm1 , 1)
15850 register_op( "floor", e_floor , 1)
15851 register_op( "log", e_log , 1)
15852 register_op( "log10", e_log10 , 1)
15853 register_op( "log2", e_log2 , 1)
15854 register_op( "log1p", e_log1p , 1)
15855 register_op( "round", e_round , 1)
15856 register_op( "sin", e_sin , 1)
15857 register_op( "sinc", e_sinc , 1)
15858 register_op( "sinh", e_sinh , 1)
15859 register_op( "sec", e_sec , 1)
15860 register_op( "csc", e_csc , 1)
15861 register_op( "sqrt", e_sqrt , 1)
15862 register_op( "tan", e_tan , 1)
15863 register_op( "tanh", e_tanh , 1)
15864 register_op( "cot", e_cot , 1)
15865 register_op( "rad2deg", e_r2d , 1)
15866 register_op( "deg2rad", e_d2r , 1)
15867 register_op( "deg2grad", e_d2g , 1)
15868 register_op( "grad2deg", e_g2d , 1)
15869 register_op( "sgn", e_sgn , 1)
15870 register_op( "not", e_notl , 1)
15871 register_op( "erf", e_erf , 1)
15872 register_op( "erfc", e_erfc , 1)
15873 register_op( "ncdf", e_ncdf , 1)
15874 register_op( "frac", e_frac , 1)
15875 register_op( "trunc", e_trunc , 1)
15876 register_op( "atan2", e_atan2 , 2)
15877 register_op( "mod", e_mod , 2)
15878 register_op( "logn", e_logn , 2)
15879 register_op( "pow", e_pow , 2)
15880 register_op( "root", e_root , 2)
15881 register_op( "roundn", e_roundn , 2)
15882 register_op( "equal", e_equal , 2)
15883 register_op("not_equal", e_nequal , 2)
15884 register_op( "hypot", e_hypot , 2)
15885 register_op( "shr", e_shr , 2)
15886 register_op( "shl", e_shl , 2)
15887 register_op( "clamp", e_clamp , 3)
15888 register_op( "iclamp", e_iclamp , 3)
15889 register_op( "inrange", e_inrange , 3)
15890 #undef register_op
15893 } // namespace details
15895 class function_traits
15897 public:
15899 function_traits()
15900 : allow_zero_parameters_(false),
15901 has_side_effects_(true),
15902 min_num_args_(0),
15903 max_num_args_(std::numeric_limits<std::size_t>::max())
15906 inline bool& allow_zero_parameters()
15908 return allow_zero_parameters_;
15911 inline bool& has_side_effects()
15913 return has_side_effects_;
15916 std::size_t& min_num_args()
15918 return min_num_args_;
15921 std::size_t& max_num_args()
15923 return max_num_args_;
15926 private:
15928 bool allow_zero_parameters_;
15929 bool has_side_effects_;
15930 std::size_t min_num_args_;
15931 std::size_t max_num_args_;
15934 template <typename FunctionType>
15935 void enable_zero_parameters(FunctionType& func)
15937 func.allow_zero_parameters() = true;
15939 if (0 != func.min_num_args())
15941 func.min_num_args() = 0;
15945 template <typename FunctionType>
15946 void disable_zero_parameters(FunctionType& func)
15948 func.allow_zero_parameters() = false;
15951 template <typename FunctionType>
15952 void enable_has_side_effects(FunctionType& func)
15954 func.has_side_effects() = true;
15957 template <typename FunctionType>
15958 void disable_has_side_effects(FunctionType& func)
15960 func.has_side_effects() = false;
15963 template <typename FunctionType>
15964 void set_min_num_args(FunctionType& func, const std::size_t& num_args)
15966 func.min_num_args() = num_args;
15968 if ((0 != func.min_num_args()) && func.allow_zero_parameters())
15969 func.allow_zero_parameters() = false;
15972 template <typename FunctionType>
15973 void set_max_num_args(FunctionType& func, const std::size_t& num_args)
15975 func.max_num_args() = num_args;
15978 template <typename T>
15979 class ifunction : public function_traits
15981 public:
15983 explicit ifunction(const std::size_t& pc)
15984 : param_count(pc)
15987 virtual ~ifunction()
15990 #define empty_method_body \
15992 return std::numeric_limits<T>::quiet_NaN(); \
15995 inline virtual T operator() ()
15996 empty_method_body
15998 inline virtual T operator() (const T&)
15999 empty_method_body
16001 inline virtual T operator() (const T&,const T&)
16002 empty_method_body
16004 inline virtual T operator() (const T&, const T&, const T&)
16005 empty_method_body
16007 inline virtual T operator() (const T&, const T&, const T&, const T&)
16008 empty_method_body
16010 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&)
16011 empty_method_body
16013 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&)
16014 empty_method_body
16016 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16017 empty_method_body
16019 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16020 empty_method_body
16022 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16023 empty_method_body
16025 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16026 empty_method_body
16028 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16029 const T&)
16030 empty_method_body
16032 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16033 const T&, const T&)
16034 empty_method_body
16036 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16037 const T&, const T&, const T&)
16038 empty_method_body
16040 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16041 const T&, const T&, const T&, const T&)
16042 empty_method_body
16044 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16045 const T&, const T&, const T&, const T&, const T&)
16046 empty_method_body
16048 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16049 const T&, const T&, const T&, const T&, const T&, const T&)
16050 empty_method_body
16052 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16053 const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16054 empty_method_body
16056 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16057 const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16058 empty_method_body
16060 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16061 const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16062 empty_method_body
16064 inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16065 const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16066 empty_method_body
16068 #undef empty_method_body
16070 std::size_t param_count;
16073 template <typename T>
16074 class ivararg_function : public function_traits
16076 public:
16078 virtual ~ivararg_function()
16081 inline virtual T operator() (const std::vector<T>&)
16083 exprtk_debug(("ivararg_function::operator() - Operator has not been overridden.\n"));
16084 return std::numeric_limits<T>::quiet_NaN();
16088 template <typename T>
16089 class igeneric_function : public function_traits
16091 public:
16093 enum return_type
16095 e_rtrn_scalar = 0,
16096 e_rtrn_string = 1,
16097 e_rtrn_overload = 2
16100 typedef T type;
16101 typedef type_store<T> generic_type;
16102 typedef typename generic_type::parameter_list parameter_list_t;
16104 igeneric_function(const std::string& param_seq = "", const return_type rtr_type = e_rtrn_scalar)
16105 : parameter_sequence(param_seq),
16106 rtrn_type(rtr_type)
16109 virtual ~igeneric_function()
16112 #define igeneric_function_empty_body(N) \
16114 exprtk_debug(("igeneric_function::operator() - Operator has not been overridden. ["#N"]\n")); \
16115 return std::numeric_limits<T>::quiet_NaN(); \
16118 // f(i_0,i_1,....,i_N) --> Scalar
16119 inline virtual T operator() (parameter_list_t)
16120 igeneric_function_empty_body(1)
16122 // f(i_0,i_1,....,i_N) --> String
16123 inline virtual T operator() (std::string&, parameter_list_t)
16124 igeneric_function_empty_body(2)
16126 // f(psi,i_0,i_1,....,i_N) --> Scalar
16127 inline virtual T operator() (const std::size_t&, parameter_list_t)
16128 igeneric_function_empty_body(3)
16130 // f(psi,i_0,i_1,....,i_N) --> String
16131 inline virtual T operator() (const std::size_t&, std::string&, parameter_list_t)
16132 igeneric_function_empty_body(4)
16134 std::string parameter_sequence;
16135 return_type rtrn_type;
16138 template <typename T> class parser;
16139 template <typename T> class expression_helper;
16141 template <typename T>
16142 class symbol_table
16144 public:
16146 typedef T (*ff00_functor)();
16147 typedef T (*ff01_functor)(T);
16148 typedef T (*ff02_functor)(T, T);
16149 typedef T (*ff03_functor)(T, T, T);
16150 typedef T (*ff04_functor)(T, T, T, T);
16151 typedef T (*ff05_functor)(T, T, T, T, T);
16152 typedef T (*ff06_functor)(T, T, T, T, T, T);
16153 typedef T (*ff07_functor)(T, T, T, T, T, T, T);
16154 typedef T (*ff08_functor)(T, T, T, T, T, T, T, T);
16155 typedef T (*ff09_functor)(T, T, T, T, T, T, T, T, T);
16156 typedef T (*ff10_functor)(T, T, T, T, T, T, T, T, T, T);
16157 typedef T (*ff11_functor)(T, T, T, T, T, T, T, T, T, T, T);
16158 typedef T (*ff12_functor)(T, T, T, T, T, T, T, T, T, T, T, T);
16159 typedef T (*ff13_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T);
16160 typedef T (*ff14_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T);
16161 typedef T (*ff15_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T);
16163 protected:
16165 struct freefunc00 : public exprtk::ifunction<T>
16167 using exprtk::ifunction<T>::operator();
16169 explicit freefunc00(ff00_functor ff) : exprtk::ifunction<T>(0), f(ff) {}
16170 inline T operator() ()
16171 { return f(); }
16172 ff00_functor f;
16175 struct freefunc01 : public exprtk::ifunction<T>
16177 using exprtk::ifunction<T>::operator();
16179 explicit freefunc01(ff01_functor ff) : exprtk::ifunction<T>(1), f(ff) {}
16180 inline T operator() (const T& v0)
16181 { return f(v0); }
16182 ff01_functor f;
16185 struct freefunc02 : public exprtk::ifunction<T>
16187 using exprtk::ifunction<T>::operator();
16189 explicit freefunc02(ff02_functor ff) : exprtk::ifunction<T>(2), f(ff) {}
16190 inline T operator() (const T& v0, const T& v1)
16191 { return f(v0, v1); }
16192 ff02_functor f;
16195 struct freefunc03 : public exprtk::ifunction<T>
16197 using exprtk::ifunction<T>::operator();
16199 explicit freefunc03(ff03_functor ff) : exprtk::ifunction<T>(3), f(ff) {}
16200 inline T operator() (const T& v0, const T& v1, const T& v2)
16201 { return f(v0, v1, v2); }
16202 ff03_functor f;
16205 struct freefunc04 : public exprtk::ifunction<T>
16207 using exprtk::ifunction<T>::operator();
16209 explicit freefunc04(ff04_functor ff) : exprtk::ifunction<T>(4), f(ff) {}
16210 inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3)
16211 { return f(v0, v1, v2, v3); }
16212 ff04_functor f;
16215 struct freefunc05 : public exprtk::ifunction<T>
16217 using exprtk::ifunction<T>::operator();
16219 explicit freefunc05(ff05_functor ff) : exprtk::ifunction<T>(5), f(ff) {}
16220 inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4)
16221 { return f(v0, v1, v2, v3, v4); }
16222 ff05_functor f;
16225 struct freefunc06 : public exprtk::ifunction<T>
16227 using exprtk::ifunction<T>::operator();
16229 explicit freefunc06(ff06_functor ff) : exprtk::ifunction<T>(6), f(ff) {}
16230 inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5)
16231 { return f(v0, v1, v2, v3, v4, v5); }
16232 ff06_functor f;
16235 struct freefunc07 : public exprtk::ifunction<T>
16237 using exprtk::ifunction<T>::operator();
16239 explicit freefunc07(ff07_functor ff) : exprtk::ifunction<T>(7), f(ff) {}
16240 inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
16241 const T& v5, const T& v6)
16242 { return f(v0, v1, v2, v3, v4, v5, v6); }
16243 ff07_functor f;
16246 struct freefunc08 : public exprtk::ifunction<T>
16248 using exprtk::ifunction<T>::operator();
16250 explicit freefunc08(ff08_functor ff) : exprtk::ifunction<T>(8), f(ff) {}
16251 inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
16252 const T& v5, const T& v6, const T& v7)
16253 { return f(v0, v1, v2, v3, v4, v5, v6, v7); }
16254 ff08_functor f;
16257 struct freefunc09 : public exprtk::ifunction<T>
16259 using exprtk::ifunction<T>::operator();
16261 explicit freefunc09(ff09_functor ff) : exprtk::ifunction<T>(9), f(ff) {}
16262 inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
16263 const T& v5, const T& v6, const T& v7, const T& v8)
16264 { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8); }
16265 ff09_functor f;
16268 struct freefunc10 : public exprtk::ifunction<T>
16270 using exprtk::ifunction<T>::operator();
16272 explicit freefunc10(ff10_functor ff) : exprtk::ifunction<T>(10), f(ff) {}
16273 inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
16274 const T& v5, const T& v6, const T& v7, const T& v8, const T& v9)
16275 { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9); }
16276 ff10_functor f;
16279 struct freefunc11 : public exprtk::ifunction<T>
16281 using exprtk::ifunction<T>::operator();
16283 explicit freefunc11(ff11_functor ff) : exprtk::ifunction<T>(11), f(ff) {}
16284 inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
16285 const T& v5, const T& v6, const T& v7, const T& v8, const T& v9, const T& v10)
16286 { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10); }
16287 ff11_functor f;
16290 struct freefunc12 : public exprtk::ifunction<T>
16292 using exprtk::ifunction<T>::operator();
16294 explicit freefunc12(ff12_functor ff) : exprtk::ifunction<T>(12), f(ff) {}
16295 inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
16296 const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
16297 const T& v10, const T& v11)
16298 { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11); }
16299 ff12_functor f;
16302 struct freefunc13 : public exprtk::ifunction<T>
16304 using exprtk::ifunction<T>::operator();
16306 explicit freefunc13(ff13_functor ff) : exprtk::ifunction<T>(13), f(ff) {}
16307 inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
16308 const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
16309 const T& v10, const T& v11, const T& v12)
16310 { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12); }
16311 ff13_functor f;
16314 struct freefunc14 : public exprtk::ifunction<T>
16316 using exprtk::ifunction<T>::operator();
16318 explicit freefunc14(ff14_functor ff) : exprtk::ifunction<T>(14), f(ff) {}
16319 inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
16320 const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
16321 const T& v10, const T& v11, const T& v12, const T& v13)
16322 { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13); }
16323 ff14_functor f;
16326 struct freefunc15 : public exprtk::ifunction<T>
16328 using exprtk::ifunction<T>::operator();
16330 explicit freefunc15(ff15_functor ff) : exprtk::ifunction<T>(15), f(ff) {}
16331 inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
16332 const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
16333 const T& v10, const T& v11, const T& v12, const T& v13, const T& v14)
16334 { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13, v14); }
16335 ff15_functor f;
16338 template <typename Type, typename RawType>
16339 struct type_store
16341 typedef details::expression_node<T>* expression_ptr;
16342 typedef typename details::variable_node<T> variable_node_t;
16343 typedef ifunction<T> ifunction_t;
16344 typedef ivararg_function<T> ivararg_function_t;
16345 typedef igeneric_function<T> igeneric_function_t;
16346 typedef details::vector_holder<T> vector_t;
16347 #ifndef exprtk_disable_string_capabilities
16348 typedef typename details::stringvar_node<T> stringvar_node_t;
16349 #endif
16351 typedef Type type_t;
16352 typedef type_t* type_ptr;
16353 typedef std::pair<bool,type_ptr> type_pair_t;
16354 typedef std::map<std::string,type_pair_t,details::ilesscompare> type_map_t;
16355 typedef typename type_map_t::iterator tm_itr_t;
16356 typedef typename type_map_t::const_iterator tm_const_itr_t;
16358 enum { lut_size = 256 };
16360 type_map_t map;
16361 std::size_t size;
16363 type_store()
16364 : size(0)
16367 inline bool symbol_exists(const std::string& symbol_name) const
16369 if (symbol_name.empty())
16370 return false;
16371 else if (map.end() != map.find(symbol_name))
16372 return true;
16373 else
16374 return false;
16377 template <typename PtrType>
16378 inline std::string entity_name(const PtrType& ptr) const
16380 if (map.empty())
16381 return std::string();
16383 tm_const_itr_t itr = map.begin();
16385 while (map.end() != itr)
16387 if (itr->second.second == ptr)
16389 return itr->first;
16391 else
16392 ++itr;
16395 return std::string();
16398 inline bool is_constant(const std::string& symbol_name) const
16400 if (symbol_name.empty())
16401 return false;
16402 else
16404 const tm_const_itr_t itr = map.find(symbol_name);
16406 if (map.end() == itr)
16407 return false;
16408 else
16409 return (*itr).second.first;
16413 template <typename Tie, typename RType>
16414 inline bool add_impl(const std::string& symbol_name, RType t, const bool is_const)
16416 if (symbol_name.size() > 1)
16418 for (std::size_t i = 0; i < details::reserved_symbols_size; ++i)
16420 if (details::imatch(symbol_name, details::reserved_symbols[i]))
16422 return false;
16427 const tm_itr_t itr = map.find(symbol_name);
16429 if (map.end() == itr)
16431 map[symbol_name] = Tie::make(t,is_const);
16432 ++size;
16435 return true;
16438 struct tie_array
16440 static inline std::pair<bool,vector_t*> make(std::pair<T*,std::size_t> v, const bool is_const = false)
16442 return std::make_pair(is_const, new vector_t(v.first, v.second));
16446 struct tie_stdvec
16448 template <typename Allocator>
16449 static inline std::pair<bool,vector_t*> make(std::vector<T,Allocator>& v, const bool is_const = false)
16451 return std::make_pair(is_const, new vector_t(v));
16455 struct tie_vecview
16457 static inline std::pair<bool,vector_t*> make(exprtk::vector_view<T>& v, const bool is_const = false)
16459 return std::make_pair(is_const, new vector_t(v));
16463 struct tie_stddeq
16465 template <typename Allocator>
16466 static inline std::pair<bool,vector_t*> make(std::deque<T,Allocator>& v, const bool is_const = false)
16468 return std::make_pair(is_const, new vector_t(v));
16472 template <std::size_t v_size>
16473 inline bool add(const std::string& symbol_name, T (&v)[v_size], const bool is_const = false)
16475 return add_impl<tie_array,std::pair<T*,std::size_t> >
16476 (symbol_name, std::make_pair(v,v_size), is_const);
16479 inline bool add(const std::string& symbol_name, T* v, const std::size_t v_size, const bool is_const = false)
16481 return add_impl<tie_array,std::pair<T*,std::size_t> >
16482 (symbol_name, std::make_pair(v,v_size), is_const);
16485 template <typename Allocator>
16486 inline bool add(const std::string& symbol_name, std::vector<T,Allocator>& v, const bool is_const = false)
16488 return add_impl<tie_stdvec,std::vector<T,Allocator>&>
16489 (symbol_name, v, is_const);
16492 inline bool add(const std::string& symbol_name, exprtk::vector_view<T>& v, const bool is_const = false)
16494 return add_impl<tie_vecview,exprtk::vector_view<T>&>
16495 (symbol_name, v, is_const);
16498 template <typename Allocator>
16499 inline bool add(const std::string& symbol_name, std::deque<T,Allocator>& v, const bool is_const = false)
16501 return add_impl<tie_stddeq,std::deque<T,Allocator>&>
16502 (symbol_name, v, is_const);
16505 inline bool add(const std::string& symbol_name, RawType& t, const bool is_const = false)
16507 struct tie
16509 static inline std::pair<bool,variable_node_t*> make(T& t,const bool is_const = false)
16511 return std::make_pair(is_const, new variable_node_t(t));
16514 #ifndef exprtk_disable_string_capabilities
16515 static inline std::pair<bool,stringvar_node_t*> make(std::string& t,const bool is_const = false)
16517 return std::make_pair(is_const, new stringvar_node_t(t));
16519 #endif
16521 static inline std::pair<bool,function_t*> make(function_t& t, const bool is_constant = false)
16523 return std::make_pair(is_constant,&t);
16526 static inline std::pair<bool,vararg_function_t*> make(vararg_function_t& t, const bool is_const = false)
16528 return std::make_pair(is_const,&t);
16531 static inline std::pair<bool,generic_function_t*> make(generic_function_t& t, const bool is_constant = false)
16533 return std::make_pair(is_constant,&t);
16537 const tm_itr_t itr = map.find(symbol_name);
16539 if (map.end() == itr)
16541 map[symbol_name] = tie::make(t,is_const);
16542 ++size;
16545 return true;
16548 inline type_ptr get(const std::string& symbol_name) const
16550 const tm_const_itr_t itr = map.find(symbol_name);
16552 if (map.end() == itr)
16553 return reinterpret_cast<type_ptr>(0);
16554 else
16555 return itr->second.second;
16558 template <typename TType, typename TRawType, typename PtrType>
16559 struct ptr_match
16561 static inline bool test(const PtrType, const void*)
16563 return false;
16567 template <typename TType, typename TRawType>
16568 struct ptr_match<TType,TRawType,variable_node_t*>
16570 static inline bool test(const variable_node_t* p, const void* ptr)
16572 exprtk_debug(("ptr_match::test() - %p <--> %p\n",(void*)(&(p->ref())),ptr));
16573 return (&(p->ref()) == ptr);
16577 inline type_ptr get_from_varptr(const void* ptr) const
16579 tm_const_itr_t itr = map.begin();
16581 while (map.end() != itr)
16583 type_ptr ret_ptr = itr->second.second;
16585 if (ptr_match<Type,RawType,type_ptr>::test(ret_ptr,ptr))
16587 return ret_ptr;
16590 ++itr;
16593 return type_ptr(0);
16596 inline bool remove(const std::string& symbol_name, const bool delete_node = true)
16598 const tm_itr_t itr = map.find(symbol_name);
16600 if (map.end() != itr)
16602 struct deleter
16604 static inline void process(std::pair<bool,variable_node_t*>& n) { delete n.second; }
16605 static inline void process(std::pair<bool,vector_t*>& n) { delete n.second; }
16606 #ifndef exprtk_disable_string_capabilities
16607 static inline void process(std::pair<bool,stringvar_node_t*>& n) { delete n.second; }
16608 #endif
16609 static inline void process(std::pair<bool,function_t*>&) { }
16612 if (delete_node)
16614 deleter::process((*itr).second);
16617 map.erase(itr);
16618 --size;
16620 return true;
16622 else
16623 return false;
16626 inline RawType& type_ref(const std::string& symbol_name)
16628 struct init_type
16630 static inline double set(double) { return (0.0); }
16631 static inline double set(long double) { return (0.0); }
16632 static inline float set(float) { return (0.0f); }
16633 static inline std::string set(std::string) { return std::string(""); }
16636 static RawType null_type = init_type::set(RawType());
16638 const tm_const_itr_t itr = map.find(symbol_name);
16640 if (map.end() == itr)
16641 return null_type;
16642 else
16643 return itr->second.second->ref();
16646 inline void clear(const bool delete_node = true)
16648 struct deleter
16650 static inline void process(std::pair<bool,variable_node_t*>& n) { delete n.second; }
16651 static inline void process(std::pair<bool,vector_t*>& n) { delete n.second; }
16652 static inline void process(std::pair<bool,function_t*>&) { }
16653 #ifndef exprtk_disable_string_capabilities
16654 static inline void process(std::pair<bool,stringvar_node_t*>& n) { delete n.second; }
16655 #endif
16658 if (!map.empty())
16660 if (delete_node)
16662 tm_itr_t itr = map.begin();
16663 tm_itr_t end = map.end ();
16665 while (end != itr)
16667 deleter::process((*itr).second);
16668 ++itr;
16672 map.clear();
16675 size = 0;
16678 template <typename Allocator,
16679 template <typename, typename> class Sequence>
16680 inline std::size_t get_list(Sequence<std::pair<std::string,RawType>,Allocator>& list) const
16682 std::size_t count = 0;
16684 if (!map.empty())
16686 tm_const_itr_t itr = map.begin();
16687 tm_const_itr_t end = map.end ();
16689 while (end != itr)
16691 list.push_back(std::make_pair((*itr).first,itr->second.second->ref()));
16692 ++itr;
16693 ++count;
16697 return count;
16700 template <typename Allocator,
16701 template <typename, typename> class Sequence>
16702 inline std::size_t get_list(Sequence<std::string,Allocator>& vlist) const
16704 std::size_t count = 0;
16706 if (!map.empty())
16708 tm_const_itr_t itr = map.begin();
16709 tm_const_itr_t end = map.end ();
16711 while (end != itr)
16713 vlist.push_back((*itr).first);
16714 ++itr;
16715 ++count;
16719 return count;
16723 typedef details::expression_node<T>* expression_ptr;
16724 typedef typename details::variable_node<T> variable_t;
16725 typedef typename details::vector_holder<T> vector_holder_t;
16726 typedef variable_t* variable_ptr;
16727 #ifndef exprtk_disable_string_capabilities
16728 typedef typename details::stringvar_node<T> stringvar_t;
16729 typedef stringvar_t* stringvar_ptr;
16730 #endif
16731 typedef ifunction <T> function_t;
16732 typedef ivararg_function <T> vararg_function_t;
16733 typedef igeneric_function<T> generic_function_t;
16734 typedef function_t* function_ptr;
16735 typedef vararg_function_t* vararg_function_ptr;
16736 typedef generic_function_t* generic_function_ptr;
16738 static const std::size_t lut_size = 256;
16740 // Symbol Table Holder
16741 struct control_block
16743 struct st_data
16745 type_store<typename details::variable_node<T>,T> variable_store;
16746 #ifndef exprtk_disable_string_capabilities
16747 type_store<typename details::stringvar_node<T>,std::string> stringvar_store;
16748 #endif
16749 type_store<ifunction<T>,ifunction<T> > function_store;
16750 type_store<ivararg_function <T>,ivararg_function <T> > vararg_function_store;
16751 type_store<igeneric_function<T>,igeneric_function<T> > generic_function_store;
16752 type_store<igeneric_function<T>,igeneric_function<T> > string_function_store;
16753 type_store<igeneric_function<T>,igeneric_function<T> > overload_function_store;
16754 type_store<vector_holder_t,vector_holder_t> vector_store;
16756 st_data()
16758 for (std::size_t i = 0; i < details::reserved_words_size; ++i)
16760 reserved_symbol_table_.insert(details::reserved_words[i]);
16763 for (std::size_t i = 0; i < details::reserved_symbols_size; ++i)
16765 reserved_symbol_table_.insert(details::reserved_symbols[i]);
16769 ~st_data()
16771 for (std::size_t i = 0; i < free_function_list_.size(); ++i)
16773 delete free_function_list_[i];
16777 inline bool is_reserved_symbol(const std::string& symbol) const
16779 return (reserved_symbol_table_.end() != reserved_symbol_table_.find(symbol));
16782 static inline st_data* create()
16784 return (new st_data);
16787 static inline void destroy(st_data*& sd)
16789 delete sd;
16790 sd = reinterpret_cast<st_data*>(0);
16793 std::list<T> local_symbol_list_;
16794 std::list<std::string> local_stringvar_list_;
16795 std::set<std::string> reserved_symbol_table_;
16796 std::vector<ifunction<T>*> free_function_list_;
16799 control_block()
16800 : ref_count(1),
16801 data_(st_data::create())
16804 explicit control_block(st_data* data)
16805 : ref_count(1),
16806 data_(data)
16809 ~control_block()
16811 if (data_ && (0 == ref_count))
16813 st_data::destroy(data_);
16817 static inline control_block* create()
16819 return (new control_block);
16822 template <typename SymTab>
16823 static inline void destroy(control_block*& cntrl_blck, SymTab* sym_tab)
16825 if (cntrl_blck)
16827 if (
16828 (0 != cntrl_blck->ref_count) &&
16829 (0 == --cntrl_blck->ref_count)
16832 if (sym_tab)
16833 sym_tab->clear();
16835 delete cntrl_blck;
16838 cntrl_blck = 0;
16842 std::size_t ref_count;
16843 st_data* data_;
16846 public:
16848 symbol_table()
16849 : control_block_(control_block::create())
16851 clear();
16854 ~symbol_table()
16856 control_block::destroy(control_block_,this);
16859 symbol_table(const symbol_table<T>& st)
16861 control_block_ = st.control_block_;
16862 control_block_->ref_count++;
16865 inline symbol_table<T>& operator=(const symbol_table<T>& st)
16867 if (this != &st)
16869 control_block::destroy(control_block_,reinterpret_cast<symbol_table<T>*>(0));
16871 control_block_ = st.control_block_;
16872 control_block_->ref_count++;
16875 return (*this);
16878 inline bool operator==(const symbol_table<T>& st) const
16880 return (this == &st) || (control_block_ == st.control_block_);
16883 inline void clear_variables(const bool delete_node = true)
16885 local_data().variable_store.clear(delete_node);
16888 inline void clear_functions()
16890 local_data().function_store.clear();
16893 inline void clear_strings()
16895 #ifndef exprtk_disable_string_capabilities
16896 local_data().stringvar_store.clear();
16897 #endif
16900 inline void clear_vectors()
16902 local_data().vector_store.clear();
16905 inline void clear_local_constants()
16907 local_data().local_symbol_list_.clear();
16910 inline void clear()
16912 if (!valid()) return;
16913 clear_variables ();
16914 clear_functions ();
16915 clear_strings ();
16916 clear_vectors ();
16917 clear_local_constants();
16920 inline std::size_t variable_count() const
16922 if (valid())
16923 return local_data().variable_store.size;
16924 else
16925 return 0;
16928 #ifndef exprtk_disable_string_capabilities
16929 inline std::size_t stringvar_count() const
16931 if (valid())
16932 return local_data().stringvar_store.size;
16933 else
16934 return 0;
16936 #endif
16938 inline std::size_t function_count() const
16940 if (valid())
16941 return local_data().function_store.size;
16942 else
16943 return 0;
16946 inline std::size_t vector_count() const
16948 if (valid())
16949 return local_data().vector_store.size;
16950 else
16951 return 0;
16954 inline variable_ptr get_variable(const std::string& variable_name) const
16956 if (!valid())
16957 return reinterpret_cast<variable_ptr>(0);
16958 else if (!valid_symbol(variable_name))
16959 return reinterpret_cast<variable_ptr>(0);
16960 else
16961 return local_data().variable_store.get(variable_name);
16964 inline variable_ptr get_variable(const T& var_ref) const
16966 if (!valid())
16967 return reinterpret_cast<variable_ptr>(0);
16968 else
16969 return local_data().variable_store.get_from_varptr(
16970 reinterpret_cast<const void*>(&var_ref));
16973 #ifndef exprtk_disable_string_capabilities
16974 inline stringvar_ptr get_stringvar(const std::string& string_name) const
16976 if (!valid())
16977 return reinterpret_cast<stringvar_ptr>(0);
16978 else if (!valid_symbol(string_name))
16979 return reinterpret_cast<stringvar_ptr>(0);
16980 else
16981 return local_data().stringvar_store.get(string_name);
16983 #endif
16985 inline function_ptr get_function(const std::string& function_name) const
16987 if (!valid())
16988 return reinterpret_cast<function_ptr>(0);
16989 else if (!valid_symbol(function_name))
16990 return reinterpret_cast<function_ptr>(0);
16991 else
16992 return local_data().function_store.get(function_name);
16995 inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const
16997 if (!valid())
16998 return reinterpret_cast<vararg_function_ptr>(0);
16999 else if (!valid_symbol(vararg_function_name))
17000 return reinterpret_cast<vararg_function_ptr>(0);
17001 else
17002 return local_data().vararg_function_store.get(vararg_function_name);
17005 inline generic_function_ptr get_generic_function(const std::string& function_name) const
17007 if (!valid())
17008 return reinterpret_cast<generic_function_ptr>(0);
17009 else if (!valid_symbol(function_name))
17010 return reinterpret_cast<generic_function_ptr>(0);
17011 else
17012 return local_data().generic_function_store.get(function_name);
17015 inline generic_function_ptr get_string_function(const std::string& function_name) const
17017 if (!valid())
17018 return reinterpret_cast<generic_function_ptr>(0);
17019 else if (!valid_symbol(function_name))
17020 return reinterpret_cast<generic_function_ptr>(0);
17021 else
17022 return local_data().string_function_store.get(function_name);
17025 inline generic_function_ptr get_overload_function(const std::string& function_name) const
17027 if (!valid())
17028 return reinterpret_cast<generic_function_ptr>(0);
17029 else if (!valid_symbol(function_name))
17030 return reinterpret_cast<generic_function_ptr>(0);
17031 else
17032 return local_data().overload_function_store.get(function_name);
17035 typedef vector_holder_t* vector_holder_ptr;
17037 inline vector_holder_ptr get_vector(const std::string& vector_name) const
17039 if (!valid())
17040 return reinterpret_cast<vector_holder_ptr>(0);
17041 else if (!valid_symbol(vector_name))
17042 return reinterpret_cast<vector_holder_ptr>(0);
17043 else
17044 return local_data().vector_store.get(vector_name);
17047 inline T& variable_ref(const std::string& symbol_name)
17049 static T null_var = T(0);
17050 if (!valid())
17051 return null_var;
17052 else if (!valid_symbol(symbol_name))
17053 return null_var;
17054 else
17055 return local_data().variable_store.type_ref(symbol_name);
17058 #ifndef exprtk_disable_string_capabilities
17059 inline std::string& stringvar_ref(const std::string& symbol_name)
17061 static std::string null_stringvar;
17062 if (!valid())
17063 return null_stringvar;
17064 else if (!valid_symbol(symbol_name))
17065 return null_stringvar;
17066 else
17067 return local_data().stringvar_store.type_ref(symbol_name);
17069 #endif
17071 inline bool is_constant_node(const std::string& symbol_name) const
17073 if (!valid())
17074 return false;
17075 else if (!valid_symbol(symbol_name))
17076 return false;
17077 else
17078 return local_data().variable_store.is_constant(symbol_name);
17081 #ifndef exprtk_disable_string_capabilities
17082 inline bool is_constant_string(const std::string& symbol_name) const
17084 if (!valid())
17085 return false;
17086 else if (!valid_symbol(symbol_name))
17087 return false;
17088 else if (!local_data().stringvar_store.symbol_exists(symbol_name))
17089 return false;
17090 else
17091 return local_data().stringvar_store.is_constant(symbol_name);
17093 #endif
17095 inline bool create_variable(const std::string& variable_name, const T& value = T(0))
17097 if (!valid())
17098 return false;
17099 else if (!valid_symbol(variable_name))
17100 return false;
17101 else if (symbol_exists(variable_name))
17102 return false;
17104 local_data().local_symbol_list_.push_back(value);
17105 T& t = local_data().local_symbol_list_.back();
17107 return add_variable(variable_name,t);
17110 #ifndef exprtk_disable_string_capabilities
17111 inline bool create_stringvar(const std::string& stringvar_name, const std::string& value = std::string(""))
17113 if (!valid())
17114 return false;
17115 else if (!valid_symbol(stringvar_name))
17116 return false;
17117 else if (symbol_exists(stringvar_name))
17118 return false;
17120 local_data().local_stringvar_list_.push_back(value);
17121 std::string& s = local_data().local_stringvar_list_.back();
17123 return add_stringvar(stringvar_name,s);
17125 #endif
17127 inline bool add_variable(const std::string& variable_name, T& t, const bool is_constant = false)
17129 if (!valid())
17130 return false;
17131 else if (!valid_symbol(variable_name))
17132 return false;
17133 else if (symbol_exists(variable_name))
17134 return false;
17135 else
17136 return local_data().variable_store.add(variable_name, t, is_constant);
17139 inline bool add_constant(const std::string& constant_name, const T& value)
17141 if (!valid())
17142 return false;
17143 else if (!valid_symbol(constant_name))
17144 return false;
17145 else if (symbol_exists(constant_name))
17146 return false;
17148 local_data().local_symbol_list_.push_back(value);
17149 T& t = local_data().local_symbol_list_.back();
17151 return add_variable(constant_name, t, true);
17154 #ifndef exprtk_disable_string_capabilities
17155 inline bool add_stringvar(const std::string& stringvar_name, std::string& s, const bool is_constant = false)
17157 if (!valid())
17158 return false;
17159 else if (!valid_symbol(stringvar_name))
17160 return false;
17161 else if (symbol_exists(stringvar_name))
17162 return false;
17163 else
17164 return local_data().stringvar_store.add(stringvar_name, s, is_constant);
17166 #endif
17168 inline bool add_function(const std::string& function_name, function_t& function)
17170 if (!valid())
17171 return false;
17172 else if (!valid_symbol(function_name))
17173 return false;
17174 else if (symbol_exists(function_name))
17175 return false;
17176 else
17177 return local_data().function_store.add(function_name,function);
17180 inline bool add_function(const std::string& vararg_function_name, vararg_function_t& vararg_function)
17182 if (!valid())
17183 return false;
17184 else if (!valid_symbol(vararg_function_name))
17185 return false;
17186 else if (symbol_exists(vararg_function_name))
17187 return false;
17188 else
17189 return local_data().vararg_function_store.add(vararg_function_name,vararg_function);
17192 inline bool add_function(const std::string& function_name, generic_function_t& function)
17194 if (!valid())
17195 return false;
17196 else if (!valid_symbol(function_name))
17197 return false;
17198 else if (symbol_exists(function_name))
17199 return false;
17200 else if (
17202 (generic_function_t::e_rtrn_scalar == function.rtrn_type) ||
17203 (generic_function_t::e_rtrn_string == function.rtrn_type)
17204 ) &&
17205 std::string::npos != function.parameter_sequence.find_first_not_of("STVZ*?|")
17207 return false;
17208 else if (
17209 (generic_function_t::e_rtrn_overload == function.rtrn_type) &&
17210 std::string::npos != function.parameter_sequence.find_first_not_of("STVZ*?|:")
17212 return false;
17214 switch (function.rtrn_type)
17216 case generic_function_t::e_rtrn_scalar :
17217 return local_data().generic_function_store.add(function_name,function);
17219 case generic_function_t::e_rtrn_string :
17220 return local_data().string_function_store.add(function_name,function);
17222 case generic_function_t::e_rtrn_overload :
17223 return local_data().overload_function_store.add(function_name,function);
17226 return false;
17229 #define exprtk_define_freefunction(NN) \
17230 inline bool add_function(const std::string& function_name, ff##NN##_functor function) \
17232 if (!valid()) \
17233 { return false; } \
17234 if (!valid_symbol(function_name)) \
17235 { return false; } \
17236 if (symbol_exists(function_name)) \
17237 { return false; } \
17239 exprtk::ifunction<T>* ifunc = new freefunc##NN(function); \
17241 local_data().free_function_list_.push_back(ifunc); \
17243 return add_function(function_name,(*local_data().free_function_list_.back())); \
17246 exprtk_define_freefunction(00) exprtk_define_freefunction(01)
17247 exprtk_define_freefunction(02) exprtk_define_freefunction(03)
17248 exprtk_define_freefunction(04) exprtk_define_freefunction(05)
17249 exprtk_define_freefunction(06) exprtk_define_freefunction(07)
17250 exprtk_define_freefunction(08) exprtk_define_freefunction(09)
17251 exprtk_define_freefunction(10) exprtk_define_freefunction(11)
17252 exprtk_define_freefunction(12) exprtk_define_freefunction(13)
17253 exprtk_define_freefunction(14) exprtk_define_freefunction(15)
17255 #undef exprtk_define_freefunction
17257 inline bool add_reserved_function(const std::string& function_name, function_t& function)
17259 if (!valid())
17260 return false;
17261 else if (!valid_symbol(function_name,false))
17262 return false;
17263 else if (symbol_exists(function_name,false))
17264 return false;
17265 else
17266 return local_data().function_store.add(function_name,function);
17269 inline bool add_reserved_function(const std::string& vararg_function_name, vararg_function_t& vararg_function)
17271 if (!valid())
17272 return false;
17273 else if (!valid_symbol(vararg_function_name,false))
17274 return false;
17275 else if (symbol_exists(vararg_function_name,false))
17276 return false;
17277 else
17278 return local_data().vararg_function_store.add(vararg_function_name,vararg_function);
17281 inline bool add_reserved_function(const std::string& function_name, generic_function_t& function)
17283 if (!valid())
17284 return false;
17285 else if (!valid_symbol(function_name,false))
17286 return false;
17287 else if (symbol_exists(function_name,false))
17288 return false;
17289 else if (
17291 (generic_function_t::e_rtrn_scalar == function.rtrn_type) ||
17292 (generic_function_t::e_rtrn_string == function.rtrn_type)
17293 ) &&
17294 std::string::npos != function.parameter_sequence.find_first_not_of("STV*?|")
17296 return false;
17297 else if (
17298 generic_function_t::e_rtrn_overload &&
17299 std::string::npos != function.parameter_sequence.find_first_not_of("STV*?|:")
17301 return false;
17303 switch (function.rtrn_type)
17305 case generic_function_t::e_rtrn_scalar :
17306 return local_data().generic_function_store.add(function_name,function);
17308 case generic_function_t::e_rtrn_string :
17309 return local_data().string_function_store.add(function_name,function);
17311 case generic_function_t::e_rtrn_overload :
17312 return local_data().overload_function_store.add(function_name,function);
17315 return false;
17318 template <std::size_t N>
17319 inline bool add_vector(const std::string& vector_name, T (&v)[N])
17321 if (!valid())
17322 return false;
17323 else if (!valid_symbol(vector_name))
17324 return false;
17325 else if (symbol_exists(vector_name))
17326 return false;
17327 else
17328 return local_data().vector_store.add(vector_name,v);
17331 inline bool add_vector(const std::string& vector_name, T* v, const std::size_t& v_size)
17333 if (!valid())
17334 return false;
17335 else if (!valid_symbol(vector_name))
17336 return false;
17337 else if (symbol_exists(vector_name))
17338 return false;
17339 else if (0 == v_size)
17340 return false;
17341 else
17342 return local_data().vector_store.add(vector_name, v, v_size);
17345 template <typename Allocator>
17346 inline bool add_vector(const std::string& vector_name, std::vector<T,Allocator>& v)
17348 if (!valid())
17349 return false;
17350 else if (!valid_symbol(vector_name))
17351 return false;
17352 else if (symbol_exists(vector_name))
17353 return false;
17354 else if (0 == v.size())
17355 return false;
17356 else
17357 return local_data().vector_store.add(vector_name,v);
17360 inline bool add_vector(const std::string& vector_name, exprtk::vector_view<T>& v)
17362 if (!valid())
17363 return false;
17364 else if (!valid_symbol(vector_name))
17365 return false;
17366 else if (symbol_exists(vector_name))
17367 return false;
17368 else if (0 == v.size())
17369 return false;
17370 else
17371 return local_data().vector_store.add(vector_name,v);
17374 inline bool remove_variable(const std::string& variable_name, const bool delete_node = true)
17376 if (!valid())
17377 return false;
17378 else
17379 return local_data().variable_store.remove(variable_name, delete_node);
17382 #ifndef exprtk_disable_string_capabilities
17383 inline bool remove_stringvar(const std::string& string_name)
17385 if (!valid())
17386 return false;
17387 else
17388 return local_data().stringvar_store.remove(string_name);
17390 #endif
17392 inline bool remove_function(const std::string& function_name)
17394 if (!valid())
17395 return false;
17396 else
17397 return local_data().function_store.remove(function_name);
17400 inline bool remove_vararg_function(const std::string& vararg_function_name)
17402 if (!valid())
17403 return false;
17404 else
17405 return local_data().vararg_function_store.remove(vararg_function_name);
17408 inline bool remove_vector(const std::string& vector_name)
17410 if (!valid())
17411 return false;
17412 else
17413 return local_data().vector_store.remove(vector_name);
17416 inline bool add_constants()
17418 return add_pi () &&
17419 add_epsilon () &&
17420 add_infinity() ;
17423 inline bool add_pi()
17425 const typename details::numeric::details::number_type<T>::type num_type;
17426 static const T local_pi = details::numeric::details::const_pi_impl<T>(num_type);
17427 return add_constant("pi",local_pi);
17430 inline bool add_epsilon()
17432 static const T local_epsilon = details::numeric::details::epsilon_type<T>::value();
17433 return add_constant("epsilon",local_epsilon);
17436 inline bool add_infinity()
17438 static const T local_infinity = std::numeric_limits<T>::infinity();
17439 return add_constant("inf",local_infinity);
17442 template <typename Package>
17443 inline bool add_package(Package& package)
17445 return package.register_package(*this);
17448 template <typename Allocator,
17449 template <typename, typename> class Sequence>
17450 inline std::size_t get_variable_list(Sequence<std::pair<std::string,T>,Allocator>& vlist) const
17452 if (!valid())
17453 return 0;
17454 else
17455 return local_data().variable_store.get_list(vlist);
17458 template <typename Allocator,
17459 template <typename, typename> class Sequence>
17460 inline std::size_t get_variable_list(Sequence<std::string,Allocator>& vlist) const
17462 if (!valid())
17463 return 0;
17464 else
17465 return local_data().variable_store.get_list(vlist);
17468 #ifndef exprtk_disable_string_capabilities
17469 template <typename Allocator,
17470 template <typename, typename> class Sequence>
17471 inline std::size_t get_stringvar_list(Sequence<std::pair<std::string,std::string>,Allocator>& svlist) const
17473 if (!valid())
17474 return 0;
17475 else
17476 return local_data().stringvar_store.get_list(svlist);
17479 template <typename Allocator,
17480 template <typename, typename> class Sequence>
17481 inline std::size_t get_stringvar_list(Sequence<std::string,Allocator>& svlist) const
17483 if (!valid())
17484 return 0;
17485 else
17486 return local_data().stringvar_store.get_list(svlist);
17488 #endif
17490 template <typename Allocator,
17491 template <typename, typename> class Sequence>
17492 inline std::size_t get_vector_list(Sequence<std::string,Allocator>& vlist) const
17494 if (!valid())
17495 return 0;
17496 else
17497 return local_data().vector_store.get_list(vlist);
17500 inline bool symbol_exists(const std::string& symbol_name, const bool check_reserved_symb = true) const
17503 Function will return true if symbol_name exists as either a
17504 reserved symbol, variable, stringvar, vector or function name
17505 in any of the type stores.
17507 if (!valid())
17508 return false;
17509 else if (local_data().variable_store.symbol_exists(symbol_name))
17510 return true;
17511 #ifndef exprtk_disable_string_capabilities
17512 else if (local_data().stringvar_store.symbol_exists(symbol_name))
17513 return true;
17514 #endif
17515 else if (local_data().vector_store.symbol_exists(symbol_name))
17516 return true;
17517 else if (local_data().function_store.symbol_exists(symbol_name))
17518 return true;
17519 else if (check_reserved_symb && local_data().is_reserved_symbol(symbol_name))
17520 return true;
17521 else
17522 return false;
17525 inline bool is_variable(const std::string& variable_name) const
17527 if (!valid())
17528 return false;
17529 else
17530 return local_data().variable_store.symbol_exists(variable_name);
17533 #ifndef exprtk_disable_string_capabilities
17534 inline bool is_stringvar(const std::string& stringvar_name) const
17536 if (!valid())
17537 return false;
17538 else
17539 return local_data().stringvar_store.symbol_exists(stringvar_name);
17542 inline bool is_conststr_stringvar(const std::string& symbol_name) const
17544 if (!valid())
17545 return false;
17546 else if (!valid_symbol(symbol_name))
17547 return false;
17548 else if (!local_data().stringvar_store.symbol_exists(symbol_name))
17549 return false;
17551 return (
17552 local_data().stringvar_store.symbol_exists(symbol_name) ||
17553 local_data().stringvar_store.is_constant (symbol_name)
17556 #endif
17558 inline bool is_function(const std::string& function_name) const
17560 if (!valid())
17561 return false;
17562 else
17563 return local_data().function_store.symbol_exists(function_name);
17566 inline bool is_vararg_function(const std::string& vararg_function_name) const
17568 if (!valid())
17569 return false;
17570 else
17571 return local_data().vararg_function_store.symbol_exists(vararg_function_name);
17574 inline bool is_vector(const std::string& vector_name) const
17576 if (!valid())
17577 return false;
17578 else
17579 return local_data().vector_store.symbol_exists(vector_name);
17582 inline std::string get_variable_name(const expression_ptr& ptr) const
17584 return local_data().variable_store.entity_name(ptr);
17587 inline std::string get_vector_name(const vector_holder_ptr& ptr) const
17589 return local_data().vector_store.entity_name(ptr);
17592 #ifndef exprtk_disable_string_capabilities
17593 inline std::string get_stringvar_name(const expression_ptr& ptr) const
17595 return local_data().stringvar_store.entity_name(ptr);
17598 inline std::string get_conststr_stringvar_name(const expression_ptr& ptr) const
17600 return local_data().stringvar_store.entity_name(ptr);
17602 #endif
17604 inline bool valid() const
17606 // Symbol table sanity check.
17607 return control_block_ && control_block_->data_;
17610 inline void load_from(const symbol_table<T>& st)
17613 std::vector<std::string> name_list;
17615 st.local_data().function_store.get_list(name_list);
17617 if (!name_list.empty())
17619 for (std::size_t i = 0; i < name_list.size(); ++i)
17621 exprtk::ifunction<T>& ifunc = *st.get_function(name_list[i]);
17622 add_function(name_list[i],ifunc);
17628 std::vector<std::string> name_list;
17630 st.local_data().vararg_function_store.get_list(name_list);
17632 if (!name_list.empty())
17634 for (std::size_t i = 0; i < name_list.size(); ++i)
17636 exprtk::ivararg_function<T>& ivafunc = *st.get_vararg_function(name_list[i]);
17637 add_function(name_list[i],ivafunc);
17643 std::vector<std::string> name_list;
17645 st.local_data().generic_function_store.get_list(name_list);
17647 if (!name_list.empty())
17649 for (std::size_t i = 0; i < name_list.size(); ++i)
17651 exprtk::igeneric_function<T>& ifunc = *st.get_generic_function(name_list[i]);
17652 add_function(name_list[i],ifunc);
17658 std::vector<std::string> name_list;
17660 st.local_data().string_function_store.get_list(name_list);
17662 if (!name_list.empty())
17664 for (std::size_t i = 0; i < name_list.size(); ++i)
17666 exprtk::igeneric_function<T>& ifunc = *st.get_string_function(name_list[i]);
17667 add_function(name_list[i],ifunc);
17673 std::vector<std::string> name_list;
17675 st.local_data().overload_function_store.get_list(name_list);
17677 if (!name_list.empty())
17679 for (std::size_t i = 0; i < name_list.size(); ++i)
17681 exprtk::igeneric_function<T>& ifunc = *st.get_overload_function(name_list[i]);
17682 add_function(name_list[i],ifunc);
17688 private:
17690 inline bool valid_symbol(const std::string& symbol, const bool check_reserved_symb = true) const
17692 if (symbol.empty())
17693 return false;
17694 else if (!details::is_letter(symbol[0]))
17695 return false;
17696 else if (symbol.size() > 1)
17698 for (std::size_t i = 1; i < symbol.size(); ++i)
17700 if (
17701 !details::is_letter_or_digit(symbol[i]) &&
17702 ('_' != symbol[i])
17705 if (('.' == symbol[i]) && (i < (symbol.size() - 1)))
17706 continue;
17707 else
17708 return false;
17713 return (check_reserved_symb) ? (!local_data().is_reserved_symbol(symbol)) : true;
17716 inline bool valid_function(const std::string& symbol) const
17718 if (symbol.empty())
17719 return false;
17720 else if (!details::is_letter(symbol[0]))
17721 return false;
17722 else if (symbol.size() > 1)
17724 for (std::size_t i = 1; i < symbol.size(); ++i)
17726 if (
17727 !details::is_letter_or_digit(symbol[i]) &&
17728 ('_' != symbol[i])
17731 if (('.' == symbol[i]) && (i < (symbol.size() - 1)))
17732 continue;
17733 else
17734 return false;
17739 return true;
17742 typedef typename control_block::st_data local_data_t;
17744 inline local_data_t& local_data()
17746 return *(control_block_->data_);
17749 inline const local_data_t& local_data() const
17751 return *(control_block_->data_);
17754 control_block* control_block_;
17756 friend class parser<T>;
17759 template <typename T>
17760 class function_compositor;
17762 template <typename T>
17763 class expression
17765 private:
17767 typedef details::expression_node<T>* expression_ptr;
17768 typedef details::vector_holder<T>* vector_holder_ptr;
17769 typedef std::vector<symbol_table<T> > symtab_list_t;
17771 struct control_block
17773 enum data_type
17775 e_unknown ,
17776 e_expr ,
17777 e_vecholder,
17778 e_data ,
17779 e_vecdata ,
17780 e_string
17783 struct data_pack
17785 data_pack()
17786 : pointer(0),
17787 type(e_unknown),
17788 size(0)
17791 data_pack(void* ptr, const data_type dt, const std::size_t sz = 0)
17792 : pointer(ptr),
17793 type(dt),
17794 size(sz)
17797 void* pointer;
17798 data_type type;
17799 std::size_t size;
17802 typedef std::vector<data_pack> local_data_list_t;
17803 typedef results_context<T> results_context_t;
17805 control_block()
17806 : ref_count(0),
17807 expr (0),
17808 results (0),
17809 retinv_null(false),
17810 return_invoked(&retinv_null)
17813 explicit control_block(expression_ptr e)
17814 : ref_count(1),
17815 expr (e),
17816 results (0),
17817 retinv_null(false),
17818 return_invoked(&retinv_null)
17821 ~control_block()
17823 if (expr && details::branch_deletable(expr))
17825 destroy_node(expr);
17828 if (!local_data_list.empty())
17830 for (std::size_t i = 0; i < local_data_list.size(); ++i)
17832 switch (local_data_list[i].type)
17834 case e_expr : delete reinterpret_cast<expression_ptr>(local_data_list[i].pointer);
17835 break;
17837 case e_vecholder : delete reinterpret_cast<vector_holder_ptr>(local_data_list[i].pointer);
17838 break;
17840 case e_data : delete (T*)(local_data_list[i].pointer);
17841 break;
17843 case e_vecdata : delete [] (T*)(local_data_list[i].pointer);
17844 break;
17846 case e_string : delete (std::string*)(local_data_list[i].pointer);
17847 break;
17849 default : break;
17854 if (results)
17856 delete results;
17860 static inline control_block* create(expression_ptr e)
17862 return new control_block(e);
17865 static inline void destroy(control_block*& cntrl_blck)
17867 if (cntrl_blck)
17869 if (
17870 (0 != cntrl_blck->ref_count) &&
17871 (0 == --cntrl_blck->ref_count)
17874 delete cntrl_blck;
17877 cntrl_blck = 0;
17881 std::size_t ref_count;
17882 expression_ptr expr;
17883 local_data_list_t local_data_list;
17884 results_context_t* results;
17885 bool retinv_null;
17886 bool* return_invoked;
17888 friend class function_compositor<T>;
17891 public:
17893 expression()
17894 : control_block_(0)
17896 set_expression(new details::null_node<T>());
17899 expression(const expression<T>& e)
17900 : control_block_ (e.control_block_ ),
17901 symbol_table_list_(e.symbol_table_list_)
17903 control_block_->ref_count++;
17906 explicit expression(const symbol_table<T>& symbol_table)
17907 : control_block_(0)
17909 set_expression(new details::null_node<T>());
17910 symbol_table_list_.push_back(symbol_table);
17913 inline expression<T>& operator=(const expression<T>& e)
17915 if (this != &e)
17917 if (control_block_)
17919 if (
17920 (0 != control_block_->ref_count) &&
17921 (0 == --control_block_->ref_count)
17924 delete control_block_;
17927 control_block_ = 0;
17930 control_block_ = e.control_block_;
17931 control_block_->ref_count++;
17932 symbol_table_list_ = e.symbol_table_list_;
17935 return *this;
17938 inline bool operator==(const expression<T>& e) const
17940 return (this == &e);
17943 inline bool operator!() const
17945 return (
17946 (0 == control_block_ ) ||
17947 (0 == control_block_->expr)
17951 inline expression<T>& release()
17953 control_block::destroy(control_block_);
17955 return (*this);
17958 ~expression()
17960 control_block::destroy(control_block_);
17963 inline T value() const
17965 return control_block_->expr->value();
17968 inline T operator() () const
17970 return value();
17973 inline operator T() const
17975 return value();
17978 inline operator bool() const
17980 return details::is_true(value());
17983 inline void register_symbol_table(symbol_table<T>& st)
17985 symbol_table_list_.push_back(st);
17988 inline const symbol_table<T>& get_symbol_table(const std::size_t& index = 0) const
17990 return symbol_table_list_[index];
17993 inline symbol_table<T>& get_symbol_table(const std::size_t& index = 0)
17995 return symbol_table_list_[index];
17998 typedef results_context<T> results_context_t;
18000 inline const results_context_t& results() const
18002 if (control_block_->results)
18003 return (*control_block_->results);
18004 else
18006 static const results_context_t null_results;
18007 return null_results;
18011 inline bool return_invoked() const
18013 return (*control_block_->return_invoked);
18016 private:
18018 inline symtab_list_t get_symbol_table_list() const
18020 return symbol_table_list_;
18023 inline void set_expression(const expression_ptr expr)
18025 if (expr)
18027 if (control_block_)
18029 if (0 == --control_block_->ref_count)
18031 delete control_block_;
18035 control_block_ = control_block::create(expr);
18039 inline void register_local_var(expression_ptr expr)
18041 if (expr)
18043 if (control_block_)
18045 control_block_->
18046 local_data_list.push_back(
18047 typename expression<T>::control_block::
18048 data_pack(reinterpret_cast<void*>(expr),
18049 control_block::e_expr));
18054 inline void register_local_var(vector_holder_ptr vec_holder)
18056 if (vec_holder)
18058 if (control_block_)
18060 control_block_->
18061 local_data_list.push_back(
18062 typename expression<T>::control_block::
18063 data_pack(reinterpret_cast<void*>(vec_holder),
18064 control_block::e_vecholder));
18069 inline void register_local_data(void* data, const std::size_t& size = 0, const std::size_t data_mode = 0)
18071 if (data)
18073 if (control_block_)
18075 typename control_block::data_type dt = control_block::e_data;
18077 switch (data_mode)
18079 case 0 : dt = control_block::e_data; break;
18080 case 1 : dt = control_block::e_vecdata; break;
18081 case 2 : dt = control_block::e_string; break;
18084 control_block_->
18085 local_data_list.push_back(
18086 typename expression<T>::control_block::
18087 data_pack(reinterpret_cast<void*>(data), dt, size));
18092 inline const typename control_block::local_data_list_t& local_data_list()
18094 if (control_block_)
18096 return control_block_->local_data_list;
18098 else
18100 static typename control_block::local_data_list_t null_local_data_list;
18101 return null_local_data_list;
18105 inline void register_return_results(results_context_t* rc)
18107 if (control_block_ && rc)
18109 control_block_->results = rc;
18113 inline void set_retinvk(bool* retinvk_ptr)
18115 if (control_block_)
18117 control_block_->return_invoked = retinvk_ptr;
18121 control_block* control_block_;
18122 symtab_list_t symbol_table_list_;
18124 friend class parser<T>;
18125 friend class expression_helper<T>;
18126 friend class function_compositor<T>;
18129 template <typename T>
18130 class expression_helper
18132 public:
18134 static inline bool is_constant(const expression<T>& expr)
18136 return details::is_constant_node(expr.control_block_->expr);
18139 static inline bool is_variable(const expression<T>& expr)
18141 return details::is_variable_node(expr.control_block_->expr);
18144 static inline bool is_unary(const expression<T>& expr)
18146 return details::is_unary_node(expr.control_block_->expr);
18149 static inline bool is_binary(const expression<T>& expr)
18151 return details::is_binary_node(expr.control_block_->expr);
18154 static inline bool is_function(const expression<T>& expr)
18156 return details::is_function(expr.control_block_->expr);
18159 static inline bool is_null(const expression<T>& expr)
18161 return details::is_null_node(expr.control_block_->expr);
18165 template <typename T>
18166 inline bool is_valid(const expression<T>& expr)
18168 return !expression_helper<T>::is_null(expr);
18171 namespace parser_error
18173 enum error_mode
18175 e_unknown = 0,
18176 e_syntax = 1,
18177 e_token = 2,
18178 e_numeric = 4,
18179 e_symtab = 5,
18180 e_lexer = 6,
18181 e_helper = 7
18184 struct type
18186 type()
18187 : mode(parser_error::e_unknown),
18188 line_no (0),
18189 column_no(0)
18192 lexer::token token;
18193 error_mode mode;
18194 std::string diagnostic;
18195 std::string src_location;
18196 std::string error_line;
18197 std::size_t line_no;
18198 std::size_t column_no;
18201 inline type make_error(const error_mode mode,
18202 const std::string& diagnostic = "",
18203 const std::string& src_location = "")
18205 type t;
18206 t.mode = mode;
18207 t.token.type = lexer::token::e_error;
18208 t.diagnostic = diagnostic;
18209 t.src_location = src_location;
18210 exprtk_debug(("%s\n",diagnostic .c_str()));
18211 return t;
18214 inline type make_error(const error_mode mode,
18215 const lexer::token& tk,
18216 const std::string& diagnostic = "",
18217 const std::string& src_location = "")
18219 type t;
18220 t.mode = mode;
18221 t.token = tk;
18222 t.diagnostic = diagnostic;
18223 t.src_location = src_location;
18224 exprtk_debug(("%s\n",diagnostic .c_str()));
18225 return t;
18228 inline std::string to_str(error_mode mode)
18230 switch (mode)
18232 case e_unknown : return std::string("Unknown Error");
18233 case e_syntax : return std::string("Syntax Error" );
18234 case e_token : return std::string("Token Error" );
18235 case e_numeric : return std::string("Numeric Error");
18236 case e_symtab : return std::string("Symbol Error" );
18237 case e_lexer : return std::string("Lexer Error" );
18238 case e_helper : return std::string("Helper Error" );
18239 default : return std::string("Unknown Error");
18243 inline bool update_error(type& error, const std::string& expression)
18245 if (
18246 expression.empty() ||
18247 (error.token.position > expression.size()) ||
18248 (std::numeric_limits<std::size_t>::max() == error.token.position)
18251 return false;
18254 std::size_t error_line_start = 0;
18256 for (std::size_t i = error.token.position; i > 0; --i)
18258 const details::char_t c = expression[i];
18260 if (('\n' == c) || ('\r' == c))
18262 error_line_start = i + 1;
18263 break;
18267 std::size_t next_nl_position = std::min(expression.size(),
18268 expression.find_first_of('\n',error.token.position + 1));
18270 error.column_no = error.token.position - error_line_start;
18271 error.error_line = expression.substr(error_line_start,
18272 next_nl_position - error_line_start);
18274 error.line_no = 0;
18276 for (std::size_t i = 0; i < next_nl_position; ++i)
18278 if ('\n' == expression[i])
18279 ++error.line_no;
18282 return true;
18285 inline void dump_error(const type& error)
18287 printf("Position: %02d Type: [%s] Msg: %s\n",
18288 static_cast<int>(error.token.position),
18289 exprtk::parser_error::to_str(error.mode).c_str(),
18290 error.diagnostic.c_str());
18294 namespace details
18296 template <typename Parser>
18297 inline void disable_type_checking(Parser& p)
18299 p.state_.type_check_enabled = false;
18303 template <typename T>
18304 class parser : public lexer::parser_helper
18306 private:
18308 enum precedence_level
18310 e_level00,
18311 e_level01,
18312 e_level02,
18313 e_level03,
18314 e_level04,
18315 e_level05,
18316 e_level06,
18317 e_level07,
18318 e_level08,
18319 e_level09,
18320 e_level10,
18321 e_level11,
18322 e_level12,
18323 e_level13,
18324 e_level14
18327 typedef const T& cref_t;
18328 typedef const T const_t;
18329 typedef ifunction <T> F;
18330 typedef ivararg_function <T> VAF;
18331 typedef igeneric_function <T> GF;
18332 typedef ifunction <T> ifunction_t;
18333 typedef ivararg_function <T> ivararg_function_t;
18334 typedef igeneric_function <T> igeneric_function_t;
18335 typedef details::expression_node <T> expression_node_t;
18336 typedef details::literal_node <T> literal_node_t;
18337 typedef details::unary_node <T> unary_node_t;
18338 typedef details::binary_node <T> binary_node_t;
18339 typedef details::trinary_node <T> trinary_node_t;
18340 typedef details::quaternary_node <T> quaternary_node_t;
18341 typedef details::conditional_node<T> conditional_node_t;
18342 typedef details::cons_conditional_node<T> cons_conditional_node_t;
18343 typedef details::while_loop_node <T> while_loop_node_t;
18344 typedef details::repeat_until_loop_node<T> repeat_until_loop_node_t;
18345 typedef details::for_loop_node <T> for_loop_node_t;
18346 #ifndef exprtk_disable_break_continue
18347 typedef details::while_loop_bc_node <T> while_loop_bc_node_t;
18348 typedef details::repeat_until_loop_bc_node<T> repeat_until_loop_bc_node_t;
18349 typedef details::for_loop_bc_node<T> for_loop_bc_node_t;
18350 #endif
18351 typedef details::switch_node <T> switch_node_t;
18352 typedef details::variable_node <T> variable_node_t;
18353 typedef details::vector_elem_node<T> vector_elem_node_t;
18354 typedef details::rebasevector_elem_node<T> rebasevector_elem_node_t;
18355 typedef details::rebasevector_celem_node<T> rebasevector_celem_node_t;
18356 typedef details::vector_node <T> vector_node_t;
18357 typedef details::range_pack <T> range_t;
18358 #ifndef exprtk_disable_string_capabilities
18359 typedef details::stringvar_node <T> stringvar_node_t;
18360 typedef details::string_literal_node<T> string_literal_node_t;
18361 typedef details::string_range_node <T> string_range_node_t;
18362 typedef details::const_string_range_node<T> const_string_range_node_t;
18363 typedef details::generic_string_range_node<T> generic_string_range_node_t;
18364 typedef details::string_concat_node <T> string_concat_node_t;
18365 typedef details::assignment_string_node<T> assignment_string_node_t;
18366 typedef details::assignment_string_range_node<T> assignment_string_range_node_t;
18367 typedef details::conditional_string_node<T> conditional_string_node_t;
18368 typedef details::cons_conditional_str_node<T> cons_conditional_str_node_t;
18369 #endif
18370 typedef details::assignment_node<T> assignment_node_t;
18371 typedef details::assignment_vec_elem_node <T> assignment_vec_elem_node_t;
18372 typedef details::assignment_rebasevec_elem_node <T> assignment_rebasevec_elem_node_t;
18373 typedef details::assignment_rebasevec_celem_node<T> assignment_rebasevec_celem_node_t;
18374 typedef details::assignment_vec_node <T> assignment_vec_node_t;
18375 typedef details::assignment_vecvec_node <T> assignment_vecvec_node_t;
18376 typedef details::scand_node<T> scand_node_t;
18377 typedef details::scor_node<T> scor_node_t;
18378 typedef lexer::token token_t;
18379 typedef expression_node_t* expression_node_ptr;
18380 typedef expression<T> expression_t;
18381 typedef symbol_table<T> symbol_table_t;
18382 typedef typename expression<T>::symtab_list_t symbol_table_list_t;
18383 typedef details::vector_holder<T>* vector_holder_ptr;
18385 typedef typename details::functor_t<T> functor_t;
18386 typedef typename functor_t::qfunc_t quaternary_functor_t;
18387 typedef typename functor_t::tfunc_t trinary_functor_t;
18388 typedef typename functor_t::bfunc_t binary_functor_t;
18389 typedef typename functor_t::ufunc_t unary_functor_t;
18391 typedef details::operator_type operator_t;
18393 typedef std::map<operator_t, unary_functor_t> unary_op_map_t;
18394 typedef std::map<operator_t, binary_functor_t> binary_op_map_t;
18395 typedef std::map<operator_t,trinary_functor_t> trinary_op_map_t;
18397 typedef std::map<std::string,std::pair<trinary_functor_t ,operator_t> > sf3_map_t;
18398 typedef std::map<std::string,std::pair<quaternary_functor_t,operator_t> > sf4_map_t;
18400 typedef std::map<binary_functor_t,operator_t> inv_binary_op_map_t;
18401 typedef std::multimap<std::string,details::base_operation_t,details::ilesscompare> base_ops_map_t;
18402 typedef std::set<std::string,details::ilesscompare> disabled_func_set_t;
18404 typedef details::T0oT1_define<T, cref_t, cref_t> vov_t;
18405 typedef details::T0oT1_define<T, const_t, cref_t> cov_t;
18406 typedef details::T0oT1_define<T, cref_t, const_t> voc_t;
18408 typedef details::T0oT1oT2_define<T, cref_t, cref_t, cref_t> vovov_t;
18409 typedef details::T0oT1oT2_define<T, cref_t, cref_t, const_t> vovoc_t;
18410 typedef details::T0oT1oT2_define<T, cref_t, const_t, cref_t> vocov_t;
18411 typedef details::T0oT1oT2_define<T, const_t, cref_t, cref_t> covov_t;
18412 typedef details::T0oT1oT2_define<T, const_t, cref_t, const_t> covoc_t;
18413 typedef details::T0oT1oT2_define<T, const_t, const_t, cref_t> cocov_t;
18414 typedef details::T0oT1oT2_define<T, cref_t, const_t, const_t> vococ_t;
18416 typedef details::T0oT1oT2oT3_define<T, cref_t, cref_t, cref_t, cref_t> vovovov_t;
18417 typedef details::T0oT1oT2oT3_define<T, cref_t, cref_t, cref_t, const_t> vovovoc_t;
18418 typedef details::T0oT1oT2oT3_define<T, cref_t, cref_t, const_t, cref_t> vovocov_t;
18419 typedef details::T0oT1oT2oT3_define<T, cref_t, const_t, cref_t, cref_t> vocovov_t;
18420 typedef details::T0oT1oT2oT3_define<T, const_t, cref_t, cref_t, cref_t> covovov_t;
18422 typedef details::T0oT1oT2oT3_define<T, const_t, cref_t, const_t, cref_t> covocov_t;
18423 typedef details::T0oT1oT2oT3_define<T, cref_t, const_t, cref_t, const_t> vocovoc_t;
18424 typedef details::T0oT1oT2oT3_define<T, const_t, cref_t, cref_t, const_t> covovoc_t;
18425 typedef details::T0oT1oT2oT3_define<T, cref_t, const_t, const_t, cref_t> vococov_t;
18427 typedef results_context<T> results_context_t;
18429 typedef parser_helper prsrhlpr_t;
18431 struct scope_element
18433 enum element_type
18435 e_none ,
18436 e_variable,
18437 e_vector ,
18438 e_vecelem ,
18439 e_string
18442 typedef details::vector_holder<T> vector_holder_t;
18443 typedef variable_node_t* variable_node_ptr;
18444 typedef vector_holder_t* vector_holder_ptr;
18445 typedef expression_node_t* expression_node_ptr;
18446 #ifndef exprtk_disable_string_capabilities
18447 typedef stringvar_node_t* stringvar_node_ptr;
18448 #endif
18450 scope_element()
18451 : name("???"),
18452 size (std::numeric_limits<std::size_t>::max()),
18453 index(std::numeric_limits<std::size_t>::max()),
18454 depth(std::numeric_limits<std::size_t>::max()),
18455 ref_count(0),
18456 ip_index (0),
18457 type (e_none),
18458 active(false),
18459 data (0),
18460 var_node(0),
18461 vec_node(0)
18462 #ifndef exprtk_disable_string_capabilities
18463 ,str_node(0)
18464 #endif
18467 bool operator < (const scope_element& se) const
18469 if (ip_index < se.ip_index)
18470 return true;
18471 else if (ip_index > se.ip_index)
18472 return false;
18473 else if (depth < se.depth)
18474 return true;
18475 else if (depth > se.depth)
18476 return false;
18477 else if (index < se.index)
18478 return true;
18479 else if (index > se.index)
18480 return false;
18481 else
18482 return (name < se.name);
18485 void clear()
18487 name = "???";
18488 size = std::numeric_limits<std::size_t>::max();
18489 index = std::numeric_limits<std::size_t>::max();
18490 depth = std::numeric_limits<std::size_t>::max();
18491 type = e_none;
18492 active = false;
18493 ref_count = 0;
18494 ip_index = 0;
18495 data = 0;
18496 var_node = 0;
18497 vec_node = 0;
18498 #ifndef exprtk_disable_string_capabilities
18499 str_node = 0;
18500 #endif
18503 std::string name;
18504 std::size_t size;
18505 std::size_t index;
18506 std::size_t depth;
18507 std::size_t ref_count;
18508 std::size_t ip_index;
18509 element_type type;
18510 bool active;
18511 void* data;
18512 expression_node_ptr var_node;
18513 vector_holder_ptr vec_node;
18514 #ifndef exprtk_disable_string_capabilities
18515 stringvar_node_ptr str_node;
18516 #endif
18519 class scope_element_manager
18521 public:
18523 typedef expression_node_t* expression_node_ptr;
18524 typedef variable_node_t* variable_node_ptr;
18525 typedef parser<T> parser_t;
18527 explicit scope_element_manager(parser<T>& p)
18528 : parser_(p),
18529 input_param_cnt_(0)
18532 inline std::size_t size() const
18534 return element_.size();
18537 inline bool empty() const
18539 return element_.empty();
18542 inline scope_element& get_element(const std::size_t& index)
18544 if (index < element_.size())
18545 return element_[index];
18546 else
18547 return null_element_;
18550 inline scope_element& get_element(const std::string& var_name,
18551 const std::size_t index = std::numeric_limits<std::size_t>::max())
18553 const std::size_t current_depth = parser_.state_.scope_depth;
18555 for (std::size_t i = 0; i < element_.size(); ++i)
18557 scope_element& se = element_[i];
18559 if (se.depth > current_depth)
18560 continue;
18561 else if (
18562 details::imatch(se.name, var_name) &&
18563 (se.index == index)
18565 return se;
18568 return null_element_;
18571 inline scope_element& get_active_element(const std::string& var_name,
18572 const std::size_t index = std::numeric_limits<std::size_t>::max())
18574 const std::size_t current_depth = parser_.state_.scope_depth;
18576 for (std::size_t i = 0; i < element_.size(); ++i)
18578 scope_element& se = element_[i];
18580 if (se.depth > current_depth)
18581 continue;
18582 else if (
18583 details::imatch(se.name, var_name) &&
18584 (se.index == index) &&
18585 (se.active)
18587 return se;
18590 return null_element_;
18593 inline bool add_element(const scope_element& se)
18595 for (std::size_t i = 0; i < element_.size(); ++i)
18597 scope_element& cse = element_[i];
18599 if (
18600 details::imatch(cse.name, se.name) &&
18601 (cse.depth <= se.depth) &&
18602 (cse.index == se.index) &&
18603 (cse.size == se.size ) &&
18604 (cse.type == se.type ) &&
18605 (cse.active)
18607 return false;
18610 element_.push_back(se);
18611 std::sort(element_.begin(),element_.end());
18613 return true;
18616 inline void deactivate(const std::size_t& scope_depth)
18618 exprtk_debug(("deactivate() - Scope depth: %d\n",
18619 static_cast<int>(parser_.state_.scope_depth)));
18621 for (std::size_t i = 0; i < element_.size(); ++i)
18623 scope_element& se = element_[i];
18625 if (se.active && (se.depth >= scope_depth))
18627 exprtk_debug(("deactivate() - element[%02d] '%s'\n",
18628 static_cast<int>(i),
18629 se.name.c_str()));
18631 se.active = false;
18636 inline void free_element(scope_element& se)
18638 #ifdef exprtk_enable_debugging
18639 exprtk_debug(("free_element() - se[%s]\n", se.name.c_str()));
18640 #endif
18642 switch (se.type)
18644 case scope_element::e_variable : if (se.data ) delete (T*) se.data;
18645 if (se.var_node) delete se.var_node;
18646 break;
18648 case scope_element::e_vector : if (se.data ) delete[] (T*) se.data;
18649 if (se.vec_node) delete se.vec_node;
18650 break;
18652 case scope_element::e_vecelem : if (se.var_node) delete se.var_node;
18653 break;
18655 #ifndef exprtk_disable_string_capabilities
18656 case scope_element::e_string : if (se.data ) delete (std::string*) se.data;
18657 if (se.str_node) delete se.str_node;
18658 break;
18659 #endif
18661 default : return;
18664 se.clear();
18667 inline void cleanup()
18669 for (std::size_t i = 0; i < element_.size(); ++i)
18671 free_element(element_[i]);
18674 element_.clear();
18676 input_param_cnt_ = 0;
18679 inline std::size_t next_ip_index()
18681 return ++input_param_cnt_;
18684 inline expression_node_ptr get_variable(const T& v)
18686 for (std::size_t i = 0; i < element_.size(); ++i)
18688 scope_element& se = element_[i];
18690 if (
18691 se.active &&
18692 se.var_node &&
18693 details::is_variable_node(se.var_node)
18696 variable_node_ptr vn = reinterpret_cast<variable_node_ptr>(se.var_node);
18698 if (&(vn->ref()) == (&v))
18700 return se.var_node;
18705 return expression_node_ptr(0);
18708 private:
18710 scope_element_manager& operator=(const scope_element_manager&);
18712 parser_t& parser_;
18713 std::vector<scope_element> element_;
18714 scope_element null_element_;
18715 std::size_t input_param_cnt_;
18718 class scope_handler
18720 public:
18722 typedef parser<T> parser_t;
18724 explicit scope_handler(parser<T>& p)
18725 : parser_(p)
18727 parser_.state_.scope_depth++;
18728 #ifdef exprtk_enable_debugging
18729 const std::string depth(2 * parser_.state_.scope_depth,'-');
18730 exprtk_debug(("%s> Scope Depth: %02d\n",
18731 depth.c_str(),
18732 static_cast<int>(parser_.state_.scope_depth)));
18733 #endif
18736 ~scope_handler()
18738 parser_.sem_.deactivate(parser_.state_.scope_depth);
18739 parser_.state_.scope_depth--;
18740 #ifdef exprtk_enable_debugging
18741 const std::string depth(2 * parser_.state_.scope_depth,'-');
18742 exprtk_debug(("<%s Scope Depth: %02d\n",
18743 depth.c_str(),
18744 static_cast<int>(parser_.state_.scope_depth)));
18745 #endif
18748 private:
18750 scope_handler& operator=(const scope_handler&);
18752 parser_t& parser_;
18755 struct symtab_store
18757 symbol_table_list_t symtab_list_;
18759 typedef typename symbol_table_t::local_data_t local_data_t;
18760 typedef typename symbol_table_t::variable_ptr variable_ptr;
18761 typedef typename symbol_table_t::function_ptr function_ptr;
18762 #ifndef exprtk_disable_string_capabilities
18763 typedef typename symbol_table_t::stringvar_ptr stringvar_ptr;
18764 #endif
18765 typedef typename symbol_table_t::vector_holder_ptr vector_holder_ptr;
18766 typedef typename symbol_table_t::vararg_function_ptr vararg_function_ptr;
18767 typedef typename symbol_table_t::generic_function_ptr generic_function_ptr;
18769 inline bool empty() const
18771 return symtab_list_.empty();
18774 inline void clear()
18776 symtab_list_.clear();
18779 inline bool valid() const
18781 if (!empty())
18783 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
18785 if (symtab_list_[i].valid())
18786 return true;
18790 return false;
18793 inline bool valid_symbol(const std::string& symbol) const
18795 if (!symtab_list_.empty())
18796 return symtab_list_[0].valid_symbol(symbol);
18797 else
18798 return false;
18801 inline bool valid_function_name(const std::string& symbol) const
18803 if (!symtab_list_.empty())
18804 return symtab_list_[0].valid_function(symbol);
18805 else
18806 return false;
18809 inline variable_ptr get_variable(const std::string& variable_name) const
18811 if (!valid_symbol(variable_name))
18812 return reinterpret_cast<variable_ptr>(0);
18814 variable_ptr result = reinterpret_cast<variable_ptr>(0);
18816 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
18818 if (!symtab_list_[i].valid())
18819 continue;
18820 else
18821 result = local_data(i)
18822 .variable_store.get(variable_name);
18824 if (result) break;
18827 return result;
18830 inline variable_ptr get_variable(const T& var_ref) const
18832 variable_ptr result = reinterpret_cast<variable_ptr>(0);
18834 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
18836 if (!symtab_list_[i].valid())
18837 continue;
18838 else
18839 result = local_data(i).variable_store
18840 .get_from_varptr(reinterpret_cast<const void*>(&var_ref));
18842 if (result) break;
18845 return result;
18848 #ifndef exprtk_disable_string_capabilities
18849 inline stringvar_ptr get_stringvar(const std::string& string_name) const
18851 if (!valid_symbol(string_name))
18852 return reinterpret_cast<stringvar_ptr>(0);
18854 stringvar_ptr result = reinterpret_cast<stringvar_ptr>(0);
18856 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
18858 if (!symtab_list_[i].valid())
18859 continue;
18860 else
18861 result = local_data(i)
18862 .stringvar_store.get(string_name);
18864 if (result) break;
18867 return result;
18869 #endif
18871 inline function_ptr get_function(const std::string& function_name) const
18873 if (!valid_function_name(function_name))
18874 return reinterpret_cast<function_ptr>(0);
18876 function_ptr result = reinterpret_cast<function_ptr>(0);
18878 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
18880 if (!symtab_list_[i].valid())
18881 continue;
18882 else
18883 result = local_data(i)
18884 .function_store.get(function_name);
18886 if (result) break;
18889 return result;
18892 inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const
18894 if (!valid_function_name(vararg_function_name))
18895 return reinterpret_cast<vararg_function_ptr>(0);
18897 vararg_function_ptr result = reinterpret_cast<vararg_function_ptr>(0);
18899 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
18901 if (!symtab_list_[i].valid())
18902 continue;
18903 else
18904 result = local_data(i)
18905 .vararg_function_store.get(vararg_function_name);
18907 if (result) break;
18910 return result;
18913 inline generic_function_ptr get_generic_function(const std::string& function_name) const
18915 if (!valid_function_name(function_name))
18916 return reinterpret_cast<generic_function_ptr>(0);
18918 generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0);
18920 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
18922 if (!symtab_list_[i].valid())
18923 continue;
18924 else
18925 result = local_data(i)
18926 .generic_function_store.get(function_name);
18928 if (result) break;
18931 return result;
18934 inline generic_function_ptr get_string_function(const std::string& function_name) const
18936 if (!valid_function_name(function_name))
18937 return reinterpret_cast<generic_function_ptr>(0);
18939 generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0);
18941 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
18943 if (!symtab_list_[i].valid())
18944 continue;
18945 else
18946 result =
18947 local_data(i).string_function_store.get(function_name);
18949 if (result) break;
18952 return result;
18955 inline generic_function_ptr get_overload_function(const std::string& function_name) const
18957 if (!valid_function_name(function_name))
18958 return reinterpret_cast<generic_function_ptr>(0);
18960 generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0);
18962 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
18964 if (!symtab_list_[i].valid())
18965 continue;
18966 else
18967 result =
18968 local_data(i).overload_function_store.get(function_name);
18970 if (result) break;
18973 return result;
18976 inline vector_holder_ptr get_vector(const std::string& vector_name) const
18978 if (!valid_symbol(vector_name))
18979 return reinterpret_cast<vector_holder_ptr>(0);
18981 vector_holder_ptr result = reinterpret_cast<vector_holder_ptr>(0);
18983 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
18985 if (!symtab_list_[i].valid())
18986 continue;
18987 else
18988 result =
18989 local_data(i).vector_store.get(vector_name);
18991 if (result) break;
18994 return result;
18997 inline bool is_constant_node(const std::string& symbol_name) const
18999 if (!valid_symbol(symbol_name))
19000 return false;
19002 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19004 if (!symtab_list_[i].valid())
19005 continue;
19006 else if (local_data(i).variable_store.is_constant(symbol_name))
19007 return true;
19010 return false;
19013 #ifndef exprtk_disable_string_capabilities
19014 inline bool is_constant_string(const std::string& symbol_name) const
19016 if (!valid_symbol(symbol_name))
19017 return false;
19019 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19021 if (!symtab_list_[i].valid())
19022 continue;
19023 else if (!local_data(i).stringvar_store.symbol_exists(symbol_name))
19024 continue;
19025 else if ( local_data(i).stringvar_store.is_constant(symbol_name))
19026 return true;
19029 return false;
19031 #endif
19033 inline bool symbol_exists(const std::string& symbol) const
19035 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19037 if (!symtab_list_[i].valid())
19038 continue;
19039 else if (symtab_list_[i].symbol_exists(symbol))
19040 return true;
19043 return false;
19046 inline bool is_variable(const std::string& variable_name) const
19048 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19050 if (!symtab_list_[i].valid())
19051 continue;
19052 else if (
19053 symtab_list_[i].local_data().variable_store
19054 .symbol_exists(variable_name)
19056 return true;
19059 return false;
19062 #ifndef exprtk_disable_string_capabilities
19063 inline bool is_stringvar(const std::string& stringvar_name) const
19065 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19067 if (!symtab_list_[i].valid())
19068 continue;
19069 else if (
19070 symtab_list_[i].local_data().stringvar_store
19071 .symbol_exists(stringvar_name)
19073 return true;
19076 return false;
19079 inline bool is_conststr_stringvar(const std::string& symbol_name) const
19081 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19083 if (!symtab_list_[i].valid())
19084 continue;
19085 else if (
19086 symtab_list_[i].local_data().stringvar_store
19087 .symbol_exists(symbol_name)
19090 return (
19091 local_data(i).stringvar_store.symbol_exists(symbol_name) ||
19092 local_data(i).stringvar_store.is_constant (symbol_name)
19098 return false;
19100 #endif
19102 inline bool is_function(const std::string& function_name) const
19104 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19106 if (!symtab_list_[i].valid())
19107 continue;
19108 else if (
19109 local_data(i).vararg_function_store
19110 .symbol_exists(function_name)
19112 return true;
19115 return false;
19118 inline bool is_vararg_function(const std::string& vararg_function_name) const
19120 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19122 if (!symtab_list_[i].valid())
19123 continue;
19124 else if (
19125 local_data(i).vararg_function_store
19126 .symbol_exists(vararg_function_name)
19128 return true;
19131 return false;
19134 inline bool is_vector(const std::string& vector_name) const
19136 for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19138 if (!symtab_list_[i].valid())
19139 continue;
19140 else if (
19141 local_data(i).vector_store
19142 .symbol_exists(vector_name)
19144 return true;
19147 return false;
19150 inline std::string get_variable_name(const expression_node_ptr& ptr) const
19152 return local_data().variable_store.entity_name(ptr);
19155 inline std::string get_vector_name(const vector_holder_ptr& ptr) const
19157 return local_data().vector_store.entity_name(ptr);
19160 #ifndef exprtk_disable_string_capabilities
19161 inline std::string get_stringvar_name(const expression_node_ptr& ptr) const
19163 return local_data().stringvar_store.entity_name(ptr);
19166 inline std::string get_conststr_stringvar_name(const expression_node_ptr& ptr) const
19168 return local_data().stringvar_store.entity_name(ptr);
19170 #endif
19172 inline local_data_t& local_data(const std::size_t& index = 0)
19174 return symtab_list_[index].local_data();
19177 inline const local_data_t& local_data(const std::size_t& index = 0) const
19179 return symtab_list_[index].local_data();
19182 inline symbol_table_t& get_symbol_table(const std::size_t& index = 0)
19184 return symtab_list_[index];
19188 struct parser_state
19190 parser_state()
19191 : type_check_enabled(true)
19193 reset();
19196 void reset()
19198 parsing_return_stmt = false;
19199 parsing_break_stmt = false;
19200 return_stmt_present = false;
19201 side_effect_present = false;
19202 scope_depth = 0;
19205 #ifndef exprtk_enable_debugging
19206 void activate_side_effect(const std::string&)
19207 #else
19208 void activate_side_effect(const std::string& source)
19209 #endif
19211 if (!side_effect_present)
19213 side_effect_present = true;
19215 exprtk_debug(("activate_side_effect() - caller: %s\n",source.c_str()));
19219 bool parsing_return_stmt;
19220 bool parsing_break_stmt;
19221 bool return_stmt_present;
19222 bool side_effect_present;
19223 bool type_check_enabled;
19224 std::size_t scope_depth;
19227 public:
19229 struct unknown_symbol_resolver
19232 enum usr_symbol_type
19234 e_usr_unknown_type = 0,
19235 e_usr_variable_type = 1,
19236 e_usr_constant_type = 2
19239 enum usr_mode
19241 e_usrmode_default = 0,
19242 e_usrmode_extended = 1
19245 usr_mode mode;
19247 unknown_symbol_resolver(const usr_mode m = e_usrmode_default)
19248 : mode(m)
19251 virtual ~unknown_symbol_resolver()
19254 virtual bool process(const std::string& /*unknown_symbol*/,
19255 usr_symbol_type& st,
19256 T& default_value,
19257 std::string& error_message)
19259 if (e_usrmode_default != mode)
19260 return false;
19262 st = e_usr_variable_type;
19263 default_value = T(0);
19264 error_message.clear();
19266 return true;
19269 virtual bool process(const std::string& /* unknown_symbol */,
19270 symbol_table_t& /* symbol_table */,
19271 std::string& /* error_message */)
19273 return false;
19277 enum collect_type
19279 e_ct_none = 0,
19280 e_ct_variables = 1,
19281 e_ct_functions = 2,
19282 e_ct_assignments = 4
19285 enum symbol_type
19287 e_st_unknown = 0,
19288 e_st_variable = 1,
19289 e_st_vector = 2,
19290 e_st_vecelem = 3,
19291 e_st_string = 4,
19292 e_st_function = 5,
19293 e_st_local_variable = 6,
19294 e_st_local_vector = 7,
19295 e_st_local_string = 8
19298 class dependent_entity_collector
19300 public:
19302 typedef std::pair<std::string,symbol_type> symbol_t;
19303 typedef std::vector<symbol_t> symbol_list_t;
19305 dependent_entity_collector(const std::size_t options = e_ct_none)
19306 : options_(options),
19307 collect_variables_ ((options_ & e_ct_variables ) == e_ct_variables ),
19308 collect_functions_ ((options_ & e_ct_functions ) == e_ct_functions ),
19309 collect_assignments_((options_ & e_ct_assignments) == e_ct_assignments),
19310 return_present_ (false),
19311 final_stmt_return_(false)
19314 template <typename Allocator,
19315 template <typename, typename> class Sequence>
19316 inline std::size_t symbols(Sequence<symbol_t,Allocator>& symbols_list)
19318 if (!collect_variables_ && !collect_functions_)
19319 return 0;
19320 else if (symbol_name_list_.empty())
19321 return 0;
19323 for (std::size_t i = 0; i < symbol_name_list_.size(); ++i)
19325 details::case_normalise(symbol_name_list_[i].first);
19328 std::sort(symbol_name_list_.begin(),symbol_name_list_.end());
19330 std::unique_copy(symbol_name_list_.begin(),
19331 symbol_name_list_.end (),
19332 std::back_inserter(symbols_list));
19334 return symbols_list.size();
19337 template <typename Allocator,
19338 template <typename, typename> class Sequence>
19339 inline std::size_t assignment_symbols(Sequence<symbol_t,Allocator>& assignment_list)
19341 if (!collect_assignments_)
19342 return 0;
19343 else if (assignment_name_list_.empty())
19344 return 0;
19346 for (std::size_t i = 0; i < assignment_name_list_.size(); ++i)
19348 details::case_normalise(assignment_name_list_[i].first);
19351 std::sort(assignment_name_list_.begin(),assignment_name_list_.end());
19353 std::unique_copy(assignment_name_list_.begin(),
19354 assignment_name_list_.end (),
19355 std::back_inserter(assignment_list));
19357 return assignment_list.size();
19360 void clear()
19362 symbol_name_list_ .clear();
19363 assignment_name_list_.clear();
19364 retparam_list_ .clear();
19365 return_present_ = false;
19366 final_stmt_return_ = false;
19369 bool& collect_variables()
19371 return collect_variables_;
19374 bool& collect_functions()
19376 return collect_functions_;
19379 bool& collect_assignments()
19381 return collect_assignments_;
19384 bool return_present() const
19386 return return_present_;
19389 bool final_stmt_return() const
19391 return final_stmt_return_;
19394 typedef std::vector<std::string> retparam_list_t;
19396 retparam_list_t return_param_type_list() const
19398 return retparam_list_;
19401 private:
19403 inline void add_symbol(const std::string& symbol, const symbol_type st)
19405 switch (st)
19407 case e_st_variable :
19408 case e_st_vector :
19409 case e_st_string :
19410 case e_st_local_variable :
19411 case e_st_local_vector :
19412 case e_st_local_string : if (collect_variables_)
19413 symbol_name_list_
19414 .push_back(std::make_pair(symbol, st));
19415 break;
19417 case e_st_function : if (collect_functions_)
19418 symbol_name_list_
19419 .push_back(std::make_pair(symbol, st));
19420 break;
19422 default : return;
19426 inline void add_assignment(const std::string& symbol, const symbol_type st)
19428 switch (st)
19430 case e_st_variable :
19431 case e_st_vector :
19432 case e_st_string : if (collect_assignments_)
19433 assignment_name_list_
19434 .push_back(std::make_pair(symbol, st));
19435 break;
19437 default : return;
19441 std::size_t options_;
19442 bool collect_variables_;
19443 bool collect_functions_;
19444 bool collect_assignments_;
19445 bool return_present_;
19446 bool final_stmt_return_;
19447 symbol_list_t symbol_name_list_;
19448 symbol_list_t assignment_name_list_;
19449 retparam_list_t retparam_list_;
19451 friend class parser<T>;
19454 class settings_store
19456 private:
19458 typedef std::set<std::string,details::ilesscompare> disabled_entity_set_t;
19459 typedef disabled_entity_set_t::iterator des_itr_t;
19461 public:
19463 enum settings_compilation_options
19465 e_unknown = 0,
19466 e_replacer = 1,
19467 e_joiner = 2,
19468 e_numeric_check = 4,
19469 e_bracket_check = 8,
19470 e_sequence_check = 16,
19471 e_commutative_check = 32,
19472 e_strength_reduction = 64,
19473 e_disable_vardef = 128,
19474 e_collect_vars = 256,
19475 e_collect_funcs = 512,
19476 e_collect_assings = 1024,
19477 e_disable_usr_on_rsrvd = 2048,
19478 e_disable_zero_return = 4096
19481 enum settings_base_funcs
19483 e_bf_unknown = 0,
19484 e_bf_abs , e_bf_acos , e_bf_acosh , e_bf_asin ,
19485 e_bf_asinh , e_bf_atan , e_bf_atan2 , e_bf_atanh ,
19486 e_bf_avg , e_bf_ceil , e_bf_clamp , e_bf_cos ,
19487 e_bf_cosh , e_bf_cot , e_bf_csc , e_bf_equal ,
19488 e_bf_erf , e_bf_erfc , e_bf_exp , e_bf_expm1 ,
19489 e_bf_floor , e_bf_frac , e_bf_hypot , e_bf_iclamp ,
19490 e_bf_like , e_bf_log , e_bf_log10 , e_bf_log1p ,
19491 e_bf_log2 , e_bf_logn , e_bf_mand , e_bf_max ,
19492 e_bf_min , e_bf_mod , e_bf_mor , e_bf_mul ,
19493 e_bf_ncdf , e_bf_pow , e_bf_root , e_bf_round ,
19494 e_bf_roundn , e_bf_sec , e_bf_sgn , e_bf_sin ,
19495 e_bf_sinc , e_bf_sinh , e_bf_sqrt , e_bf_sum ,
19496 e_bf_swap , e_bf_tan , e_bf_tanh , e_bf_trunc ,
19497 e_bf_not_equal , e_bf_inrange , e_bf_deg2grad , e_bf_deg2rad,
19498 e_bf_rad2deg , e_bf_grad2deg
19501 enum settings_control_structs
19503 e_ctrl_unknown = 0,
19504 e_ctrl_ifelse,
19505 e_ctrl_switch,
19506 e_ctrl_for_loop,
19507 e_ctrl_while_loop,
19508 e_ctrl_repeat_loop,
19509 e_ctrl_return
19512 enum settings_logic_opr
19514 e_logic_unknown = 0,
19515 e_logic_and, e_logic_nand, e_logic_nor,
19516 e_logic_not, e_logic_or, e_logic_xnor,
19517 e_logic_xor, e_logic_scand, e_logic_scor
19520 enum settings_arithmetic_opr
19522 e_arith_unknown = 0,
19523 e_arith_add, e_arith_sub, e_arith_mul,
19524 e_arith_div, e_arith_mod, e_arith_pow
19527 enum settings_assignment_opr
19529 e_assign_unknown = 0,
19530 e_assign_assign, e_assign_addass, e_assign_subass,
19531 e_assign_mulass, e_assign_divass, e_assign_modass
19534 enum settings_inequality_opr
19536 e_ineq_unknown = 0,
19537 e_ineq_lt, e_ineq_lte, e_ineq_eq,
19538 e_ineq_equal, e_ineq_ne, e_ineq_nequal,
19539 e_ineq_gte, e_ineq_gt
19542 static const std::size_t compile_all_opts = e_replacer +
19543 e_joiner +
19544 e_numeric_check +
19545 e_bracket_check +
19546 e_sequence_check +
19547 e_commutative_check +
19548 e_strength_reduction;
19550 settings_store(const std::size_t compile_options = compile_all_opts)
19552 load_compile_options(compile_options);
19555 settings_store& enable_all_base_functions()
19557 disabled_func_set_.clear();
19558 return (*this);
19561 settings_store& enable_all_control_structures()
19563 disabled_ctrl_set_.clear();
19564 return (*this);
19567 settings_store& enable_all_logic_ops()
19569 disabled_logic_set_.clear();
19570 return (*this);
19573 settings_store& enable_all_arithmetic_ops()
19575 disabled_arithmetic_set_.clear();
19576 return (*this);
19579 settings_store& enable_all_assignment_ops()
19581 disabled_assignment_set_.clear();
19582 return (*this);
19585 settings_store& enable_all_inequality_ops()
19587 disabled_inequality_set_.clear();
19588 return (*this);
19591 settings_store& enable_local_vardef()
19593 disable_vardef_ = false;
19594 return (*this);
19597 settings_store& disable_all_base_functions()
19599 std::copy(details::base_function_list,
19600 details::base_function_list + details::base_function_list_size,
19601 std::insert_iterator<disabled_entity_set_t>
19602 (disabled_func_set_, disabled_func_set_.begin()));
19603 return (*this);
19606 settings_store& disable_all_control_structures()
19608 std::copy(details::cntrl_struct_list,
19609 details::cntrl_struct_list + details::cntrl_struct_list_size,
19610 std::insert_iterator<disabled_entity_set_t>
19611 (disabled_ctrl_set_, disabled_ctrl_set_.begin()));
19612 return (*this);
19615 settings_store& disable_all_logic_ops()
19617 std::copy(details::logic_ops_list,
19618 details::logic_ops_list + details::logic_ops_list_size,
19619 std::insert_iterator<disabled_entity_set_t>
19620 (disabled_logic_set_, disabled_logic_set_.begin()));
19621 return (*this);
19624 settings_store& disable_all_arithmetic_ops()
19626 std::copy(details::arithmetic_ops_list,
19627 details::arithmetic_ops_list + details::arithmetic_ops_list_size,
19628 std::insert_iterator<disabled_entity_set_t>
19629 (disabled_arithmetic_set_, disabled_arithmetic_set_.begin()));
19630 return (*this);
19633 settings_store& disable_all_assignment_ops()
19635 std::copy(details::assignment_ops_list,
19636 details::assignment_ops_list + details::assignment_ops_list_size,
19637 std::insert_iterator<disabled_entity_set_t>
19638 (disabled_assignment_set_, disabled_assignment_set_.begin()));
19639 return (*this);
19642 settings_store& disable_all_inequality_ops()
19644 std::copy(details::inequality_ops_list,
19645 details::inequality_ops_list + details::inequality_ops_list_size,
19646 std::insert_iterator<disabled_entity_set_t>
19647 (disabled_inequality_set_, disabled_inequality_set_.begin()));
19648 return (*this);
19651 settings_store& disable_local_vardef()
19653 disable_vardef_ = true;
19654 return (*this);
19657 bool replacer_enabled () const { return enable_replacer_; }
19658 bool commutative_check_enabled () const { return enable_commutative_check_; }
19659 bool joiner_enabled () const { return enable_joiner_; }
19660 bool numeric_check_enabled () const { return enable_numeric_check_; }
19661 bool bracket_check_enabled () const { return enable_bracket_check_; }
19662 bool sequence_check_enabled () const { return enable_sequence_check_; }
19663 bool strength_reduction_enabled () const { return enable_strength_reduction_; }
19664 bool collect_variables_enabled () const { return enable_collect_vars_; }
19665 bool collect_functions_enabled () const { return enable_collect_funcs_; }
19666 bool collect_assignments_enabled() const { return enable_collect_assings_; }
19667 bool vardef_disabled () const { return disable_vardef_; }
19668 bool rsrvd_sym_usr_disabled () const { return disable_rsrvd_sym_usr_; }
19669 bool zero_return_disabled () const { return disable_zero_return_; }
19671 bool function_enabled(const std::string& function_name) const
19673 if (disabled_func_set_.empty())
19674 return true;
19675 else
19676 return (disabled_func_set_.end() == disabled_func_set_.find(function_name));
19679 bool control_struct_enabled(const std::string& control_struct) const
19681 if (disabled_ctrl_set_.empty())
19682 return true;
19683 else
19684 return (disabled_ctrl_set_.end() == disabled_ctrl_set_.find(control_struct));
19687 bool logic_enabled(const std::string& logic_operation) const
19689 if (disabled_logic_set_.empty())
19690 return true;
19691 else
19692 return (disabled_logic_set_.end() == disabled_logic_set_.find(logic_operation));
19695 bool arithmetic_enabled(const details::operator_type& arithmetic_operation) const
19697 if (disabled_logic_set_.empty())
19698 return true;
19699 else
19700 return disabled_arithmetic_set_.end() == disabled_arithmetic_set_
19701 .find(arith_opr_to_string(arithmetic_operation));
19704 bool assignment_enabled(const details::operator_type& assignment) const
19706 if (disabled_assignment_set_.empty())
19707 return true;
19708 else
19709 return disabled_assignment_set_.end() == disabled_assignment_set_
19710 .find(assign_opr_to_string(assignment));
19713 bool inequality_enabled(const details::operator_type& inequality) const
19715 if (disabled_inequality_set_.empty())
19716 return true;
19717 else
19718 return disabled_inequality_set_.end() == disabled_inequality_set_
19719 .find(inequality_opr_to_string(inequality));
19722 bool function_disabled(const std::string& function_name) const
19724 if (disabled_func_set_.empty())
19725 return false;
19726 else
19727 return (disabled_func_set_.end() != disabled_func_set_.find(function_name));
19730 bool control_struct_disabled(const std::string& control_struct) const
19732 if (disabled_ctrl_set_.empty())
19733 return false;
19734 else
19735 return (disabled_ctrl_set_.end() != disabled_ctrl_set_.find(control_struct));
19738 bool logic_disabled(const std::string& logic_operation) const
19740 if (disabled_logic_set_.empty())
19741 return false;
19742 else
19743 return (disabled_logic_set_.end() != disabled_logic_set_.find(logic_operation));
19746 bool assignment_disabled(const details::operator_type assignment_operation) const
19748 if (disabled_assignment_set_.empty())
19749 return false;
19750 else
19751 return disabled_assignment_set_.end() != disabled_assignment_set_
19752 .find(assign_opr_to_string(assignment_operation));
19755 bool logic_disabled(const details::operator_type logic_operation) const
19757 if (disabled_logic_set_.empty())
19758 return false;
19759 else
19760 return disabled_logic_set_.end() != disabled_logic_set_
19761 .find(logic_opr_to_string(logic_operation));
19764 bool arithmetic_disabled(const details::operator_type arithmetic_operation) const
19766 if (disabled_arithmetic_set_.empty())
19767 return false;
19768 else
19769 return disabled_arithmetic_set_.end() != disabled_arithmetic_set_
19770 .find(arith_opr_to_string(arithmetic_operation));
19773 bool inequality_disabled(const details::operator_type& inequality) const
19775 if (disabled_inequality_set_.empty())
19776 return false;
19777 else
19778 return disabled_inequality_set_.end() != disabled_inequality_set_
19779 .find(inequality_opr_to_string(inequality));
19782 settings_store& disable_base_function(settings_base_funcs bf)
19784 if (
19785 (e_bf_unknown != bf) &&
19786 (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1))
19789 disabled_func_set_.insert(details::base_function_list[bf - 1]);
19792 return (*this);
19795 settings_store& disable_control_structure(settings_control_structs ctrl_struct)
19797 if (
19798 (e_ctrl_unknown != ctrl_struct) &&
19799 (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1))
19802 disabled_ctrl_set_.insert(details::cntrl_struct_list[ctrl_struct - 1]);
19805 return (*this);
19808 settings_store& disable_logic_operation(settings_logic_opr logic)
19810 if (
19811 (e_logic_unknown != logic) &&
19812 (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1))
19815 disabled_logic_set_.insert(details::logic_ops_list[logic - 1]);
19818 return (*this);
19821 settings_store& disable_arithmetic_operation(settings_arithmetic_opr arithmetic)
19823 if (
19824 (e_arith_unknown != arithmetic) &&
19825 (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1))
19828 disabled_arithmetic_set_.insert(details::arithmetic_ops_list[arithmetic - 1]);
19831 return (*this);
19834 settings_store& disable_assignment_operation(settings_assignment_opr assignment)
19836 if (
19837 (e_assign_unknown != assignment) &&
19838 (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1))
19841 disabled_assignment_set_.insert(details::assignment_ops_list[assignment - 1]);
19844 return (*this);
19847 settings_store& disable_inequality_operation(settings_inequality_opr inequality)
19849 if (
19850 (e_ineq_unknown != inequality) &&
19851 (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1))
19854 disabled_inequality_set_.insert(details::inequality_ops_list[inequality - 1]);
19857 return (*this);
19860 settings_store& enable_base_function(settings_base_funcs bf)
19862 if (
19863 (e_bf_unknown != bf) &&
19864 (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1))
19867 const des_itr_t itr = disabled_func_set_.find(details::base_function_list[bf - 1]);
19869 if (disabled_func_set_.end() != itr)
19871 disabled_func_set_.erase(itr);
19875 return (*this);
19878 settings_store& enable_control_structure(settings_control_structs ctrl_struct)
19880 if (
19881 (e_ctrl_unknown != ctrl_struct) &&
19882 (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1))
19885 const des_itr_t itr = disabled_ctrl_set_.find(details::cntrl_struct_list[ctrl_struct - 1]);
19887 if (disabled_ctrl_set_.end() != itr)
19889 disabled_ctrl_set_.erase(itr);
19893 return (*this);
19896 settings_store& enable_logic_operation(settings_logic_opr logic)
19898 if (
19899 (e_logic_unknown != logic) &&
19900 (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1))
19903 const des_itr_t itr = disabled_logic_set_.find(details::logic_ops_list[logic - 1]);
19905 if (disabled_logic_set_.end() != itr)
19907 disabled_logic_set_.erase(itr);
19911 return (*this);
19914 settings_store& enable_arithmetic_operation(settings_arithmetic_opr arithmetic)
19916 if (
19917 (e_arith_unknown != arithmetic) &&
19918 (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1))
19921 const des_itr_t itr = disabled_arithmetic_set_.find(details::arithmetic_ops_list[arithmetic - 1]);
19923 if (disabled_arithmetic_set_.end() != itr)
19925 disabled_arithmetic_set_.erase(itr);
19929 return (*this);
19932 settings_store& enable_assignment_operation(settings_assignment_opr assignment)
19934 if (
19935 (e_assign_unknown != assignment) &&
19936 (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1))
19939 const des_itr_t itr = disabled_assignment_set_.find(details::assignment_ops_list[assignment - 1]);
19941 if (disabled_assignment_set_.end() != itr)
19943 disabled_assignment_set_.erase(itr);
19947 return (*this);
19950 settings_store& enable_inequality_operation(settings_inequality_opr inequality)
19952 if (
19953 (e_ineq_unknown != inequality) &&
19954 (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1))
19957 const des_itr_t itr = disabled_inequality_set_.find(details::inequality_ops_list[inequality - 1]);
19959 if (disabled_inequality_set_.end() != itr)
19961 disabled_inequality_set_.erase(itr);
19965 return (*this);
19968 private:
19970 void load_compile_options(const std::size_t compile_options)
19972 enable_replacer_ = (compile_options & e_replacer ) == e_replacer;
19973 enable_joiner_ = (compile_options & e_joiner ) == e_joiner;
19974 enable_numeric_check_ = (compile_options & e_numeric_check ) == e_numeric_check;
19975 enable_bracket_check_ = (compile_options & e_bracket_check ) == e_bracket_check;
19976 enable_sequence_check_ = (compile_options & e_sequence_check ) == e_sequence_check;
19977 enable_commutative_check_ = (compile_options & e_commutative_check ) == e_commutative_check;
19978 enable_strength_reduction_ = (compile_options & e_strength_reduction ) == e_strength_reduction;
19979 enable_collect_vars_ = (compile_options & e_collect_vars ) == e_collect_vars;
19980 enable_collect_funcs_ = (compile_options & e_collect_funcs ) == e_collect_funcs;
19981 enable_collect_assings_ = (compile_options & e_collect_assings ) == e_collect_assings;
19982 disable_vardef_ = (compile_options & e_disable_vardef ) == e_disable_vardef;
19983 disable_rsrvd_sym_usr_ = (compile_options & e_disable_usr_on_rsrvd) == e_disable_usr_on_rsrvd;
19984 disable_zero_return_ = (compile_options & e_disable_zero_return ) == e_disable_zero_return;
19987 std::string assign_opr_to_string(details::operator_type opr) const
19989 switch (opr)
19991 case details::e_assign : return ":=";
19992 case details::e_addass : return "+=";
19993 case details::e_subass : return "-=";
19994 case details::e_mulass : return "*=";
19995 case details::e_divass : return "/=";
19996 case details::e_modass : return "%=";
19997 default : return "";
20001 std::string arith_opr_to_string(details::operator_type opr) const
20003 switch (opr)
20005 case details::e_add : return "+";
20006 case details::e_sub : return "-";
20007 case details::e_mul : return "*";
20008 case details::e_div : return "/";
20009 case details::e_mod : return "%";
20010 default : return "";
20014 std::string inequality_opr_to_string(details::operator_type opr) const
20016 switch (opr)
20018 case details::e_lt : return "<";
20019 case details::e_lte : return "<=";
20020 case details::e_eq : return "==";
20021 case details::e_equal : return "=";
20022 case details::e_ne : return "!=";
20023 case details::e_nequal: return "<>";
20024 case details::e_gte : return ">=";
20025 case details::e_gt : return ">";
20026 default : return "";
20030 std::string logic_opr_to_string(details::operator_type opr) const
20032 switch (opr)
20034 case details::e_and : return "and" ;
20035 case details::e_or : return "or" ;
20036 case details::e_xor : return "xor" ;
20037 case details::e_nand : return "nand";
20038 case details::e_nor : return "nor" ;
20039 case details::e_xnor : return "xnor";
20040 case details::e_notl : return "not" ;
20041 default : return "" ;
20045 bool enable_replacer_;
20046 bool enable_joiner_;
20047 bool enable_numeric_check_;
20048 bool enable_bracket_check_;
20049 bool enable_sequence_check_;
20050 bool enable_commutative_check_;
20051 bool enable_strength_reduction_;
20052 bool enable_collect_vars_;
20053 bool enable_collect_funcs_;
20054 bool enable_collect_assings_;
20055 bool disable_vardef_;
20056 bool disable_rsrvd_sym_usr_;
20057 bool disable_zero_return_;
20059 disabled_entity_set_t disabled_func_set_ ;
20060 disabled_entity_set_t disabled_ctrl_set_ ;
20061 disabled_entity_set_t disabled_logic_set_;
20062 disabled_entity_set_t disabled_arithmetic_set_;
20063 disabled_entity_set_t disabled_assignment_set_;
20064 disabled_entity_set_t disabled_inequality_set_;
20066 friend class parser<T>;
20069 typedef settings_store settings_t;
20071 parser(const settings_t& settings = settings_t())
20072 : settings_(settings),
20073 resolve_unknown_symbol_(false),
20074 results_context_(0),
20075 unknown_symbol_resolver_(reinterpret_cast<unknown_symbol_resolver*>(0)),
20076 #ifdef _MSC_VER
20077 #pragma warning(push)
20078 #pragma warning (disable:4355)
20079 #endif
20080 sem_(*this),
20081 #ifdef _MSC_VER
20082 #pragma warning(pop)
20083 #endif
20084 operator_joiner_2_(2),
20085 operator_joiner_3_(3)
20087 init_precompilation();
20089 load_operations_map (base_ops_map_ );
20090 load_unary_operations_map (unary_op_map_ );
20091 load_binary_operations_map (binary_op_map_ );
20092 load_inv_binary_operations_map(inv_binary_op_map_);
20093 load_sf3_map (sf3_map_ );
20094 load_sf4_map (sf4_map_ );
20096 expression_generator_.init_synthesize_map();
20097 expression_generator_.set_parser(*this);
20098 expression_generator_.set_uom(unary_op_map_);
20099 expression_generator_.set_bom(binary_op_map_);
20100 expression_generator_.set_ibom(inv_binary_op_map_);
20101 expression_generator_.set_sf3m(sf3_map_);
20102 expression_generator_.set_sf4m(sf4_map_);
20103 expression_generator_.set_strength_reduction_state(settings_.strength_reduction_enabled());
20106 ~parser()
20109 inline void init_precompilation()
20111 if (settings_.collect_variables_enabled())
20112 dec_.collect_variables() = true;
20114 if (settings_.collect_functions_enabled())
20115 dec_.collect_functions() = true;
20117 if (settings_.collect_assignments_enabled())
20118 dec_.collect_assignments() = true;
20120 if (settings_.replacer_enabled())
20122 symbol_replacer_.clear();
20123 symbol_replacer_.add_replace("true" , "1", lexer::token::e_number);
20124 symbol_replacer_.add_replace("false", "0", lexer::token::e_number);
20125 helper_assembly_.token_modifier_list.clear();
20126 helper_assembly_.register_modifier(&symbol_replacer_);
20129 if (settings_.commutative_check_enabled())
20131 for (std::size_t i = 0; i < details::reserved_words_size; ++i)
20133 commutative_inserter_.ignore_symbol(details::reserved_words[i]);
20136 helper_assembly_.token_inserter_list.clear();
20137 helper_assembly_.register_inserter(&commutative_inserter_);
20140 if (settings_.joiner_enabled())
20142 helper_assembly_.token_joiner_list.clear();
20143 helper_assembly_.register_joiner(&operator_joiner_2_);
20144 helper_assembly_.register_joiner(&operator_joiner_3_);
20147 if (
20148 settings_.numeric_check_enabled () ||
20149 settings_.bracket_check_enabled () ||
20150 settings_.sequence_check_enabled()
20153 helper_assembly_.token_scanner_list.clear();
20155 if (settings_.numeric_check_enabled())
20157 helper_assembly_.register_scanner(&numeric_checker_);
20160 if (settings_.bracket_check_enabled())
20162 helper_assembly_.register_scanner(&bracket_checker_);
20165 if (settings_.sequence_check_enabled())
20167 helper_assembly_.register_scanner(&sequence_validator_ );
20168 helper_assembly_.register_scanner(&sequence_validator_3tkns_);
20173 inline bool compile(const std::string& expression_string, expression<T>& expr)
20175 state_ .reset();
20176 error_list_ .clear();
20177 brkcnt_list_ .clear();
20178 synthesis_error_.clear();
20179 sem_ .cleanup();
20181 return_cleanup();
20183 expression_generator_.set_allocator(node_allocator_);
20185 if (expression_string.empty())
20187 set_error(
20188 make_error(parser_error::e_syntax,
20189 "ERR000 - Empty expression!",
20190 exprtk_error_location));
20192 return false;
20195 if (!init(expression_string))
20197 process_lexer_errors();
20198 return false;
20201 if (lexer().empty())
20203 set_error(
20204 make_error(parser_error::e_syntax,
20205 "ERR001 - Empty expression!",
20206 exprtk_error_location));
20208 return false;
20211 if (!run_assemblies())
20213 return false;
20216 symtab_store_.symtab_list_ = expr.get_symbol_table_list();
20217 dec_.clear();
20219 lexer().begin();
20221 next_token();
20223 expression_node_ptr e = parse_corpus();
20225 if ((0 != e) && (token_t::e_eof == current_token().type))
20227 bool* retinvk_ptr = 0;
20229 if (state_.return_stmt_present)
20231 dec_.return_present_ = true;
20233 e = expression_generator_
20234 .return_envelope(e, results_context_, retinvk_ptr);
20237 expr.set_expression(e);
20238 expr.set_retinvk(retinvk_ptr);
20240 register_local_vars(expr);
20241 register_return_results(expr);
20243 return !(!expr);
20245 else
20247 if (error_list_.empty())
20249 set_error(
20250 make_error(parser_error::e_syntax,
20251 current_token(),
20252 "ERR002 - Invalid expression encountered",
20253 exprtk_error_location));
20256 if ((0 != e) && branch_deletable(e))
20258 destroy_node(e);
20261 dec_.clear ();
20262 sem_.cleanup ();
20263 return_cleanup();
20265 return false;
20269 inline expression_t compile(const std::string& expression_string, symbol_table_t& symtab)
20271 expression_t expr;
20273 expr.register_symbol_table(symtab);
20275 compile(expression_string,expr);
20277 return expr;
20280 void process_lexer_errors()
20282 for (std::size_t i = 0; i < lexer().size(); ++i)
20284 if (lexer()[i].is_error())
20286 std::string diagnostic = "ERR003 - ";
20288 switch (lexer()[i].type)
20290 case lexer::token::e_error : diagnostic += "General token error";
20291 break;
20293 case lexer::token::e_err_symbol : diagnostic += "Symbol error";
20294 break;
20296 case lexer::token::e_err_number : diagnostic += "Invalid numeric token";
20297 break;
20299 case lexer::token::e_err_string : diagnostic += "Invalid string token";
20300 break;
20302 case lexer::token::e_err_sfunc : diagnostic += "Invalid special function token";
20303 break;
20305 default : diagnostic += "Unknown compiler error";
20308 set_error(
20309 make_error(parser_error::e_lexer,
20310 lexer()[i],
20311 diagnostic + ": " + lexer()[i].value,
20312 exprtk_error_location));
20317 inline bool run_assemblies()
20319 if (settings_.commutative_check_enabled())
20321 helper_assembly_.run_inserters(lexer());
20324 if (settings_.joiner_enabled())
20326 helper_assembly_.run_joiners(lexer());
20329 if (settings_.replacer_enabled())
20331 helper_assembly_.run_modifiers(lexer());
20334 if (
20335 settings_.numeric_check_enabled () ||
20336 settings_.bracket_check_enabled () ||
20337 settings_.sequence_check_enabled()
20340 if (!helper_assembly_.run_scanners(lexer()))
20342 if (helper_assembly_.error_token_scanner)
20344 lexer::helper::bracket_checker* bracket_checker_ptr = 0;
20345 lexer::helper::numeric_checker* numeric_checker_ptr = 0;
20346 lexer::helper::sequence_validator* sequence_validator_ptr = 0;
20347 lexer::helper::sequence_validator_3tokens* sequence_validator3_ptr = 0;
20349 if (0 != (bracket_checker_ptr = dynamic_cast<lexer::helper::bracket_checker*>(helper_assembly_.error_token_scanner)))
20351 set_error(
20352 make_error(parser_error::e_token,
20353 bracket_checker_ptr->error_token(),
20354 "ERR004 - Mismatched brackets: '" + bracket_checker_ptr->error_token().value + "'",
20355 exprtk_error_location));
20357 else if (0 != (numeric_checker_ptr = dynamic_cast<lexer::helper::numeric_checker*>(helper_assembly_.error_token_scanner)))
20359 for (std::size_t i = 0; i < numeric_checker_ptr->error_count(); ++i)
20361 lexer::token error_token = lexer()[numeric_checker_ptr->error_index(i)];
20363 set_error(
20364 make_error(parser_error::e_token,
20365 error_token,
20366 "ERR005 - Invalid numeric token: '" + error_token.value + "'",
20367 exprtk_error_location));
20370 if (numeric_checker_ptr->error_count())
20372 numeric_checker_ptr->clear_errors();
20375 else if (0 != (sequence_validator_ptr = dynamic_cast<lexer::helper::sequence_validator*>(helper_assembly_.error_token_scanner)))
20377 for (std::size_t i = 0; i < sequence_validator_ptr->error_count(); ++i)
20379 std::pair<lexer::token,lexer::token> error_token = sequence_validator_ptr->error(i);
20381 set_error(
20382 make_error(parser_error::e_token,
20383 error_token.first,
20384 "ERR006 - Invalid token sequence: '" +
20385 error_token.first.value + "' and '" +
20386 error_token.second.value + "'",
20387 exprtk_error_location));
20390 if (sequence_validator_ptr->error_count())
20392 sequence_validator_ptr->clear_errors();
20395 else if (0 != (sequence_validator3_ptr = dynamic_cast<lexer::helper::sequence_validator_3tokens*>(helper_assembly_.error_token_scanner)))
20397 for (std::size_t i = 0; i < sequence_validator3_ptr->error_count(); ++i)
20399 std::pair<lexer::token,lexer::token> error_token = sequence_validator3_ptr->error(i);
20401 set_error(
20402 make_error(parser_error::e_token,
20403 error_token.first,
20404 "ERR007 - Invalid token sequence: '" +
20405 error_token.first.value + "' and '" +
20406 error_token.second.value + "'",
20407 exprtk_error_location));
20410 if (sequence_validator3_ptr->error_count())
20412 sequence_validator3_ptr->clear_errors();
20417 return false;
20421 return true;
20424 inline settings_store& settings()
20426 return settings_;
20429 inline parser_error::type get_error(const std::size_t& index) const
20431 if (index < error_list_.size())
20432 return error_list_[index];
20433 else
20434 throw std::invalid_argument("parser::get_error() - Invalid error index specificed");
20437 inline std::string error() const
20439 if (!error_list_.empty())
20441 return error_list_[0].diagnostic;
20443 else
20444 return std::string("No Error");
20447 inline std::size_t error_count() const
20449 return error_list_.size();
20452 inline dependent_entity_collector& dec()
20454 return dec_;
20457 inline bool replace_symbol(const std::string& old_symbol, const std::string& new_symbol)
20459 if (!settings_.replacer_enabled())
20460 return false;
20461 else if (details::is_reserved_word(old_symbol))
20462 return false;
20463 else
20464 return symbol_replacer_.add_replace(old_symbol,new_symbol,lexer::token::e_symbol);
20467 inline bool remove_replace_symbol(const std::string& symbol)
20469 if (!settings_.replacer_enabled())
20470 return false;
20471 else if (details::is_reserved_word(symbol))
20472 return false;
20473 else
20474 return symbol_replacer_.remove(symbol);
20477 inline void enable_unknown_symbol_resolver(unknown_symbol_resolver* usr = reinterpret_cast<unknown_symbol_resolver*>(0))
20479 resolve_unknown_symbol_ = true;
20481 if (usr)
20482 unknown_symbol_resolver_ = usr;
20483 else
20484 unknown_symbol_resolver_ = &default_usr_;
20487 inline void enable_unknown_symbol_resolver(unknown_symbol_resolver& usr)
20489 enable_unknown_symbol_resolver(&usr);
20492 inline void disable_unknown_symbol_resolver()
20494 resolve_unknown_symbol_ = false;
20495 unknown_symbol_resolver_ = &default_usr_;
20498 private:
20500 inline bool valid_base_operation(const std::string& symbol) const
20502 const std::size_t length = symbol.size();
20504 if (
20505 (length < 3) || // Shortest base op symbol length
20506 (length > 9) // Longest base op symbol length
20508 return false;
20509 else
20510 return settings_.function_enabled(symbol) &&
20511 (base_ops_map_.end() != base_ops_map_.find(symbol));
20514 inline bool valid_vararg_operation(const std::string& symbol) const
20516 static const std::string s_sum = "sum" ;
20517 static const std::string s_mul = "mul" ;
20518 static const std::string s_avg = "avg" ;
20519 static const std::string s_min = "min" ;
20520 static const std::string s_max = "max" ;
20521 static const std::string s_mand = "mand";
20522 static const std::string s_mor = "mor" ;
20523 static const std::string s_multi = "~" ;
20524 static const std::string s_mswitch = "[*]" ;
20526 return
20528 details::imatch(symbol,s_sum ) ||
20529 details::imatch(symbol,s_mul ) ||
20530 details::imatch(symbol,s_avg ) ||
20531 details::imatch(symbol,s_min ) ||
20532 details::imatch(symbol,s_max ) ||
20533 details::imatch(symbol,s_mand ) ||
20534 details::imatch(symbol,s_mor ) ||
20535 details::imatch(symbol,s_multi ) ||
20536 details::imatch(symbol,s_mswitch)
20537 ) &&
20538 settings_.function_enabled(symbol);
20541 bool is_invalid_logic_operation(const details::operator_type operation) const
20543 return settings_.logic_disabled(operation);
20546 bool is_invalid_arithmetic_operation(const details::operator_type operation) const
20548 return settings_.arithmetic_disabled(operation);
20551 bool is_invalid_assignment_operation(const details::operator_type operation) const
20553 return settings_.assignment_disabled(operation);
20556 bool is_invalid_inequality_operation(const details::operator_type operation) const
20558 return settings_.inequality_disabled(operation);
20561 #ifdef exprtk_enable_debugging
20562 inline void next_token()
20564 const std::string ct_str = current_token().value;
20565 parser_helper::next_token();
20566 const std::string depth(2 * state_.scope_depth,' ');
20567 exprtk_debug(("%s"
20568 "prev[%s] --> curr[%s]\n",
20569 depth.c_str(),
20570 ct_str.c_str(),
20571 current_token().value.c_str()));
20573 #endif
20575 inline expression_node_ptr parse_corpus()
20577 std::vector<expression_node_ptr> arg_list;
20578 std::vector<bool> side_effect_list;
20580 scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
20582 lexer::token begin_token;
20583 lexer::token end_token;
20585 for ( ; ; )
20587 state_.side_effect_present = false;
20589 begin_token = current_token();
20591 expression_node_ptr arg = parse_expression();
20593 if (0 == arg)
20595 if (error_list_.empty())
20597 set_error(
20598 make_error(parser_error::e_syntax,
20599 current_token(),
20600 "ERR008 - Invalid expression encountered",
20601 exprtk_error_location));
20604 return error_node();
20606 else
20608 arg_list.push_back(arg);
20610 side_effect_list.push_back(state_.side_effect_present);
20612 end_token = current_token();
20614 const std::string sub_expr = construct_subexpr(begin_token, end_token);
20616 exprtk_debug(("parse_corpus(%02d) Subexpr: %s\n",
20617 static_cast<int>(arg_list.size() - 1),
20618 sub_expr.c_str()));
20620 exprtk_debug(("parse_corpus(%02d) - Side effect present: %s\n",
20621 static_cast<int>(arg_list.size() - 1),
20622 state_.side_effect_present ? "true" : "false"));
20624 exprtk_debug(("-------------------------------------------------\n"));
20627 if (lexer().finished())
20628 break;
20629 else if (token_is(token_t::e_eof,prsrhlpr_t::e_hold))
20631 if (lexer().finished())
20632 break;
20633 else
20634 next_token();
20638 if (
20639 !arg_list.empty() &&
20640 is_return_node(arg_list.back())
20643 dec_.final_stmt_return_ = true;
20646 const expression_node_ptr result = simplify(arg_list,side_effect_list);
20648 sdd.delete_ptr = (0 == result);
20650 return result;
20653 std::string construct_subexpr(lexer::token& begin_token, lexer::token& end_token)
20655 std::string result = lexer().substr(begin_token.position,end_token.position);
20657 for (std::size_t i = 0; i < result.size(); ++i)
20659 if (details::is_whitespace(result[i])) result[i] = ' ';
20662 return result;
20665 static const precedence_level default_precedence = e_level00;
20667 struct state_t
20669 inline void set(const precedence_level& l,
20670 const precedence_level& r,
20671 const details::operator_type& o)
20673 left = l;
20674 right = r;
20675 operation = o;
20678 inline void reset()
20680 left = e_level00;
20681 right = e_level00;
20682 operation = details::e_default;
20685 precedence_level left;
20686 precedence_level right;
20687 details::operator_type operation;
20690 inline expression_node_ptr parse_expression(precedence_level precedence = e_level00)
20692 expression_node_ptr expression = parse_branch(precedence);
20694 if (0 == expression)
20696 return error_node();
20699 bool break_loop = false;
20701 state_t current_state;
20703 for ( ; ; )
20705 current_state.reset();
20707 switch (current_token().type)
20709 case token_t::e_assign : current_state.set(e_level00,e_level00, details::e_assign); break;
20710 case token_t::e_addass : current_state.set(e_level00,e_level00, details::e_addass); break;
20711 case token_t::e_subass : current_state.set(e_level00,e_level00, details::e_subass); break;
20712 case token_t::e_mulass : current_state.set(e_level00,e_level00, details::e_mulass); break;
20713 case token_t::e_divass : current_state.set(e_level00,e_level00, details::e_divass); break;
20714 case token_t::e_modass : current_state.set(e_level00,e_level00, details::e_modass); break;
20715 case token_t::e_swap : current_state.set(e_level00,e_level00, details::e_swap ); break;
20716 case token_t::e_lt : current_state.set(e_level05,e_level06, details:: e_lt); break;
20717 case token_t::e_lte : current_state.set(e_level05,e_level06, details:: e_lte); break;
20718 case token_t::e_eq : current_state.set(e_level05,e_level06, details:: e_eq); break;
20719 case token_t::e_ne : current_state.set(e_level05,e_level06, details:: e_ne); break;
20720 case token_t::e_gte : current_state.set(e_level05,e_level06, details:: e_gte); break;
20721 case token_t::e_gt : current_state.set(e_level05,e_level06, details:: e_gt); break;
20722 case token_t::e_add : current_state.set(e_level07,e_level08, details:: e_add); break;
20723 case token_t::e_sub : current_state.set(e_level07,e_level08, details:: e_sub); break;
20724 case token_t::e_div : current_state.set(e_level10,e_level11, details:: e_div); break;
20725 case token_t::e_mul : current_state.set(e_level10,e_level11, details:: e_mul); break;
20726 case token_t::e_mod : current_state.set(e_level10,e_level11, details:: e_mod); break;
20727 case token_t::e_pow : current_state.set(e_level12,e_level12, details:: e_pow); break;
20728 default : if (token_t::e_symbol == current_token().type)
20730 static const std::string s_and = "and";
20731 static const std::string s_nand = "nand";
20732 static const std::string s_or = "or";
20733 static const std::string s_nor = "nor";
20734 static const std::string s_xor = "xor";
20735 static const std::string s_xnor = "xnor";
20736 static const std::string s_in = "in";
20737 static const std::string s_like = "like";
20738 static const std::string s_ilike = "ilike";
20739 static const std::string s_and1 = "&";
20740 static const std::string s_or1 = "|";
20741 static const std::string s_not = "not";
20743 if (details::imatch(current_token().value,s_and))
20745 current_state.set(e_level03, e_level04, details::e_and);
20746 break;
20748 else if (details::imatch(current_token().value,s_and1))
20750 #ifndef exprtk_disable_sc_andor
20751 current_state.set(e_level03, e_level04, details::e_scand);
20752 #else
20753 current_state.set(e_level03, e_level04, details::e_and);
20754 #endif
20755 break;
20757 else if (details::imatch(current_token().value,s_nand))
20759 current_state.set(e_level03, e_level04, details::e_nand);
20760 break;
20762 else if (details::imatch(current_token().value,s_or))
20764 current_state.set(e_level01, e_level02, details::e_or);
20765 break;
20767 else if (details::imatch(current_token().value,s_or1))
20769 #ifndef exprtk_disable_sc_andor
20770 current_state.set(e_level01, e_level02, details::e_scor);
20771 #else
20772 current_state.set(e_level01, e_level02, details::e_or);
20773 #endif
20774 break;
20776 else if (details::imatch(current_token().value,s_nor))
20778 current_state.set(e_level01, e_level02, details::e_nor);
20779 break;
20781 else if (details::imatch(current_token().value,s_xor))
20783 current_state.set(e_level01, e_level02, details::e_xor);
20784 break;
20786 else if (details::imatch(current_token().value,s_xnor))
20788 current_state.set(e_level01, e_level02, details::e_xnor);
20789 break;
20791 else if (details::imatch(current_token().value,s_in))
20793 current_state.set(e_level04, e_level04, details::e_in);
20794 break;
20796 else if (details::imatch(current_token().value,s_like))
20798 current_state.set(e_level04, e_level04, details::e_like);
20799 break;
20801 else if (details::imatch(current_token().value,s_ilike))
20803 current_state.set(e_level04, e_level04, details::e_ilike);
20804 break;
20806 else if (details::imatch(current_token().value,s_not))
20808 break;
20812 break_loop = true;
20815 if (break_loop)
20817 parse_pending_string_rangesize(expression);
20818 break;
20820 else if (current_state.left < precedence)
20821 break;
20823 const lexer::token prev_token = current_token();
20825 next_token();
20827 expression_node_ptr right_branch = error_node();
20828 expression_node_ptr new_expression = error_node();
20830 if (is_invalid_logic_operation(current_state.operation))
20832 free_node(node_allocator_,expression);
20834 set_error(
20835 make_error(parser_error::e_syntax,
20836 prev_token,
20837 "ERR009 - Invalid or disabled logic operation '" + details::to_str(current_state.operation) + "'",
20838 exprtk_error_location));
20840 return error_node();
20842 else if (is_invalid_arithmetic_operation(current_state.operation))
20844 free_node(node_allocator_,expression);
20846 set_error(
20847 make_error(parser_error::e_syntax,
20848 prev_token,
20849 "ERR010 - Invalid or disabled arithmetic operation '" + details::to_str(current_state.operation) + "'",
20850 exprtk_error_location));
20852 return error_node();
20854 else if (is_invalid_inequality_operation(current_state.operation))
20856 free_node(node_allocator_,expression);
20858 set_error(
20859 make_error(parser_error::e_syntax,
20860 prev_token,
20861 "ERR011 - Invalid inequality operation '" + details::to_str(current_state.operation) + "'",
20862 exprtk_error_location));
20864 return error_node();
20866 else if (is_invalid_assignment_operation(current_state.operation))
20868 free_node(node_allocator_,expression);
20870 set_error(
20871 make_error(parser_error::e_syntax,
20872 prev_token,
20873 "ERR012 - Invalid or disabled assignment operation '" + details::to_str(current_state.operation) + "'",
20874 exprtk_error_location));
20876 return error_node();
20879 if (0 != (right_branch = parse_expression(current_state.right)))
20881 if (
20882 details::is_return_node( expression) ||
20883 details::is_return_node(right_branch)
20886 free_node(node_allocator_, expression);
20887 free_node(node_allocator_, right_branch);
20889 set_error(
20890 make_error(parser_error::e_syntax,
20891 prev_token,
20892 "ERR013 - Return statements cannot be part of sub-expressions",
20893 exprtk_error_location));
20895 return error_node();
20898 new_expression = expression_generator_
20900 current_state.operation,
20901 expression,
20902 right_branch
20906 if (0 == new_expression)
20908 if (error_list_.empty())
20910 set_error(
20911 make_error(parser_error::e_syntax,
20912 prev_token,
20913 !synthesis_error_.empty() ?
20914 synthesis_error_ :
20915 "ERR014 - General parsing error at token: '" + prev_token.value + "'",
20916 exprtk_error_location));
20919 free_node(node_allocator_, expression);
20920 free_node(node_allocator_, right_branch);
20922 return error_node();
20924 else
20926 if (
20927 token_is(token_t::e_ternary,prsrhlpr_t::e_hold) &&
20928 (precedence == e_level00)
20931 expression = parse_ternary_conditional_statement(new_expression);
20933 else
20934 expression = new_expression;
20936 parse_pending_string_rangesize(expression);
20940 return expression;
20943 bool simplify_unary_negation_branch(expression_node_ptr& node)
20946 typedef details::unary_branch_node<T,details::neg_op<T> > ubn_t;
20947 ubn_t* n = dynamic_cast<ubn_t*>(node);
20949 if (n)
20951 expression_node_ptr un_r = n->branch(0);
20952 n->release();
20953 free_node(node_allocator_,node);
20954 node = un_r;
20956 return true;
20961 typedef details::unary_variable_node<T,details::neg_op<T> > uvn_t;
20963 uvn_t* n = dynamic_cast<uvn_t*>(node);
20965 if (n)
20967 const T& v = n->v();
20968 expression_node_ptr return_node = error_node();
20970 if (
20971 (0 != (return_node = symtab_store_.get_variable(v))) ||
20972 (0 != (return_node = sem_ .get_variable(v)))
20975 free_node(node_allocator_,node);
20976 node = return_node;
20978 return true;
20980 else
20982 set_error(
20983 make_error(parser_error::e_syntax,
20984 current_token(),
20985 "ERR015 - Failed to find variable node in symbol table",
20986 exprtk_error_location));
20988 free_node(node_allocator_,node);
20990 return false;
20995 return false;
20998 static inline expression_node_ptr error_node()
21000 return reinterpret_cast<expression_node_ptr>(0);
21003 template <typename Type, std::size_t N>
21004 struct scoped_delete
21006 typedef Type* ptr_t;
21008 scoped_delete(parser<T>& pr, ptr_t& p)
21009 : delete_ptr(true),
21010 parser_(pr),
21011 p_(&p)
21014 scoped_delete(parser<T>& pr, ptr_t (&p)[N])
21015 : delete_ptr(true),
21016 parser_(pr),
21017 p_(&p[0])
21020 ~scoped_delete()
21022 if (delete_ptr)
21024 for (std::size_t i = 0; i < N; ++i)
21026 free_node(parser_.node_allocator_,p_[i]);
21031 bool delete_ptr;
21032 parser<T>& parser_;
21033 ptr_t* p_;
21035 private:
21037 scoped_delete<Type,N>& operator=(const scoped_delete<Type,N>&);
21040 template <typename Type>
21041 struct scoped_deq_delete
21043 typedef Type* ptr_t;
21045 scoped_deq_delete(parser<T>& pr, std::deque<ptr_t>& deq)
21046 : delete_ptr(true),
21047 parser_(pr),
21048 deq_(deq)
21051 ~scoped_deq_delete()
21053 if (delete_ptr && !deq_.empty())
21055 for (std::size_t i = 0; i < deq_.size(); ++i)
21057 free_node(parser_.node_allocator_,deq_[i]);
21060 deq_.clear();
21064 bool delete_ptr;
21065 parser<T>& parser_;
21066 std::deque<ptr_t>& deq_;
21068 private:
21070 scoped_deq_delete<Type>& operator=(const scoped_deq_delete<Type>&);
21073 template <typename Type>
21074 struct scoped_vec_delete
21076 typedef Type* ptr_t;
21078 scoped_vec_delete(parser<T>& pr, std::vector<ptr_t>& vec)
21079 : delete_ptr(true),
21080 parser_(pr),
21081 vec_(vec)
21084 ~scoped_vec_delete()
21086 if (delete_ptr && !vec_.empty())
21088 for (std::size_t i = 0; i < vec_.size(); ++i)
21090 free_node(parser_.node_allocator_,vec_[i]);
21093 vec_.clear();
21097 bool delete_ptr;
21098 parser<T>& parser_;
21099 std::vector<ptr_t>& vec_;
21101 private:
21103 scoped_vec_delete<Type>& operator=(const scoped_vec_delete<Type>&);
21106 struct scoped_bool_negator
21108 explicit scoped_bool_negator(bool& bb)
21109 : b(bb)
21110 { b = !b; }
21112 ~scoped_bool_negator()
21113 { b = !b; }
21115 bool& b;
21118 struct scoped_bool_or_restorer
21120 explicit scoped_bool_or_restorer(bool& bb)
21121 : b(bb),
21122 original_value_(bb)
21125 ~scoped_bool_or_restorer()
21127 b = b || original_value_;
21130 bool& b;
21131 bool original_value_;
21134 inline expression_node_ptr parse_function_invocation(ifunction<T>* function, const std::string& function_name)
21136 expression_node_ptr func_node = reinterpret_cast<expression_node_ptr>(0);
21138 switch (function->param_count)
21140 case 0 : func_node = parse_function_call_0 (function,function_name); break;
21141 case 1 : func_node = parse_function_call< 1>(function,function_name); break;
21142 case 2 : func_node = parse_function_call< 2>(function,function_name); break;
21143 case 3 : func_node = parse_function_call< 3>(function,function_name); break;
21144 case 4 : func_node = parse_function_call< 4>(function,function_name); break;
21145 case 5 : func_node = parse_function_call< 5>(function,function_name); break;
21146 case 6 : func_node = parse_function_call< 6>(function,function_name); break;
21147 case 7 : func_node = parse_function_call< 7>(function,function_name); break;
21148 case 8 : func_node = parse_function_call< 8>(function,function_name); break;
21149 case 9 : func_node = parse_function_call< 9>(function,function_name); break;
21150 case 10 : func_node = parse_function_call<10>(function,function_name); break;
21151 case 11 : func_node = parse_function_call<11>(function,function_name); break;
21152 case 12 : func_node = parse_function_call<12>(function,function_name); break;
21153 case 13 : func_node = parse_function_call<13>(function,function_name); break;
21154 case 14 : func_node = parse_function_call<14>(function,function_name); break;
21155 case 15 : func_node = parse_function_call<15>(function,function_name); break;
21156 case 16 : func_node = parse_function_call<16>(function,function_name); break;
21157 case 17 : func_node = parse_function_call<17>(function,function_name); break;
21158 case 18 : func_node = parse_function_call<18>(function,function_name); break;
21159 case 19 : func_node = parse_function_call<19>(function,function_name); break;
21160 case 20 : func_node = parse_function_call<20>(function,function_name); break;
21161 default : {
21162 set_error(
21163 make_error(parser_error::e_syntax,
21164 current_token(),
21165 "ERR016 - Invalid number of parameters for function: '" + function_name + "'",
21166 exprtk_error_location));
21168 return error_node();
21172 if (func_node)
21173 return func_node;
21174 else
21176 set_error(
21177 make_error(parser_error::e_syntax,
21178 current_token(),
21179 "ERR017 - Failed to generate call to function: '" + function_name + "'",
21180 exprtk_error_location));
21182 return error_node();
21186 template <std::size_t NumberofParameters>
21187 inline expression_node_ptr parse_function_call(ifunction<T>* function, const std::string& function_name)
21189 #ifdef _MSC_VER
21190 #pragma warning(push)
21191 #pragma warning(disable: 4127)
21192 #endif
21193 if (0 == NumberofParameters)
21195 set_error(
21196 make_error(parser_error::e_syntax,
21197 current_token(),
21198 "ERR018 - Expecting ifunction '" + function_name + "' to have non-zero parameter count",
21199 exprtk_error_location));
21201 return error_node();
21203 #ifdef _MSC_VER
21204 #pragma warning(pop)
21205 #endif
21207 expression_node_ptr branch[NumberofParameters];
21208 expression_node_ptr result = error_node();
21210 std::fill_n(branch, NumberofParameters, reinterpret_cast<expression_node_ptr>(0));
21212 scoped_delete<expression_node_t,NumberofParameters> sd((*this),branch);
21214 next_token();
21216 if (!token_is(token_t::e_lbracket))
21218 set_error(
21219 make_error(parser_error::e_syntax,
21220 current_token(),
21221 "ERR019 - Expecting argument list for function: '" + function_name + "'",
21222 exprtk_error_location));
21224 return error_node();
21227 for (int i = 0; i < static_cast<int>(NumberofParameters); ++i)
21229 branch[i] = parse_expression();
21231 if (0 == branch[i])
21233 set_error(
21234 make_error(parser_error::e_syntax,
21235 current_token(),
21236 "ERR020 - Failed to parse argument " + details::to_str(i) + " for function: '" + function_name + "'",
21237 exprtk_error_location));
21239 return error_node();
21241 else if (i < static_cast<int>(NumberofParameters - 1))
21243 if (!token_is(token_t::e_comma))
21245 set_error(
21246 make_error(parser_error::e_syntax,
21247 current_token(),
21248 "ERR021 - Invalid number of arguments for function: '" + function_name + "'",
21249 exprtk_error_location));
21251 return error_node();
21256 if (!token_is(token_t::e_rbracket))
21258 set_error(
21259 make_error(parser_error::e_syntax,
21260 current_token(),
21261 "ERR022 - Invalid number of arguments for function: '" + function_name + "'",
21262 exprtk_error_location));
21264 return error_node();
21266 else
21267 result = expression_generator_.function(function,branch);
21269 sd.delete_ptr = false;
21271 return result;
21274 inline expression_node_ptr parse_function_call_0(ifunction<T>* function, const std::string& function_name)
21276 expression_node_ptr result = expression_generator_.function(function);
21278 state_.side_effect_present = function->has_side_effects();
21280 next_token();
21282 if (
21283 token_is(token_t::e_lbracket) &&
21284 !token_is(token_t::e_rbracket)
21287 set_error(
21288 make_error(parser_error::e_syntax,
21289 current_token(),
21290 "ERR023 - Expecting '()' to proceed call to function: '" + function_name + "'",
21291 exprtk_error_location));
21293 free_node(node_allocator_,result);
21295 return error_node();
21297 else
21298 return result;
21301 template <std::size_t MaxNumberofParameters>
21302 inline std::size_t parse_base_function_call(expression_node_ptr (&param_list)[MaxNumberofParameters], const std::string& function_name = "")
21304 std::fill_n(param_list, MaxNumberofParameters, reinterpret_cast<expression_node_ptr>(0));
21306 scoped_delete<expression_node_t,MaxNumberofParameters> sd((*this),param_list);
21308 next_token();
21310 if (!token_is(token_t::e_lbracket))
21312 set_error(
21313 make_error(parser_error::e_syntax,
21314 current_token(),
21315 "ERR024 - Expected a '(' at start of function call to '" + function_name +
21316 "', instead got: '" + current_token().value + "'",
21317 exprtk_error_location));
21319 return 0;
21322 if (token_is(token_t::e_rbracket, e_hold))
21324 set_error(
21325 make_error(parser_error::e_syntax,
21326 current_token(),
21327 "ERR025 - Expected at least one input parameter for function call '" + function_name + "'",
21328 exprtk_error_location));
21330 return 0;
21333 std::size_t param_index = 0;
21335 for (; param_index < MaxNumberofParameters; ++param_index)
21337 param_list[param_index] = parse_expression();
21339 if (0 == param_list[param_index])
21340 return 0;
21341 else if (token_is(token_t::e_rbracket))
21343 sd.delete_ptr = false;
21344 break;
21346 else if (token_is(token_t::e_comma))
21347 continue;
21348 else
21350 set_error(
21351 make_error(parser_error::e_syntax,
21352 current_token(),
21353 "ERR026 - Expected a ',' between function input parameters, instead got: '" + current_token().value + "'",
21354 exprtk_error_location));
21356 return 0;
21360 if (sd.delete_ptr)
21362 set_error(
21363 make_error(parser_error::e_syntax,
21364 current_token(),
21365 "ERR027 - Invalid number of input parameters passed to function '" + function_name + "'",
21366 exprtk_error_location));
21368 return 0;
21371 return (param_index + 1);
21374 inline expression_node_ptr parse_base_operation()
21376 typedef std::pair<base_ops_map_t::iterator,base_ops_map_t::iterator> map_range_t;
21378 const std::string operation_name = current_token().value;
21379 const token_t diagnostic_token = current_token();
21381 map_range_t itr_range = base_ops_map_.equal_range(operation_name);
21383 if (0 == std::distance(itr_range.first,itr_range.second))
21385 set_error(
21386 make_error(parser_error::e_syntax,
21387 diagnostic_token,
21388 "ERR028 - No entry found for base operation: " + operation_name,
21389 exprtk_error_location));
21391 return error_node();
21394 static const std::size_t MaxNumberofParameters = 4;
21395 expression_node_ptr param_list[MaxNumberofParameters] = {0};
21397 const std::size_t parameter_count = parse_base_function_call(param_list, operation_name);
21399 if ((parameter_count > 0) && (parameter_count <= MaxNumberofParameters))
21401 for (base_ops_map_t::iterator itr = itr_range.first; itr != itr_range.second; ++itr)
21403 const details::base_operation_t& operation = itr->second;
21405 if (operation.num_params == parameter_count)
21407 switch (parameter_count)
21409 #define base_opr_case(N) \
21410 case N : { \
21411 expression_node_ptr pl##N[N] = {0}; \
21412 std::copy(param_list, param_list + N, pl##N); \
21413 lodge_symbol(operation_name, e_st_function); \
21414 return expression_generator_(operation.type, pl##N); \
21417 base_opr_case(1)
21418 base_opr_case(2)
21419 base_opr_case(3)
21420 base_opr_case(4)
21421 #undef base_opr_case
21427 for (std::size_t i = 0; i < MaxNumberofParameters; ++i)
21429 free_node(node_allocator_, param_list[i]);
21432 set_error(
21433 make_error(parser_error::e_syntax,
21434 diagnostic_token,
21435 "ERR029 - Invalid number of input parameters for call to function: '" + operation_name + "'",
21436 exprtk_error_location));
21438 return error_node();
21441 inline expression_node_ptr parse_conditional_statement_01(expression_node_ptr condition)
21443 // Parse: [if][(][condition][,][consequent][,][alternative][)]
21445 expression_node_ptr consequent = error_node();
21446 expression_node_ptr alternative = error_node();
21448 bool result = true;
21450 if (!token_is(token_t::e_comma))
21452 set_error(
21453 make_error(parser_error::e_syntax,
21454 current_token(),
21455 "ERR030 - Expected ',' between if-statement condition and consequent",
21456 exprtk_error_location));
21457 result = false;
21459 else if (0 == (consequent = parse_expression()))
21461 set_error(
21462 make_error(parser_error::e_syntax,
21463 current_token(),
21464 "ERR031 - Failed to parse consequent for if-statement",
21465 exprtk_error_location));
21466 result = false;
21468 else if (!token_is(token_t::e_comma))
21470 set_error(
21471 make_error(parser_error::e_syntax,
21472 current_token(),
21473 "ERR032 - Expected ',' between if-statement consequent and alternative",
21474 exprtk_error_location));
21475 result = false;
21477 else if (0 == (alternative = parse_expression()))
21479 set_error(
21480 make_error(parser_error::e_syntax,
21481 current_token(),
21482 "ERR033 - Failed to parse alternative for if-statement",
21483 exprtk_error_location));
21484 result = false;
21486 else if (!token_is(token_t::e_rbracket))
21488 set_error(
21489 make_error(parser_error::e_syntax,
21490 current_token(),
21491 "ERR034 - Expected ')' at the end of if-statement",
21492 exprtk_error_location));
21493 result = false;
21496 #ifndef exprtk_disable_string_capabilities
21497 if (result)
21499 const bool consq_is_str = is_generally_string_node( consequent);
21500 const bool alter_is_str = is_generally_string_node(alternative);
21502 if (consq_is_str || alter_is_str)
21504 if (consq_is_str && alter_is_str)
21506 return expression_generator_
21507 .conditional_string(condition, consequent, alternative);
21510 set_error(
21511 make_error(parser_error::e_syntax,
21512 current_token(),
21513 "ERR035 - Return types of ternary if-statement differ",
21514 exprtk_error_location));
21516 result = false;
21519 #endif
21521 if (!result)
21523 free_node(node_allocator_, condition);
21524 free_node(node_allocator_, consequent);
21525 free_node(node_allocator_,alternative);
21527 return error_node();
21529 else
21530 return expression_generator_
21531 .conditional(condition, consequent, alternative);
21534 inline expression_node_ptr parse_conditional_statement_02(expression_node_ptr condition)
21536 expression_node_ptr consequent = error_node();
21537 expression_node_ptr alternative = error_node();
21539 bool result = true;
21541 if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
21543 if (0 == (consequent = parse_multi_sequence("if-statement-01")))
21545 set_error(
21546 make_error(parser_error::e_syntax,
21547 current_token(),
21548 "ERR036 - Failed to parse body of consequent for if-statement",
21549 exprtk_error_location));
21551 result = false;
21554 else
21556 if (
21557 settings_.commutative_check_enabled() &&
21558 token_is(token_t::e_mul,prsrhlpr_t::e_hold)
21561 next_token();
21564 if (0 != (consequent = parse_expression()))
21566 if (!token_is(token_t::e_eof))
21568 set_error(
21569 make_error(parser_error::e_syntax,
21570 current_token(),
21571 "ERR037 - Expected ';' at the end of the consequent for if-statement",
21572 exprtk_error_location));
21574 result = false;
21577 else
21579 set_error(
21580 make_error(parser_error::e_syntax,
21581 current_token(),
21582 "ERR038 - Failed to parse body of consequent for if-statement",
21583 exprtk_error_location));
21585 result = false;
21589 if (result)
21591 if (details::imatch(current_token().value,"else"))
21593 next_token();
21595 if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
21597 if (0 == (alternative = parse_multi_sequence("else-statement-01")))
21599 set_error(
21600 make_error(parser_error::e_syntax,
21601 current_token(),
21602 "ERR039 - Failed to parse body of the 'else' for if-statement",
21603 exprtk_error_location));
21605 result = false;
21608 else if (details::imatch(current_token().value,"if"))
21610 if (0 == (alternative = parse_conditional_statement()))
21612 set_error(
21613 make_error(parser_error::e_syntax,
21614 current_token(),
21615 "ERR040 - Failed to parse body of if-else statement",
21616 exprtk_error_location));
21618 result = false;
21621 else if (0 != (alternative = parse_expression()))
21623 if (!token_is(token_t::e_eof))
21625 set_error(
21626 make_error(parser_error::e_syntax,
21627 current_token(),
21628 "ERR041 - Expected ';' at the end of the 'else-if' for the if-statement",
21629 exprtk_error_location));
21631 result = false;
21634 else
21636 set_error(
21637 make_error(parser_error::e_syntax,
21638 current_token(),
21639 "ERR042 - Failed to parse body of the 'else' for if-statement",
21640 exprtk_error_location));
21642 result = false;
21647 #ifndef exprtk_disable_string_capabilities
21648 if (result)
21650 const bool consq_is_str = is_generally_string_node( consequent);
21651 const bool alter_is_str = is_generally_string_node(alternative);
21653 if (consq_is_str || alter_is_str)
21655 if (consq_is_str && alter_is_str)
21657 return expression_generator_
21658 .conditional_string(condition, consequent, alternative);
21661 set_error(
21662 make_error(parser_error::e_syntax,
21663 current_token(),
21664 "ERR043 - Return types of ternary if-statement differ",
21665 exprtk_error_location));
21667 result = false;
21670 #endif
21672 if (!result)
21674 free_node(node_allocator_, condition);
21675 free_node(node_allocator_, consequent);
21676 free_node(node_allocator_, alternative);
21678 return error_node();
21680 else
21681 return expression_generator_
21682 .conditional(condition, consequent, alternative);
21685 inline expression_node_ptr parse_conditional_statement()
21687 expression_node_ptr condition = error_node();
21689 next_token();
21691 if (!token_is(token_t::e_lbracket))
21693 set_error(
21694 make_error(parser_error::e_syntax,
21695 current_token(),
21696 "ERR044 - Expected '(' at start of if-statement, instead got: '" + current_token().value + "'",
21697 exprtk_error_location));
21699 return error_node();
21701 else if (0 == (condition = parse_expression()))
21703 set_error(
21704 make_error(parser_error::e_syntax,
21705 current_token(),
21706 "ERR045 - Failed to parse condition for if-statement",
21707 exprtk_error_location));
21709 return error_node();
21711 else if (token_is(token_t::e_comma,prsrhlpr_t::e_hold))
21713 // if (x,y,z)
21714 return parse_conditional_statement_01(condition);
21716 else if (token_is(token_t::e_rbracket))
21718 // 00. if (x) y;
21719 // 01. if (x) y; else z;
21720 // 02. if (x) y; else {z0; ... zn;}
21721 // 03. if (x) y; else if (z) w;
21722 // 04. if (x) y; else if (z) w; else u;
21723 // 05. if (x) y; else if (z) w; else {u0; ... un;}
21724 // 06. if (x) y; else if (z) {w0; ... wn;}
21725 // 07. if (x) {y0; ... yn;}
21726 // 08. if (x) {y0; ... yn;} else z;
21727 // 09. if (x) {y0; ... yn;} else {z0; ... zn;};
21728 // 10. if (x) {y0; ... yn;} else if (z) w;
21729 // 11. if (x) {y0; ... yn;} else if (z) w; else u;
21730 // 12. if (x) {y0; ... nex;} else if (z) w; else {u0 ... un;}
21731 // 13. if (x) {y0; ... yn;} else if (z) {w0; ... wn;}
21732 return parse_conditional_statement_02(condition);
21735 set_error(
21736 make_error(parser_error::e_syntax,
21737 current_token(),
21738 "ERR046 - Invalid if-statement",
21739 exprtk_error_location));
21741 free_node(node_allocator_,condition);
21743 return error_node();
21746 inline expression_node_ptr parse_ternary_conditional_statement(expression_node_ptr condition)
21748 // Parse: [condition][?][consequent][:][alternative]
21749 expression_node_ptr consequent = error_node();
21750 expression_node_ptr alternative = error_node();
21752 bool result = true;
21754 if (0 == condition)
21756 set_error(
21757 make_error(parser_error::e_syntax,
21758 current_token(),
21759 "ERR047 - Encountered invalid condition branch for ternary if-statement",
21760 exprtk_error_location));
21762 return error_node();
21764 else if (!token_is(token_t::e_ternary))
21766 set_error(
21767 make_error(parser_error::e_syntax,
21768 current_token(),
21769 "ERR048 - Expected '?' after condition of ternary if-statement",
21770 exprtk_error_location));
21772 result = false;
21774 else if (0 == (consequent = parse_expression()))
21776 set_error(
21777 make_error(parser_error::e_syntax,
21778 current_token(),
21779 "ERR049 - Failed to parse consequent for ternary if-statement",
21780 exprtk_error_location));
21782 result = false;
21784 else if (!token_is(token_t::e_colon))
21786 set_error(
21787 make_error(parser_error::e_syntax,
21788 current_token(),
21789 "ERR050 - Expected ':' between ternary if-statement consequent and alternative",
21790 exprtk_error_location));
21792 result = false;
21794 else if (0 == (alternative = parse_expression()))
21796 set_error(
21797 make_error(parser_error::e_syntax,
21798 current_token(),
21799 "ERR051 - Failed to parse alternative for ternary if-statement",
21800 exprtk_error_location));
21802 result = false;
21805 #ifndef exprtk_disable_string_capabilities
21806 if (result)
21808 const bool consq_is_str = is_generally_string_node( consequent);
21809 const bool alter_is_str = is_generally_string_node(alternative);
21811 if (consq_is_str || alter_is_str)
21813 if (consq_is_str && alter_is_str)
21815 return expression_generator_
21816 .conditional_string(condition, consequent, alternative);
21819 set_error(
21820 make_error(parser_error::e_syntax,
21821 current_token(),
21822 "ERR052 - Return types of ternary if-statement differ",
21823 exprtk_error_location));
21825 result = false;
21828 #endif
21830 if (!result)
21832 free_node(node_allocator_, condition);
21833 free_node(node_allocator_, consequent);
21834 free_node(node_allocator_, alternative);
21836 return error_node();
21838 else
21839 return expression_generator_
21840 .conditional(condition, consequent, alternative);
21843 inline expression_node_ptr parse_not_statement()
21845 if (settings_.logic_disabled("not"))
21847 set_error(
21848 make_error(parser_error::e_syntax,
21849 current_token(),
21850 "ERR053 - Invalid or disabled logic operation 'not'",
21851 exprtk_error_location));
21853 return error_node();
21856 return parse_base_operation();
21859 inline expression_node_ptr parse_while_loop()
21861 // Parse: [while][(][test expr][)][{][expression][}]
21862 expression_node_ptr condition = error_node();
21863 expression_node_ptr branch = error_node();
21864 expression_node_ptr result_node = error_node();
21866 bool result = true;
21868 next_token();
21870 if (!token_is(token_t::e_lbracket))
21872 set_error(
21873 make_error(parser_error::e_syntax,
21874 current_token(),
21875 "ERR054 - Expected '(' at start of while-loop condition statement",
21876 exprtk_error_location));
21878 return error_node();
21880 else if (0 == (condition = parse_expression()))
21882 set_error(
21883 make_error(parser_error::e_syntax,
21884 current_token(),
21885 "ERR055 - Failed to parse condition for while-loop",
21886 exprtk_error_location));
21888 return error_node();
21890 else if (!token_is(token_t::e_rbracket))
21892 set_error(
21893 make_error(parser_error::e_syntax,
21894 current_token(),
21895 "ERR056 - Expected ')' at end of while-loop condition statement",
21896 exprtk_error_location));
21898 result = false;
21901 brkcnt_list_.push_front(false);
21903 if (result)
21905 if (0 == (branch = parse_multi_sequence("while-loop")))
21907 set_error(
21908 make_error(parser_error::e_syntax,
21909 current_token(),
21910 "ERR057 - Failed to parse body of while-loop"));
21911 result = false;
21913 else if (0 == (result_node = expression_generator_.while_loop(condition,
21914 branch,
21915 brkcnt_list_.front())))
21917 set_error(
21918 make_error(parser_error::e_syntax,
21919 current_token(),
21920 "ERR058 - Failed to synthesize while-loop",
21921 exprtk_error_location));
21923 result = false;
21927 if (!result)
21929 free_node(node_allocator_, branch);
21930 free_node(node_allocator_, condition);
21931 free_node(node_allocator_, result_node);
21933 brkcnt_list_.pop_front();
21935 return error_node();
21937 else
21938 return result_node;
21941 inline expression_node_ptr parse_repeat_until_loop()
21943 // Parse: [repeat][{][expression][}][until][(][test expr][)]
21944 expression_node_ptr condition = error_node();
21945 expression_node_ptr branch = error_node();
21946 next_token();
21948 std::vector<expression_node_ptr> arg_list;
21949 std::vector<bool> side_effect_list;
21951 scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
21953 brkcnt_list_.push_front(false);
21955 if (details::imatch(current_token().value,"until"))
21957 next_token();
21958 branch = node_allocator_.allocate<details::null_node<T> >();
21960 else
21962 const token_t::token_type seperator = token_t::e_eof;
21964 scope_handler sh(*this);
21966 scoped_bool_or_restorer sbr(state_.side_effect_present);
21968 for ( ; ; )
21970 state_.side_effect_present = false;
21972 expression_node_ptr arg = parse_expression();
21974 if (0 == arg)
21975 return error_node();
21976 else
21978 arg_list.push_back(arg);
21979 side_effect_list.push_back(state_.side_effect_present);
21982 if (details::imatch(current_token().value,"until"))
21984 next_token();
21985 break;
21988 const bool is_next_until = peek_token_is(token_t::e_symbol) &&
21989 peek_token_is("until");
21991 if (!token_is(seperator) && is_next_until)
21993 set_error(
21994 make_error(parser_error::e_syntax,
21995 current_token(),
21996 "ERR059 - Expected '" + token_t::to_str(seperator) + "' in body of repeat until loop",
21997 exprtk_error_location));
21999 return error_node();
22002 if (details::imatch(current_token().value,"until"))
22004 next_token();
22005 break;
22009 branch = simplify(arg_list,side_effect_list);
22011 sdd.delete_ptr = (0 == branch);
22013 if (sdd.delete_ptr)
22015 brkcnt_list_.pop_front();
22017 set_error(
22018 make_error(parser_error::e_syntax,
22019 current_token(),
22020 "ERR060 - Failed to parse body of repeat until loop",
22021 exprtk_error_location));
22023 return error_node();
22027 if (!token_is(token_t::e_lbracket))
22029 brkcnt_list_.pop_front();
22031 set_error(
22032 make_error(parser_error::e_syntax,
22033 current_token(),
22034 "ERR061 - Expected '(' before condition statement of repeat until loop",
22035 exprtk_error_location));
22037 free_node(node_allocator_,branch);
22039 return error_node();
22041 else if (0 == (condition = parse_expression()))
22043 brkcnt_list_.pop_front();
22045 set_error(
22046 make_error(parser_error::e_syntax,
22047 current_token(),
22048 "ERR062 - Failed to parse condition for repeat until loop",
22049 exprtk_error_location));
22051 free_node(node_allocator_,branch);
22053 return error_node();
22055 else if (!token_is(token_t::e_rbracket))
22057 set_error(
22058 make_error(parser_error::e_syntax,
22059 current_token(),
22060 "ERR063 - Expected ')' after condition of repeat until loop",
22061 exprtk_error_location));
22063 free_node(node_allocator_, branch);
22064 free_node(node_allocator_, condition);
22066 brkcnt_list_.pop_front();
22068 return error_node();
22071 expression_node_ptr result;
22073 result = expression_generator_
22074 .repeat_until_loop(condition, branch, brkcnt_list_.front());
22076 if (0 == result)
22078 set_error(
22079 make_error(parser_error::e_syntax,
22080 current_token(),
22081 "ERR064 - Failed to synthesize repeat until loop",
22082 exprtk_error_location));
22084 free_node(node_allocator_,condition);
22086 brkcnt_list_.pop_front();
22088 return error_node();
22090 else
22092 brkcnt_list_.pop_front();
22093 return result;
22097 inline expression_node_ptr parse_for_loop()
22099 expression_node_ptr initialiser = error_node();
22100 expression_node_ptr condition = error_node();
22101 expression_node_ptr incrementor = error_node();
22102 expression_node_ptr loop_body = error_node();
22104 scope_element* se = 0;
22105 bool result = true;
22107 next_token();
22109 scope_handler sh(*this);
22111 if (!token_is(token_t::e_lbracket))
22113 set_error(
22114 make_error(parser_error::e_syntax,
22115 current_token(),
22116 "ERR065 - Expected '(' at start of for-loop",
22117 exprtk_error_location));
22119 return error_node();
22122 if (!token_is(token_t::e_eof))
22124 if (
22125 !token_is(token_t::e_symbol,prsrhlpr_t::e_hold) &&
22126 details::imatch(current_token().value,"var")
22129 next_token();
22131 if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold))
22133 set_error(
22134 make_error(parser_error::e_syntax,
22135 current_token(),
22136 "ERR066 - Expected a variable at the start of initialiser section of for-loop",
22137 exprtk_error_location));
22139 return error_node();
22141 else if (!peek_token_is(token_t::e_assign))
22143 set_error(
22144 make_error(parser_error::e_syntax,
22145 current_token(),
22146 "ERR067 - Expected variable assignment of initialiser section of for-loop",
22147 exprtk_error_location));
22149 return error_node();
22152 const std::string loop_counter_symbol = current_token().value;
22154 se = &sem_.get_element(loop_counter_symbol);
22156 if ((se->name == loop_counter_symbol) && se->active)
22158 set_error(
22159 make_error(parser_error::e_syntax,
22160 current_token(),
22161 "ERR068 - For-loop variable '" + loop_counter_symbol+ "' is being shadowed by a previous declaration",
22162 exprtk_error_location));
22164 return error_node();
22166 else if (!symtab_store_.is_variable(loop_counter_symbol))
22168 if (
22169 !se->active &&
22170 (se->name == loop_counter_symbol) &&
22171 (se->type == scope_element::e_variable)
22174 se->active = true;
22175 se->ref_count++;
22177 else
22179 scope_element nse;
22180 nse.name = loop_counter_symbol;
22181 nse.active = true;
22182 nse.ref_count = 1;
22183 nse.type = scope_element::e_variable;
22184 nse.depth = state_.scope_depth;
22185 nse.data = new T(T(0));
22186 nse.var_node = node_allocator_.allocate<variable_node_t>(*(T*)(nse.data));
22188 if (!sem_.add_element(nse))
22190 set_error(
22191 make_error(parser_error::e_syntax,
22192 current_token(),
22193 "ERR069 - Failed to add new local variable '" + loop_counter_symbol + "' to SEM",
22194 exprtk_error_location));
22196 sem_.free_element(nse);
22198 result = false;
22200 else
22202 exprtk_debug(("parse_for_loop() - INFO - Added new local variable: %s\n",nse.name.c_str()));
22204 state_.activate_side_effect("parse_for_loop()");
22210 if (0 == (initialiser = parse_expression()))
22212 set_error(
22213 make_error(parser_error::e_syntax,
22214 current_token(),
22215 "ERR070 - Failed to parse initialiser of for-loop",
22216 exprtk_error_location));
22218 result = false;
22220 else if (!token_is(token_t::e_eof))
22222 set_error(
22223 make_error(parser_error::e_syntax,
22224 current_token(),
22225 "ERR071 - Expected ';' after initialiser of for-loop",
22226 exprtk_error_location));
22228 result = false;
22232 if (!token_is(token_t::e_eof))
22234 if (0 == (condition = parse_expression()))
22236 set_error(
22237 make_error(parser_error::e_syntax,
22238 current_token(),
22239 "ERR072 - Failed to parse condition of for-loop",
22240 exprtk_error_location));
22242 result = false;
22244 else if (!token_is(token_t::e_eof))
22246 set_error(
22247 make_error(parser_error::e_syntax,
22248 current_token(),
22249 "ERR073 - Expected ';' after condition section of for-loop",
22250 exprtk_error_location));
22252 result = false;
22256 if (!token_is(token_t::e_rbracket))
22258 if (0 == (incrementor = parse_expression()))
22260 set_error(
22261 make_error(parser_error::e_syntax,
22262 current_token(),
22263 "ERR074 - Failed to parse incrementor of for-loop",
22264 exprtk_error_location));
22266 result = false;
22268 else if (!token_is(token_t::e_rbracket))
22270 set_error(
22271 make_error(parser_error::e_syntax,
22272 current_token(),
22273 "ERR075 - Expected ')' after incrementor section of for-loop",
22274 exprtk_error_location));
22276 result = false;
22280 if (result)
22282 brkcnt_list_.push_front(false);
22284 if (0 == (loop_body = parse_multi_sequence("for-loop")))
22286 set_error(
22287 make_error(parser_error::e_syntax,
22288 current_token(),
22289 "ERR076 - Failed to parse body of for-loop",
22290 exprtk_error_location));
22292 result = false;
22296 if (!result)
22298 if (se)
22300 se->ref_count--;
22303 free_node(node_allocator_, initialiser);
22304 free_node(node_allocator_, condition);
22305 free_node(node_allocator_, incrementor);
22306 free_node(node_allocator_, loop_body);
22308 if (!brkcnt_list_.empty())
22310 brkcnt_list_.pop_front();
22313 return error_node();
22315 else
22317 expression_node_ptr result_node =
22318 expression_generator_.for_loop(initialiser,
22319 condition,
22320 incrementor,
22321 loop_body,
22322 brkcnt_list_.front());
22323 brkcnt_list_.pop_front();
22325 return result_node;
22329 inline expression_node_ptr parse_switch_statement()
22331 std::vector<expression_node_ptr> arg_list;
22332 expression_node_ptr result = error_node();
22334 if (!details::imatch(current_token().value,"switch"))
22336 set_error(
22337 make_error(parser_error::e_syntax,
22338 current_token(),
22339 "ERR077 - Expected keyword 'switch'",
22340 exprtk_error_location));
22342 return error_node();
22345 scoped_vec_delete<expression_node_t> svd((*this),arg_list);
22347 next_token();
22349 if (!token_is(token_t::e_lcrlbracket))
22351 set_error(
22352 make_error(parser_error::e_syntax,
22353 current_token(),
22354 "ERR078 - Expected '{' for call to switch statement",
22355 exprtk_error_location));
22357 return error_node();
22360 for ( ; ; )
22362 if (!details::imatch("case",current_token().value))
22364 set_error(
22365 make_error(parser_error::e_syntax,
22366 current_token(),
22367 "ERR079 - Expected either a 'case' or 'default' statement",
22368 exprtk_error_location));
22370 return error_node();
22373 next_token();
22375 expression_node_ptr condition = parse_expression();
22377 if (0 == condition)
22378 return error_node();
22379 else if (!token_is(token_t::e_colon))
22381 set_error(
22382 make_error(parser_error::e_syntax,
22383 current_token(),
22384 "ERR080 - Expected ':' for case of switch statement",
22385 exprtk_error_location));
22387 return error_node();
22390 expression_node_ptr consequent = parse_expression();
22392 if (0 == consequent)
22393 return error_node();
22394 else if (!token_is(token_t::e_eof))
22396 set_error(
22397 make_error(parser_error::e_syntax,
22398 current_token(),
22399 "ERR081 - Expected ';' at end of case for switch statement",
22400 exprtk_error_location));
22402 return error_node();
22405 // Can we optimise away the case statement?
22406 if (is_constant_node(condition) && is_false(condition))
22408 free_node(node_allocator_, condition);
22409 free_node(node_allocator_, consequent);
22411 else
22413 arg_list.push_back( condition);
22414 arg_list.push_back(consequent);
22417 if (details::imatch("default",current_token().value))
22419 next_token();
22420 if (!token_is(token_t::e_colon))
22422 set_error(
22423 make_error(parser_error::e_syntax,
22424 current_token(),
22425 "ERR082 - Expected ':' for default of switch statement",
22426 exprtk_error_location));
22428 return error_node();
22431 expression_node_ptr default_statement = error_node();
22433 if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
22434 default_statement = parse_multi_sequence("switch-default");
22435 else
22436 default_statement = parse_expression();
22438 if (0 == default_statement)
22439 return error_node();
22440 else if (!token_is(token_t::e_eof))
22442 free_node(node_allocator_,default_statement);
22444 set_error(
22445 make_error(parser_error::e_syntax,
22446 current_token(),
22447 "ERR083 - Expected ';' at end of default for switch statement",
22448 exprtk_error_location));
22450 return error_node();
22453 arg_list.push_back(default_statement);
22454 break;
22458 if (!token_is(token_t::e_rcrlbracket))
22460 set_error(
22461 make_error(parser_error::e_syntax,
22462 current_token(),
22463 "ERR084 - Expected '}' at end of switch statement",
22464 exprtk_error_location));
22466 return error_node();
22469 result = expression_generator_.switch_statement(arg_list);
22471 svd.delete_ptr = (0 == result);
22473 return result;
22476 inline expression_node_ptr parse_multi_switch_statement()
22478 std::vector<expression_node_ptr> arg_list;
22480 if (!details::imatch(current_token().value,"[*]"))
22482 set_error(
22483 make_error(parser_error::e_syntax,
22484 current_token(),
22485 "ERR085 - Expected token '[*]'",
22486 exprtk_error_location));
22488 return error_node();
22491 scoped_vec_delete<expression_node_t> svd((*this),arg_list);
22493 next_token();
22495 if (!token_is(token_t::e_lcrlbracket))
22497 set_error(
22498 make_error(parser_error::e_syntax,
22499 current_token(),
22500 "ERR086 - Expected '{' for call to [*] statement",
22501 exprtk_error_location));
22503 return error_node();
22506 for ( ; ; )
22508 if (!details::imatch("case",current_token().value))
22510 set_error(
22511 make_error(parser_error::e_syntax,
22512 current_token(),
22513 "ERR087 - Expected a 'case' statement for multi-switch",
22514 exprtk_error_location));
22516 return error_node();
22519 next_token();
22521 expression_node_ptr condition = parse_expression();
22523 if (0 == condition)
22524 return error_node();
22526 if (!token_is(token_t::e_colon))
22528 set_error(
22529 make_error(parser_error::e_syntax,
22530 current_token(),
22531 "ERR088 - Expected ':' for case of [*] statement",
22532 exprtk_error_location));
22534 return error_node();
22537 expression_node_ptr consequent = parse_expression();
22539 if (0 == consequent)
22540 return error_node();
22542 if (!token_is(token_t::e_eof))
22544 set_error(
22545 make_error(parser_error::e_syntax,
22546 current_token(),
22547 "ERR089 - Expected ';' at end of case for [*] statement",
22548 exprtk_error_location));
22550 return error_node();
22553 // Can we optimise away the case statement?
22554 if (is_constant_node(condition) && is_false(condition))
22556 free_node(node_allocator_, condition);
22557 free_node(node_allocator_, consequent);
22559 else
22561 arg_list.push_back( condition);
22562 arg_list.push_back(consequent);
22565 if (token_is(token_t::e_rcrlbracket,prsrhlpr_t::e_hold))
22567 break;
22571 if (!token_is(token_t::e_rcrlbracket))
22573 set_error(
22574 make_error(parser_error::e_syntax,
22575 current_token(),
22576 "ERR090 - Expected '}' at end of [*] statement",
22577 exprtk_error_location));
22579 return error_node();
22582 const expression_node_ptr result = expression_generator_.multi_switch_statement(arg_list);
22584 svd.delete_ptr = (0 == result);
22586 return result;
22589 inline expression_node_ptr parse_vararg_function()
22591 std::vector<expression_node_ptr> arg_list;
22593 details::operator_type opt_type = details::e_default;
22594 const std::string symbol = current_token().value;
22596 if (details::imatch(symbol,"~"))
22598 next_token();
22599 return parse_multi_sequence();
22601 else if (details::imatch(symbol,"[*]"))
22603 return parse_multi_switch_statement();
22605 else if (details::imatch(symbol, "avg" )) opt_type = details::e_avg ;
22606 else if (details::imatch(symbol, "mand")) opt_type = details::e_mand;
22607 else if (details::imatch(symbol, "max" )) opt_type = details::e_max ;
22608 else if (details::imatch(symbol, "min" )) opt_type = details::e_min ;
22609 else if (details::imatch(symbol, "mor" )) opt_type = details::e_mor ;
22610 else if (details::imatch(symbol, "mul" )) opt_type = details::e_prod;
22611 else if (details::imatch(symbol, "sum" )) opt_type = details::e_sum ;
22612 else
22614 set_error(
22615 make_error(parser_error::e_syntax,
22616 current_token(),
22617 "ERR091 - Unsupported vararg function: " + symbol,
22618 exprtk_error_location));
22620 return error_node();
22623 scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
22625 lodge_symbol(symbol, e_st_function);
22627 next_token();
22629 if (!token_is(token_t::e_lbracket))
22631 set_error(
22632 make_error(parser_error::e_syntax,
22633 current_token(),
22634 "ERR092 - Expected '(' for call to vararg function: " + symbol,
22635 exprtk_error_location));
22637 return error_node();
22640 for ( ; ; )
22642 expression_node_ptr arg = parse_expression();
22644 if (0 == arg)
22645 return error_node();
22646 else
22647 arg_list.push_back(arg);
22649 if (token_is(token_t::e_rbracket))
22650 break;
22651 else if (!token_is(token_t::e_comma))
22653 set_error(
22654 make_error(parser_error::e_syntax,
22655 current_token(),
22656 "ERR093 - Expected ',' for call to vararg function: " + symbol,
22657 exprtk_error_location));
22659 return error_node();
22663 const expression_node_ptr result = expression_generator_.vararg_function(opt_type,arg_list);
22665 sdd.delete_ptr = (0 == result);
22666 return result;
22669 #ifndef exprtk_disable_string_capabilities
22670 inline expression_node_ptr parse_string_range_statement(expression_node_ptr& expression)
22672 if (!token_is(token_t::e_lsqrbracket))
22674 set_error(
22675 make_error(parser_error::e_syntax,
22676 current_token(),
22677 "ERR094 - Expected '[' as start of string range definition",
22678 exprtk_error_location));
22680 free_node(node_allocator_,expression);
22682 return error_node();
22684 else if (token_is(token_t::e_rsqrbracket))
22686 return node_allocator_.allocate<details::string_size_node<T> >(expression);
22689 range_t rp;
22691 if (!parse_range(rp,true))
22693 free_node(node_allocator_,expression);
22695 return error_node();
22698 expression_node_ptr result = expression_generator_(expression,rp);
22700 if (0 == result)
22702 set_error(
22703 make_error(parser_error::e_syntax,
22704 current_token(),
22705 "ERR095 - Failed to generate string range node",
22706 exprtk_error_location));
22708 free_node(node_allocator_,expression);
22711 rp.clear();
22713 return result;
22715 #else
22716 inline expression_node_ptr parse_string_range_statement(expression_node_ptr&)
22718 return error_node();
22720 #endif
22722 inline void parse_pending_string_rangesize(expression_node_ptr& expression)
22724 // Allow no more than 100 range calls, eg: s[][][]...[][]
22725 const std::size_t max_rangesize_parses = 100;
22727 std::size_t i = 0;
22729 while
22731 (0 != expression) &&
22732 (i++ < max_rangesize_parses) &&
22733 error_list_.empty() &&
22734 is_generally_string_node(expression) &&
22735 token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold)
22738 expression = parse_string_range_statement(expression);
22742 template <typename Allocator1,
22743 typename Allocator2,
22744 template <typename, typename> class Sequence>
22745 inline expression_node_ptr simplify(Sequence<expression_node_ptr,Allocator1>& expression_list,
22746 Sequence<bool,Allocator2>& side_effect_list,
22747 const bool specialise_on_final_type = false)
22749 if (expression_list.empty())
22750 return error_node();
22751 else if (1 == expression_list.size())
22752 return expression_list[0];
22754 Sequence<expression_node_ptr,Allocator1> tmp_expression_list;
22756 bool return_node_present = false;
22758 for (std::size_t i = 0; i < (expression_list.size() - 1); ++i)
22760 if (is_variable_node(expression_list[i]))
22761 continue;
22762 else if (
22763 is_return_node (expression_list[i]) ||
22764 is_break_node (expression_list[i]) ||
22765 is_continue_node(expression_list[i])
22768 tmp_expression_list.push_back(expression_list[i]);
22770 // Remove all subexpressions after first short-circuit
22771 // node has been encountered.
22773 for (std::size_t j = i + 1; j < expression_list.size(); ++j)
22775 free_node(node_allocator_,expression_list[j]);
22778 return_node_present = true;
22780 break;
22782 else if (
22783 is_constant_node(expression_list[i]) ||
22784 is_null_node (expression_list[i]) ||
22785 !side_effect_list[i]
22788 free_node(node_allocator_,expression_list[i]);
22789 continue;
22791 else
22792 tmp_expression_list.push_back(expression_list[i]);
22795 if (!return_node_present)
22797 tmp_expression_list.push_back(expression_list.back());
22800 expression_list.swap(tmp_expression_list);
22802 if (tmp_expression_list.size() > expression_list.size())
22804 exprtk_debug(("simplify() - Reduced subexpressions from %d to %d\n",
22805 static_cast<int>(tmp_expression_list.size()),
22806 static_cast<int>(expression_list .size())));
22809 if (
22810 return_node_present ||
22811 side_effect_list.back() ||
22812 (expression_list.size() > 1)
22814 state_.activate_side_effect("simplify()");
22816 if (1 == expression_list.size())
22817 return expression_list[0];
22818 else if (specialise_on_final_type && is_generally_string_node(expression_list.back()))
22819 return expression_generator_.vararg_function(details::e_smulti,expression_list);
22820 else
22821 return expression_generator_.vararg_function(details::e_multi,expression_list);
22824 inline expression_node_ptr parse_multi_sequence(const std::string& source = "")
22826 token_t::token_type close_bracket = token_t::e_rcrlbracket;
22827 token_t::token_type seperator = token_t::e_eof;
22829 if (!token_is(token_t::e_lcrlbracket))
22831 if (token_is(token_t::e_lbracket))
22833 close_bracket = token_t::e_rbracket;
22834 seperator = token_t::e_comma;
22836 else
22838 set_error(
22839 make_error(parser_error::e_syntax,
22840 current_token(),
22841 "ERR096 - Expected '" + token_t::to_str(close_bracket) + "' for call to multi-sequence" +
22842 ((!source.empty()) ? std::string(" section of " + source): ""),
22843 exprtk_error_location));
22845 return error_node();
22848 else if (token_is(token_t::e_rcrlbracket))
22850 return node_allocator_.allocate<details::null_node<T> >();
22853 std::vector<expression_node_ptr> arg_list;
22854 std::vector<bool> side_effect_list;
22856 expression_node_ptr result = error_node();
22858 scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
22860 scope_handler sh(*this);
22862 scoped_bool_or_restorer sbr(state_.side_effect_present);
22864 for ( ; ; )
22866 state_.side_effect_present = false;
22868 expression_node_ptr arg = parse_expression();
22870 if (0 == arg)
22871 return error_node();
22872 else
22874 arg_list.push_back(arg);
22875 side_effect_list.push_back(state_.side_effect_present);
22878 if (token_is(close_bracket))
22879 break;
22881 const bool is_next_close = peek_token_is(close_bracket);
22883 if (!token_is(seperator) && is_next_close)
22885 set_error(
22886 make_error(parser_error::e_syntax,
22887 current_token(),
22888 "ERR097 - Expected '" + details::to_str(seperator) + "' for call to multi-sequence section of " + source,
22889 exprtk_error_location));
22891 return error_node();
22894 if (token_is(close_bracket))
22895 break;
22898 result = simplify(arg_list,side_effect_list,source.empty());
22900 sdd.delete_ptr = (0 == result);
22901 return result;
22904 inline bool parse_range(range_t& rp, const bool skip_lsqr = false)
22906 // Examples of valid ranges:
22907 // 1. [1:5] -> 1..5
22908 // 2. [ :5] -> 0..5
22909 // 3. [1: ] -> 1..end
22910 // 4. [x:y] -> x..y where x <= y
22911 // 5. [x+1:y/2] -> x+1..y/2 where x+1 <= y/2
22912 // 6. [ :y] -> 0..y where 0 <= y
22913 // 7. [x: ] -> x..end where x <= end
22915 rp.clear();
22917 if (!skip_lsqr && !token_is(token_t::e_lsqrbracket))
22919 set_error(
22920 make_error(parser_error::e_syntax,
22921 current_token(),
22922 "ERR098 - Expected '[' for start of range",
22923 exprtk_error_location));
22925 return false;
22928 if (token_is(token_t::e_colon))
22930 rp.n0_c.first = true;
22931 rp.n0_c.second = 0;
22932 rp.cache.first = 0;
22934 else
22936 expression_node_ptr r0 = parse_expression();
22938 if (0 == r0)
22940 set_error(
22941 make_error(parser_error::e_syntax,
22942 current_token(),
22943 "ERR099 - Failed parse begin section of range",
22944 exprtk_error_location));
22946 return false;
22948 else if (is_constant_node(r0))
22950 const T r0_value = r0->value();
22952 if (r0_value >= T(0))
22954 rp.n0_c.first = true;
22955 rp.n0_c.second = static_cast<std::size_t>(details::numeric::to_int64(r0_value));
22956 rp.cache.first = rp.n0_c.second;
22959 free_node(node_allocator_,r0);
22961 if (r0_value < T(0))
22963 set_error(
22964 make_error(parser_error::e_syntax,
22965 current_token(),
22966 "ERR100 - Range lower bound less than zero! Constraint: r0 >= 0",
22967 exprtk_error_location));
22969 return false;
22972 else
22974 rp.n0_e.first = true;
22975 rp.n0_e.second = r0;
22978 if (!token_is(token_t::e_colon))
22980 set_error(
22981 make_error(parser_error::e_syntax,
22982 current_token(),
22983 "ERR101 - Expected ':' for break in range",
22984 exprtk_error_location));
22986 rp.free();
22988 return false;
22992 if (token_is(token_t::e_rsqrbracket))
22994 rp.n1_c.first = true;
22995 rp.n1_c.second = std::numeric_limits<std::size_t>::max();
22997 else
22999 expression_node_ptr r1 = parse_expression();
23001 if (0 == r1)
23003 set_error(
23004 make_error(parser_error::e_syntax,
23005 current_token(),
23006 "ERR102 - Failed parse end section of range",
23007 exprtk_error_location));
23009 rp.free();
23011 return false;
23013 else if (is_constant_node(r1))
23015 const T r1_value = r1->value();
23017 if (r1_value >= T(0))
23019 rp.n1_c.first = true;
23020 rp.n1_c.second = static_cast<std::size_t>(details::numeric::to_int64(r1_value));
23021 rp.cache.second = rp.n1_c.second;
23024 free_node(node_allocator_,r1);
23026 if (r1_value < T(0))
23028 set_error(
23029 make_error(parser_error::e_syntax,
23030 current_token(),
23031 "ERR103 - Range upper bound less than zero! Constraint: r1 >= 0",
23032 exprtk_error_location));
23034 return false;
23037 else
23039 rp.n1_e.first = true;
23040 rp.n1_e.second = r1;
23043 if (!token_is(token_t::e_rsqrbracket))
23045 set_error(
23046 make_error(parser_error::e_syntax,
23047 current_token(),
23048 "ERR104 - Expected ']' for start of range",
23049 exprtk_error_location));
23051 rp.free();
23053 return false;
23057 if (rp.const_range())
23059 std::size_t r0 = 0;
23060 std::size_t r1 = 0;
23062 const bool rp_result = rp(r0,r1);
23064 if (!rp_result || (r0 > r1))
23066 set_error(
23067 make_error(parser_error::e_syntax,
23068 current_token(),
23069 "ERR105 - Invalid range, Constraint: r0 <= r1",
23070 exprtk_error_location));
23072 return false;
23076 return true;
23079 inline void lodge_symbol(const std::string& symbol,
23080 const symbol_type st)
23082 dec_.add_symbol(symbol,st);
23085 #ifndef exprtk_disable_string_capabilities
23086 inline expression_node_ptr parse_string()
23088 const std::string symbol = current_token().value;
23090 typedef details::stringvar_node<T>* strvar_node_t;
23092 expression_node_ptr result = error_node();
23093 strvar_node_t const_str_node = static_cast<strvar_node_t>(0);
23095 scope_element& se = sem_.get_active_element(symbol);
23097 if (scope_element::e_string == se.type)
23099 se.active = true;
23100 result = se.str_node;
23101 lodge_symbol(symbol, e_st_local_string);
23103 else
23105 if (!symtab_store_.is_conststr_stringvar(symbol))
23107 set_error(
23108 make_error(parser_error::e_syntax,
23109 current_token(),
23110 "ERR106 - Unknown string symbol",
23111 exprtk_error_location));
23113 return error_node();
23116 result = symtab_store_.get_stringvar(symbol);
23118 if (symtab_store_.is_constant_string(symbol))
23120 const_str_node = static_cast<strvar_node_t>(result);
23121 result = expression_generator_(const_str_node->str());
23124 lodge_symbol(symbol, e_st_string);
23127 if (peek_token_is(token_t::e_lsqrbracket))
23129 next_token();
23131 if (peek_token_is(token_t::e_rsqrbracket))
23133 next_token();
23134 next_token();
23136 if (const_str_node)
23138 free_node(node_allocator_,result);
23140 return expression_generator_(T(const_str_node->size()));
23142 else
23143 return node_allocator_.allocate<details::stringvar_size_node<T> >
23144 (static_cast<details::stringvar_node<T>*>(result)->ref());
23147 range_t rp;
23149 if (!parse_range(rp))
23151 free_node(node_allocator_,result);
23153 return error_node();
23155 else if (const_str_node)
23157 free_node(node_allocator_,result);
23158 result = expression_generator_(const_str_node->ref(),rp);
23160 else
23161 result = expression_generator_(static_cast<details::stringvar_node<T>*>
23162 (result)->ref(), rp);
23164 if (result)
23165 rp.clear();
23167 else
23168 next_token();
23170 return result;
23172 #else
23173 inline expression_node_ptr parse_string()
23175 return error_node();
23177 #endif
23179 #ifndef exprtk_disable_string_capabilities
23180 inline expression_node_ptr parse_const_string()
23182 const std::string const_str = current_token().value;
23183 expression_node_ptr result = expression_generator_(const_str);
23185 if (peek_token_is(token_t::e_lsqrbracket))
23187 next_token();
23189 if (peek_token_is(token_t::e_rsqrbracket))
23191 next_token();
23192 next_token();
23194 free_node(node_allocator_,result);
23196 return expression_generator_(T(const_str.size()));
23199 range_t rp;
23201 if (!parse_range(rp))
23203 free_node(node_allocator_,result);
23205 return error_node();
23208 free_node(node_allocator_,result);
23210 if (rp.n1_c.first && (rp.n1_c.second == std::numeric_limits<std::size_t>::max()))
23212 rp.n1_c.second = const_str.size() - 1;
23213 rp.cache.second = rp.n1_c.second;
23216 if (
23217 (rp.n0_c.first && (rp.n0_c.second >= const_str.size())) ||
23218 (rp.n1_c.first && (rp.n1_c.second >= const_str.size()))
23221 set_error(
23222 make_error(parser_error::e_syntax,
23223 current_token(),
23224 "ERR107 - Overflow in range for string: '" + const_str + "'[" +
23225 (rp.n0_c.first ? details::to_str(static_cast<int>(rp.n0_c.second)) : "?") + ":" +
23226 (rp.n1_c.first ? details::to_str(static_cast<int>(rp.n1_c.second)) : "?") + "]",
23227 exprtk_error_location));
23229 return error_node();
23232 result = expression_generator_(const_str,rp);
23234 if (result)
23235 rp.clear();
23237 else
23238 next_token();
23240 return result;
23242 #else
23243 inline expression_node_ptr parse_const_string()
23245 return error_node();
23247 #endif
23249 inline expression_node_ptr parse_vector()
23251 const std::string symbol = current_token().value;
23253 vector_holder_ptr vec = vector_holder_ptr(0);
23255 const scope_element& se = sem_.get_active_element(symbol);
23257 if (
23258 !details::imatch(se.name, symbol) ||
23259 (se.depth > state_.scope_depth) ||
23260 (scope_element::e_vector != se.type)
23263 if (0 == (vec = symtab_store_.get_vector(symbol)))
23265 set_error(
23266 make_error(parser_error::e_syntax,
23267 current_token(),
23268 "ERR108 - Symbol '" + symbol+ " not a vector",
23269 exprtk_error_location));
23271 return error_node();
23274 else
23275 vec = se.vec_node;
23277 expression_node_ptr index_expr = error_node();
23279 next_token();
23281 if (!token_is(token_t::e_lsqrbracket))
23283 return node_allocator_.allocate<vector_node_t>(vec);
23285 else if (token_is(token_t::e_rsqrbracket))
23287 return expression_generator_(T(vec->size()));
23289 else if (0 == (index_expr = parse_expression()))
23291 set_error(
23292 make_error(parser_error::e_syntax,
23293 current_token(),
23294 "ERR109 - Failed to parse index for vector: '" + symbol + "'",
23295 exprtk_error_location));
23297 return error_node();
23299 else if (!token_is(token_t::e_rsqrbracket))
23301 set_error(
23302 make_error(parser_error::e_syntax,
23303 current_token(),
23304 "ERR110 - Expected ']' for index of vector: '" + symbol + "'",
23305 exprtk_error_location));
23307 free_node(node_allocator_,index_expr);
23309 return error_node();
23312 // Perform compile-time range check
23313 if (details::is_constant_node(index_expr))
23315 const std::size_t index = static_cast<std::size_t>(details::numeric::to_int32(index_expr->value()));
23316 const std::size_t vec_size = vec->size();
23318 if (index >= vec_size)
23320 set_error(
23321 make_error(parser_error::e_syntax,
23322 current_token(),
23323 "ERR111 - Index of " + details::to_str(index) + " out of range for "
23324 "vector '" + symbol + "' of size " + details::to_str(vec_size),
23325 exprtk_error_location));
23327 free_node(node_allocator_,index_expr);
23329 return error_node();
23333 return expression_generator_.vector_element(symbol, vec, index_expr);
23336 inline expression_node_ptr parse_vararg_function_call(ivararg_function<T>* vararg_function, const std::string& vararg_function_name)
23338 std::vector<expression_node_ptr> arg_list;
23340 expression_node_ptr result = error_node();
23342 scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
23344 next_token();
23346 if (token_is(token_t::e_lbracket))
23348 if (token_is(token_t::e_rbracket))
23350 if (!vararg_function->allow_zero_parameters())
23352 set_error(
23353 make_error(parser_error::e_syntax,
23354 current_token(),
23355 "ERR112 - Zero parameter call to vararg function: "
23356 + vararg_function_name + " not allowed",
23357 exprtk_error_location));
23359 return error_node();
23362 else
23364 for ( ; ; )
23366 expression_node_ptr arg = parse_expression();
23368 if (0 == arg)
23369 return error_node();
23370 else
23371 arg_list.push_back(arg);
23373 if (token_is(token_t::e_rbracket))
23374 break;
23375 else if (!token_is(token_t::e_comma))
23377 set_error(
23378 make_error(parser_error::e_syntax,
23379 current_token(),
23380 "ERR113 - Expected ',' for call to vararg function: "
23381 + vararg_function_name,
23382 exprtk_error_location));
23384 return error_node();
23389 else if (!vararg_function->allow_zero_parameters())
23391 set_error(
23392 make_error(parser_error::e_syntax,
23393 current_token(),
23394 "ERR114 - Zero parameter call to vararg function: "
23395 + vararg_function_name + " not allowed",
23396 exprtk_error_location));
23398 return error_node();
23401 if (arg_list.size() < vararg_function->min_num_args())
23403 set_error(
23404 make_error(parser_error::e_syntax,
23405 current_token(),
23406 "ERR115 - Invalid number of parameters to call to vararg function: "
23407 + vararg_function_name + ", require at least "
23408 + details::to_str(static_cast<int>(vararg_function->min_num_args())) + " parameters",
23409 exprtk_error_location));
23411 return error_node();
23413 else if (arg_list.size() > vararg_function->max_num_args())
23415 set_error(
23416 make_error(parser_error::e_syntax,
23417 current_token(),
23418 "ERR116 - Invalid number of parameters to call to vararg function: "
23419 + vararg_function_name + ", require no more than "
23420 + details::to_str(static_cast<int>(vararg_function->max_num_args())) + " parameters",
23421 exprtk_error_location));
23423 return error_node();
23426 result = expression_generator_.vararg_function_call(vararg_function,arg_list);
23428 sdd.delete_ptr = (0 == result);
23430 return result;
23433 class type_checker
23435 public:
23437 enum return_type_t
23439 e_overload = ' ',
23440 e_numeric = 'T',
23441 e_string = 'S'
23444 struct function_prototype_t
23446 return_type_t return_type;
23447 std::string param_seq;
23450 typedef parser<T> parser_t;
23451 typedef std::vector<function_prototype_t> function_definition_list_t;
23453 type_checker(parser_t& p,
23454 const std::string& func_name,
23455 const std::string& func_prototypes,
23456 const return_type_t default_return_type)
23457 : invalid_state_(true),
23458 parser_(p),
23459 function_name_(func_name),
23460 default_return_type_(default_return_type)
23462 parse_function_prototypes(func_prototypes);
23465 void set_default_return_type(const std::string& return_type)
23467 default_return_type_ = return_type;
23470 bool verify(const std::string& param_seq, std::size_t& pseq_index)
23472 if (function_definition_list_.empty())
23473 return true;
23475 std::vector<std::pair<std::size_t,char> > error_list;
23477 for (std::size_t i = 0; i < function_definition_list_.size(); ++i)
23479 details::char_t diff_value = 0;
23480 std::size_t diff_index = 0;
23482 const bool result = details::sequence_match(function_definition_list_[i].param_seq,
23483 param_seq,
23484 diff_index, diff_value);
23486 if (result)
23488 pseq_index = i;
23489 return true;
23491 else
23492 error_list.push_back(std::make_pair(diff_index, diff_value));
23495 if (1 == error_list.size())
23497 parser_.
23498 set_error(
23499 make_error(parser_error::e_syntax,
23500 parser_.current_token(),
23501 "ERR117 - Failed parameter type check for function '" + function_name_ + "', "
23502 "Expected '" + function_definition_list_[0].param_seq +
23503 "' call set: '" + param_seq + "'",
23504 exprtk_error_location));
23506 else
23508 // find first with largest diff_index;
23509 std::size_t max_diff_index = 0;
23511 for (std::size_t i = 1; i < error_list.size(); ++i)
23513 if (error_list[i].first > error_list[max_diff_index].first)
23515 max_diff_index = i;
23519 parser_.
23520 set_error(
23521 make_error(parser_error::e_syntax,
23522 parser_.current_token(),
23523 "ERR118 - Failed parameter type check for function '" + function_name_ + "', "
23524 "Best match: '" + function_definition_list_[max_diff_index].param_seq +
23525 "' call set: '" + param_seq + "'",
23526 exprtk_error_location));
23529 return false;
23532 std::size_t paramseq_count() const
23534 return function_definition_list_.size();
23537 std::string paramseq(const std::size_t& index) const
23539 return function_definition_list_[index].param_seq;
23542 return_type_t return_type(const std::size_t& index) const
23544 return function_definition_list_[index].return_type;
23547 bool invalid() const
23549 return !invalid_state_;
23552 bool allow_zero_parameters() const
23555 for (std::size_t i = 0; i < function_definition_list_.size(); ++i)
23557 if (std::string::npos != function_definition_list_[i].param_seq.find("Z"))
23559 return true;
23563 return false;
23566 private:
23568 std::vector<std::string> split_param_seq(const std::string& param_seq, const details::char_t delimiter = '|') const
23570 std::string::const_iterator current_begin = param_seq.begin();
23571 std::string::const_iterator iter = param_seq.begin();
23573 std::vector<std::string> result;
23575 while (iter != param_seq.end())
23577 if (*iter == delimiter)
23579 result.push_back(std::string(current_begin, iter));
23580 current_begin = ++iter;
23582 else
23583 ++iter;
23586 if (current_begin != iter)
23588 result.push_back(std::string(current_begin, iter));
23591 return result;
23594 inline bool is_valid_token(std::string param_seq,
23595 function_prototype_t& funcproto) const
23597 // Determine return type
23598 funcproto.return_type = default_return_type_;
23600 if (param_seq.size() > 2)
23602 if (':' == param_seq[1])
23604 // Note: Only overloaded igeneric functions can have return
23605 // type definitions.
23606 if (type_checker::e_overload != default_return_type_)
23607 return false;
23609 switch (param_seq[0])
23611 case 'T' : funcproto.return_type = type_checker::e_numeric;
23612 break;
23614 case 'S' : funcproto.return_type = type_checker::e_string;
23615 break;
23617 default : return false;
23620 param_seq.erase(0,2);
23624 if (
23625 (std::string::npos != param_seq.find("?*")) ||
23626 (std::string::npos != param_seq.find("**"))
23629 return false;
23631 else if (
23632 (std::string::npos == param_seq.find_first_not_of("STV*?|")) ||
23633 ("Z" == param_seq)
23636 funcproto.param_seq = param_seq;
23637 return true;
23640 return false;
23643 void parse_function_prototypes(const std::string& func_prototypes)
23645 if (func_prototypes.empty())
23646 return;
23648 std::vector<std::string> param_seq_list = split_param_seq(func_prototypes);
23650 typedef std::map<std::string,std::size_t> param_seq_map_t;
23651 param_seq_map_t param_seq_map;
23653 for (std::size_t i = 0; i < param_seq_list.size(); ++i)
23655 function_prototype_t func_proto;
23657 if (!is_valid_token(param_seq_list[i], func_proto))
23659 invalid_state_ = false;
23661 parser_.
23662 set_error(
23663 make_error(parser_error::e_syntax,
23664 parser_.current_token(),
23665 "ERR119 - Invalid parameter sequence of '" + param_seq_list[i] +
23666 "' for function: " + function_name_,
23667 exprtk_error_location));
23668 return;
23671 param_seq_map_t::const_iterator seq_itr = param_seq_map.find(param_seq_list[i]);
23673 if (param_seq_map.end() != seq_itr)
23675 invalid_state_ = false;
23677 parser_.
23678 set_error(
23679 make_error(parser_error::e_syntax,
23680 parser_.current_token(),
23681 "ERR120 - Function '" + function_name_ + "' has a parameter sequence conflict between " +
23682 "pseq_idx[" + details::to_str(seq_itr->second) + "] and" +
23683 "pseq_idx[" + details::to_str(i) + "] " +
23684 "param seq: " + param_seq_list[i],
23685 exprtk_error_location));
23686 return;
23689 function_definition_list_.push_back(func_proto);
23693 type_checker(const type_checker&);
23694 type_checker& operator=(const type_checker&);
23696 bool invalid_state_;
23697 parser_t& parser_;
23698 std::string function_name_;
23699 const return_type_t default_return_type_;
23700 function_definition_list_t function_definition_list_;
23703 inline expression_node_ptr parse_generic_function_call(igeneric_function<T>* function, const std::string& function_name)
23705 std::vector<expression_node_ptr> arg_list;
23707 scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
23709 next_token();
23711 std::string param_type_list;
23713 type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_string);
23715 if (tc.invalid())
23717 set_error(
23718 make_error(parser_error::e_syntax,
23719 current_token(),
23720 "ERR121 - Type checker instantiation failure for generic function: " + function_name,
23721 exprtk_error_location));
23723 return error_node();
23726 if (token_is(token_t::e_lbracket))
23728 if (token_is(token_t::e_rbracket))
23730 if (
23731 !function->allow_zero_parameters() &&
23732 !tc .allow_zero_parameters()
23735 set_error(
23736 make_error(parser_error::e_syntax,
23737 current_token(),
23738 "ERR122 - Zero parameter call to generic function: "
23739 + function_name + " not allowed",
23740 exprtk_error_location));
23742 return error_node();
23745 else
23747 for ( ; ; )
23749 expression_node_ptr arg = parse_expression();
23751 if (0 == arg)
23752 return error_node();
23754 if (is_ivector_node(arg))
23755 param_type_list += 'V';
23756 else if (is_generally_string_node(arg))
23757 param_type_list += 'S';
23758 else // Everything else is assumed to be a scalar returning expression
23759 param_type_list += 'T';
23761 arg_list.push_back(arg);
23763 if (token_is(token_t::e_rbracket))
23764 break;
23765 else if (!token_is(token_t::e_comma))
23767 set_error(
23768 make_error(parser_error::e_syntax,
23769 current_token(),
23770 "ERR123 - Expected ',' for call to generic function: " + function_name,
23771 exprtk_error_location));
23773 return error_node();
23778 else if (
23779 !function->parameter_sequence.empty() &&
23780 function->allow_zero_parameters () &&
23781 !tc .allow_zero_parameters ()
23784 set_error(
23785 make_error(parser_error::e_syntax,
23786 current_token(),
23787 "ERR124 - Zero parameter call to generic function: "
23788 + function_name + " not allowed",
23789 exprtk_error_location));
23791 return error_node();
23794 std::size_t param_seq_index = 0;
23796 if (
23797 state_.type_check_enabled &&
23798 !tc.verify(param_type_list, param_seq_index)
23801 set_error(
23802 make_error(parser_error::e_syntax,
23803 current_token(),
23804 "ERR125 - Invalid input parameter sequence for call to generic function: " + function_name,
23805 exprtk_error_location));
23807 return error_node();
23810 expression_node_ptr result = error_node();
23812 if (tc.paramseq_count() <= 1)
23813 result = expression_generator_
23814 .generic_function_call(function, arg_list);
23815 else
23816 result = expression_generator_
23817 .generic_function_call(function, arg_list, param_seq_index);
23819 sdd.delete_ptr = (0 == result);
23821 return result;
23824 inline bool parse_igeneric_function_params(std::string& param_type_list,
23825 std::vector<expression_node_ptr>& arg_list,
23826 const std::string& function_name,
23827 igeneric_function<T>* function,
23828 const type_checker& tc)
23830 if (token_is(token_t::e_lbracket))
23832 if (token_is(token_t::e_rbracket))
23834 if (
23835 !function->allow_zero_parameters() &&
23836 !tc .allow_zero_parameters()
23839 set_error(
23840 make_error(parser_error::e_syntax,
23841 current_token(),
23842 "ERR126 - Zero parameter call to generic function: "
23843 + function_name + " not allowed",
23844 exprtk_error_location));
23846 return false;
23849 else
23851 for ( ; ; )
23853 expression_node_ptr arg = parse_expression();
23855 if (0 == arg)
23856 return false;
23858 if (is_ivector_node(arg))
23859 param_type_list += 'V';
23860 else if (is_generally_string_node(arg))
23861 param_type_list += 'S';
23862 else // Everything else is a scalar returning expression
23863 param_type_list += 'T';
23865 arg_list.push_back(arg);
23867 if (token_is(token_t::e_rbracket))
23868 break;
23869 else if (!token_is(token_t::e_comma))
23871 set_error(
23872 make_error(parser_error::e_syntax,
23873 current_token(),
23874 "ERR127 - Expected ',' for call to string function: " + function_name,
23875 exprtk_error_location));
23877 return false;
23882 return true;
23884 else
23885 return false;
23888 #ifndef exprtk_disable_string_capabilities
23889 inline expression_node_ptr parse_string_function_call(igeneric_function<T>* function, const std::string& function_name)
23891 // Move pass the function name
23892 next_token();
23894 std::string param_type_list;
23896 type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_string);
23898 if (
23899 (!function->parameter_sequence.empty()) &&
23900 (0 == tc.paramseq_count())
23903 return error_node();
23906 std::vector<expression_node_ptr> arg_list;
23907 scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
23909 if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc))
23911 return error_node();
23914 std::size_t param_seq_index = 0;
23916 if (!tc.verify(param_type_list, param_seq_index))
23918 set_error(
23919 make_error(parser_error::e_syntax,
23920 current_token(),
23921 "ERR128 - Invalid input parameter sequence for call to string function: " + function_name,
23922 exprtk_error_location));
23924 return error_node();
23927 expression_node_ptr result = error_node();
23929 if (tc.paramseq_count() <= 1)
23930 result = expression_generator_
23931 .string_function_call(function, arg_list);
23932 else
23933 result = expression_generator_
23934 .string_function_call(function, arg_list, param_seq_index);
23936 sdd.delete_ptr = (0 == result);
23938 return result;
23941 inline expression_node_ptr parse_overload_function_call(igeneric_function<T>* function, const std::string& function_name)
23943 // Move pass the function name
23944 next_token();
23946 std::string param_type_list;
23948 type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_overload);
23950 if (
23951 (!function->parameter_sequence.empty()) &&
23952 (0 == tc.paramseq_count())
23955 return error_node();
23958 std::vector<expression_node_ptr> arg_list;
23959 scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
23961 if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc))
23963 return error_node();
23966 std::size_t param_seq_index = 0;
23968 if (!tc.verify(param_type_list, param_seq_index))
23970 set_error(
23971 make_error(parser_error::e_syntax,
23972 current_token(),
23973 "ERR129 - Invalid input parameter sequence for call to overloaded function: " + function_name,
23974 exprtk_error_location));
23976 return error_node();
23979 expression_node_ptr result = error_node();
23981 if (type_checker::e_numeric == tc.return_type(param_seq_index))
23983 if (tc.paramseq_count() <= 1)
23984 result = expression_generator_
23985 .generic_function_call(function, arg_list);
23986 else
23987 result = expression_generator_
23988 .generic_function_call(function, arg_list, param_seq_index);
23990 else if (type_checker::e_string == tc.return_type(param_seq_index))
23992 if (tc.paramseq_count() <= 1)
23993 result = expression_generator_
23994 .string_function_call(function, arg_list);
23995 else
23996 result = expression_generator_
23997 .string_function_call(function, arg_list, param_seq_index);
23999 else
24001 set_error(
24002 make_error(parser_error::e_syntax,
24003 current_token(),
24004 "ERR130 - Invalid return type for call to overloaded function: " + function_name,
24005 exprtk_error_location));
24008 sdd.delete_ptr = (0 == result);
24009 return result;
24011 #endif
24013 template <typename Type, std::size_t NumberOfParameters>
24014 struct parse_special_function_impl
24016 static inline expression_node_ptr process(parser<Type>& p, const details::operator_type opt_type, const std::string& sf_name)
24018 expression_node_ptr branch[NumberOfParameters];
24019 expression_node_ptr result = error_node();
24021 std::fill_n(branch,NumberOfParameters,reinterpret_cast<expression_node_ptr>(0));
24023 scoped_delete<expression_node_t,NumberOfParameters> sd(p,branch);
24025 p.next_token();
24027 if (!p.token_is(token_t::e_lbracket))
24029 p.set_error(
24030 make_error(parser_error::e_syntax,
24031 p.current_token(),
24032 "ERR131 - Expected '(' for special function '" + sf_name + "'",
24033 exprtk_error_location));
24035 return error_node();
24038 for (std::size_t i = 0; i < NumberOfParameters; ++i)
24040 branch[i] = p.parse_expression();
24042 if (0 == branch[i])
24044 return p.error_node();
24046 else if (i < (NumberOfParameters - 1))
24048 if (!p.token_is(token_t::e_comma))
24050 p.set_error(
24051 make_error(parser_error::e_syntax,
24052 p.current_token(),
24053 "ERR132 - Expected ',' before next parameter of special function '" + sf_name + "'",
24054 exprtk_error_location));
24056 return p.error_node();
24061 if (!p.token_is(token_t::e_rbracket))
24063 p.set_error(
24064 make_error(parser_error::e_syntax,
24065 p.current_token(),
24066 "ERR133 - Invalid number of parameters for special function '" + sf_name + "'",
24067 exprtk_error_location));
24069 return p.error_node();
24071 else
24072 result = p.expression_generator_.special_function(opt_type,branch);
24074 sd.delete_ptr = (0 == result);
24076 return result;
24080 inline expression_node_ptr parse_special_function()
24082 const std::string sf_name = current_token().value;
24084 // Expect: $fDD(expr0,expr1,expr2) or $fDD(expr0,expr1,expr2,expr3)
24085 if (
24086 !details::is_digit(sf_name[2]) ||
24087 !details::is_digit(sf_name[3])
24090 set_error(
24091 make_error(parser_error::e_token,
24092 current_token(),
24093 "ERR134 - Invalid special function[1]: " + sf_name,
24094 exprtk_error_location));
24096 return error_node();
24099 const int id = (sf_name[2] - '0') * 10 +
24100 (sf_name[3] - '0');
24102 if (id >= details::e_sffinal)
24104 set_error(
24105 make_error(parser_error::e_token,
24106 current_token(),
24107 "ERR135 - Invalid special function[2]: " + sf_name,
24108 exprtk_error_location));
24110 return error_node();
24113 const int sf_3_to_4 = details::e_sf48;
24114 const details::operator_type opt_type = details::operator_type(id + 1000);
24115 const std::size_t NumberOfParameters = (id < (sf_3_to_4 - 1000)) ? 3U : 4U;
24117 switch (NumberOfParameters)
24119 case 3 : return parse_special_function_impl<T,3>::process((*this), opt_type, sf_name);
24120 case 4 : return parse_special_function_impl<T,4>::process((*this), opt_type, sf_name);
24121 default : return error_node();
24125 inline expression_node_ptr parse_null_statement()
24127 next_token();
24128 return node_allocator_.allocate<details::null_node<T> >();
24131 #ifndef exprtk_disable_break_continue
24132 inline expression_node_ptr parse_break_statement()
24134 if (state_.parsing_break_stmt)
24136 set_error(
24137 make_error(parser_error::e_syntax,
24138 current_token(),
24139 "ERR136 - Break call within a break call is not allowed",
24140 exprtk_error_location));
24142 return error_node();
24145 scoped_bool_negator sbn(state_.parsing_break_stmt);
24147 if (!brkcnt_list_.empty())
24149 next_token();
24151 brkcnt_list_.front() = true;
24153 expression_node_ptr return_expr = error_node();
24155 if (token_is(token_t::e_lsqrbracket))
24157 if (0 == (return_expr = parse_expression()))
24159 set_error(
24160 make_error(parser_error::e_syntax,
24161 current_token(),
24162 "ERR137 - Failed to parse return expression for 'break' statement",
24163 exprtk_error_location));
24165 return error_node();
24167 else if (!token_is(token_t::e_rsqrbracket))
24169 set_error(
24170 make_error(parser_error::e_syntax,
24171 current_token(),
24172 "ERR138 - Expected ']' at the completion of break's return expression",
24173 exprtk_error_location));
24175 free_node(node_allocator_,return_expr);
24177 return error_node();
24181 state_.activate_side_effect("parse_break_statement()");
24183 return node_allocator_.allocate<details::break_node<T> >(return_expr);
24185 else
24187 set_error(
24188 make_error(parser_error::e_syntax,
24189 current_token(),
24190 "ERR139 - Invalid use of 'break', allowed only in the scope of a loop",
24191 exprtk_error_location));
24194 return error_node();
24197 inline expression_node_ptr parse_continue_statement()
24199 if (!brkcnt_list_.empty())
24201 next_token();
24203 brkcnt_list_.front() = true;
24204 state_.activate_side_effect("parse_continue_statement()");
24206 return node_allocator_.allocate<details::continue_node<T> >();
24208 else
24210 set_error(
24211 make_error(parser_error::e_syntax,
24212 current_token(),
24213 "ERR140 - Invalid use of 'continue', allowed only in the scope of a loop",
24214 exprtk_error_location));
24216 return error_node();
24219 #endif
24221 inline expression_node_ptr parse_define_vector_statement(const std::string& vec_name)
24223 expression_node_ptr size_expr = error_node();
24225 if (!token_is(token_t::e_lsqrbracket))
24227 set_error(
24228 make_error(parser_error::e_syntax,
24229 current_token(),
24230 "ERR141 - Expected '[' as part of vector size definition",
24231 exprtk_error_location));
24233 return error_node();
24235 else if (0 == (size_expr = parse_expression()))
24237 set_error(
24238 make_error(parser_error::e_syntax,
24239 current_token(),
24240 "ERR142 - Failed to determine size of vector '" + vec_name + "'",
24241 exprtk_error_location));
24243 return error_node();
24245 else if (!is_constant_node(size_expr))
24247 free_node(node_allocator_,size_expr);
24249 set_error(
24250 make_error(parser_error::e_syntax,
24251 current_token(),
24252 "ERR143 - Expected a literal number as size of vector '" + vec_name + "'",
24253 exprtk_error_location));
24255 return error_node();
24258 const T vector_size = size_expr->value();
24260 free_node(node_allocator_,size_expr);
24262 const T max_vector_size = T(2000000000.0);
24264 if (
24265 (vector_size <= T(0)) ||
24266 std::not_equal_to<T>()
24267 (T(0),vector_size - details::numeric::trunc(vector_size)) ||
24268 (vector_size > max_vector_size)
24271 set_error(
24272 make_error(parser_error::e_syntax,
24273 current_token(),
24274 "ERR144 - Invalid vector size. Must be an integer in the range [0,2e9], size: " +
24275 details::to_str(details::numeric::to_int32(vector_size)),
24276 exprtk_error_location));
24278 return error_node();
24281 std::vector<expression_node_ptr> vec_initilizer_list;
24283 scoped_vec_delete<expression_node_t> svd((*this),vec_initilizer_list);
24285 bool single_value_initialiser = false;
24286 bool vec_to_vec_initialiser = false;
24287 bool null_initialisation = false;
24289 if (!token_is(token_t::e_rsqrbracket))
24291 set_error(
24292 make_error(parser_error::e_syntax,
24293 current_token(),
24294 "ERR145 - Expected ']' as part of vector size definition",
24295 exprtk_error_location));
24297 return error_node();
24299 else if (!token_is(token_t::e_eof))
24301 if (!token_is(token_t::e_assign))
24303 set_error(
24304 make_error(parser_error::e_syntax,
24305 current_token(),
24306 "ERR146 - Expected ':=' as part of vector definition",
24307 exprtk_error_location));
24309 return error_node();
24311 else if (token_is(token_t::e_lsqrbracket))
24313 expression_node_ptr initialiser = parse_expression();
24315 if (0 == initialiser)
24317 set_error(
24318 make_error(parser_error::e_syntax,
24319 current_token(),
24320 "ERR147 - Failed to parse single vector initialiser",
24321 exprtk_error_location));
24323 return error_node();
24326 vec_initilizer_list.push_back(initialiser);
24328 if (!token_is(token_t::e_rsqrbracket))
24330 set_error(
24331 make_error(parser_error::e_syntax,
24332 current_token(),
24333 "ERR148 - Expected ']' to close single value vector initialiser",
24334 exprtk_error_location));
24336 return error_node();
24339 single_value_initialiser = true;
24341 else if (!token_is(token_t::e_lcrlbracket))
24343 expression_node_ptr initialiser = error_node();
24345 // Is this a vector to vector assignment and initialisation?
24346 if (token_t::e_symbol == current_token().type)
24348 // Is it a locally defined vector?
24349 scope_element& se = sem_.get_active_element(current_token().value);
24351 if (scope_element::e_vector == se.type)
24353 if (0 != (initialiser = parse_expression()))
24354 vec_initilizer_list.push_back(initialiser);
24355 else
24356 return error_node();
24358 // Are we dealing with a user defined vector?
24359 else if (symtab_store_.is_vector(current_token().value))
24361 lodge_symbol(current_token().value, e_st_vector);
24363 if (0 != (initialiser = parse_expression()))
24364 vec_initilizer_list.push_back(initialiser);
24365 else
24366 return error_node();
24368 // Are we dealing with a null initialisation vector definition?
24369 else if (token_is(token_t::e_symbol,"null"))
24370 null_initialisation = true;
24373 if (!null_initialisation)
24375 if (0 == initialiser)
24377 set_error(
24378 make_error(parser_error::e_syntax,
24379 current_token(),
24380 "ERR149 - Expected '{' as part of vector initialiser list",
24381 exprtk_error_location));
24383 return error_node();
24385 else
24386 vec_to_vec_initialiser = true;
24389 else if (!token_is(token_t::e_rcrlbracket))
24391 for ( ; ; )
24393 expression_node_ptr initialiser = parse_expression();
24395 if (0 == initialiser)
24397 set_error(
24398 make_error(parser_error::e_syntax,
24399 current_token(),
24400 "ERR150 - Expected '{' as part of vector initialiser list",
24401 exprtk_error_location));
24403 return error_node();
24405 else
24406 vec_initilizer_list.push_back(initialiser);
24408 if (token_is(token_t::e_rcrlbracket))
24409 break;
24411 const bool is_next_close = peek_token_is(token_t::e_rcrlbracket);
24413 if (!token_is(token_t::e_comma) && is_next_close)
24415 set_error(
24416 make_error(parser_error::e_syntax,
24417 current_token(),
24418 "ERR151 - Expected ',' between vector initialisers",
24419 exprtk_error_location));
24421 return error_node();
24424 if (token_is(token_t::e_rcrlbracket))
24425 break;
24429 if (
24430 !token_is(token_t::e_rbracket , prsrhlpr_t::e_hold) &&
24431 !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) &&
24432 !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold)
24435 if (!token_is(token_t::e_eof))
24437 set_error(
24438 make_error(parser_error::e_syntax,
24439 current_token(),
24440 "ERR152 - Expected ';' at end of vector definition",
24441 exprtk_error_location));
24443 return error_node();
24447 if (vec_initilizer_list.size() > vector_size)
24449 set_error(
24450 make_error(parser_error::e_syntax,
24451 current_token(),
24452 "ERR153 - Initialiser list larger than the number of elements in the vector: '" + vec_name + "'",
24453 exprtk_error_location));
24455 return error_node();
24459 typename symbol_table_t::vector_holder_ptr vec_holder = typename symbol_table_t::vector_holder_ptr(0);
24461 const std::size_t vec_size = static_cast<std::size_t>(details::numeric::to_int32(vector_size));
24463 scope_element& se = sem_.get_element(vec_name);
24465 if (se.name == vec_name)
24467 if (se.active)
24469 set_error(
24470 make_error(parser_error::e_syntax,
24471 current_token(),
24472 "ERR154 - Illegal redefinition of local vector: '" + vec_name + "'",
24473 exprtk_error_location));
24475 return error_node();
24477 else if (
24478 (se.size == vec_size) &&
24479 (scope_element::e_vector == se.type)
24482 vec_holder = se.vec_node;
24483 se.active = true;
24484 se.depth = state_.scope_depth;
24485 se.ref_count++;
24489 if (0 == vec_holder)
24491 scope_element nse;
24492 nse.name = vec_name;
24493 nse.active = true;
24494 nse.ref_count = 1;
24495 nse.type = scope_element::e_vector;
24496 nse.depth = state_.scope_depth;
24497 nse.size = vec_size;
24498 nse.data = new T[vec_size];
24499 nse.vec_node = new typename scope_element::vector_holder_t((T*)(nse.data),nse.size);
24501 if (!sem_.add_element(nse))
24503 set_error(
24504 make_error(parser_error::e_syntax,
24505 current_token(),
24506 "ERR155 - Failed to add new local vector '" + vec_name + "' to SEM",
24507 exprtk_error_location));
24509 sem_.free_element(nse);
24511 return error_node();
24514 vec_holder = nse.vec_node;
24516 exprtk_debug(("parse_define_vector_statement() - INFO - Added new local vector: %s[%d]\n",
24517 nse.name.c_str(),
24518 static_cast<int>(nse.size)));
24521 state_.activate_side_effect("parse_define_vector_statement()");
24523 lodge_symbol(vec_name, e_st_local_vector);
24525 expression_node_ptr result = error_node();
24527 if (null_initialisation)
24528 result = expression_generator_(T(0.0));
24529 else if (vec_to_vec_initialiser)
24531 expression_node_ptr vec_node = node_allocator_.allocate<vector_node_t>(vec_holder);
24533 result = expression_generator_(
24534 details::e_assign,
24535 vec_node,
24536 vec_initilizer_list[0]);
24538 else
24539 result = node_allocator_
24540 .allocate<details::vector_assignment_node<T> >(
24541 (*vec_holder)[0],
24542 vec_size,
24543 vec_initilizer_list,
24544 single_value_initialiser);
24546 svd.delete_ptr = (0 == result);
24548 return result;
24551 #ifndef exprtk_disable_string_capabilities
24552 inline expression_node_ptr parse_define_string_statement(const std::string& str_name, expression_node_ptr initialisation_expression)
24554 stringvar_node_t* str_node = reinterpret_cast<stringvar_node_t*>(0);
24556 scope_element& se = sem_.get_element(str_name);
24558 if (se.name == str_name)
24560 if (se.active)
24562 set_error(
24563 make_error(parser_error::e_syntax,
24564 current_token(),
24565 "ERR156 - Illegal redefinition of local variable: '" + str_name + "'",
24566 exprtk_error_location));
24568 free_node(node_allocator_,initialisation_expression);
24570 return error_node();
24572 else if (scope_element::e_string == se.type)
24574 str_node = se.str_node;
24575 se.active = true;
24576 se.depth = state_.scope_depth;
24577 se.ref_count++;
24581 if (0 == str_node)
24583 scope_element nse;
24584 nse.name = str_name;
24585 nse.active = true;
24586 nse.ref_count = 1;
24587 nse.type = scope_element::e_string;
24588 nse.depth = state_.scope_depth;
24589 nse.data = new std::string;
24590 nse.str_node = new stringvar_node_t(*(std::string*)(nse.data));
24592 if (!sem_.add_element(nse))
24594 set_error(
24595 make_error(parser_error::e_syntax,
24596 current_token(),
24597 "ERR157 - Failed to add new local string variable '" + str_name + "' to SEM",
24598 exprtk_error_location));
24600 free_node(node_allocator_,initialisation_expression);
24602 sem_.free_element(nse);
24604 return error_node();
24607 str_node = nse.str_node;
24609 exprtk_debug(("parse_define_string_statement() - INFO - Added new local string variable: %s\n",nse.name.c_str()));
24612 lodge_symbol(str_name, e_st_local_string);
24614 state_.activate_side_effect("parse_define_string_statement()");
24616 expression_node_ptr branch[2] = {0};
24618 branch[0] = str_node;
24619 branch[1] = initialisation_expression;
24621 return expression_generator_(details::e_assign,branch);
24623 #else
24624 inline expression_node_ptr parse_define_string_statement(const std::string&, expression_node_ptr)
24626 return error_node();
24628 #endif
24630 inline bool local_variable_is_shadowed(const std::string& symbol)
24632 const scope_element& se = sem_.get_element(symbol);
24633 return (se.name == symbol) && se.active;
24636 inline expression_node_ptr parse_define_var_statement()
24638 if (settings_.vardef_disabled())
24640 set_error(
24641 make_error(parser_error::e_syntax,
24642 current_token(),
24643 "ERR158 - Illegal variable definition",
24644 exprtk_error_location));
24646 return error_node();
24648 else if (!details::imatch(current_token().value,"var"))
24650 return error_node();
24652 else
24653 next_token();
24655 const std::string var_name = current_token().value;
24657 expression_node_ptr initialisation_expression = error_node();
24659 if (!token_is(token_t::e_symbol))
24661 set_error(
24662 make_error(parser_error::e_syntax,
24663 current_token(),
24664 "ERR159 - Expected a symbol for variable definition",
24665 exprtk_error_location));
24667 return error_node();
24669 else if (details::is_reserved_symbol(var_name))
24671 set_error(
24672 make_error(parser_error::e_syntax,
24673 current_token(),
24674 "ERR160 - Illegal redefinition of reserved keyword: '" + var_name + "'",
24675 exprtk_error_location));
24677 return error_node();
24679 else if (symtab_store_.symbol_exists(var_name))
24681 set_error(
24682 make_error(parser_error::e_syntax,
24683 current_token(),
24684 "ERR161 - Illegal redefinition of variable '" + var_name + "'",
24685 exprtk_error_location));
24687 return error_node();
24689 else if (local_variable_is_shadowed(var_name))
24691 set_error(
24692 make_error(parser_error::e_syntax,
24693 current_token(),
24694 "ERR162 - Illegal redefinition of local variable: '" + var_name + "'",
24695 exprtk_error_location));
24697 return error_node();
24699 else if (token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold))
24701 return parse_define_vector_statement(var_name);
24703 else if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
24705 return parse_uninitialised_var_statement(var_name);
24707 else if (token_is(token_t::e_assign))
24709 if (0 == (initialisation_expression = parse_expression()))
24711 set_error(
24712 make_error(parser_error::e_syntax,
24713 current_token(),
24714 "ERR163 - Failed to parse initialisation expression",
24715 exprtk_error_location));
24717 return error_node();
24721 if (
24722 !token_is(token_t::e_rbracket , prsrhlpr_t::e_hold) &&
24723 !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) &&
24724 !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold)
24727 if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold))
24729 set_error(
24730 make_error(parser_error::e_syntax,
24731 current_token(),
24732 "ERR164 - Expected ';' after variable definition",
24733 exprtk_error_location));
24735 free_node(node_allocator_,initialisation_expression);
24737 return error_node();
24741 if (
24742 (0 != initialisation_expression) &&
24743 details::is_generally_string_node(initialisation_expression)
24746 return parse_define_string_statement(var_name,initialisation_expression);
24749 expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0);
24751 scope_element& se = sem_.get_element(var_name);
24753 if (se.name == var_name)
24755 if (se.active)
24757 set_error(
24758 make_error(parser_error::e_syntax,
24759 current_token(),
24760 "ERR165 - Illegal redefinition of local variable: '" + var_name + "'",
24761 exprtk_error_location));
24763 free_node(node_allocator_, initialisation_expression);
24765 return error_node();
24767 else if (scope_element::e_variable == se.type)
24769 var_node = se.var_node;
24770 se.active = true;
24771 se.depth = state_.scope_depth;
24772 se.ref_count++;
24776 if (0 == var_node)
24778 scope_element nse;
24779 nse.name = var_name;
24780 nse.active = true;
24781 nse.ref_count = 1;
24782 nse.type = scope_element::e_variable;
24783 nse.depth = state_.scope_depth;
24784 nse.data = new T(T(0));
24785 nse.var_node = node_allocator_.allocate<variable_node_t>(*(T*)(nse.data));
24787 if (!sem_.add_element(nse))
24789 set_error(
24790 make_error(parser_error::e_syntax,
24791 current_token(),
24792 "ERR166 - Failed to add new local variable '" + var_name + "' to SEM",
24793 exprtk_error_location));
24795 free_node(node_allocator_, initialisation_expression);
24797 sem_.free_element(nse);
24799 return error_node();
24802 var_node = nse.var_node;
24804 exprtk_debug(("parse_define_var_statement() - INFO - Added new local variable: %s\n",nse.name.c_str()));
24807 state_.activate_side_effect("parse_define_var_statement()");
24809 lodge_symbol(var_name, e_st_local_variable);
24811 expression_node_ptr branch[2] = {0};
24813 branch[0] = var_node;
24814 branch[1] = initialisation_expression ? initialisation_expression : expression_generator_(T(0));
24816 return expression_generator_(details::e_assign,branch);
24819 inline expression_node_ptr parse_uninitialised_var_statement(const std::string& var_name)
24821 if (
24822 !token_is(token_t::e_lcrlbracket) ||
24823 !token_is(token_t::e_rcrlbracket)
24826 set_error(
24827 make_error(parser_error::e_syntax,
24828 current_token(),
24829 "ERR167 - Expected a '{}' for uninitialised var definition",
24830 exprtk_error_location));
24832 return error_node();
24834 else if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold))
24836 set_error(
24837 make_error(parser_error::e_syntax,
24838 current_token(),
24839 "ERR168 - Expected ';' after uninitialised variable definition",
24840 exprtk_error_location));
24842 return error_node();
24845 expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0);
24847 scope_element& se = sem_.get_element(var_name);
24849 if (se.name == var_name)
24851 if (se.active)
24853 set_error(
24854 make_error(parser_error::e_syntax,
24855 current_token(),
24856 "ERR169 - Illegal redefinition of local variable: '" + var_name + "'",
24857 exprtk_error_location));
24859 return error_node();
24861 else if (scope_element::e_variable == se.type)
24863 var_node = se.var_node;
24864 se.active = true;
24865 se.ref_count++;
24869 if (0 == var_node)
24871 scope_element nse;
24872 nse.name = var_name;
24873 nse.active = true;
24874 nse.ref_count = 1;
24875 nse.type = scope_element::e_variable;
24876 nse.depth = state_.scope_depth;
24877 nse.ip_index = sem_.next_ip_index();
24878 nse.data = new T(T(0));
24879 nse.var_node = node_allocator_.allocate<variable_node_t>(*(T*)(nse.data));
24881 if (!sem_.add_element(nse))
24883 set_error(
24884 make_error(parser_error::e_syntax,
24885 current_token(),
24886 "ERR170 - Failed to add new local variable '" + var_name + "' to SEM",
24887 exprtk_error_location));
24889 sem_.free_element(nse);
24891 return error_node();
24894 exprtk_debug(("parse_uninitialised_var_statement() - INFO - Added new local variable: %s\n",
24895 nse.name.c_str()));
24898 lodge_symbol(var_name, e_st_local_variable);
24900 state_.activate_side_effect("parse_uninitialised_var_statement()");
24902 return expression_generator_(T(0));
24905 inline expression_node_ptr parse_swap_statement()
24907 if (!details::imatch(current_token().value,"swap"))
24909 return error_node();
24911 else
24912 next_token();
24914 if (!token_is(token_t::e_lbracket))
24916 set_error(
24917 make_error(parser_error::e_syntax,
24918 current_token(),
24919 "ERR171 - Expected '(' at start of swap statement",
24920 exprtk_error_location));
24922 return error_node();
24925 expression_node_ptr variable0 = error_node();
24926 expression_node_ptr variable1 = error_node();
24928 bool variable0_generated = false;
24929 bool variable1_generated = false;
24931 const std::string var0_name = current_token().value;
24933 if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold))
24935 set_error(
24936 make_error(parser_error::e_syntax,
24937 current_token(),
24938 "ERR172 - Expected a symbol for variable or vector element definition",
24939 exprtk_error_location));
24941 return error_node();
24943 else if (peek_token_is(token_t::e_lsqrbracket))
24945 if (0 == (variable0 = parse_vector()))
24947 set_error(
24948 make_error(parser_error::e_syntax,
24949 current_token(),
24950 "ERR173 - First parameter to swap is an invalid vector element: '" + var0_name + "'",
24951 exprtk_error_location));
24953 return error_node();
24956 variable0_generated = true;
24958 else
24960 if (symtab_store_.is_variable(var0_name))
24962 variable0 = symtab_store_.get_variable(var0_name);
24965 scope_element& se = sem_.get_element(var0_name);
24967 if (
24968 (se.active) &&
24969 (se.name == var0_name) &&
24970 (scope_element::e_variable == se.type)
24973 variable0 = se.var_node;
24976 lodge_symbol(var0_name, e_st_variable);
24978 if (0 == variable0)
24980 set_error(
24981 make_error(parser_error::e_syntax,
24982 current_token(),
24983 "ERR174 - First parameter to swap is an invalid variable: '" + var0_name + "'",
24984 exprtk_error_location));
24986 return error_node();
24988 else
24989 next_token();
24992 if (!token_is(token_t::e_comma))
24994 set_error(
24995 make_error(parser_error::e_syntax,
24996 current_token(),
24997 "ERR175 - Expected ',' between parameters to swap",
24998 exprtk_error_location));
25000 if (variable0_generated)
25002 free_node(node_allocator_,variable0);
25005 return error_node();
25008 const std::string var1_name = current_token().value;
25010 if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold))
25012 set_error(
25013 make_error(parser_error::e_syntax,
25014 current_token(),
25015 "ERR176 - Expected a symbol for variable or vector element definition",
25016 exprtk_error_location));
25018 if (variable0_generated)
25020 free_node(node_allocator_,variable0);
25023 return error_node();
25025 else if (peek_token_is(token_t::e_lsqrbracket))
25027 if (0 == (variable1 = parse_vector()))
25029 set_error(
25030 make_error(parser_error::e_syntax,
25031 current_token(),
25032 "ERR177 - Second parameter to swap is an invalid vector element: '" + var1_name + "'",
25033 exprtk_error_location));
25035 if (variable0_generated)
25037 free_node(node_allocator_,variable0);
25040 return error_node();
25043 variable1_generated = true;
25045 else
25047 if (symtab_store_.is_variable(var1_name))
25049 variable1 = symtab_store_.get_variable(var1_name);
25052 scope_element& se = sem_.get_element(var1_name);
25054 if (
25055 (se.active) &&
25056 (se.name == var1_name) &&
25057 (scope_element::e_variable == se.type)
25060 variable1 = se.var_node;
25063 lodge_symbol(var1_name, e_st_variable);
25065 if (0 == variable1)
25067 set_error(
25068 make_error(parser_error::e_syntax,
25069 current_token(),
25070 "ERR178 - Second parameter to swap is an invalid variable: '" + var1_name + "'",
25071 exprtk_error_location));
25073 if (variable0_generated)
25075 free_node(node_allocator_,variable0);
25078 return error_node();
25080 else
25081 next_token();
25084 if (!token_is(token_t::e_rbracket))
25086 set_error(
25087 make_error(parser_error::e_syntax,
25088 current_token(),
25089 "ERR179 - Expected ')' at end of swap statement",
25090 exprtk_error_location));
25092 if (variable0_generated)
25094 free_node(node_allocator_,variable0);
25097 if (variable1_generated)
25099 free_node(node_allocator_,variable1);
25102 return error_node();
25105 typedef details::variable_node<T>* variable_node_ptr;
25107 variable_node_ptr v0 = variable_node_ptr(0);
25108 variable_node_ptr v1 = variable_node_ptr(0);
25110 expression_node_ptr result = error_node();
25112 if (
25113 (0 != (v0 = dynamic_cast<variable_node_ptr>(variable0))) &&
25114 (0 != (v1 = dynamic_cast<variable_node_ptr>(variable1)))
25117 result = node_allocator_.allocate<details::swap_node<T> >(v0, v1);
25119 if (variable0_generated)
25121 free_node(node_allocator_,variable0);
25124 if (variable1_generated)
25126 free_node(node_allocator_,variable1);
25129 else
25130 result = node_allocator_.allocate<details::swap_generic_node<T> >
25131 (variable0, variable1);
25133 state_.activate_side_effect("parse_swap_statement()");
25135 return result;
25138 #ifndef exprtk_disable_return_statement
25139 inline expression_node_ptr parse_return_statement()
25141 if (state_.parsing_return_stmt)
25143 set_error(
25144 make_error(parser_error::e_syntax,
25145 current_token(),
25146 "ERR180 - Return call within a return call is not allowed",
25147 exprtk_error_location));
25149 return error_node();
25152 scoped_bool_negator sbn(state_.parsing_return_stmt);
25154 std::vector<expression_node_ptr> arg_list;
25156 scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
25158 if (!details::imatch(current_token().value,"return"))
25160 return error_node();
25162 else
25163 next_token();
25165 if (!token_is(token_t::e_lsqrbracket))
25167 set_error(
25168 make_error(parser_error::e_syntax,
25169 current_token(),
25170 "ERR181 - Expected '[' at start of return statement",
25171 exprtk_error_location));
25173 return error_node();
25175 else if (!token_is(token_t::e_rsqrbracket))
25177 for ( ; ; )
25179 expression_node_ptr arg = parse_expression();
25181 if (0 == arg)
25182 return error_node();
25184 arg_list.push_back(arg);
25186 if (token_is(token_t::e_rsqrbracket))
25187 break;
25188 else if (!token_is(token_t::e_comma))
25190 set_error(
25191 make_error(parser_error::e_syntax,
25192 current_token(),
25193 "ERR182 - Expected ',' between values during call to return",
25194 exprtk_error_location));
25196 return error_node();
25200 else if (settings_.zero_return_disabled())
25202 set_error(
25203 make_error(parser_error::e_syntax,
25204 current_token(),
25205 "ERR183 - Zero parameter return statement not allowed",
25206 exprtk_error_location));
25208 return error_node();
25211 const lexer::token prev_token = current_token();
25213 if (token_is(token_t::e_rsqrbracket))
25215 if (!arg_list.empty())
25217 set_error(
25218 make_error(parser_error::e_syntax,
25219 prev_token,
25220 "ERR184 - Invalid ']' found during return call",
25221 exprtk_error_location));
25223 return error_node();
25227 std::string ret_param_type_list;
25229 for (std::size_t i = 0; i < arg_list.size(); ++i)
25231 if (0 == arg_list[i])
25232 return error_node();
25233 else if (is_ivector_node(arg_list[i]))
25234 ret_param_type_list += 'V';
25235 else if (is_generally_string_node(arg_list[i]))
25236 ret_param_type_list += 'S';
25237 else
25238 ret_param_type_list += 'T';
25241 dec_.retparam_list_.push_back(ret_param_type_list);
25243 expression_node_ptr result = expression_generator_.return_call(arg_list);
25245 sdd.delete_ptr = (0 == result);
25247 state_.return_stmt_present = true;
25249 state_.activate_side_effect("parse_return_statement()");
25251 return result;
25253 #else
25254 inline expression_node_ptr parse_return_statement()
25256 return error_node();
25258 #endif
25260 inline bool post_variable_process(const std::string& symbol)
25262 if (
25263 peek_token_is(token_t::e_lbracket ) ||
25264 peek_token_is(token_t::e_lcrlbracket) ||
25265 peek_token_is(token_t::e_lsqrbracket)
25268 if (!settings_.commutative_check_enabled())
25270 set_error(
25271 make_error(parser_error::e_syntax,
25272 current_token(),
25273 "ERR185 - Invalid sequence of variable '"+ symbol + "' and bracket",
25274 exprtk_error_location));
25276 return false;
25279 lexer().insert_front(token_t::e_mul);
25282 return true;
25285 inline bool post_bracket_process(const typename token_t::token_type& token, expression_node_ptr& branch)
25287 bool implied_mul = false;
25289 if (is_generally_string_node(branch))
25290 return true;
25292 const lexer::parser_helper::token_advance_mode hold = prsrhlpr_t::e_hold;
25294 switch (token)
25296 case token_t::e_lcrlbracket : implied_mul = token_is(token_t::e_lbracket ,hold) ||
25297 token_is(token_t::e_lcrlbracket,hold) ||
25298 token_is(token_t::e_lsqrbracket,hold) ;
25299 break;
25301 case token_t::e_lbracket : implied_mul = token_is(token_t::e_lbracket ,hold) ||
25302 token_is(token_t::e_lcrlbracket,hold) ||
25303 token_is(token_t::e_lsqrbracket,hold) ;
25304 break;
25306 case token_t::e_lsqrbracket : implied_mul = token_is(token_t::e_lbracket ,hold) ||
25307 token_is(token_t::e_lcrlbracket,hold) ||
25308 token_is(token_t::e_lsqrbracket,hold) ;
25309 break;
25311 default : return true;
25314 if (implied_mul)
25316 if (!settings_.commutative_check_enabled())
25318 set_error(
25319 make_error(parser_error::e_syntax,
25320 current_token(),
25321 "ERR186 - Invalid sequence of brackets",
25322 exprtk_error_location));
25324 return false;
25326 else if (token_t::e_eof != current_token().type)
25328 lexer().insert_front(current_token().type);
25329 lexer().insert_front(token_t::e_mul);
25330 next_token();
25334 return true;
25337 inline expression_node_ptr parse_symtab_symbol()
25339 const std::string symbol = current_token().value;
25341 // Are we dealing with a variable or a special constant?
25342 expression_node_ptr variable = symtab_store_.get_variable(symbol);
25344 if (variable)
25346 if (symtab_store_.is_constant_node(symbol))
25348 variable = expression_generator_(variable->value());
25351 if (!post_variable_process(symbol))
25352 return error_node();
25354 lodge_symbol(symbol, e_st_variable);
25355 next_token();
25357 return variable;
25360 // Are we dealing with a locally defined variable, vector or string?
25361 if (!sem_.empty())
25363 scope_element& se = sem_.get_active_element(symbol);
25365 if (se.active && details::imatch(se.name, symbol))
25367 if (scope_element::e_variable == se.type)
25369 se.active = true;
25370 lodge_symbol(symbol, e_st_local_variable);
25372 if (!post_variable_process(symbol))
25373 return error_node();
25375 next_token();
25377 return se.var_node;
25379 else if (scope_element::e_vector == se.type)
25381 return parse_vector();
25383 #ifndef exprtk_disable_string_capabilities
25384 else if (scope_element::e_string == se.type)
25386 return parse_string();
25388 #endif
25392 #ifndef exprtk_disable_string_capabilities
25393 // Are we dealing with a string variable?
25394 if (symtab_store_.is_stringvar(symbol))
25396 return parse_string();
25398 #endif
25401 // Are we dealing with a function?
25402 ifunction<T>* function = symtab_store_.get_function(symbol);
25404 if (function)
25406 lodge_symbol(symbol, e_st_function);
25408 expression_node_ptr func_node =
25409 parse_function_invocation(function,symbol);
25411 if (func_node)
25412 return func_node;
25413 else
25415 set_error(
25416 make_error(parser_error::e_syntax,
25417 current_token(),
25418 "ERR187 - Failed to generate node for function: '" + symbol + "'",
25419 exprtk_error_location));
25421 return error_node();
25427 // Are we dealing with a vararg function?
25428 ivararg_function<T>* vararg_function = symtab_store_.get_vararg_function(symbol);
25430 if (vararg_function)
25432 lodge_symbol(symbol, e_st_function);
25434 expression_node_ptr vararg_func_node =
25435 parse_vararg_function_call(vararg_function, symbol);
25437 if (vararg_func_node)
25438 return vararg_func_node;
25439 else
25441 set_error(
25442 make_error(parser_error::e_syntax,
25443 current_token(),
25444 "ERR188 - Failed to generate node for vararg function: '" + symbol + "'",
25445 exprtk_error_location));
25447 return error_node();
25453 // Are we dealing with a vararg generic function?
25454 igeneric_function<T>* generic_function = symtab_store_.get_generic_function(symbol);
25456 if (generic_function)
25458 lodge_symbol(symbol, e_st_function);
25460 expression_node_ptr genericfunc_node =
25461 parse_generic_function_call(generic_function, symbol);
25463 if (genericfunc_node)
25464 return genericfunc_node;
25465 else
25467 set_error(
25468 make_error(parser_error::e_syntax,
25469 current_token(),
25470 "ERR189 - Failed to generate node for generic function: '" + symbol + "'",
25471 exprtk_error_location));
25473 return error_node();
25478 #ifndef exprtk_disable_string_capabilities
25480 // Are we dealing with a vararg string returning function?
25481 igeneric_function<T>* string_function = symtab_store_.get_string_function(symbol);
25483 if (string_function)
25485 lodge_symbol(symbol, e_st_function);
25487 expression_node_ptr stringfunc_node =
25488 parse_string_function_call(string_function, symbol);
25490 if (stringfunc_node)
25491 return stringfunc_node;
25492 else
25494 set_error(
25495 make_error(parser_error::e_syntax,
25496 current_token(),
25497 "ERR190 - Failed to generate node for string function: '" + symbol + "'",
25498 exprtk_error_location));
25500 return error_node();
25506 // Are we dealing with a vararg overloaded scalar/string returning function?
25507 igeneric_function<T>* overload_function = symtab_store_.get_overload_function(symbol);
25509 if (overload_function)
25511 lodge_symbol(symbol, e_st_function);
25513 expression_node_ptr overloadfunc_node =
25514 parse_overload_function_call(overload_function, symbol);
25516 if (overloadfunc_node)
25517 return overloadfunc_node;
25518 else
25520 set_error(
25521 make_error(parser_error::e_syntax,
25522 current_token(),
25523 "ERR191 - Failed to generate node for overload function: '" + symbol + "'",
25524 exprtk_error_location));
25526 return error_node();
25530 #endif
25532 // Are we dealing with a vector?
25533 if (symtab_store_.is_vector(symbol))
25535 lodge_symbol(symbol, e_st_vector);
25536 return parse_vector();
25539 if (details::is_reserved_symbol(symbol))
25541 if (
25542 settings_.function_enabled(symbol) ||
25543 !details::is_base_function(symbol)
25546 set_error(
25547 make_error(parser_error::e_syntax,
25548 current_token(),
25549 "ERR192 - Invalid use of reserved symbol '" + symbol + "'",
25550 exprtk_error_location));
25552 return error_node();
25556 // Should we handle unknown symbols?
25557 if (resolve_unknown_symbol_ && unknown_symbol_resolver_)
25559 if (!(settings_.rsrvd_sym_usr_disabled() && details::is_reserved_symbol(symbol)))
25561 symbol_table_t& symtab = symtab_store_.get_symbol_table();
25563 std::string error_message;
25565 if (unknown_symbol_resolver::e_usrmode_default == unknown_symbol_resolver_->mode)
25567 T default_value = T(0);
25569 typename unknown_symbol_resolver::usr_symbol_type usr_symbol_type = unknown_symbol_resolver::e_usr_unknown_type;
25571 if (unknown_symbol_resolver_->process(symbol, usr_symbol_type, default_value, error_message))
25573 bool create_result = false;
25575 switch (usr_symbol_type)
25577 case unknown_symbol_resolver::e_usr_variable_type : create_result = symtab.create_variable(symbol, default_value);
25578 break;
25580 case unknown_symbol_resolver::e_usr_constant_type : create_result = symtab.add_constant(symbol, default_value);
25581 break;
25583 default : create_result = false;
25586 if (create_result)
25588 expression_node_ptr var = symtab_store_.get_variable(symbol);
25590 if (var)
25592 if (symtab_store_.is_constant_node(symbol))
25594 var = expression_generator_(var->value());
25597 lodge_symbol(symbol, e_st_variable);
25599 if (!post_variable_process(symbol))
25600 return error_node();
25602 next_token();
25604 return var;
25609 set_error(
25610 make_error(parser_error::e_symtab,
25611 current_token(),
25612 "ERR193 - Failed to create variable: '" + symbol + "'" +
25613 (error_message.empty() ? "" : " - " + error_message),
25614 exprtk_error_location));
25617 else if (unknown_symbol_resolver::e_usrmode_extended == unknown_symbol_resolver_->mode)
25619 if (unknown_symbol_resolver_->process(symbol, symtab, error_message))
25621 expression_node_ptr result = parse_symtab_symbol();
25623 if (result)
25625 return result;
25629 set_error(
25630 make_error(parser_error::e_symtab,
25631 current_token(),
25632 "ERR194 - Failed to resolve symbol: '" + symbol + "'" +
25633 (error_message.empty() ? "" : " - " + error_message),
25634 exprtk_error_location));
25637 return error_node();
25641 set_error(
25642 make_error(parser_error::e_syntax,
25643 current_token(),
25644 "ERR195 - Undefined symbol: '" + symbol + "'",
25645 exprtk_error_location));
25647 return error_node();
25650 inline expression_node_ptr parse_symbol()
25652 static const std::string symbol_if = "if" ;
25653 static const std::string symbol_while = "while" ;
25654 static const std::string symbol_repeat = "repeat" ;
25655 static const std::string symbol_for = "for" ;
25656 static const std::string symbol_switch = "switch" ;
25657 static const std::string symbol_null = "null" ;
25658 static const std::string symbol_break = "break" ;
25659 static const std::string symbol_continue = "continue";
25660 static const std::string symbol_var = "var" ;
25661 static const std::string symbol_swap = "swap" ;
25662 static const std::string symbol_return = "return" ;
25663 static const std::string symbol_not = "not" ;
25665 if (valid_vararg_operation(current_token().value))
25667 return parse_vararg_function();
25669 else if (details::imatch(current_token().value, symbol_not))
25671 return parse_not_statement();
25673 else if (valid_base_operation(current_token().value))
25675 return parse_base_operation();
25677 else if (
25678 details::imatch(current_token().value, symbol_if) &&
25679 settings_.control_struct_enabled(current_token().value)
25682 return parse_conditional_statement();
25684 else if (
25685 details::imatch(current_token().value, symbol_while) &&
25686 settings_.control_struct_enabled(current_token().value)
25689 return parse_while_loop();
25691 else if (
25692 details::imatch(current_token().value, symbol_repeat) &&
25693 settings_.control_struct_enabled(current_token().value)
25696 return parse_repeat_until_loop();
25698 else if (
25699 details::imatch(current_token().value, symbol_for) &&
25700 settings_.control_struct_enabled(current_token().value)
25703 return parse_for_loop();
25705 else if (
25706 details::imatch(current_token().value, symbol_switch) &&
25707 settings_.control_struct_enabled(current_token().value)
25710 return parse_switch_statement();
25712 else if (details::is_valid_sf_symbol(current_token().value))
25714 return parse_special_function();
25716 else if (details::imatch(current_token().value, symbol_null))
25718 return parse_null_statement();
25720 #ifndef exprtk_disable_break_continue
25721 else if (details::imatch(current_token().value, symbol_break))
25723 return parse_break_statement();
25725 else if (details::imatch(current_token().value, symbol_continue))
25727 return parse_continue_statement();
25729 #endif
25730 else if (details::imatch(current_token().value, symbol_var))
25732 return parse_define_var_statement();
25734 else if (details::imatch(current_token().value, symbol_swap))
25736 return parse_swap_statement();
25738 #ifndef exprtk_disable_return_statement
25739 else if (
25740 details::imatch(current_token().value, symbol_return) &&
25741 settings_.control_struct_enabled(current_token().value)
25744 return parse_return_statement();
25746 #endif
25747 else if (symtab_store_.valid() || !sem_.empty())
25749 return parse_symtab_symbol();
25751 else
25753 set_error(
25754 make_error(parser_error::e_symtab,
25755 current_token(),
25756 "ERR196 - Variable or function detected, yet symbol-table is invalid, Symbol: " + current_token().value,
25757 exprtk_error_location));
25759 return error_node();
25763 inline expression_node_ptr parse_branch(precedence_level precedence = e_level00)
25765 expression_node_ptr branch = error_node();
25767 if (token_t::e_number == current_token().type)
25769 T numeric_value = T(0);
25771 if (details::string_to_real(current_token().value, numeric_value))
25773 expression_node_ptr literal_exp = expression_generator_(numeric_value);
25775 if (0 == literal_exp)
25777 set_error(
25778 make_error(parser_error::e_numeric,
25779 current_token(),
25780 "ERR197 - Failed generate node for scalar: '" + current_token().value + "'",
25781 exprtk_error_location));
25783 return error_node();
25786 next_token();
25787 branch = literal_exp;
25789 else
25791 set_error(
25792 make_error(parser_error::e_numeric,
25793 current_token(),
25794 "ERR198 - Failed to convert '" + current_token().value + "' to a number",
25795 exprtk_error_location));
25797 return error_node();
25800 else if (token_t::e_symbol == current_token().type)
25802 branch = parse_symbol();
25804 #ifndef exprtk_disable_string_capabilities
25805 else if (token_t::e_string == current_token().type)
25807 branch = parse_const_string();
25809 #endif
25810 else if (token_t::e_lbracket == current_token().type)
25812 next_token();
25814 if (0 == (branch = parse_expression()))
25815 return error_node();
25816 else if (!token_is(token_t::e_rbracket))
25818 set_error(
25819 make_error(parser_error::e_syntax,
25820 current_token(),
25821 "ERR199 - Expected ')' instead of: '" + current_token().value + "'",
25822 exprtk_error_location));
25824 free_node(node_allocator_,branch);
25826 return error_node();
25828 else if (!post_bracket_process(token_t::e_lbracket,branch))
25830 free_node(node_allocator_,branch);
25832 return error_node();
25835 else if (token_t::e_lsqrbracket == current_token().type)
25837 next_token();
25839 if (0 == (branch = parse_expression()))
25840 return error_node();
25841 else if (!token_is(token_t::e_rsqrbracket))
25843 set_error(
25844 make_error(parser_error::e_syntax,
25845 current_token(),
25846 "ERR200 - Expected ']' instead of: '" + current_token().value + "'",
25847 exprtk_error_location));
25849 free_node(node_allocator_,branch);
25851 return error_node();
25853 else if (!post_bracket_process(token_t::e_lsqrbracket,branch))
25855 free_node(node_allocator_,branch);
25857 return error_node();
25860 else if (token_t::e_lcrlbracket == current_token().type)
25862 next_token();
25864 if (0 == (branch = parse_expression()))
25865 return error_node();
25866 else if (!token_is(token_t::e_rcrlbracket))
25868 set_error(
25869 make_error(parser_error::e_syntax,
25870 current_token(),
25871 "ERR201 - Expected '}' instead of: '" + current_token().value + "'",
25872 exprtk_error_location));
25874 free_node(node_allocator_,branch);
25876 return error_node();
25878 else if (!post_bracket_process(token_t::e_lcrlbracket,branch))
25880 free_node(node_allocator_,branch);
25882 return error_node();
25885 else if (token_t::e_sub == current_token().type)
25887 next_token();
25888 branch = parse_expression(e_level11);
25890 if (
25891 branch &&
25893 details::is_neg_unary_node (branch) &&
25894 simplify_unary_negation_branch(branch)
25898 branch = expression_generator_(details::e_neg,branch);
25901 else if (token_t::e_add == current_token().type)
25903 next_token();
25904 branch = parse_expression(e_level13);
25906 else if (token_t::e_eof == current_token().type)
25908 set_error(
25909 make_error(parser_error::e_syntax,
25910 current_token(),
25911 "ERR202 - Premature end of expression[1]",
25912 exprtk_error_location));
25914 return error_node();
25916 else
25918 set_error(
25919 make_error(parser_error::e_syntax,
25920 current_token(),
25921 "ERR203 - Premature end of expression[2]",
25922 exprtk_error_location));
25924 return error_node();
25927 if (
25928 branch &&
25929 (e_level00 == precedence) &&
25930 token_is(token_t::e_ternary,prsrhlpr_t::e_hold)
25933 branch = parse_ternary_conditional_statement(branch);
25936 parse_pending_string_rangesize(branch);
25938 return branch;
25941 template <typename Type>
25942 class expression_generator
25944 public:
25946 typedef details::expression_node<Type>* expression_node_ptr;
25947 typedef expression_node_ptr (*synthesize_functor_t)(expression_generator<T>&, const details::operator_type& operation, expression_node_ptr (&branch)[2]);
25948 typedef std::map<std::string,synthesize_functor_t> synthesize_map_t;
25949 typedef typename exprtk::parser<Type> parser_t;
25950 typedef const Type& vtype;
25951 typedef const Type ctype;
25953 inline void init_synthesize_map()
25955 #ifndef exprtk_disable_enhanced_features
25956 synthesize_map_["(v)o(v)"] = synthesize_vov_expression::process;
25957 synthesize_map_["(c)o(v)"] = synthesize_cov_expression::process;
25958 synthesize_map_["(v)o(c)"] = synthesize_voc_expression::process;
25960 #define register_synthezier(S) \
25961 synthesize_map_[S ::node_type::id()] = S ::process; \
25963 register_synthezier(synthesize_vovov_expression0)
25964 register_synthezier(synthesize_vovov_expression1)
25965 register_synthezier(synthesize_vovoc_expression0)
25966 register_synthezier(synthesize_vovoc_expression1)
25967 register_synthezier(synthesize_vocov_expression0)
25968 register_synthezier(synthesize_vocov_expression1)
25969 register_synthezier(synthesize_covov_expression0)
25970 register_synthezier(synthesize_covov_expression1)
25971 register_synthezier(synthesize_covoc_expression0)
25972 register_synthezier(synthesize_covoc_expression1)
25973 register_synthezier(synthesize_cocov_expression1)
25974 register_synthezier(synthesize_vococ_expression0)
25976 register_synthezier(synthesize_vovovov_expression0)
25977 register_synthezier(synthesize_vovovoc_expression0)
25978 register_synthezier(synthesize_vovocov_expression0)
25979 register_synthezier(synthesize_vocovov_expression0)
25980 register_synthezier(synthesize_covovov_expression0)
25981 register_synthezier(synthesize_covocov_expression0)
25982 register_synthezier(synthesize_vocovoc_expression0)
25983 register_synthezier(synthesize_covovoc_expression0)
25984 register_synthezier(synthesize_vococov_expression0)
25986 register_synthezier(synthesize_vovovov_expression1)
25987 register_synthezier(synthesize_vovovoc_expression1)
25988 register_synthezier(synthesize_vovocov_expression1)
25989 register_synthezier(synthesize_vocovov_expression1)
25990 register_synthezier(synthesize_covovov_expression1)
25991 register_synthezier(synthesize_covocov_expression1)
25992 register_synthezier(synthesize_vocovoc_expression1)
25993 register_synthezier(synthesize_covovoc_expression1)
25994 register_synthezier(synthesize_vococov_expression1)
25996 register_synthezier(synthesize_vovovov_expression2)
25997 register_synthezier(synthesize_vovovoc_expression2)
25998 register_synthezier(synthesize_vovocov_expression2)
25999 register_synthezier(synthesize_vocovov_expression2)
26000 register_synthezier(synthesize_covovov_expression2)
26001 register_synthezier(synthesize_covocov_expression2)
26002 register_synthezier(synthesize_vocovoc_expression2)
26003 register_synthezier(synthesize_covovoc_expression2)
26005 register_synthezier(synthesize_vovovov_expression3)
26006 register_synthezier(synthesize_vovovoc_expression3)
26007 register_synthezier(synthesize_vovocov_expression3)
26008 register_synthezier(synthesize_vocovov_expression3)
26009 register_synthezier(synthesize_covovov_expression3)
26010 register_synthezier(synthesize_covocov_expression3)
26011 register_synthezier(synthesize_vocovoc_expression3)
26012 register_synthezier(synthesize_covovoc_expression3)
26013 register_synthezier(synthesize_vococov_expression3)
26015 register_synthezier(synthesize_vovovov_expression4)
26016 register_synthezier(synthesize_vovovoc_expression4)
26017 register_synthezier(synthesize_vovocov_expression4)
26018 register_synthezier(synthesize_vocovov_expression4)
26019 register_synthezier(synthesize_covovov_expression4)
26020 register_synthezier(synthesize_covocov_expression4)
26021 register_synthezier(synthesize_vocovoc_expression4)
26022 register_synthezier(synthesize_covovoc_expression4)
26023 #endif
26026 inline void set_parser(parser_t& p)
26028 parser_ = &p;
26031 inline void set_uom(unary_op_map_t& unary_op_map)
26033 unary_op_map_ = &unary_op_map;
26036 inline void set_bom(binary_op_map_t& binary_op_map)
26038 binary_op_map_ = &binary_op_map;
26041 inline void set_ibom(inv_binary_op_map_t& inv_binary_op_map)
26043 inv_binary_op_map_ = &inv_binary_op_map;
26046 inline void set_sf3m(sf3_map_t& sf3_map)
26048 sf3_map_ = &sf3_map;
26051 inline void set_sf4m(sf4_map_t& sf4_map)
26053 sf4_map_ = &sf4_map;
26056 inline void set_allocator(details::node_allocator& na)
26058 node_allocator_ = &na;
26061 inline void set_strength_reduction_state(const bool enabled)
26063 strength_reduction_enabled_ = enabled;
26066 inline bool strength_reduction_enabled() const
26068 return strength_reduction_enabled_;
26071 inline bool valid_operator(const details::operator_type& operation, binary_functor_t& bop)
26073 typename binary_op_map_t::iterator bop_itr = binary_op_map_->find(operation);
26075 if ((*binary_op_map_).end() == bop_itr)
26076 return false;
26078 bop = bop_itr->second;
26080 return true;
26083 inline bool valid_operator(const details::operator_type& operation, unary_functor_t& uop)
26085 typename unary_op_map_t::iterator uop_itr = unary_op_map_->find(operation);
26087 if ((*unary_op_map_).end() == uop_itr)
26088 return false;
26090 uop = uop_itr->second;
26092 return true;
26095 inline details::operator_type get_operator(const binary_functor_t& bop) const
26097 return (*inv_binary_op_map_).find(bop)->second;
26100 inline expression_node_ptr operator() (const Type& v) const
26102 return node_allocator_->allocate<literal_node_t>(v);
26105 #ifndef exprtk_disable_string_capabilities
26106 inline expression_node_ptr operator() (const std::string& s) const
26108 return node_allocator_->allocate<string_literal_node_t>(s);
26111 inline expression_node_ptr operator() (std::string& s, range_t& rp) const
26113 return node_allocator_->allocate_rr<string_range_node_t>(s,rp);
26116 inline expression_node_ptr operator() (const std::string& s, range_t& rp) const
26118 return node_allocator_->allocate_tt<const_string_range_node_t>(s,rp);
26121 inline expression_node_ptr operator() (expression_node_ptr branch, range_t& rp) const
26123 if (is_generally_string_node(branch))
26124 return node_allocator_->allocate_tt<generic_string_range_node_t>(branch,rp);
26125 else
26126 return error_node();
26128 #endif
26130 inline bool unary_optimisable(const details::operator_type& operation) const
26132 return (details::e_abs == operation) || (details::e_acos == operation) ||
26133 (details::e_acosh == operation) || (details::e_asin == operation) ||
26134 (details::e_asinh == operation) || (details::e_atan == operation) ||
26135 (details::e_atanh == operation) || (details::e_ceil == operation) ||
26136 (details::e_cos == operation) || (details::e_cosh == operation) ||
26137 (details::e_exp == operation) || (details::e_expm1 == operation) ||
26138 (details::e_floor == operation) || (details::e_log == operation) ||
26139 (details::e_log10 == operation) || (details::e_log2 == operation) ||
26140 (details::e_log1p == operation) || (details::e_neg == operation) ||
26141 (details::e_pos == operation) || (details::e_round == operation) ||
26142 (details::e_sin == operation) || (details::e_sinc == operation) ||
26143 (details::e_sinh == operation) || (details::e_sqrt == operation) ||
26144 (details::e_tan == operation) || (details::e_tanh == operation) ||
26145 (details::e_cot == operation) || (details::e_sec == operation) ||
26146 (details::e_csc == operation) || (details::e_r2d == operation) ||
26147 (details::e_d2r == operation) || (details::e_d2g == operation) ||
26148 (details::e_g2d == operation) || (details::e_notl == operation) ||
26149 (details::e_sgn == operation) || (details::e_erf == operation) ||
26150 (details::e_erfc == operation) || (details::e_ncdf == operation) ||
26151 (details::e_frac == operation) || (details::e_trunc == operation) ;
26154 inline bool sf3_optimisable(const std::string& sf3id, trinary_functor_t& tfunc) const
26156 typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id);
26158 if (sf3_map_->end() == itr)
26159 return false;
26160 else
26161 tfunc = itr->second.first;
26163 return true;
26166 inline bool sf4_optimisable(const std::string& sf4id, quaternary_functor_t& qfunc) const
26168 typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id);
26170 if (sf4_map_->end() == itr)
26171 return false;
26172 else
26173 qfunc = itr->second.first;
26175 return true;
26178 inline bool sf3_optimisable(const std::string& sf3id, details::operator_type& operation) const
26180 typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id);
26182 if (sf3_map_->end() == itr)
26183 return false;
26184 else
26185 operation = itr->second.second;
26187 return true;
26190 inline bool sf4_optimisable(const std::string& sf4id, details::operator_type& operation) const
26192 typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id);
26194 if (sf4_map_->end() == itr)
26195 return false;
26196 else
26197 operation = itr->second.second;
26199 return true;
26202 inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[1])
26204 if (0 == branch[0])
26206 return error_node();
26208 else if (details::is_null_node(branch[0]))
26210 return branch[0];
26212 else if (details::is_break_node(branch[0]))
26214 return error_node();
26216 else if (details::is_continue_node(branch[0]))
26218 return error_node();
26220 else if (details::is_constant_node(branch[0]))
26222 return synthesize_expression<unary_node_t,1>(operation,branch);
26224 else if (unary_optimisable(operation) && details::is_variable_node(branch[0]))
26226 return synthesize_uv_expression(operation,branch);
26228 else if (unary_optimisable(operation) && details::is_ivector_node(branch[0]))
26230 return synthesize_uvec_expression(operation,branch);
26232 else
26233 return synthesize_unary_expression(operation,branch);
26236 inline bool is_assignment_operation(const details::operator_type& operation) const
26238 return (
26239 (details::e_addass == operation) ||
26240 (details::e_subass == operation) ||
26241 (details::e_mulass == operation) ||
26242 (details::e_divass == operation) ||
26243 (details::e_modass == operation)
26244 ) &&
26245 parser_->settings_.assignment_enabled(operation);
26248 #ifndef exprtk_disable_string_capabilities
26249 inline bool valid_string_operation(const details::operator_type& operation) const
26251 return (details::e_add == operation) ||
26252 (details::e_lt == operation) ||
26253 (details::e_lte == operation) ||
26254 (details::e_gt == operation) ||
26255 (details::e_gte == operation) ||
26256 (details::e_eq == operation) ||
26257 (details::e_ne == operation) ||
26258 (details::e_in == operation) ||
26259 (details::e_like == operation) ||
26260 (details::e_ilike == operation) ||
26261 (details::e_assign == operation) ||
26262 (details::e_addass == operation) ||
26263 (details::e_swap == operation) ;
26265 #else
26266 inline bool valid_string_operation(const details::operator_type&) const
26268 return false;
26270 #endif
26272 inline std::string to_str(const details::operator_type& operation) const
26274 switch (operation)
26276 case details::e_add : return "+" ;
26277 case details::e_sub : return "-" ;
26278 case details::e_mul : return "*" ;
26279 case details::e_div : return "/" ;
26280 case details::e_mod : return "%" ;
26281 case details::e_pow : return "^" ;
26282 case details::e_lt : return "<" ;
26283 case details::e_lte : return "<=" ;
26284 case details::e_gt : return ">" ;
26285 case details::e_gte : return ">=" ;
26286 case details::e_eq : return "==" ;
26287 case details::e_ne : return "!=" ;
26288 case details::e_and : return "and" ;
26289 case details::e_nand : return "nand" ;
26290 case details::e_or : return "or" ;
26291 case details::e_nor : return "nor" ;
26292 case details::e_xor : return "xor" ;
26293 case details::e_xnor : return "xnor" ;
26294 default : return "UNKNOWN";
26298 inline bool operation_optimisable(const details::operator_type& operation) const
26300 return (details::e_add == operation) ||
26301 (details::e_sub == operation) ||
26302 (details::e_mul == operation) ||
26303 (details::e_div == operation) ||
26304 (details::e_mod == operation) ||
26305 (details::e_pow == operation) ||
26306 (details::e_lt == operation) ||
26307 (details::e_lte == operation) ||
26308 (details::e_gt == operation) ||
26309 (details::e_gte == operation) ||
26310 (details::e_eq == operation) ||
26311 (details::e_ne == operation) ||
26312 (details::e_and == operation) ||
26313 (details::e_nand == operation) ||
26314 (details::e_or == operation) ||
26315 (details::e_nor == operation) ||
26316 (details::e_xor == operation) ||
26317 (details::e_xnor == operation) ;
26320 inline std::string branch_to_id(expression_node_ptr branch) const
26322 static const std::string null_str ("(null)" );
26323 static const std::string const_str ("(c)" );
26324 static const std::string var_str ("(v)" );
26325 static const std::string vov_str ("(vov)" );
26326 static const std::string cov_str ("(cov)" );
26327 static const std::string voc_str ("(voc)" );
26328 static const std::string str_str ("(s)" );
26329 static const std::string strrng_str ("(rngs)" );
26330 static const std::string cs_str ("(cs)" );
26331 static const std::string cstrrng_str("(crngs)");
26333 if (details::is_null_node(branch))
26334 return null_str;
26335 else if (details::is_constant_node(branch))
26336 return const_str;
26337 else if (details::is_variable_node(branch))
26338 return var_str;
26339 else if (details::is_vov_node(branch))
26340 return vov_str;
26341 else if (details::is_cov_node(branch))
26342 return cov_str;
26343 else if (details::is_voc_node(branch))
26344 return voc_str;
26345 else if (details::is_string_node(branch))
26346 return str_str;
26347 else if (details::is_const_string_node(branch))
26348 return cs_str;
26349 else if (details::is_string_range_node(branch))
26350 return strrng_str;
26351 else if (details::is_const_string_range_node(branch))
26352 return cstrrng_str;
26353 else if (details::is_t0ot1ot2_node(branch))
26354 return "(" + dynamic_cast<details::T0oT1oT2_base_node<T>*>(branch)->type_id() + ")";
26355 else if (details::is_t0ot1ot2ot3_node(branch))
26356 return "(" + dynamic_cast<details::T0oT1oT2oT3_base_node<T>*>(branch)->type_id() + ")";
26357 else
26358 return "ERROR";
26361 inline std::string branch_to_id(expression_node_ptr (&branch)[2]) const
26363 return branch_to_id(branch[0]) + std::string("o") + branch_to_id(branch[1]);
26366 inline bool cov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26368 if (!operation_optimisable(operation))
26369 return false;
26370 else
26371 return details::is_constant_node(branch[0]) &&
26372 details::is_variable_node(branch[1]) ;
26375 inline bool voc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26377 if (!operation_optimisable(operation))
26378 return false;
26379 else
26380 return details::is_variable_node(branch[0]) &&
26381 details::is_constant_node(branch[1]) ;
26384 inline bool vov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26386 if (!operation_optimisable(operation))
26387 return false;
26388 else
26389 return details::is_variable_node(branch[0]) &&
26390 details::is_variable_node(branch[1]) ;
26393 inline bool cob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26395 if (!operation_optimisable(operation))
26396 return false;
26397 else
26398 return details::is_constant_node(branch[0]) &&
26399 !details::is_constant_node(branch[1]) ;
26402 inline bool boc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26404 if (!operation_optimisable(operation))
26405 return false;
26406 else
26407 return !details::is_constant_node(branch[0]) &&
26408 details::is_constant_node(branch[1]) ;
26411 inline bool cocob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26413 if (
26414 (details::e_add == operation) ||
26415 (details::e_sub == operation) ||
26416 (details::e_mul == operation) ||
26417 (details::e_div == operation)
26420 return (details::is_constant_node(branch[0]) && details::is_cob_node(branch[1])) ||
26421 (details::is_constant_node(branch[1]) && details::is_cob_node(branch[0])) ;
26423 else
26424 return false;
26427 inline bool coboc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26429 if (
26430 (details::e_add == operation) ||
26431 (details::e_sub == operation) ||
26432 (details::e_mul == operation) ||
26433 (details::e_div == operation)
26436 return (details::is_constant_node(branch[0]) && details::is_boc_node(branch[1])) ||
26437 (details::is_constant_node(branch[1]) && details::is_boc_node(branch[0])) ;
26439 else
26440 return false;
26443 inline bool uvouv_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26445 if (!operation_optimisable(operation))
26446 return false;
26447 else
26448 return details::is_uv_node(branch[0]) &&
26449 details::is_uv_node(branch[1]) ;
26452 inline bool vob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26454 if (!operation_optimisable(operation))
26455 return false;
26456 else
26457 return details::is_variable_node(branch[0]) &&
26458 !details::is_variable_node(branch[1]) ;
26461 inline bool bov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26463 if (!operation_optimisable(operation))
26464 return false;
26465 else
26466 return !details::is_variable_node(branch[0]) &&
26467 details::is_variable_node(branch[1]) ;
26470 inline bool binext_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26472 if (!operation_optimisable(operation))
26473 return false;
26474 else
26475 return !details::is_constant_node(branch[0]) ||
26476 !details::is_constant_node(branch[1]) ;
26479 inline bool is_invalid_assignment_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26481 if (is_assignment_operation(operation))
26483 const bool b1_is_genstring = details::is_generally_string_node(branch[1]);
26485 if (details::is_string_node(branch[0]))
26486 return !b1_is_genstring;
26487 else
26488 return (
26489 !details::is_variable_node (branch[0]) &&
26490 !details::is_vector_elem_node (branch[0]) &&
26491 !details::is_rebasevector_elem_node (branch[0]) &&
26492 !details::is_rebasevector_celem_node(branch[0]) &&
26493 !details::is_vector_node (branch[0])
26495 || b1_is_genstring;
26497 else
26498 return false;
26501 inline bool is_constpow_operation(const details::operator_type& operation, expression_node_ptr(&branch)[2]) const
26503 if (
26504 !details::is_constant_node(branch[1]) ||
26505 details::is_constant_node(branch[0]) ||
26506 details::is_variable_node(branch[0]) ||
26507 details::is_vector_node (branch[0]) ||
26508 details::is_generally_string_node(branch[0])
26510 return false;
26512 const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
26514 return cardinal_pow_optimisable(operation, c);
26517 inline bool is_invalid_break_continue_op(expression_node_ptr (&branch)[2]) const
26519 return (
26520 details::is_break_node (branch[0]) ||
26521 details::is_break_node (branch[1]) ||
26522 details::is_continue_node(branch[0]) ||
26523 details::is_continue_node(branch[1])
26527 inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26529 const bool b0_string = is_generally_string_node(branch[0]);
26530 const bool b1_string = is_generally_string_node(branch[1]);
26532 bool result = false;
26534 if (b0_string != b1_string)
26535 result = true;
26536 else if (!valid_string_operation(operation) && b0_string && b1_string)
26537 result = true;
26539 if (result)
26541 parser_->set_synthesis_error("Invalid string operation");
26544 return result;
26547 inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[3]) const
26549 const bool b0_string = is_generally_string_node(branch[0]);
26550 const bool b1_string = is_generally_string_node(branch[1]);
26551 const bool b2_string = is_generally_string_node(branch[2]);
26553 bool result = false;
26555 if ((b0_string != b1_string) || (b1_string != b2_string))
26556 result = true;
26557 else if ((details::e_inrange != operation) && b0_string && b1_string && b2_string)
26558 result = true;
26560 if (result)
26562 parser_->set_synthesis_error("Invalid string operation");
26565 return result;
26568 inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26570 const bool b0_string = is_generally_string_node(branch[0]);
26571 const bool b1_string = is_generally_string_node(branch[1]);
26573 return (b0_string && b1_string && valid_string_operation(operation));
26576 inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[3]) const
26578 const bool b0_string = is_generally_string_node(branch[0]);
26579 const bool b1_string = is_generally_string_node(branch[1]);
26580 const bool b2_string = is_generally_string_node(branch[2]);
26582 return (b0_string && b1_string && b2_string && (details::e_inrange == operation));
26585 #ifndef exprtk_disable_sc_andor
26586 inline bool is_shortcircuit_expression(const details::operator_type& operation) const
26588 return (
26589 (details::e_scand == operation) ||
26590 (details::e_scor == operation)
26593 #else
26594 inline bool is_shortcircuit_expression(const details::operator_type&) const
26596 return false;
26598 #endif
26600 inline bool is_null_present(expression_node_ptr (&branch)[2]) const
26602 return (
26603 details::is_null_node(branch[0]) ||
26604 details::is_null_node(branch[1])
26608 inline bool is_vector_eqineq_logic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26610 if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1]))
26611 return false;
26612 else
26613 return (
26614 (details::e_lt == operation) ||
26615 (details::e_lte == operation) ||
26616 (details::e_gt == operation) ||
26617 (details::e_gte == operation) ||
26618 (details::e_eq == operation) ||
26619 (details::e_ne == operation) ||
26620 (details::e_equal == operation) ||
26621 (details::e_and == operation) ||
26622 (details::e_nand == operation) ||
26623 (details:: e_or == operation) ||
26624 (details:: e_nor == operation) ||
26625 (details:: e_xor == operation) ||
26626 (details::e_xnor == operation)
26630 inline bool is_vector_arithmetic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26632 if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1]))
26633 return false;
26634 else
26635 return (
26636 (details::e_add == operation) ||
26637 (details::e_sub == operation) ||
26638 (details::e_mul == operation) ||
26639 (details::e_div == operation) ||
26640 (details::e_pow == operation)
26644 inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[2])
26646 if ((0 == branch[0]) || (0 == branch[1]))
26648 return error_node();
26650 else if (is_invalid_string_op(operation,branch))
26652 return error_node();
26654 else if (is_invalid_assignment_op(operation,branch))
26656 return error_node();
26658 else if (is_invalid_break_continue_op(branch))
26660 return error_node();
26662 else if (details::e_assign == operation)
26664 return synthesize_assignment_expression(operation, branch);
26666 else if (details::e_swap == operation)
26668 return synthesize_swap_expression(branch);
26670 else if (is_assignment_operation(operation))
26672 return synthesize_assignment_operation_expression(operation, branch);
26674 else if (is_vector_eqineq_logic_operation(operation, branch))
26676 return synthesize_veceqineqlogic_operation_expression(operation, branch);
26678 else if (is_vector_arithmetic_operation(operation, branch))
26680 return synthesize_vecarithmetic_operation_expression(operation, branch);
26682 else if (is_shortcircuit_expression(operation))
26684 return synthesize_shortcircuit_expression(operation, branch);
26686 else if (is_string_operation(operation, branch))
26688 return synthesize_string_expression(operation, branch);
26690 else if (is_null_present(branch))
26692 return synthesize_null_expression(operation, branch);
26694 #ifndef exprtk_disable_cardinal_pow_optimisation
26695 else if (is_constpow_operation(operation, branch))
26697 return cardinal_pow_optimisation(branch);
26699 #endif
26701 expression_node_ptr result = error_node();
26703 #ifndef exprtk_disable_enhanced_features
26704 if (synthesize_expression(operation, branch, result))
26706 return result;
26708 else
26709 #endif
26713 Possible reductions:
26714 1. c o cob -> cob
26715 2. cob o c -> cob
26716 3. c o boc -> boc
26717 4. boc o c -> boc
26719 result = error_node();
26721 if (cocob_optimisable(operation, branch))
26723 result = synthesize_cocob_expression::process((*this), operation, branch);
26725 else if (coboc_optimisable(operation, branch) && (0 == result))
26727 result = synthesize_coboc_expression::process((*this), operation, branch);
26730 if (result)
26731 return result;
26734 if (uvouv_optimisable(operation, branch))
26736 return synthesize_uvouv_expression(operation, branch);
26738 else if (vob_optimisable(operation, branch))
26740 return synthesize_vob_expression::process((*this), operation, branch);
26742 else if (bov_optimisable(operation, branch))
26744 return synthesize_bov_expression::process((*this), operation, branch);
26746 else if (cob_optimisable(operation, branch))
26748 return synthesize_cob_expression::process((*this), operation, branch);
26750 else if (boc_optimisable(operation, branch))
26752 return synthesize_boc_expression::process((*this), operation, branch);
26754 #ifndef exprtk_disable_enhanced_features
26755 else if (cov_optimisable(operation, branch))
26757 return synthesize_cov_expression::process((*this), operation, branch);
26759 #endif
26760 else if (binext_optimisable(operation, branch))
26762 return synthesize_binary_ext_expression::process((*this), operation, branch);
26764 else
26765 return synthesize_expression<binary_node_t,2>(operation, branch);
26768 inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[3])
26770 if (
26771 (0 == branch[0]) ||
26772 (0 == branch[1]) ||
26773 (0 == branch[2])
26776 details::free_all_nodes(*node_allocator_,branch);
26778 return error_node();
26780 else if (is_invalid_string_op(operation, branch))
26782 return error_node();
26784 else if (is_string_operation(operation, branch))
26786 return synthesize_string_expression(operation, branch);
26788 else
26789 return synthesize_expression<trinary_node_t,3>(operation, branch);
26792 inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[4])
26794 return synthesize_expression<quaternary_node_t,4>(operation,branch);
26797 inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr b0)
26799 expression_node_ptr branch[1] = { b0 };
26800 return (*this)(operation,branch);
26803 inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr& b0, expression_node_ptr& b1)
26805 expression_node_ptr result = error_node();
26807 if ((0 != b0) && (0 != b1))
26809 expression_node_ptr branch[2] = { b0, b1 };
26810 result = expression_generator<Type>::operator()(operation, branch);
26811 b0 = branch[0];
26812 b1 = branch[1];
26815 return result;
26818 inline expression_node_ptr conditional(expression_node_ptr condition,
26819 expression_node_ptr consequent,
26820 expression_node_ptr alternative) const
26822 if ((0 == condition) || (0 == consequent))
26824 free_node(*node_allocator_, condition);
26825 free_node(*node_allocator_, consequent);
26826 free_node(*node_allocator_, alternative);
26828 return error_node();
26830 // Can the condition be immediately evaluated? if so optimise.
26831 else if (details::is_constant_node(condition))
26833 // True branch
26834 if (details::is_true(condition))
26836 free_node(*node_allocator_, condition);
26837 free_node(*node_allocator_, alternative);
26839 return consequent;
26841 // False branch
26842 else
26844 free_node(*node_allocator_, condition);
26845 free_node(*node_allocator_, consequent);
26847 if (alternative)
26848 return alternative;
26849 else
26850 return node_allocator_->allocate<details::null_node<T> >();
26853 else if ((0 != consequent) && (0 != alternative))
26855 return node_allocator_->
26856 allocate<conditional_node_t>(condition, consequent, alternative);
26858 else
26859 return node_allocator_->
26860 allocate<cons_conditional_node_t>(condition, consequent);
26863 #ifndef exprtk_disable_string_capabilities
26864 inline expression_node_ptr conditional_string(expression_node_ptr condition,
26865 expression_node_ptr consequent,
26866 expression_node_ptr alternative) const
26868 if ((0 == condition) || (0 == consequent))
26870 free_node(*node_allocator_, condition);
26871 free_node(*node_allocator_, consequent);
26872 free_node(*node_allocator_, alternative);
26874 return error_node();
26876 // Can the condition be immediately evaluated? if so optimise.
26877 else if (details::is_constant_node(condition))
26879 // True branch
26880 if (details::is_true(condition))
26882 free_node(*node_allocator_, condition);
26883 free_node(*node_allocator_, alternative);
26885 return consequent;
26887 // False branch
26888 else
26890 free_node(*node_allocator_, condition);
26891 free_node(*node_allocator_, consequent);
26893 if (alternative)
26894 return alternative;
26895 else
26896 return node_allocator_->
26897 allocate_c<details::string_literal_node<Type> >("");
26900 else if ((0 != consequent) && (0 != alternative))
26901 return node_allocator_->
26902 allocate<conditional_string_node_t>(condition, consequent, alternative);
26903 else
26904 return error_node();
26906 #else
26907 inline expression_node_ptr conditional_string(expression_node_ptr,
26908 expression_node_ptr,
26909 expression_node_ptr) const
26911 return error_node();
26913 #endif
26915 inline expression_node_ptr while_loop(expression_node_ptr& condition,
26916 expression_node_ptr& branch,
26917 const bool brkcont = false) const
26919 if (!brkcont && details::is_constant_node(condition))
26921 expression_node_ptr result = error_node();
26922 if (details::is_true(condition))
26923 // Infinite loops are not allowed.
26924 result = error_node();
26925 else
26926 result = node_allocator_->allocate<details::null_node<Type> >();
26928 free_node(*node_allocator_, condition);
26929 free_node(*node_allocator_, branch);
26931 return result;
26933 else if (details::is_null_node(condition))
26935 free_node(*node_allocator_,condition);
26937 return branch;
26939 else if (!brkcont)
26940 return node_allocator_->allocate<while_loop_node_t>(condition,branch);
26941 #ifndef exprtk_disable_break_continue
26942 else
26943 return node_allocator_->allocate<while_loop_bc_node_t>(condition,branch);
26944 #else
26945 return error_node();
26946 #endif
26949 inline expression_node_ptr repeat_until_loop(expression_node_ptr& condition,
26950 expression_node_ptr& branch,
26951 const bool brkcont = false) const
26953 if (!brkcont && details::is_constant_node(condition))
26955 if (
26956 details::is_true(condition) &&
26957 details::is_constant_node(branch)
26960 free_node(*node_allocator_,condition);
26962 return branch;
26965 free_node(*node_allocator_, condition);
26966 free_node(*node_allocator_, branch);
26968 return error_node();
26970 else if (details::is_null_node(condition))
26972 free_node(*node_allocator_,condition);
26974 return branch;
26976 else if (!brkcont)
26977 return node_allocator_->allocate<repeat_until_loop_node_t>(condition,branch);
26978 #ifndef exprtk_disable_break_continue
26979 else
26980 return node_allocator_->allocate<repeat_until_loop_bc_node_t>(condition,branch);
26981 #else
26982 return error_node();
26983 #endif
26986 inline expression_node_ptr for_loop(expression_node_ptr& initialiser,
26987 expression_node_ptr& condition,
26988 expression_node_ptr& incrementor,
26989 expression_node_ptr& loop_body,
26990 bool brkcont = false) const
26992 if (!brkcont && details::is_constant_node(condition))
26994 expression_node_ptr result = error_node();
26996 if (details::is_true(condition))
26997 // Infinite loops are not allowed.
26998 result = error_node();
26999 else
27000 result = node_allocator_->allocate<details::null_node<Type> >();
27002 free_node(*node_allocator_, initialiser);
27003 free_node(*node_allocator_, condition);
27004 free_node(*node_allocator_, incrementor);
27005 free_node(*node_allocator_, loop_body);
27007 return result;
27009 else if (details::is_null_node(condition) || (0 == condition))
27011 free_node(*node_allocator_, initialiser);
27012 free_node(*node_allocator_, condition);
27013 free_node(*node_allocator_, incrementor);
27015 return loop_body;
27017 else if (!brkcont)
27018 return node_allocator_->allocate<for_loop_node_t>
27020 initialiser,
27021 condition,
27022 incrementor,
27023 loop_body
27026 #ifndef exprtk_disable_break_continue
27027 else
27028 return node_allocator_->allocate<for_loop_bc_node_t>
27030 initialiser,
27031 condition,
27032 incrementor,
27033 loop_body
27035 #else
27036 return error_node();
27037 #endif
27040 template <typename Allocator,
27041 template <typename, typename> class Sequence>
27042 inline expression_node_ptr const_optimise_switch(Sequence<expression_node_ptr,Allocator>& arg_list)
27044 expression_node_ptr result = error_node();
27046 for (std::size_t i = 0; i < (arg_list.size() / 2); ++i)
27048 expression_node_ptr condition = arg_list[(2 * i) ];
27049 expression_node_ptr consequent = arg_list[(2 * i) + 1];
27051 if ((0 == result) && details::is_true(condition))
27053 result = consequent;
27054 break;
27058 if (0 == result)
27060 result = arg_list.back();
27063 for (std::size_t i = 0; i < arg_list.size(); ++i)
27065 expression_node_ptr current_expr = arg_list[i];
27067 if (current_expr && (current_expr != result))
27069 free_node(*node_allocator_,current_expr);
27073 return result;
27076 template <typename Allocator,
27077 template <typename, typename> class Sequence>
27078 inline expression_node_ptr const_optimise_mswitch(Sequence<expression_node_ptr,Allocator>& arg_list)
27080 expression_node_ptr result = error_node();
27082 for (std::size_t i = 0; i < (arg_list.size() / 2); ++i)
27084 expression_node_ptr condition = arg_list[(2 * i) ];
27085 expression_node_ptr consequent = arg_list[(2 * i) + 1];
27087 if (details::is_true(condition))
27089 result = consequent;
27093 if (0 == result)
27095 T zero = T(0);
27096 result = node_allocator_->allocate<literal_node_t>(zero);
27099 for (std::size_t i = 0; i < arg_list.size(); ++i)
27101 expression_node_ptr& current_expr = arg_list[i];
27103 if (current_expr && (current_expr != result))
27105 free_node(*node_allocator_,current_expr);
27109 return result;
27112 struct switch_nodes
27114 typedef std::vector<expression_node_ptr> arg_list_t;
27116 #define case_stmt(N) \
27117 if (is_true(arg[(2 * N)])) { return arg[(2 * N) + 1]->value(); } \
27119 struct switch_1
27121 static inline T process(const arg_list_t& arg)
27123 case_stmt(0)
27125 return arg.back()->value();
27129 struct switch_2
27131 static inline T process(const arg_list_t& arg)
27133 case_stmt(0) case_stmt(1)
27135 return arg.back()->value();
27139 struct switch_3
27141 static inline T process(const arg_list_t& arg)
27143 case_stmt(0) case_stmt(1)
27144 case_stmt(2)
27146 return arg.back()->value();
27150 struct switch_4
27152 static inline T process(const arg_list_t& arg)
27154 case_stmt(0) case_stmt(1)
27155 case_stmt(2) case_stmt(3)
27157 return arg.back()->value();
27161 struct switch_5
27163 static inline T process(const arg_list_t& arg)
27165 case_stmt(0) case_stmt(1)
27166 case_stmt(2) case_stmt(3)
27167 case_stmt(4)
27169 return arg.back()->value();
27173 struct switch_6
27175 static inline T process(const arg_list_t& arg)
27177 case_stmt(0) case_stmt(1)
27178 case_stmt(2) case_stmt(3)
27179 case_stmt(4) case_stmt(5)
27181 return arg.back()->value();
27185 struct switch_7
27187 static inline T process(const arg_list_t& arg)
27189 case_stmt(0) case_stmt(1)
27190 case_stmt(2) case_stmt(3)
27191 case_stmt(4) case_stmt(5)
27192 case_stmt(6)
27194 return arg.back()->value();
27198 #undef case_stmt
27201 template <typename Allocator,
27202 template <typename, typename> class Sequence>
27203 inline expression_node_ptr switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list)
27205 if (arg_list.empty())
27206 return error_node();
27207 else if (
27208 !all_nodes_valid(arg_list) ||
27209 (arg_list.size() < 3) ||
27210 ((arg_list.size() % 2) != 1)
27213 details::free_all_nodes(*node_allocator_,arg_list);
27215 return error_node();
27217 else if (is_constant_foldable(arg_list))
27218 return const_optimise_switch(arg_list);
27220 switch ((arg_list.size() - 1) / 2)
27222 #define case_stmt(N) \
27223 case N : \
27224 return node_allocator_-> \
27225 allocate<details::switch_n_node \
27226 <Type,typename switch_nodes::switch_##N> >(arg_list); \
27228 case_stmt(1)
27229 case_stmt(2)
27230 case_stmt(3)
27231 case_stmt(4)
27232 case_stmt(5)
27233 case_stmt(6)
27234 case_stmt(7)
27235 #undef case_stmt
27237 default : return node_allocator_->allocate<details::switch_node<Type> >(arg_list);
27241 template <typename Allocator,
27242 template <typename, typename> class Sequence>
27243 inline expression_node_ptr multi_switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list)
27245 if (!all_nodes_valid(arg_list))
27247 details::free_all_nodes(*node_allocator_,arg_list);
27249 return error_node();
27251 else if (is_constant_foldable(arg_list))
27252 return const_optimise_mswitch(arg_list);
27253 else
27254 return node_allocator_->allocate<details::multi_switch_node<Type> >(arg_list);
27257 #define unary_opr_switch_statements \
27258 case_stmt(details:: e_abs, details:: abs_op) \
27259 case_stmt(details:: e_acos, details:: acos_op) \
27260 case_stmt(details::e_acosh, details::acosh_op) \
27261 case_stmt(details:: e_asin, details:: asin_op) \
27262 case_stmt(details::e_asinh, details::asinh_op) \
27263 case_stmt(details:: e_atan, details:: atan_op) \
27264 case_stmt(details::e_atanh, details::atanh_op) \
27265 case_stmt(details:: e_ceil, details:: ceil_op) \
27266 case_stmt(details:: e_cos, details:: cos_op) \
27267 case_stmt(details:: e_cosh, details:: cosh_op) \
27268 case_stmt(details:: e_exp, details:: exp_op) \
27269 case_stmt(details::e_expm1, details::expm1_op) \
27270 case_stmt(details::e_floor, details::floor_op) \
27271 case_stmt(details:: e_log, details:: log_op) \
27272 case_stmt(details::e_log10, details::log10_op) \
27273 case_stmt(details:: e_log2, details:: log2_op) \
27274 case_stmt(details::e_log1p, details::log1p_op) \
27275 case_stmt(details:: e_neg, details:: neg_op) \
27276 case_stmt(details:: e_pos, details:: pos_op) \
27277 case_stmt(details::e_round, details::round_op) \
27278 case_stmt(details:: e_sin, details:: sin_op) \
27279 case_stmt(details:: e_sinc, details:: sinc_op) \
27280 case_stmt(details:: e_sinh, details:: sinh_op) \
27281 case_stmt(details:: e_sqrt, details:: sqrt_op) \
27282 case_stmt(details:: e_tan, details:: tan_op) \
27283 case_stmt(details:: e_tanh, details:: tanh_op) \
27284 case_stmt(details:: e_cot, details:: cot_op) \
27285 case_stmt(details:: e_sec, details:: sec_op) \
27286 case_stmt(details:: e_csc, details:: csc_op) \
27287 case_stmt(details:: e_r2d, details:: r2d_op) \
27288 case_stmt(details:: e_d2r, details:: d2r_op) \
27289 case_stmt(details:: e_d2g, details:: d2g_op) \
27290 case_stmt(details:: e_g2d, details:: g2d_op) \
27291 case_stmt(details:: e_notl, details:: notl_op) \
27292 case_stmt(details:: e_sgn, details:: sgn_op) \
27293 case_stmt(details:: e_erf, details:: erf_op) \
27294 case_stmt(details:: e_erfc, details:: erfc_op) \
27295 case_stmt(details:: e_ncdf, details:: ncdf_op) \
27296 case_stmt(details:: e_frac, details:: frac_op) \
27297 case_stmt(details::e_trunc, details::trunc_op) \
27299 inline expression_node_ptr synthesize_uv_expression(const details::operator_type& operation,
27300 expression_node_ptr (&branch)[1])
27302 T& v = static_cast<details::variable_node<T>*>(branch[0])->ref();
27304 switch (operation)
27306 #define case_stmt(op0,op1) \
27307 case op0 : return node_allocator_-> \
27308 allocate<typename details::unary_variable_node<Type,op1<Type> > >(v); \
27310 unary_opr_switch_statements
27311 #undef case_stmt
27312 default : return error_node();
27316 inline expression_node_ptr synthesize_uvec_expression(const details::operator_type& operation,
27317 expression_node_ptr (&branch)[1])
27319 switch (operation)
27321 #define case_stmt(op0,op1) \
27322 case op0 : return node_allocator_-> \
27323 allocate<typename details::unary_vector_node<Type,op1<Type> > > \
27324 (operation, branch[0]); \
27326 unary_opr_switch_statements
27327 #undef case_stmt
27328 default : return error_node();
27332 inline expression_node_ptr synthesize_unary_expression(const details::operator_type& operation,
27333 expression_node_ptr (&branch)[1])
27335 switch (operation)
27337 #define case_stmt(op0,op1) \
27338 case op0 : return node_allocator_-> \
27339 allocate<typename details::unary_branch_node<Type,op1<Type> > >(branch[0]); \
27341 unary_opr_switch_statements
27342 #undef case_stmt
27343 default : return error_node();
27347 inline expression_node_ptr const_optimise_sf3(const details::operator_type& operation,
27348 expression_node_ptr (&branch)[3])
27350 expression_node_ptr temp_node = error_node();
27352 switch (operation)
27354 #define case_stmt(op) \
27355 case details::e_sf##op : temp_node = node_allocator_-> \
27356 allocate<details::sf3_node<Type,details::sf##op##_op<Type> > > \
27357 (operation, branch); \
27358 break; \
27360 case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
27361 case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
27362 case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
27363 case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
27364 case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
27365 case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
27366 case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
27367 case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31)
27368 case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35)
27369 case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39)
27370 case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43)
27371 case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47)
27372 #undef case_stmt
27373 default : return error_node();
27376 const T v = temp_node->value();
27378 details::free_node(*node_allocator_,temp_node);
27380 return node_allocator_->allocate<literal_node_t>(v);
27383 inline expression_node_ptr varnode_optimise_sf3(const details::operator_type& operation, expression_node_ptr (&branch)[3])
27385 typedef details::variable_node<Type>* variable_ptr;
27387 const Type& v0 = static_cast<variable_ptr>(branch[0])->ref();
27388 const Type& v1 = static_cast<variable_ptr>(branch[1])->ref();
27389 const Type& v2 = static_cast<variable_ptr>(branch[2])->ref();
27391 switch (operation)
27393 #define case_stmt(op) \
27394 case details::e_sf##op : return node_allocator_-> \
27395 allocate_rrr<details::sf3_var_node<Type,details::sf##op##_op<Type> > > \
27396 (v0, v1, v2); \
27398 case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
27399 case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
27400 case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
27401 case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
27402 case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
27403 case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
27404 case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
27405 case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31)
27406 case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35)
27407 case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39)
27408 case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43)
27409 case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47)
27410 #undef case_stmt
27411 default : return error_node();
27415 inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[3])
27417 if (!all_nodes_valid(branch))
27418 return error_node();
27419 else if (is_constant_foldable(branch))
27420 return const_optimise_sf3(operation,branch);
27421 else if (all_nodes_variables(branch))
27422 return varnode_optimise_sf3(operation,branch);
27423 else
27425 switch (operation)
27427 #define case_stmt(op) \
27428 case details::e_sf##op : return node_allocator_-> \
27429 allocate<details::sf3_node<Type,details::sf##op##_op<Type> > > \
27430 (operation, branch); \
27432 case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
27433 case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
27434 case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
27435 case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
27436 case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
27437 case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
27438 case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
27439 case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31)
27440 case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35)
27441 case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39)
27442 case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43)
27443 case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47)
27444 #undef case_stmt
27445 default : return error_node();
27450 inline expression_node_ptr const_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4])
27452 expression_node_ptr temp_node = error_node();
27454 switch (operation)
27456 #define case_stmt(op) \
27457 case details::e_sf##op : temp_node = node_allocator_-> \
27458 allocate<details::sf4_node<Type,details::sf##op##_op<Type> > > \
27459 (operation, branch); \
27460 break; \
27462 case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51)
27463 case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55)
27464 case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59)
27465 case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63)
27466 case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67)
27467 case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71)
27468 case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75)
27469 case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79)
27470 case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83)
27471 case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87)
27472 case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91)
27473 case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95)
27474 case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99)
27475 #undef case_stmt
27476 default : return error_node();
27479 const T v = temp_node->value();
27481 details::free_node(*node_allocator_,temp_node);
27483 return node_allocator_->allocate<literal_node_t>(v);
27486 inline expression_node_ptr varnode_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4])
27488 typedef details::variable_node<Type>* variable_ptr;
27490 const Type& v0 = static_cast<variable_ptr>(branch[0])->ref();
27491 const Type& v1 = static_cast<variable_ptr>(branch[1])->ref();
27492 const Type& v2 = static_cast<variable_ptr>(branch[2])->ref();
27493 const Type& v3 = static_cast<variable_ptr>(branch[3])->ref();
27495 switch (operation)
27497 #define case_stmt(op) \
27498 case details::e_sf##op : return node_allocator_-> \
27499 allocate_rrrr<details::sf4_var_node<Type,details::sf##op##_op<Type> > > \
27500 (v0, v1, v2, v3); \
27502 case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51)
27503 case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55)
27504 case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59)
27505 case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63)
27506 case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67)
27507 case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71)
27508 case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75)
27509 case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79)
27510 case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83)
27511 case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87)
27512 case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91)
27513 case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95)
27514 case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99)
27515 #undef case_stmt
27516 default : return error_node();
27520 inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[4])
27522 if (!all_nodes_valid(branch))
27523 return error_node();
27524 else if (is_constant_foldable(branch))
27525 return const_optimise_sf4(operation,branch);
27526 else if (all_nodes_variables(branch))
27527 return varnode_optimise_sf4(operation,branch);
27528 switch (operation)
27530 #define case_stmt(op) \
27531 case details::e_sf##op : return node_allocator_-> \
27532 allocate<details::sf4_node<Type,details::sf##op##_op<Type> > > \
27533 (operation, branch); \
27535 case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51)
27536 case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55)
27537 case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59)
27538 case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63)
27539 case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67)
27540 case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71)
27541 case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75)
27542 case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79)
27543 case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83)
27544 case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87)
27545 case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91)
27546 case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95)
27547 case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99)
27548 #undef case_stmt
27549 default : return error_node();
27553 template <typename Allocator,
27554 template <typename, typename> class Sequence>
27555 inline expression_node_ptr const_optimise_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
27557 expression_node_ptr temp_node = error_node();
27559 switch (operation)
27561 #define case_stmt(op0,op1) \
27562 case op0 : temp_node = node_allocator_-> \
27563 allocate<details::vararg_node<Type,op1<Type> > > \
27564 (arg_list); \
27565 break; \
27567 case_stmt(details::e_sum , details::vararg_add_op )
27568 case_stmt(details::e_prod , details::vararg_mul_op )
27569 case_stmt(details::e_avg , details::vararg_avg_op )
27570 case_stmt(details::e_min , details::vararg_min_op )
27571 case_stmt(details::e_max , details::vararg_max_op )
27572 case_stmt(details::e_mand , details::vararg_mand_op )
27573 case_stmt(details::e_mor , details::vararg_mor_op )
27574 case_stmt(details::e_multi , details::vararg_multi_op)
27575 #undef case_stmt
27576 default : return error_node();
27579 const T v = temp_node->value();
27581 details::free_node(*node_allocator_,temp_node);
27583 return node_allocator_->allocate<literal_node_t>(v);
27586 inline bool special_one_parameter_vararg(const details::operator_type& operation) const
27588 return (
27589 (details::e_sum == operation) ||
27590 (details::e_prod == operation) ||
27591 (details::e_avg == operation) ||
27592 (details::e_min == operation) ||
27593 (details::e_max == operation)
27597 template <typename Allocator,
27598 template <typename, typename> class Sequence>
27599 inline expression_node_ptr varnode_optimise_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
27601 switch (operation)
27603 #define case_stmt(op0,op1) \
27604 case op0 : return node_allocator_-> \
27605 allocate<details::vararg_varnode<Type,op1<Type> > >(arg_list); \
27607 case_stmt(details::e_sum , details::vararg_add_op )
27608 case_stmt(details::e_prod , details::vararg_mul_op )
27609 case_stmt(details::e_avg , details::vararg_avg_op )
27610 case_stmt(details::e_min , details::vararg_min_op )
27611 case_stmt(details::e_max , details::vararg_max_op )
27612 case_stmt(details::e_mand , details::vararg_mand_op )
27613 case_stmt(details::e_mor , details::vararg_mor_op )
27614 case_stmt(details::e_multi , details::vararg_multi_op)
27615 #undef case_stmt
27616 default : return error_node();
27620 template <typename Allocator,
27621 template <typename, typename> class Sequence>
27622 inline expression_node_ptr vectorize_func(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
27624 if (1 == arg_list.size())
27626 switch (operation)
27628 #define case_stmt(op0,op1) \
27629 case op0 : return node_allocator_-> \
27630 allocate<details::vectorize_node<Type,op1<Type> > >(arg_list[0]); \
27632 case_stmt(details::e_sum , details::vec_add_op)
27633 case_stmt(details::e_prod , details::vec_mul_op)
27634 case_stmt(details::e_avg , details::vec_avg_op)
27635 case_stmt(details::e_min , details::vec_min_op)
27636 case_stmt(details::e_max , details::vec_max_op)
27637 #undef case_stmt
27638 default : return error_node();
27641 else
27642 return error_node();
27645 template <typename Allocator,
27646 template <typename, typename> class Sequence>
27647 inline expression_node_ptr vararg_function(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
27649 if (!all_nodes_valid(arg_list))
27651 details::free_all_nodes(*node_allocator_,arg_list);
27653 return error_node();
27655 else if (is_constant_foldable(arg_list))
27656 return const_optimise_varargfunc(operation,arg_list);
27657 else if ((arg_list.size() == 1) && details::is_ivector_node(arg_list[0]))
27658 return vectorize_func(operation,arg_list);
27659 else if ((arg_list.size() == 1) && special_one_parameter_vararg(operation))
27660 return arg_list[0];
27661 else if (all_nodes_variables(arg_list))
27662 return varnode_optimise_varargfunc(operation,arg_list);
27664 #ifndef exprtk_disable_string_capabilities
27665 if (details::e_smulti == operation)
27667 return node_allocator_->
27668 allocate<details::str_vararg_node<Type,details::vararg_multi_op<Type> > >(arg_list);
27670 else
27671 #endif
27673 switch (operation)
27675 #define case_stmt(op0,op1) \
27676 case op0 : return node_allocator_-> \
27677 allocate<details::vararg_node<Type,op1<Type> > >(arg_list); \
27679 case_stmt(details::e_sum , details::vararg_add_op )
27680 case_stmt(details::e_prod , details::vararg_mul_op )
27681 case_stmt(details::e_avg , details::vararg_avg_op )
27682 case_stmt(details::e_min , details::vararg_min_op )
27683 case_stmt(details::e_max , details::vararg_max_op )
27684 case_stmt(details::e_mand , details::vararg_mand_op )
27685 case_stmt(details::e_mor , details::vararg_mor_op )
27686 case_stmt(details::e_multi , details::vararg_multi_op)
27687 #undef case_stmt
27688 default : return error_node();
27693 template <std::size_t N>
27694 inline expression_node_ptr function(ifunction_t* f, expression_node_ptr (&b)[N])
27696 typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t;
27697 expression_node_ptr result = synthesize_expression<function_N_node_t,N>(f,b);
27699 if (0 == result)
27700 return error_node();
27701 else
27703 // Can the function call be completely optimised?
27704 if (details::is_constant_node(result))
27705 return result;
27706 else if (!all_nodes_valid(b))
27707 return error_node();
27708 else if (N != f->param_count)
27710 details::free_all_nodes(*node_allocator_,b);
27712 return error_node();
27715 function_N_node_t* func_node_ptr = static_cast<function_N_node_t*>(result);
27717 if (func_node_ptr->init_branches(b))
27718 return result;
27719 else
27721 details::free_all_nodes(*node_allocator_,b);
27723 return error_node();
27728 inline expression_node_ptr function(ifunction_t* f)
27730 typedef typename details::function_N_node<Type,ifunction_t,0> function_N_node_t;
27731 return node_allocator_->allocate<function_N_node_t>(f);
27734 inline expression_node_ptr vararg_function_call(ivararg_function_t* vaf,
27735 std::vector<expression_node_ptr>& arg_list)
27737 if (!all_nodes_valid(arg_list))
27739 details::free_all_nodes(*node_allocator_,arg_list);
27741 return error_node();
27744 typedef details::vararg_function_node<Type,ivararg_function_t> alloc_type;
27746 expression_node_ptr result = node_allocator_->allocate<alloc_type>(vaf,arg_list);
27748 if (
27749 !arg_list.empty() &&
27750 !vaf->has_side_effects() &&
27751 is_constant_foldable(arg_list)
27754 const Type v = result->value();
27755 details::free_node(*node_allocator_,result);
27756 result = node_allocator_->allocate<literal_node_t>(v);
27759 parser_->state_.activate_side_effect("vararg_function_call()");
27761 return result;
27764 inline expression_node_ptr generic_function_call(igeneric_function_t* gf,
27765 std::vector<expression_node_ptr>& arg_list,
27766 const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max())
27768 if (!all_nodes_valid(arg_list))
27770 details::free_all_nodes(*node_allocator_,arg_list);
27771 return error_node();
27774 typedef details::generic_function_node <Type,igeneric_function_t> alloc_type1;
27775 typedef details::multimode_genfunction_node<Type,igeneric_function_t> alloc_type2;
27777 const std::size_t no_psi = std::numeric_limits<std::size_t>::max();
27779 expression_node_ptr result = error_node();
27781 if (no_psi == param_seq_index)
27782 result = node_allocator_->allocate<alloc_type1>(arg_list,gf);
27783 else
27784 result = node_allocator_->allocate<alloc_type2>(gf, param_seq_index, arg_list);
27786 alloc_type1* genfunc_node_ptr = static_cast<alloc_type1*>(result);
27788 if (
27789 !arg_list.empty() &&
27790 !gf->has_side_effects() &&
27791 parser_->state_.type_check_enabled &&
27792 is_constant_foldable(arg_list)
27795 genfunc_node_ptr->init_branches();
27797 const Type v = result->value();
27799 details::free_node(*node_allocator_,result);
27801 return node_allocator_->allocate<literal_node_t>(v);
27803 else if (genfunc_node_ptr->init_branches())
27805 parser_->state_.activate_side_effect("generic_function_call()");
27807 return result;
27809 else
27811 details::free_node(*node_allocator_, result);
27812 details::free_all_nodes(*node_allocator_, arg_list);
27814 return error_node();
27818 #ifndef exprtk_disable_string_capabilities
27819 inline expression_node_ptr string_function_call(igeneric_function_t* gf,
27820 std::vector<expression_node_ptr>& arg_list,
27821 const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max())
27823 if (!all_nodes_valid(arg_list))
27825 details::free_all_nodes(*node_allocator_,arg_list);
27826 return error_node();
27829 typedef details::string_function_node <Type,igeneric_function_t> alloc_type1;
27830 typedef details::multimode_strfunction_node<Type,igeneric_function_t> alloc_type2;
27832 const std::size_t no_psi = std::numeric_limits<std::size_t>::max();
27834 expression_node_ptr result = error_node();
27836 if (no_psi == param_seq_index)
27837 result = node_allocator_->allocate<alloc_type1>(gf,arg_list);
27838 else
27839 result = node_allocator_->allocate<alloc_type2>(gf, param_seq_index, arg_list);
27841 alloc_type1* strfunc_node_ptr = static_cast<alloc_type1*>(result);
27843 if (
27844 !arg_list.empty() &&
27845 !gf->has_side_effects() &&
27846 is_constant_foldable(arg_list)
27849 strfunc_node_ptr->init_branches();
27851 const Type v = result->value();
27853 details::free_node(*node_allocator_,result);
27855 return node_allocator_->allocate<literal_node_t>(v);
27857 else if (strfunc_node_ptr->init_branches())
27859 parser_->state_.activate_side_effect("string_function_call()");
27861 return result;
27863 else
27865 details::free_node (*node_allocator_,result );
27866 details::free_all_nodes(*node_allocator_,arg_list);
27868 return error_node();
27871 #endif
27873 #ifndef exprtk_disable_return_statement
27874 inline expression_node_ptr return_call(std::vector<expression_node_ptr>& arg_list)
27876 if (!all_nodes_valid(arg_list))
27878 details::free_all_nodes(*node_allocator_,arg_list);
27879 return error_node();
27882 typedef details::return_node<Type> alloc_type;
27884 expression_node_ptr result = node_allocator_->
27885 allocate_rr<alloc_type>(arg_list,parser_->results_ctx());
27887 alloc_type* return_node_ptr = static_cast<alloc_type*>(result);
27889 if (return_node_ptr->init_branches())
27891 parser_->state_.activate_side_effect("return_call()");
27893 return result;
27895 else
27897 details::free_node (*node_allocator_,result );
27898 details::free_all_nodes(*node_allocator_,arg_list);
27900 return error_node();
27904 inline expression_node_ptr return_envelope(expression_node_ptr body,
27905 results_context_t* rc,
27906 bool*& return_invoked)
27908 typedef details::return_envelope_node<Type> alloc_type;
27910 expression_node_ptr result = node_allocator_->
27911 allocate_cr<alloc_type>(body,(*rc));
27913 return_invoked = static_cast<alloc_type*>(result)->retinvk_ptr();
27915 return result;
27917 #else
27918 inline expression_node_ptr return_call(std::vector<expression_node_ptr>&)
27920 return error_node();
27923 inline expression_node_ptr return_envelope(expression_node_ptr,
27924 results_context_t*,
27925 bool*&)
27927 return error_node();
27929 #endif
27931 inline expression_node_ptr vector_element(const std::string& symbol,
27932 vector_holder_ptr vector_base,
27933 expression_node_ptr index)
27935 expression_node_ptr result = error_node();
27937 if (details::is_constant_node(index))
27939 std::size_t i = static_cast<std::size_t>(details::numeric::to_int64(index->value()));
27941 details::free_node(*node_allocator_,index);
27943 if (vector_base->rebaseable())
27945 return node_allocator_->allocate<rebasevector_celem_node_t>(i,vector_base);
27948 scope_element& se = parser_->sem_.get_element(symbol,i);
27950 if (se.index == i)
27952 result = se.var_node;
27954 else
27956 scope_element nse;
27957 nse.name = symbol;
27958 nse.active = true;
27959 nse.ref_count = 1;
27960 nse.type = scope_element::e_vecelem;
27961 nse.index = i;
27962 nse.depth = parser_->state_.scope_depth;
27963 nse.data = 0;
27964 nse.var_node = node_allocator_->allocate<variable_node_t>((*(*vector_base)[i]));
27966 if (!parser_->sem_.add_element(nse))
27968 parser_->set_synthesis_error("Failed to add new local vector element to SEM [1]");
27970 parser_->sem_.free_element(nse);
27972 result = error_node();
27975 exprtk_debug(("vector_element() - INFO - Added new local vector element: %s\n",nse.name.c_str()));
27977 parser_->state_.activate_side_effect("vector_element()");
27979 result = nse.var_node;
27982 else if (vector_base->rebaseable())
27983 result = node_allocator_->allocate<rebasevector_elem_node_t>(index,vector_base);
27984 else
27985 result = node_allocator_->allocate<vector_elem_node_t>(index,vector_base);
27987 return result;
27990 private:
27992 template <std::size_t N, typename NodePtr>
27993 inline bool is_constant_foldable(NodePtr (&b)[N]) const
27995 for (std::size_t i = 0; i < N; ++i)
27997 if (0 == b[i])
27998 return false;
27999 else if (!details::is_constant_node(b[i]))
28000 return false;
28003 return true;
28006 template <typename NodePtr,
28007 typename Allocator,
28008 template <typename, typename> class Sequence>
28009 inline bool is_constant_foldable(const Sequence<NodePtr,Allocator>& b) const
28011 for (std::size_t i = 0; i < b.size(); ++i)
28013 if (0 == b[i])
28014 return false;
28015 else if (!details::is_constant_node(b[i]))
28016 return false;
28019 return true;
28022 void lodge_assignment(symbol_type cst, expression_node_ptr node)
28024 parser_->state_.activate_side_effect("lodge_assignment()");
28026 if (!parser_->dec_.collect_assignments())
28027 return;
28029 std::string symbol_name;
28031 switch (cst)
28033 case e_st_variable : symbol_name = parser_->symtab_store_
28034 .get_variable_name(node);
28035 break;
28037 #ifndef exprtk_disable_string_capabilities
28038 case e_st_string : symbol_name = parser_->symtab_store_
28039 .get_stringvar_name(node);
28040 break;
28041 #endif
28043 case e_st_vector : {
28044 typedef details::vector_holder<T> vector_holder_t;
28046 vector_holder_t& vh = static_cast<vector_node_t*>(node)->vec_holder();
28048 symbol_name = parser_->symtab_store_.get_vector_name(&vh);
28050 break;
28052 case e_st_vecelem : {
28053 typedef details::vector_holder<T> vector_holder_t;
28055 vector_holder_t& vh = static_cast<vector_elem_node_t*>(node)->vec_holder();
28057 symbol_name = parser_->symtab_store_.get_vector_name(&vh);
28059 cst = e_st_vector;
28061 break;
28063 default : return;
28066 if (!symbol_name.empty())
28068 parser_->dec_.add_assignment(symbol_name,cst);
28072 inline expression_node_ptr synthesize_assignment_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
28074 if (details::is_variable_node(branch[0]))
28076 lodge_assignment(e_st_variable,branch[0]);
28078 return synthesize_expression<assignment_node_t,2>(operation,branch);
28080 else if (details::is_vector_elem_node(branch[0]))
28082 lodge_assignment(e_st_vecelem,branch[0]);
28084 return synthesize_expression<assignment_vec_elem_node_t, 2>(operation, branch);
28086 else if (details::is_rebasevector_elem_node(branch[0]))
28088 lodge_assignment(e_st_vecelem,branch[0]);
28090 return synthesize_expression<assignment_rebasevec_elem_node_t, 2>(operation, branch);
28092 else if (details::is_rebasevector_celem_node(branch[0]))
28094 lodge_assignment(e_st_vecelem,branch[0]);
28096 return synthesize_expression<assignment_rebasevec_celem_node_t, 2>(operation, branch);
28098 #ifndef exprtk_disable_string_capabilities
28099 else if (details::is_string_node(branch[0]))
28101 lodge_assignment(e_st_string,branch[0]);
28103 return synthesize_expression<assignment_string_node_t,2>(operation, branch);
28105 else if (details::is_string_range_node(branch[0]))
28107 lodge_assignment(e_st_string,branch[0]);
28109 return synthesize_expression<assignment_string_range_node_t,2>(operation, branch);
28111 #endif
28112 else if (details::is_vector_node(branch[0]))
28114 lodge_assignment(e_st_vector,branch[0]);
28116 if (details::is_ivector_node(branch[1]))
28117 return synthesize_expression<assignment_vecvec_node_t,2>(operation, branch);
28118 else
28119 return synthesize_expression<assignment_vec_node_t,2>(operation, branch);
28121 else
28123 parser_->set_synthesis_error("Invalid assignment operation.[1]");
28125 return error_node();
28129 inline expression_node_ptr synthesize_assignment_operation_expression(const details::operator_type& operation,
28130 expression_node_ptr (&branch)[2])
28132 if (details::is_variable_node(branch[0]))
28134 lodge_assignment(e_st_variable,branch[0]);
28136 switch (operation)
28138 #define case_stmt(op0,op1) \
28139 case op0 : return node_allocator_-> \
28140 template allocate_rrr<typename details::assignment_op_node<Type,op1<Type> > > \
28141 (operation, branch[0], branch[1]); \
28143 case_stmt(details::e_addass,details::add_op)
28144 case_stmt(details::e_subass,details::sub_op)
28145 case_stmt(details::e_mulass,details::mul_op)
28146 case_stmt(details::e_divass,details::div_op)
28147 case_stmt(details::e_modass,details::mod_op)
28148 #undef case_stmt
28149 default : return error_node();
28152 else if (details::is_vector_elem_node(branch[0]))
28154 lodge_assignment(e_st_vecelem,branch[0]);
28156 switch (operation)
28158 #define case_stmt(op0,op1) \
28159 case op0 : return node_allocator_-> \
28160 template allocate_rrr<typename details::assignment_vec_elem_op_node<Type,op1<Type> > > \
28161 (operation, branch[0], branch[1]); \
28163 case_stmt(details::e_addass,details::add_op)
28164 case_stmt(details::e_subass,details::sub_op)
28165 case_stmt(details::e_mulass,details::mul_op)
28166 case_stmt(details::e_divass,details::div_op)
28167 case_stmt(details::e_modass,details::mod_op)
28168 #undef case_stmt
28169 default : return error_node();
28172 else if (details::is_rebasevector_elem_node(branch[0]))
28174 lodge_assignment(e_st_vecelem,branch[0]);
28176 switch (operation)
28178 #define case_stmt(op0,op1) \
28179 case op0 : return node_allocator_-> \
28180 template allocate_rrr<typename details::assignment_rebasevec_elem_op_node<Type,op1<Type> > > \
28181 (operation, branch[0], branch[1]); \
28183 case_stmt(details::e_addass,details::add_op)
28184 case_stmt(details::e_subass,details::sub_op)
28185 case_stmt(details::e_mulass,details::mul_op)
28186 case_stmt(details::e_divass,details::div_op)
28187 case_stmt(details::e_modass,details::mod_op)
28188 #undef case_stmt
28189 default : return error_node();
28192 else if (details::is_rebasevector_celem_node(branch[0]))
28194 lodge_assignment(e_st_vecelem,branch[0]);
28196 switch (operation)
28198 #define case_stmt(op0,op1) \
28199 case op0 : return node_allocator_-> \
28200 template allocate_rrr<typename details::assignment_rebasevec_celem_op_node<Type,op1<Type> > > \
28201 (operation, branch[0], branch[1]); \
28203 case_stmt(details::e_addass,details::add_op)
28204 case_stmt(details::e_subass,details::sub_op)
28205 case_stmt(details::e_mulass,details::mul_op)
28206 case_stmt(details::e_divass,details::div_op)
28207 case_stmt(details::e_modass,details::mod_op)
28208 #undef case_stmt
28209 default : return error_node();
28212 else if (details::is_vector_node(branch[0]))
28214 lodge_assignment(e_st_vector,branch[0]);
28216 if (details::is_ivector_node(branch[1]))
28218 switch (operation)
28220 #define case_stmt(op0,op1) \
28221 case op0 : return node_allocator_-> \
28222 template allocate_rrr<typename details::assignment_vecvec_op_node<Type,op1<Type> > > \
28223 (operation, branch[0], branch[1]); \
28225 case_stmt(details::e_addass,details::add_op)
28226 case_stmt(details::e_subass,details::sub_op)
28227 case_stmt(details::e_mulass,details::mul_op)
28228 case_stmt(details::e_divass,details::div_op)
28229 case_stmt(details::e_modass,details::mod_op)
28230 #undef case_stmt
28231 default : return error_node();
28234 else
28236 switch (operation)
28238 #define case_stmt(op0,op1) \
28239 case op0 : return node_allocator_-> \
28240 template allocate_rrr<typename details::assignment_vec_op_node<Type,op1<Type> > > \
28241 (operation, branch[0], branch[1]); \
28243 case_stmt(details::e_addass,details::add_op)
28244 case_stmt(details::e_subass,details::sub_op)
28245 case_stmt(details::e_mulass,details::mul_op)
28246 case_stmt(details::e_divass,details::div_op)
28247 case_stmt(details::e_modass,details::mod_op)
28248 #undef case_stmt
28249 default : return error_node();
28253 #ifndef exprtk_disable_string_capabilities
28254 else if (
28255 (details::e_addass == operation) &&
28256 details::is_string_node(branch[0])
28259 typedef details::assignment_string_node<T,details::asn_addassignment> addass_t;
28261 lodge_assignment(e_st_string,branch[0]);
28263 return synthesize_expression<addass_t,2>(operation,branch);
28265 #endif
28266 else
28268 parser_->set_synthesis_error("Invalid assignment operation[2]");
28270 return error_node();
28274 inline expression_node_ptr synthesize_veceqineqlogic_operation_expression(const details::operator_type& operation,
28275 expression_node_ptr (&branch)[2])
28277 const bool is_b0_ivec = details::is_ivector_node(branch[0]);
28278 const bool is_b1_ivec = details::is_ivector_node(branch[1]);
28280 #define batch_eqineq_logic_case \
28281 case_stmt(details:: e_lt, details:: lt_op) \
28282 case_stmt(details:: e_lte, details:: lte_op) \
28283 case_stmt(details:: e_gt, details:: gt_op) \
28284 case_stmt(details:: e_gte, details:: gte_op) \
28285 case_stmt(details:: e_eq, details:: eq_op) \
28286 case_stmt(details:: e_ne, details:: ne_op) \
28287 case_stmt(details::e_equal, details::equal_op) \
28288 case_stmt(details:: e_and, details:: and_op) \
28289 case_stmt(details:: e_nand, details:: nand_op) \
28290 case_stmt(details:: e_or, details:: or_op) \
28291 case_stmt(details:: e_nor, details:: nor_op) \
28292 case_stmt(details:: e_xor, details:: xor_op) \
28293 case_stmt(details:: e_xnor, details:: xnor_op) \
28295 if (is_b0_ivec && is_b1_ivec)
28297 switch (operation)
28299 #define case_stmt(op0,op1) \
28300 case op0 : return node_allocator_-> \
28301 template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \
28302 (operation, branch[0], branch[1]); \
28304 batch_eqineq_logic_case
28305 #undef case_stmt
28306 default : return error_node();
28309 else if (is_b0_ivec && !is_b1_ivec)
28311 switch (operation)
28313 #define case_stmt(op0,op1) \
28314 case op0 : return node_allocator_-> \
28315 template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \
28316 (operation, branch[0], branch[1]); \
28318 batch_eqineq_logic_case
28319 #undef case_stmt
28320 default : return error_node();
28323 else if (!is_b0_ivec && is_b1_ivec)
28325 switch (operation)
28327 #define case_stmt(op0,op1) \
28328 case op0 : return node_allocator_-> \
28329 template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \
28330 (operation, branch[0], branch[1]); \
28332 batch_eqineq_logic_case
28333 #undef case_stmt
28334 default : return error_node();
28337 else
28338 return error_node();
28340 #undef batch_eqineq_logic_case
28343 inline expression_node_ptr synthesize_vecarithmetic_operation_expression(const details::operator_type& operation,
28344 expression_node_ptr (&branch)[2])
28346 const bool is_b0_ivec = details::is_ivector_node(branch[0]);
28347 const bool is_b1_ivec = details::is_ivector_node(branch[1]);
28349 #define vector_ops \
28350 case_stmt(details::e_add,details::add_op) \
28351 case_stmt(details::e_sub,details::sub_op) \
28352 case_stmt(details::e_mul,details::mul_op) \
28353 case_stmt(details::e_div,details::div_op) \
28354 case_stmt(details::e_mod,details::mod_op) \
28356 if (is_b0_ivec && is_b1_ivec)
28358 switch (operation)
28360 #define case_stmt(op0,op1) \
28361 case op0 : return node_allocator_-> \
28362 template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \
28363 (operation, branch[0], branch[1]); \
28365 vector_ops
28366 case_stmt(details::e_pow,details:: pow_op)
28367 #undef case_stmt
28368 default : return error_node();
28371 else if (is_b0_ivec && !is_b1_ivec)
28373 switch (operation)
28375 #define case_stmt(op0,op1) \
28376 case op0 : return node_allocator_-> \
28377 template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \
28378 (operation, branch[0], branch[1]); \
28380 vector_ops
28381 case_stmt(details::e_pow,details:: pow_op)
28382 #undef case_stmt
28383 default : return error_node();
28386 else if (!is_b0_ivec && is_b1_ivec)
28388 switch (operation)
28390 #define case_stmt(op0,op1) \
28391 case op0 : return node_allocator_-> \
28392 template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \
28393 (operation, branch[0], branch[1]); \
28395 vector_ops
28396 #undef case_stmt
28397 default : return error_node();
28400 else
28401 return error_node();
28403 #undef vector_ops
28406 inline expression_node_ptr synthesize_swap_expression(expression_node_ptr (&branch)[2])
28408 const bool v0_is_ivar = details::is_ivariable_node(branch[0]);
28409 const bool v1_is_ivar = details::is_ivariable_node(branch[1]);
28411 const bool v0_is_ivec = details::is_ivector_node (branch[0]);
28412 const bool v1_is_ivec = details::is_ivector_node (branch[1]);
28414 #ifndef exprtk_disable_string_capabilities
28415 const bool v0_is_str = details::is_generally_string_node(branch[0]);
28416 const bool v1_is_str = details::is_generally_string_node(branch[1]);
28417 #endif
28419 expression_node_ptr result = error_node();
28421 if (v0_is_ivar && v1_is_ivar)
28423 typedef details::variable_node<T>* variable_node_ptr;
28425 variable_node_ptr v0 = variable_node_ptr(0);
28426 variable_node_ptr v1 = variable_node_ptr(0);
28428 if (
28429 (0 != (v0 = dynamic_cast<variable_node_ptr>(branch[0]))) &&
28430 (0 != (v1 = dynamic_cast<variable_node_ptr>(branch[1])))
28433 result = node_allocator_->allocate<details::swap_node<T> >(v0,v1);
28435 else
28436 result = node_allocator_->allocate<details::swap_generic_node<T> >(branch[0],branch[1]);
28438 else if (v0_is_ivec && v1_is_ivec)
28440 result = node_allocator_->allocate<details::swap_vecvec_node<T> >(branch[0],branch[1]);
28442 #ifndef exprtk_disable_string_capabilities
28443 else if (v0_is_str && v1_is_str)
28445 if (is_string_node(branch[0]) && is_string_node(branch[1]))
28446 result = node_allocator_->allocate<details::swap_string_node<T> >
28447 (branch[0], branch[1]);
28448 else
28449 result = node_allocator_->allocate<details::swap_genstrings_node<T> >
28450 (branch[0], branch[1]);
28452 #endif
28453 else
28455 parser_->set_synthesis_error("Only variables, strings, vectors or vector elements can be swapped");
28457 return error_node();
28460 parser_->state_.activate_side_effect("synthesize_swap_expression()");
28462 return result;
28465 #ifndef exprtk_disable_sc_andor
28466 inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
28468 expression_node_ptr result = error_node();
28470 if (details::is_constant_node(branch[0]))
28472 if (
28473 (details::e_scand == operation) &&
28474 std::equal_to<T>()(T(0),branch[0]->value())
28476 result = node_allocator_->allocate_c<literal_node_t>(T(0));
28477 else if (
28478 (details::e_scor == operation) &&
28479 std::not_equal_to<T>()(T(0),branch[0]->value())
28481 result = node_allocator_->allocate_c<literal_node_t>(T(1));
28484 if (details::is_constant_node(branch[1]) && (0 == result))
28486 if (
28487 (details::e_scand == operation) &&
28488 std::equal_to<T>()(T(0),branch[1]->value())
28490 result = node_allocator_->allocate_c<literal_node_t>(T(0));
28491 else if (
28492 (details::e_scor == operation) &&
28493 std::not_equal_to<T>()(T(0),branch[1]->value())
28495 result = node_allocator_->allocate_c<literal_node_t>(T(1));
28498 if (result)
28500 free_node(*node_allocator_, branch[0]);
28501 free_node(*node_allocator_, branch[1]);
28503 return result;
28505 else if (details::e_scand == operation)
28507 return synthesize_expression<scand_node_t,2>(operation, branch);
28509 else if (details::e_scor == operation)
28511 return synthesize_expression<scor_node_t,2>(operation, branch);
28513 else
28514 return error_node();
28516 #else
28517 inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type&, expression_node_ptr (&)[2])
28519 return error_node();
28521 #endif
28523 #define basic_opr_switch_statements \
28524 case_stmt(details::e_add, details::add_op) \
28525 case_stmt(details::e_sub, details::sub_op) \
28526 case_stmt(details::e_mul, details::mul_op) \
28527 case_stmt(details::e_div, details::div_op) \
28528 case_stmt(details::e_mod, details::mod_op) \
28529 case_stmt(details::e_pow, details::pow_op) \
28531 #define extended_opr_switch_statements \
28532 case_stmt(details:: e_lt, details:: lt_op) \
28533 case_stmt(details:: e_lte, details:: lte_op) \
28534 case_stmt(details:: e_gt, details:: gt_op) \
28535 case_stmt(details:: e_gte, details:: gte_op) \
28536 case_stmt(details:: e_eq, details:: eq_op) \
28537 case_stmt(details:: e_ne, details:: ne_op) \
28538 case_stmt(details:: e_and, details:: and_op) \
28539 case_stmt(details::e_nand, details::nand_op) \
28540 case_stmt(details:: e_or, details:: or_op) \
28541 case_stmt(details:: e_nor, details:: nor_op) \
28542 case_stmt(details:: e_xor, details:: xor_op) \
28543 case_stmt(details::e_xnor, details::xnor_op) \
28545 #ifndef exprtk_disable_cardinal_pow_optimisation
28546 template <typename TType, template <typename, typename> class IPowNode>
28547 inline expression_node_ptr cardinal_pow_optimisation_impl(const TType& v, const unsigned int& p)
28549 switch (p)
28551 #define case_stmt(cp) \
28552 case cp : return node_allocator_-> \
28553 allocate<IPowNode<T,details::numeric::fast_exp<T,cp> > >(v); \
28555 case_stmt( 1) case_stmt( 2) case_stmt( 3) case_stmt( 4)
28556 case_stmt( 5) case_stmt( 6) case_stmt( 7) case_stmt( 8)
28557 case_stmt( 9) case_stmt(10) case_stmt(11) case_stmt(12)
28558 case_stmt(13) case_stmt(14) case_stmt(15) case_stmt(16)
28559 case_stmt(17) case_stmt(18) case_stmt(19) case_stmt(20)
28560 case_stmt(21) case_stmt(22) case_stmt(23) case_stmt(24)
28561 case_stmt(25) case_stmt(26) case_stmt(27) case_stmt(28)
28562 case_stmt(29) case_stmt(30) case_stmt(31) case_stmt(32)
28563 case_stmt(33) case_stmt(34) case_stmt(35) case_stmt(36)
28564 case_stmt(37) case_stmt(38) case_stmt(39) case_stmt(40)
28565 case_stmt(41) case_stmt(42) case_stmt(43) case_stmt(44)
28566 case_stmt(45) case_stmt(46) case_stmt(47) case_stmt(48)
28567 case_stmt(49) case_stmt(50) case_stmt(51) case_stmt(52)
28568 case_stmt(53) case_stmt(54) case_stmt(55) case_stmt(56)
28569 case_stmt(57) case_stmt(58) case_stmt(59) case_stmt(60)
28570 #undef case_stmt
28571 default : return error_node();
28575 inline expression_node_ptr cardinal_pow_optimisation(const T& v, const T& c)
28577 const bool not_recipricol = (c >= T(0));
28578 const unsigned int p = static_cast<unsigned int>(details::numeric::to_int32(details::numeric::abs(c)));
28580 if (0 == p)
28581 return node_allocator_->allocate_c<literal_node_t>(T(1));
28582 else if (std::equal_to<T>()(T(2),c))
28584 return node_allocator_->
28585 template allocate_rr<typename details::vov_node<Type,details::mul_op<Type> > >(v,v);
28587 else
28589 if (not_recipricol)
28590 return cardinal_pow_optimisation_impl<T,details::ipow_node>(v,p);
28591 else
28592 return cardinal_pow_optimisation_impl<T,details::ipowinv_node>(v,p);
28596 inline bool cardinal_pow_optimisable(const details::operator_type& operation, const T& c) const
28598 return (details::e_pow == operation) && (details::numeric::abs(c) <= T(60)) && details::numeric::is_integer(c);
28601 inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr (&branch)[2])
28603 const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
28604 const bool not_recipricol = (c >= T(0));
28605 const unsigned int p = static_cast<unsigned int>(details::numeric::to_int32(details::numeric::abs(c)));
28607 node_allocator_->free(branch[1]);
28609 if (0 == p)
28611 details::free_all_nodes(*node_allocator_, branch);
28613 return node_allocator_->allocate_c<literal_node_t>(T(1));
28615 else if (not_recipricol)
28616 return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipow_node>(branch[0],p);
28617 else
28618 return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipowninv_node>(branch[0],p);
28620 #else
28621 inline expression_node_ptr cardinal_pow_optimisation(T&, const T&)
28623 return error_node();
28626 inline bool cardinal_pow_optimisable(const details::operator_type&, const T&)
28628 return false;
28631 inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr(&)[2])
28633 return error_node();
28635 #endif
28637 struct synthesize_binary_ext_expression
28639 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
28640 const details::operator_type& operation,
28641 expression_node_ptr (&branch)[2])
28643 const bool left_neg = is_neg_unary_node(branch[0]);
28644 const bool right_neg = is_neg_unary_node(branch[1]);
28646 if (left_neg && right_neg)
28648 if (
28649 (details::e_add == operation) ||
28650 (details::e_sub == operation) ||
28651 (details::e_mul == operation) ||
28652 (details::e_div == operation)
28655 if (
28656 !expr_gen.parser_->simplify_unary_negation_branch(branch[0]) ||
28657 !expr_gen.parser_->simplify_unary_negation_branch(branch[1])
28660 details::free_all_nodes(*expr_gen.node_allocator_,branch);
28662 return error_node();
28666 switch (operation)
28668 // -f(x + 1) + -g(y + 1) --> -(f(x + 1) + g(y + 1))
28669 case details::e_add : return expr_gen(details::e_neg,
28670 expr_gen.node_allocator_->
28671 template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >
28672 (branch[0],branch[1]));
28674 // -f(x + 1) - -g(y + 1) --> g(y + 1) - f(x + 1)
28675 case details::e_sub : return expr_gen.node_allocator_->
28676 template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >
28677 (branch[1],branch[0]);
28679 default : break;
28682 else if (left_neg && !right_neg)
28684 if (
28685 (details::e_add == operation) ||
28686 (details::e_sub == operation) ||
28687 (details::e_mul == operation) ||
28688 (details::e_div == operation)
28691 if (!expr_gen.parser_->simplify_unary_negation_branch(branch[0]))
28693 details::free_all_nodes(*expr_gen.node_allocator_,branch);
28695 return error_node();
28698 switch (operation)
28700 // -f(x + 1) + g(y + 1) --> g(y + 1) - f(x + 1)
28701 case details::e_add : return expr_gen.node_allocator_->
28702 template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >
28703 (branch[1], branch[0]);
28705 // -f(x + 1) - g(y + 1) --> -(f(x + 1) + g(y + 1))
28706 case details::e_sub : return expr_gen(details::e_neg,
28707 expr_gen.node_allocator_->
28708 template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >
28709 (branch[0], branch[1]));
28711 // -f(x + 1) * g(y + 1) --> -(f(x + 1) * g(y + 1))
28712 case details::e_mul : return expr_gen(details::e_neg,
28713 expr_gen.node_allocator_->
28714 template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > >
28715 (branch[0], branch[1]));
28717 // -f(x + 1) / g(y + 1) --> -(f(x + 1) / g(y + 1))
28718 case details::e_div : return expr_gen(details::e_neg,
28719 expr_gen.node_allocator_->
28720 template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > >
28721 (branch[0], branch[1]));
28723 default : return error_node();
28727 else if (!left_neg && right_neg)
28729 if (
28730 (details::e_add == operation) ||
28731 (details::e_sub == operation) ||
28732 (details::e_mul == operation) ||
28733 (details::e_div == operation)
28736 if (!expr_gen.parser_->simplify_unary_negation_branch(branch[1]))
28738 details::free_all_nodes(*expr_gen.node_allocator_,branch);
28740 return error_node();
28743 switch (operation)
28745 // f(x + 1) + -g(y + 1) --> f(x + 1) - g(y + 1)
28746 case details::e_add : return expr_gen.node_allocator_->
28747 template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >
28748 (branch[0], branch[1]);
28750 // f(x + 1) - - g(y + 1) --> f(x + 1) + g(y + 1)
28751 case details::e_sub : return expr_gen.node_allocator_->
28752 template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >
28753 (branch[0], branch[1]);
28755 // f(x + 1) * -g(y + 1) --> -(f(x + 1) * g(y + 1))
28756 case details::e_mul : return expr_gen(details::e_neg,
28757 expr_gen.node_allocator_->
28758 template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > >
28759 (branch[0], branch[1]));
28761 // f(x + 1) / -g(y + 1) --> -(f(x + 1) / g(y + 1))
28762 case details::e_div : return expr_gen(details::e_neg,
28763 expr_gen.node_allocator_->
28764 template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > >
28765 (branch[0], branch[1]));
28767 default : return error_node();
28772 switch (operation)
28774 #define case_stmt(op0,op1) \
28775 case op0 : return expr_gen.node_allocator_-> \
28776 template allocate<typename details::binary_ext_node<Type,op1<Type> > > \
28777 (branch[0], branch[1]); \
28779 basic_opr_switch_statements
28780 extended_opr_switch_statements
28781 #undef case_stmt
28782 default : return error_node();
28787 struct synthesize_vob_expression
28789 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
28790 const details::operator_type& operation,
28791 expression_node_ptr (&branch)[2])
28793 const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref();
28795 #ifndef exprtk_disable_enhanced_features
28796 if (details::is_sf3ext_node(branch[1]))
28798 expression_node_ptr result = error_node();
28800 const bool synthesis_result =
28801 synthesize_sf4ext_expression::template compile_right<vtype>
28802 (expr_gen, v, operation, branch[1], result);
28804 if (synthesis_result)
28806 free_node(*expr_gen.node_allocator_,branch[1]);
28807 return result;
28810 #endif
28812 if (
28813 (details::e_mul == operation) ||
28814 (details::e_div == operation)
28817 if (details::is_uv_node(branch[1]))
28819 typedef details::uv_base_node<Type>* uvbn_ptr_t;
28821 details::operator_type o = static_cast<uvbn_ptr_t>(branch[1])->operation();
28823 if (details::e_neg == o)
28825 const Type& v1 = static_cast<uvbn_ptr_t>(branch[1])->v();
28827 free_node(*expr_gen.node_allocator_,branch[1]);
28829 switch (operation)
28831 case details::e_mul : return expr_gen(details::e_neg,
28832 expr_gen.node_allocator_->
28833 template allocate_rr<typename details::
28834 vov_node<Type,details::mul_op<Type> > >(v,v1));
28836 case details::e_div : return expr_gen(details::e_neg,
28837 expr_gen.node_allocator_->
28838 template allocate_rr<typename details::
28839 vov_node<Type,details::div_op<Type> > >(v,v1));
28841 default : break;
28847 switch (operation)
28849 #define case_stmt(op0,op1) \
28850 case op0 : return expr_gen.node_allocator_-> \
28851 template allocate_rc<typename details::vob_node<Type,op1<Type> > > \
28852 (v, branch[1]); \
28854 basic_opr_switch_statements
28855 extended_opr_switch_statements
28856 #undef case_stmt
28857 default : return error_node();
28862 struct synthesize_bov_expression
28864 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
28865 const details::operator_type& operation,
28866 expression_node_ptr (&branch)[2])
28868 const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref();
28870 #ifndef exprtk_disable_enhanced_features
28871 if (details::is_sf3ext_node(branch[0]))
28873 expression_node_ptr result = error_node();
28875 const bool synthesis_result =
28876 synthesize_sf4ext_expression::template compile_left<vtype>
28877 (expr_gen, v, operation, branch[0], result);
28879 if (synthesis_result)
28881 free_node(*expr_gen.node_allocator_, branch[0]);
28883 return result;
28886 #endif
28888 if (
28889 (details::e_add == operation) ||
28890 (details::e_sub == operation) ||
28891 (details::e_mul == operation) ||
28892 (details::e_div == operation)
28895 if (details::is_uv_node(branch[0]))
28897 typedef details::uv_base_node<Type>* uvbn_ptr_t;
28899 details::operator_type o = static_cast<uvbn_ptr_t>(branch[0])->operation();
28901 if (details::e_neg == o)
28903 const Type& v0 = static_cast<uvbn_ptr_t>(branch[0])->v();
28905 free_node(*expr_gen.node_allocator_,branch[0]);
28907 switch (operation)
28909 case details::e_add : return expr_gen.node_allocator_->
28910 template allocate_rr<typename details::
28911 vov_node<Type,details::sub_op<Type> > >(v,v0);
28913 case details::e_sub : return expr_gen(details::e_neg,
28914 expr_gen.node_allocator_->
28915 template allocate_rr<typename details::
28916 vov_node<Type,details::add_op<Type> > >(v0,v));
28918 case details::e_mul : return expr_gen(details::e_neg,
28919 expr_gen.node_allocator_->
28920 template allocate_rr<typename details::
28921 vov_node<Type,details::mul_op<Type> > >(v0,v));
28923 case details::e_div : return expr_gen(details::e_neg,
28924 expr_gen.node_allocator_->
28925 template allocate_rr<typename details::
28926 vov_node<Type,details::div_op<Type> > >(v0,v));
28927 default : break;
28933 switch (operation)
28935 #define case_stmt(op0,op1) \
28936 case op0 : return expr_gen.node_allocator_-> \
28937 template allocate_cr<typename details::bov_node<Type,op1<Type> > > \
28938 (branch[0], v); \
28940 basic_opr_switch_statements
28941 extended_opr_switch_statements
28942 #undef case_stmt
28943 default : return error_node();
28948 struct synthesize_cob_expression
28950 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
28951 const details::operator_type& operation,
28952 expression_node_ptr (&branch)[2])
28954 const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
28956 free_node(*expr_gen.node_allocator_,branch[0]);
28958 if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
28960 free_node(*expr_gen.node_allocator_,branch[1]);
28962 return expr_gen(T(0));
28964 else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
28966 free_node(*expr_gen.node_allocator_, branch[1]);
28968 return expr_gen(T(0));
28970 else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
28971 return branch[1];
28972 else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
28973 return branch[1];
28975 if (details::is_cob_node(branch[1]))
28977 // Simplify expressions of the form:
28978 // 1. (1 * (2 * (3 * (4 * (5 * (6 * (7 * (8 * (9 + x))))))))) --> 40320 * (9 + x)
28979 // 2. (1 + (2 + (3 + (4 + (5 + (6 + (7 + (8 + (9 + x))))))))) --> 45 + x
28980 if (
28981 (operation == details::e_mul) ||
28982 (operation == details::e_add)
28985 details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
28987 if (operation == cobnode->operation())
28989 switch (operation)
28991 case details::e_add : cobnode->set_c(c + cobnode->c()); break;
28992 case details::e_mul : cobnode->set_c(c * cobnode->c()); break;
28993 default : return error_node();
28996 return cobnode;
29000 if (operation == details::e_mul)
29002 details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
29003 details::operator_type cob_opr = cobnode->operation();
29005 if (
29006 (details::e_div == cob_opr) ||
29007 (details::e_mul == cob_opr)
29010 switch (cob_opr)
29012 case details::e_div : cobnode->set_c(c * cobnode->c()); break;
29013 case details::e_mul : cobnode->set_c(cobnode->c() / c); break;
29014 default : return error_node();
29017 return cobnode;
29020 else if (operation == details::e_div)
29022 details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
29023 details::operator_type cob_opr = cobnode->operation();
29025 if (
29026 (details::e_div == cob_opr) ||
29027 (details::e_mul == cob_opr)
29030 details::expression_node<Type>* new_cobnode = error_node();
29032 switch (cob_opr)
29034 case details::e_div : new_cobnode = expr_gen.node_allocator_->
29035 template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > >
29036 (c / cobnode->c(), cobnode->move_branch(0));
29037 break;
29039 case details::e_mul : new_cobnode = expr_gen.node_allocator_->
29040 template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
29041 (c / cobnode->c(), cobnode->move_branch(0));
29042 break;
29044 default : return error_node();
29047 free_node(*expr_gen.node_allocator_,branch[1]);
29049 return new_cobnode;
29053 #ifndef exprtk_disable_enhanced_features
29054 else if (details::is_sf3ext_node(branch[1]))
29056 expression_node_ptr result = error_node();
29058 const bool synthesis_result =
29059 synthesize_sf4ext_expression::template compile_right<ctype>
29060 (expr_gen, c, operation, branch[1], result);
29062 if (synthesis_result)
29064 free_node(*expr_gen.node_allocator_,branch[1]);
29066 return result;
29069 #endif
29071 switch (operation)
29073 #define case_stmt(op0,op1) \
29074 case op0 : return expr_gen.node_allocator_-> \
29075 template allocate_tt<typename details::cob_node<Type,op1<Type> > > \
29076 (c, branch[1]); \
29078 basic_opr_switch_statements
29079 extended_opr_switch_statements
29080 #undef case_stmt
29081 default : return error_node();
29086 struct synthesize_boc_expression
29088 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
29089 const details::operator_type& operation,
29090 expression_node_ptr (&branch)[2])
29092 const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
29094 details::free_node(*(expr_gen.node_allocator_), branch[1]);
29096 if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
29098 free_node(*expr_gen.node_allocator_, branch[0]);
29100 return expr_gen(T(0));
29102 else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
29104 free_node(*expr_gen.node_allocator_, branch[0]);
29106 return expr_gen(std::numeric_limits<T>::quiet_NaN());
29108 else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
29109 return branch[0];
29110 else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
29111 return branch[0];
29113 if (details::is_boc_node(branch[0]))
29115 // Simplify expressions of the form:
29116 // 1. (((((((((x + 9) * 8) * 7) * 6) * 5) * 4) * 3) * 2) * 1) --> (x + 9) * 40320
29117 // 2. (((((((((x + 9) + 8) + 7) + 6) + 5) + 4) + 3) + 2) + 1) --> x + 45
29118 if (
29119 (operation == details::e_mul) ||
29120 (operation == details::e_add)
29123 details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
29125 if (operation == bocnode->operation())
29127 switch (operation)
29129 case details::e_add : bocnode->set_c(c + bocnode->c()); break;
29130 case details::e_mul : bocnode->set_c(c * bocnode->c()); break;
29131 default : return error_node();
29134 return bocnode;
29137 else if (operation == details::e_div)
29139 details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
29140 details::operator_type boc_opr = bocnode->operation();
29142 if (
29143 (details::e_div == boc_opr) ||
29144 (details::e_mul == boc_opr)
29147 switch (boc_opr)
29149 case details::e_div : bocnode->set_c(c * bocnode->c()); break;
29150 case details::e_mul : bocnode->set_c(bocnode->c() / c); break;
29151 default : return error_node();
29154 return bocnode;
29157 else if (operation == details::e_pow)
29159 // (v ^ c0) ^ c1 --> v ^(c0 * c1)
29160 details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
29161 details::operator_type boc_opr = bocnode->operation();
29163 if (details::e_pow == boc_opr)
29165 bocnode->set_c(bocnode->c() * c);
29167 return bocnode;
29172 #ifndef exprtk_disable_enhanced_features
29173 if (details::is_sf3ext_node(branch[0]))
29175 expression_node_ptr result = error_node();
29177 const bool synthesis_result =
29178 synthesize_sf4ext_expression::template compile_left<ctype>
29179 (expr_gen, c, operation, branch[0], result);
29181 if (synthesis_result)
29183 free_node(*expr_gen.node_allocator_, branch[0]);
29185 return result;
29188 #endif
29190 switch (operation)
29192 #define case_stmt(op0,op1) \
29193 case op0 : return expr_gen.node_allocator_-> \
29194 template allocate_cr<typename details::boc_node<Type,op1<Type> > > \
29195 (branch[0], c); \
29197 basic_opr_switch_statements
29198 extended_opr_switch_statements
29199 #undef case_stmt
29200 default : return error_node();
29205 struct synthesize_cocob_expression
29207 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
29208 const details::operator_type& operation,
29209 expression_node_ptr (&branch)[2])
29211 expression_node_ptr result = error_node();
29213 // (cob) o c --> cob
29214 if (details::is_cob_node(branch[0]))
29216 details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[0]);
29218 const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
29220 if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
29222 free_node(*expr_gen.node_allocator_, branch[0]);
29223 free_node(*expr_gen.node_allocator_, branch[1]);
29225 return expr_gen(T(0));
29227 else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
29229 free_node(*expr_gen.node_allocator_, branch[0]);
29230 free_node(*expr_gen.node_allocator_, branch[1]);
29232 return expr_gen(T(std::numeric_limits<T>::quiet_NaN()));
29234 else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
29236 free_node(*expr_gen.node_allocator_, branch[1]);
29238 return branch[0];
29240 else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
29242 free_node(*expr_gen.node_allocator_, branch[1]);
29244 return branch[0];
29246 else if (std::equal_to<T>()(T(1),c) && (details::e_div == operation))
29248 free_node(*expr_gen.node_allocator_, branch[1]);
29250 return branch[0];
29253 const bool op_addsub = (details::e_add == cobnode->operation()) ||
29254 (details::e_sub == cobnode->operation()) ;
29256 if (op_addsub)
29258 switch (operation)
29260 case details::e_add : cobnode->set_c(cobnode->c() + c); break;
29261 case details::e_sub : cobnode->set_c(cobnode->c() - c); break;
29262 default : return error_node();
29265 result = cobnode;
29267 else if (details::e_mul == cobnode->operation())
29269 switch (operation)
29271 case details::e_mul : cobnode->set_c(cobnode->c() * c); break;
29272 case details::e_div : cobnode->set_c(cobnode->c() / c); break;
29273 default : return error_node();
29276 result = cobnode;
29278 else if (details::e_div == cobnode->operation())
29280 if (details::e_mul == operation)
29282 cobnode->set_c(cobnode->c() * c);
29283 result = cobnode;
29285 else if (details::e_div == operation)
29287 result = expr_gen.node_allocator_->
29288 template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
29289 (cobnode->c() / c, cobnode->move_branch(0));
29291 free_node(*expr_gen.node_allocator_, branch[0]);
29295 if (result)
29297 free_node(*expr_gen.node_allocator_,branch[1]);
29301 // c o (cob) --> cob
29302 else if (details::is_cob_node(branch[1]))
29304 details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
29306 const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
29308 if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
29310 free_node(*expr_gen.node_allocator_, branch[0]);
29311 free_node(*expr_gen.node_allocator_, branch[1]);
29313 return expr_gen(T(0));
29315 else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
29317 free_node(*expr_gen.node_allocator_, branch[0]);
29318 free_node(*expr_gen.node_allocator_, branch[1]);
29320 return expr_gen(T(0));
29322 else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
29324 free_node(*expr_gen.node_allocator_, branch[0]);
29326 return branch[1];
29328 else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
29330 free_node(*expr_gen.node_allocator_, branch[0]);
29332 return branch[1];
29335 if (details::e_add == cobnode->operation())
29337 if (details::e_add == operation)
29339 cobnode->set_c(c + cobnode->c());
29340 result = cobnode;
29342 else if (details::e_sub == operation)
29344 result = expr_gen.node_allocator_->
29345 template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
29346 (c - cobnode->c(), cobnode->move_branch(0));
29348 free_node(*expr_gen.node_allocator_,branch[1]);
29351 else if (details::e_sub == cobnode->operation())
29353 if (details::e_add == operation)
29355 cobnode->set_c(c + cobnode->c());
29356 result = cobnode;
29358 else if (details::e_sub == operation)
29360 result = expr_gen.node_allocator_->
29361 template allocate_tt<typename details::cob_node<Type,details::add_op<Type> > >
29362 (c - cobnode->c(), cobnode->move_branch(0));
29364 free_node(*expr_gen.node_allocator_,branch[1]);
29367 else if (details::e_mul == cobnode->operation())
29369 if (details::e_mul == operation)
29371 cobnode->set_c(c * cobnode->c());
29372 result = cobnode;
29374 else if (details::e_div == operation)
29376 result = expr_gen.node_allocator_->
29377 template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
29378 (c / cobnode->c(), cobnode->move_branch(0));
29380 free_node(*expr_gen.node_allocator_,branch[1]);
29383 else if (details::e_div == cobnode->operation())
29385 if (details::e_mul == operation)
29387 cobnode->set_c(c * cobnode->c());
29388 result = cobnode;
29390 else if (details::e_div == operation)
29392 result = expr_gen.node_allocator_->
29393 template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > >
29394 (c / cobnode->c(), cobnode->move_branch(0));
29396 free_node(*expr_gen.node_allocator_,branch[1]);
29400 if (result)
29402 free_node(*expr_gen.node_allocator_,branch[0]);
29406 return result;
29410 struct synthesize_coboc_expression
29412 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
29413 const details::operator_type& operation,
29414 expression_node_ptr (&branch)[2])
29416 expression_node_ptr result = error_node();
29418 // (boc) o c --> boc
29419 if (details::is_boc_node(branch[0]))
29421 details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
29423 const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
29425 if (details::e_add == bocnode->operation())
29427 switch (operation)
29429 case details::e_add : bocnode->set_c(bocnode->c() + c); break;
29430 case details::e_sub : bocnode->set_c(bocnode->c() - c); break;
29431 default : return error_node();
29434 result = bocnode;
29436 else if (details::e_mul == bocnode->operation())
29438 switch (operation)
29440 case details::e_mul : bocnode->set_c(bocnode->c() * c); break;
29441 case details::e_div : bocnode->set_c(bocnode->c() / c); break;
29442 default : return error_node();
29445 result = bocnode;
29447 else if (details::e_sub == bocnode->operation())
29449 if (details::e_add == operation)
29451 result = expr_gen.node_allocator_->
29452 template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > >
29453 (bocnode->move_branch(0), c - bocnode->c());
29455 free_node(*expr_gen.node_allocator_,branch[0]);
29457 else if (details::e_sub == operation)
29459 bocnode->set_c(bocnode->c() + c);
29460 result = bocnode;
29463 else if (details::e_div == bocnode->operation())
29465 switch (operation)
29467 case details::e_div : bocnode->set_c(bocnode->c() * c); break;
29468 case details::e_mul : bocnode->set_c(bocnode->c() / c); break;
29469 default : return error_node();
29472 result = bocnode;
29475 if (result)
29477 free_node(*expr_gen.node_allocator_, branch[1]);
29481 // c o (boc) --> boc
29482 else if (details::is_boc_node(branch[1]))
29484 details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[1]);
29486 const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
29488 if (details::e_add == bocnode->operation())
29490 if (details::e_add == operation)
29492 bocnode->set_c(c + bocnode->c());
29493 result = bocnode;
29495 else if (details::e_sub == operation)
29497 result = expr_gen.node_allocator_->
29498 template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
29499 (c - bocnode->c(), bocnode->move_branch(0));
29501 free_node(*expr_gen.node_allocator_,branch[1]);
29504 else if (details::e_sub == bocnode->operation())
29506 if (details::e_add == operation)
29508 result = expr_gen.node_allocator_->
29509 template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > >
29510 (bocnode->move_branch(0), c - bocnode->c());
29512 free_node(*expr_gen.node_allocator_,branch[1]);
29514 else if (details::e_sub == operation)
29516 result = expr_gen.node_allocator_->
29517 template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
29518 (c + bocnode->c(), bocnode->move_branch(0));
29520 free_node(*expr_gen.node_allocator_,branch[1]);
29523 else if (details::e_mul == bocnode->operation())
29525 if (details::e_mul == operation)
29527 bocnode->set_c(c * bocnode->c());
29528 result = bocnode;
29530 else if (details::e_div == operation)
29532 result = expr_gen.node_allocator_->
29533 template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
29534 (c / bocnode->c(), bocnode->move_branch(0));
29536 free_node(*expr_gen.node_allocator_,branch[1]);
29539 else if (details::e_div == bocnode->operation())
29541 if (details::e_mul == operation)
29543 bocnode->set_c(bocnode->c() / c);
29544 result = bocnode;
29546 else if (details::e_div == operation)
29548 result = expr_gen.node_allocator_->
29549 template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
29550 (c * bocnode->c(), bocnode->move_branch(0));
29552 free_node(*expr_gen.node_allocator_,branch[1]);
29556 if (result)
29558 free_node(*expr_gen.node_allocator_,branch[0]);
29562 return result;
29566 #ifndef exprtk_disable_enhanced_features
29567 inline bool synthesize_expression(const details::operator_type& operation,
29568 expression_node_ptr (&branch)[2],
29569 expression_node_ptr& result)
29571 result = error_node();
29573 if (!operation_optimisable(operation))
29574 return false;
29576 const std::string node_id = branch_to_id(branch);
29578 const typename synthesize_map_t::iterator itr = synthesize_map_.find(node_id);
29580 if (synthesize_map_.end() != itr)
29582 result = itr->second((*this), operation, branch);
29584 return true;
29586 else
29587 return false;
29590 struct synthesize_vov_expression
29592 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
29593 const details::operator_type& operation,
29594 expression_node_ptr (&branch)[2])
29596 const Type& v1 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
29597 const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
29599 switch (operation)
29601 #define case_stmt(op0,op1) \
29602 case op0 : return expr_gen.node_allocator_-> \
29603 template allocate_rr<typename details::vov_node<Type,op1<Type> > > \
29604 (v1, v2); \
29606 basic_opr_switch_statements
29607 extended_opr_switch_statements
29608 #undef case_stmt
29609 default : return error_node();
29614 struct synthesize_cov_expression
29616 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
29617 const details::operator_type& operation,
29618 expression_node_ptr (&branch)[2])
29620 const Type c = static_cast<details::literal_node<Type>*> (branch[0])->value();
29621 const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref ();
29623 details::free_node(*(expr_gen.node_allocator_),branch[0]);
29625 if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
29626 return expr_gen(T(0));
29627 else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
29628 return expr_gen(T(0));
29629 else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
29630 return static_cast<details::variable_node<Type>*>(branch[1]);
29631 else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
29632 return static_cast<details::variable_node<Type>*>(branch[1]);
29634 switch (operation)
29636 #define case_stmt(op0,op1) \
29637 case op0 : return expr_gen.node_allocator_-> \
29638 template allocate_cr<typename details::cov_node<Type,op1<Type> > > \
29639 (c, v); \
29641 basic_opr_switch_statements
29642 extended_opr_switch_statements
29643 #undef case_stmt
29644 default : return error_node();
29649 struct synthesize_voc_expression
29651 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
29652 const details::operator_type& operation,
29653 expression_node_ptr (&branch)[2])
29655 const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref ();
29656 const Type c = static_cast<details::literal_node<Type>*> (branch[1])->value();
29658 details::free_node(*(expr_gen.node_allocator_), branch[1]);
29660 if (expr_gen.cardinal_pow_optimisable(operation,c))
29662 if (std::equal_to<T>()(T(1),c))
29663 return branch[0];
29664 else
29665 return expr_gen.cardinal_pow_optimisation(v,c);
29667 else if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
29668 return expr_gen(T(0));
29669 else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
29670 return expr_gen(std::numeric_limits<T>::quiet_NaN());
29671 else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
29672 return static_cast<details::variable_node<Type>*>(branch[0]);
29673 else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
29674 return static_cast<details::variable_node<Type>*>(branch[0]);
29675 else if (std::equal_to<T>()(T(1),c) && (details::e_div == operation))
29676 return static_cast<details::variable_node<Type>*>(branch[0]);
29678 switch (operation)
29680 #define case_stmt(op0,op1) \
29681 case op0 : return expr_gen.node_allocator_-> \
29682 template allocate_rc<typename details::voc_node<Type,op1<Type> > > \
29683 (v, c); \
29685 basic_opr_switch_statements
29686 extended_opr_switch_statements
29687 #undef case_stmt
29688 default : return error_node();
29693 struct synthesize_sf3ext_expression
29695 template <typename T0, typename T1, typename T2>
29696 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
29697 const details::operator_type& sf3opr,
29698 T0 t0, T1 t1, T2 t2)
29700 switch (sf3opr)
29702 #define case_stmt(op) \
29703 case details::e_sf##op : return details::T0oT1oT2_sf3ext<T,T0,T1,T2,details::sf##op##_op<Type> >:: \
29704 allocate(*(expr_gen.node_allocator_), t0, t1, t2); \
29706 case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
29707 case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
29708 case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
29709 case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
29710 case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
29711 case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
29712 case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
29713 case_stmt(28) case_stmt(29) case_stmt(30)
29714 #undef case_stmt
29715 default : return error_node();
29719 template <typename T0, typename T1, typename T2>
29720 static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id,
29721 T0 t0, T1 t1, T2 t2,
29722 expression_node_ptr& result)
29724 details::operator_type sf3opr;
29726 if (!expr_gen.sf3_optimisable(id,sf3opr))
29727 return false;
29728 else
29729 result = synthesize_sf3ext_expression::template process<T0, T1, T2>
29730 (expr_gen, sf3opr, t0, t1, t2);
29732 return true;
29736 struct synthesize_sf4ext_expression
29738 template <typename T0, typename T1, typename T2, typename T3>
29739 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
29740 const details::operator_type& sf4opr,
29741 T0 t0, T1 t1, T2 t2, T3 t3)
29743 switch (sf4opr)
29745 #define case_stmt0(op) \
29746 case details::e_sf##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sf##op##_op<Type> >:: \
29747 allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3); \
29750 #define case_stmt1(op) \
29751 case details::e_sf4ext##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sfext##op##_op<Type> >:: \
29752 allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3); \
29754 case_stmt0(48) case_stmt0(49) case_stmt0(50) case_stmt0(51)
29755 case_stmt0(52) case_stmt0(53) case_stmt0(54) case_stmt0(55)
29756 case_stmt0(56) case_stmt0(57) case_stmt0(58) case_stmt0(59)
29757 case_stmt0(60) case_stmt0(61) case_stmt0(62) case_stmt0(63)
29758 case_stmt0(64) case_stmt0(65) case_stmt0(66) case_stmt0(67)
29759 case_stmt0(68) case_stmt0(69) case_stmt0(70) case_stmt0(71)
29760 case_stmt0(72) case_stmt0(73) case_stmt0(74) case_stmt0(75)
29761 case_stmt0(76) case_stmt0(77) case_stmt0(78) case_stmt0(79)
29762 case_stmt0(80) case_stmt0(81) case_stmt0(82) case_stmt0(83)
29764 case_stmt1(00) case_stmt1(01) case_stmt1(02) case_stmt1(03)
29765 case_stmt1(04) case_stmt1(05) case_stmt1(06) case_stmt1(07)
29766 case_stmt1(08) case_stmt1(09) case_stmt1(10) case_stmt1(11)
29767 case_stmt1(12) case_stmt1(13) case_stmt1(14) case_stmt1(15)
29768 case_stmt1(16) case_stmt1(17) case_stmt1(18) case_stmt1(19)
29769 case_stmt1(20) case_stmt1(21) case_stmt1(22) case_stmt1(23)
29770 case_stmt1(24) case_stmt1(25) case_stmt1(26) case_stmt1(27)
29771 case_stmt1(28) case_stmt1(29) case_stmt1(30) case_stmt1(31)
29772 case_stmt1(32) case_stmt1(33) case_stmt1(34) case_stmt1(35)
29773 case_stmt1(36) case_stmt1(37) case_stmt1(38) case_stmt1(39)
29774 case_stmt1(40) case_stmt1(41) case_stmt1(42) case_stmt1(43)
29775 case_stmt1(44) case_stmt1(45) case_stmt1(46) case_stmt1(47)
29776 case_stmt1(48) case_stmt1(49) case_stmt1(50) case_stmt1(51)
29777 case_stmt1(52) case_stmt1(53) case_stmt1(54) case_stmt1(55)
29778 case_stmt1(56) case_stmt1(57) case_stmt1(58) case_stmt1(59)
29779 case_stmt1(60) case_stmt1(61)
29781 #undef case_stmt0
29782 #undef case_stmt1
29783 default : return error_node();
29787 template <typename T0, typename T1, typename T2, typename T3>
29788 static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id,
29789 T0 t0, T1 t1, T2 t2, T3 t3,
29790 expression_node_ptr& result)
29792 details::operator_type sf4opr;
29794 if (!expr_gen.sf4_optimisable(id,sf4opr))
29795 return false;
29796 else
29797 result = synthesize_sf4ext_expression::template process<T0, T1, T2, T3>
29798 (expr_gen, sf4opr, t0, t1, t2, t3);
29800 return true;
29803 // T o (sf3ext)
29804 template <typename ExternalType>
29805 static inline bool compile_right(expression_generator<Type>& expr_gen,
29806 ExternalType t,
29807 const details::operator_type& operation,
29808 expression_node_ptr& sf3node,
29809 expression_node_ptr& result)
29811 if (!details::is_sf3ext_node(sf3node))
29812 return false;
29814 typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr;
29816 sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node);
29817 const std::string id = "t" + expr_gen.to_str(operation) + "(" + n->type_id() + ")";
29819 switch (n->type())
29821 case details::expression_node<Type>::e_covoc : return compile_right_impl
29822 <typename covoc_t::sf3_type_node,ExternalType, ctype, vtype, ctype>
29823 (expr_gen, id, t, sf3node, result);
29825 case details::expression_node<Type>::e_covov : return compile_right_impl
29826 <typename covov_t::sf3_type_node,ExternalType, ctype, vtype, vtype>
29827 (expr_gen, id, t, sf3node, result);
29829 case details::expression_node<Type>::e_vocov : return compile_right_impl
29830 <typename vocov_t::sf3_type_node,ExternalType, vtype, ctype, vtype>
29831 (expr_gen, id, t, sf3node, result);
29833 case details::expression_node<Type>::e_vovoc : return compile_right_impl
29834 <typename vovoc_t::sf3_type_node,ExternalType, vtype, vtype, ctype>
29835 (expr_gen, id, t, sf3node, result);
29837 case details::expression_node<Type>::e_vovov : return compile_right_impl
29838 <typename vovov_t::sf3_type_node,ExternalType, vtype, vtype, vtype>
29839 (expr_gen, id, t, sf3node, result);
29841 default : return false;
29845 // (sf3ext) o T
29846 template <typename ExternalType>
29847 static inline bool compile_left(expression_generator<Type>& expr_gen,
29848 ExternalType t,
29849 const details::operator_type& operation,
29850 expression_node_ptr& sf3node,
29851 expression_node_ptr& result)
29853 if (!details::is_sf3ext_node(sf3node))
29854 return false;
29856 typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr;
29858 sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node);
29860 const std::string id = "(" + n->type_id() + ")" + expr_gen.to_str(operation) + "t";
29862 switch (n->type())
29864 case details::expression_node<Type>::e_covoc : return compile_left_impl
29865 <typename covoc_t::sf3_type_node,ExternalType, ctype, vtype, ctype>
29866 (expr_gen, id, t, sf3node, result);
29868 case details::expression_node<Type>::e_covov : return compile_left_impl
29869 <typename covov_t::sf3_type_node,ExternalType, ctype, vtype, vtype>
29870 (expr_gen, id, t, sf3node, result);
29872 case details::expression_node<Type>::e_vocov : return compile_left_impl
29873 <typename vocov_t::sf3_type_node,ExternalType, vtype, ctype, vtype>
29874 (expr_gen, id, t, sf3node, result);
29876 case details::expression_node<Type>::e_vovoc : return compile_left_impl
29877 <typename vovoc_t::sf3_type_node,ExternalType, vtype, vtype, ctype>
29878 (expr_gen, id, t, sf3node, result);
29880 case details::expression_node<Type>::e_vovov : return compile_left_impl
29881 <typename vovov_t::sf3_type_node,ExternalType, vtype, vtype, vtype>
29882 (expr_gen, id, t, sf3node, result);
29884 default : return false;
29888 template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2>
29889 static inline bool compile_right_impl(expression_generator<Type>& expr_gen,
29890 const std::string& id,
29891 ExternalType t,
29892 expression_node_ptr& node,
29893 expression_node_ptr& result)
29895 SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node);
29897 if (n)
29899 T0 t0 = n->t0();
29900 T1 t1 = n->t1();
29901 T2 t2 = n->t2();
29903 return synthesize_sf4ext_expression::template compile<ExternalType, T0, T1, T2>
29904 (expr_gen, id, t, t0, t1, t2, result);
29906 else
29907 return false;
29910 template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2>
29911 static inline bool compile_left_impl(expression_generator<Type>& expr_gen,
29912 const std::string& id,
29913 ExternalType t,
29914 expression_node_ptr& node,
29915 expression_node_ptr& result)
29917 SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node);
29919 if (n)
29921 T0 t0 = n->t0();
29922 T1 t1 = n->t1();
29923 T2 t2 = n->t2();
29925 return synthesize_sf4ext_expression::template compile<T0, T1, T2, ExternalType>
29926 (expr_gen, id, t0, t1, t2, t, result);
29928 else
29929 return false;
29933 struct synthesize_vovov_expression0
29935 typedef typename vovov_t::type0 node_type;
29936 typedef typename vovov_t::sf3_type sf3_type;
29938 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
29939 const details::operator_type& operation,
29940 expression_node_ptr (&branch)[2])
29942 // (v0 o0 v1) o1 (v2)
29943 const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
29944 const Type& v0 = vov->v0();
29945 const Type& v1 = vov->v1();
29946 const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
29947 const details::operator_type o0 = vov->operation();
29948 const details::operator_type o1 = operation;
29950 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
29951 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
29953 details::free_node(*(expr_gen.node_allocator_),branch[0]);
29955 expression_node_ptr result = error_node();
29957 if (expr_gen.parser_->settings_.strength_reduction_enabled())
29959 // (v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)
29960 if ((details::e_div == o0) && (details::e_div == o1))
29962 const bool synthesis_result =
29963 synthesize_sf3ext_expression::
29964 template compile<vtype,vtype,vtype>(expr_gen, "t/(t*t)", v0, v1, v2, result);
29966 exprtk_debug(("(v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)\n"));
29968 return (synthesis_result) ? result : error_node();
29972 const bool synthesis_result =
29973 synthesize_sf3ext_expression::template compile<vtype, vtype, vtype>
29974 (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result);
29976 if (synthesis_result)
29977 return result;
29978 else if (!expr_gen.valid_operator(o0,f0))
29979 return error_node();
29980 else if (!expr_gen.valid_operator(o1,f1))
29981 return error_node();
29982 else
29983 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1);
29986 static inline std::string id(expression_generator<Type>& expr_gen,
29987 const details::operator_type o0, const details::operator_type o1)
29989 return details::build_string()
29990 << "(t" << expr_gen.to_str(o0)
29991 << "t)" << expr_gen.to_str(o1)
29992 << "t";
29996 struct synthesize_vovov_expression1
29998 typedef typename vovov_t::type1 node_type;
29999 typedef typename vovov_t::sf3_type sf3_type;
30001 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30002 const details::operator_type& operation,
30003 expression_node_ptr (&branch)[2])
30005 // (v0) o0 (v1 o1 v2)
30006 const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
30007 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
30008 const Type& v1 = vov->v0();
30009 const Type& v2 = vov->v1();
30010 const details::operator_type o0 = operation;
30011 const details::operator_type o1 = vov->operation();
30013 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30014 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30016 details::free_node(*(expr_gen.node_allocator_),branch[1]);
30018 expression_node_ptr result = error_node();
30020 if (expr_gen.parser_->settings_.strength_reduction_enabled())
30022 // v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1
30023 if ((details::e_div == o0) && (details::e_div == o1))
30025 const bool synthesis_result =
30026 synthesize_sf3ext_expression::
30027 template compile<vtype,vtype,vtype>(expr_gen, "(t*t)/t", v0, v2, v1, result);
30029 exprtk_debug(("v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1\n"));
30031 return (synthesis_result) ? result : error_node();
30035 const bool synthesis_result =
30036 synthesize_sf3ext_expression::template compile<vtype, vtype, vtype>
30037 (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result);
30039 if (synthesis_result)
30040 return result;
30041 else if (!expr_gen.valid_operator(o0,f0))
30042 return error_node();
30043 else if (!expr_gen.valid_operator(o1,f1))
30044 return error_node();
30045 else
30046 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1);
30049 static inline std::string id(expression_generator<Type>& expr_gen,
30050 const details::operator_type o0, const details::operator_type o1)
30052 return details::build_string()
30053 << "t" << expr_gen.to_str(o0)
30054 << "(t" << expr_gen.to_str(o1)
30055 << "t)";
30059 struct synthesize_vovoc_expression0
30061 typedef typename vovoc_t::type0 node_type;
30062 typedef typename vovoc_t::sf3_type sf3_type;
30064 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30065 const details::operator_type& operation,
30066 expression_node_ptr (&branch)[2])
30068 // (v0 o0 v1) o1 (c)
30069 const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
30070 const Type& v0 = vov->v0();
30071 const Type& v1 = vov->v1();
30072 const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
30073 const details::operator_type o0 = vov->operation();
30074 const details::operator_type o1 = operation;
30076 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30077 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30079 details::free_node(*(expr_gen.node_allocator_),branch[0]);
30080 details::free_node(*(expr_gen.node_allocator_),branch[1]);
30082 expression_node_ptr result = error_node();
30084 if (expr_gen.parser_->settings_.strength_reduction_enabled())
30086 // (v0 / v1) / c --> (vovoc) v0 / (v1 * c)
30087 if ((details::e_div == o0) && (details::e_div == o1))
30089 const bool synthesis_result =
30090 synthesize_sf3ext_expression::
30091 template compile<vtype,vtype,ctype>(expr_gen, "t/(t*t)", v0, v1, c, result);
30093 exprtk_debug(("(v0 / v1) / c --> (vovoc) v0 / (v1 * c)\n"));
30095 return (synthesis_result) ? result : error_node();
30099 const bool synthesis_result =
30100 synthesize_sf3ext_expression::template compile<vtype, vtype, ctype>
30101 (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result);
30103 if (synthesis_result)
30104 return result;
30105 else if (!expr_gen.valid_operator(o0,f0))
30106 return error_node();
30107 else if (!expr_gen.valid_operator(o1,f1))
30108 return error_node();
30109 else
30110 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1);
30113 static inline std::string id(expression_generator<Type>& expr_gen,
30114 const details::operator_type o0, const details::operator_type o1)
30116 return details::build_string()
30117 << "(t" << expr_gen.to_str(o0)
30118 << "t)" << expr_gen.to_str(o1)
30119 << "t";
30123 struct synthesize_vovoc_expression1
30125 typedef typename vovoc_t::type1 node_type;
30126 typedef typename vovoc_t::sf3_type sf3_type;
30128 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30129 const details::operator_type& operation,
30130 expression_node_ptr (&branch)[2])
30132 // (v0) o0 (v1 o1 c)
30133 const details::voc_base_node<Type>* voc = static_cast<const details::voc_base_node<Type>*>(branch[1]);
30134 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
30135 const Type& v1 = voc->v();
30136 const Type c = voc->c();
30137 const details::operator_type o0 = operation;
30138 const details::operator_type o1 = voc->operation();
30140 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30141 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30143 details::free_node(*(expr_gen.node_allocator_),branch[1]);
30145 expression_node_ptr result = error_node();
30147 if (expr_gen.parser_->settings_.strength_reduction_enabled())
30149 // v0 / (v1 / c) --> (vocov) (v0 * c) / v1
30150 if ((details::e_div == o0) && (details::e_div == o1))
30152 const bool synthesis_result =
30153 synthesize_sf3ext_expression::
30154 template compile<vtype,ctype,vtype>(expr_gen, "(t*t)/t", v0, c, v1, result);
30156 exprtk_debug(("v0 / (v1 / c) --> (vocov) (v0 * c) / v1\n"));
30158 return (synthesis_result) ? result : error_node();
30162 const bool synthesis_result =
30163 synthesize_sf3ext_expression::template compile<vtype, vtype, ctype>
30164 (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result);
30166 if (synthesis_result)
30167 return result;
30168 else if (!expr_gen.valid_operator(o0,f0))
30169 return error_node();
30170 else if (!expr_gen.valid_operator(o1,f1))
30171 return error_node();
30172 else
30173 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1);
30176 static inline std::string id(expression_generator<Type>& expr_gen,
30177 const details::operator_type o0, const details::operator_type o1)
30179 return details::build_string()
30180 << "t" << expr_gen.to_str(o0)
30181 << "(t" << expr_gen.to_str(o1)
30182 << "t)";
30186 struct synthesize_vocov_expression0
30188 typedef typename vocov_t::type0 node_type;
30189 typedef typename vocov_t::sf3_type sf3_type;
30191 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30192 const details::operator_type& operation,
30193 expression_node_ptr (&branch)[2])
30195 // (v0 o0 c) o1 (v1)
30196 const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
30197 const Type& v0 = voc->v();
30198 const Type c = voc->c();
30199 const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
30200 const details::operator_type o0 = voc->operation();
30201 const details::operator_type o1 = operation;
30203 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30204 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30206 details::free_node(*(expr_gen.node_allocator_),branch[0]);
30208 expression_node_ptr result = error_node();
30210 if (expr_gen.parser_->settings_.strength_reduction_enabled())
30212 // (v0 / c) / v1 --> (vovoc) v0 / (v1 * c)
30213 if ((details::e_div == o0) && (details::e_div == o1))
30215 const bool synthesis_result =
30216 synthesize_sf3ext_expression::
30217 template compile<vtype,vtype,ctype>(expr_gen, "t/(t*t)", v0, v1, c, result);
30219 exprtk_debug(("(v0 / c) / v1 --> (vovoc) v0 / (v1 * c)\n"));
30221 return (synthesis_result) ? result : error_node();
30225 const bool synthesis_result =
30226 synthesize_sf3ext_expression::template compile<vtype, ctype, vtype>
30227 (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result);
30229 if (synthesis_result)
30230 return result;
30231 else if (!expr_gen.valid_operator(o0,f0))
30232 return error_node();
30233 else if (!expr_gen.valid_operator(o1,f1))
30234 return error_node();
30235 else
30236 return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1);
30239 static inline std::string id(expression_generator<Type>& expr_gen,
30240 const details::operator_type o0, const details::operator_type o1)
30242 return details::build_string()
30243 << "(t" << expr_gen.to_str(o0)
30244 << "t)" << expr_gen.to_str(o1)
30245 << "t";
30249 struct synthesize_vocov_expression1
30251 typedef typename vocov_t::type1 node_type;
30252 typedef typename vocov_t::sf3_type sf3_type;
30254 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30255 const details::operator_type& operation,
30256 expression_node_ptr (&branch)[2])
30258 // (v0) o0 (c o1 v1)
30259 const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
30260 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
30261 const Type c = cov->c();
30262 const Type& v1 = cov->v();
30263 const details::operator_type o0 = operation;
30264 const details::operator_type o1 = cov->operation();
30266 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30267 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30269 details::free_node(*(expr_gen.node_allocator_),branch[1]);
30271 expression_node_ptr result = error_node();
30273 if (expr_gen.parser_->settings_.strength_reduction_enabled())
30275 // v0 / (c / v1) --> (vovoc) (v0 * v1) / c
30276 if ((details::e_div == o0) && (details::e_div == o1))
30278 const bool synthesis_result =
30279 synthesize_sf3ext_expression::
30280 template compile<vtype, vtype, ctype>(expr_gen, "(t*t)/t", v0, v1, c, result);
30282 exprtk_debug(("v0 / (c / v1) --> (vovoc) (v0 * v1) / c\n"));
30284 return (synthesis_result) ? result : error_node();
30288 const bool synthesis_result =
30289 synthesize_sf3ext_expression::template compile<vtype, ctype, vtype>
30290 (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result);
30292 if (synthesis_result)
30293 return result;
30294 else if (!expr_gen.valid_operator(o0,f0))
30295 return error_node();
30296 else if (!expr_gen.valid_operator(o1,f1))
30297 return error_node();
30298 else
30299 return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1);
30302 static inline std::string id(expression_generator<Type>& expr_gen,
30303 const details::operator_type o0, const details::operator_type o1)
30305 return details::build_string()
30306 << "t" << expr_gen.to_str(o0)
30307 << "(t" << expr_gen.to_str(o1)
30308 << "t)";
30312 struct synthesize_covov_expression0
30314 typedef typename covov_t::type0 node_type;
30315 typedef typename covov_t::sf3_type sf3_type;
30317 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30318 const details::operator_type& operation,
30319 expression_node_ptr (&branch)[2])
30321 // (c o0 v0) o1 (v1)
30322 const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
30323 const Type c = cov->c();
30324 const Type& v0 = cov->v();
30325 const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
30326 const details::operator_type o0 = cov->operation();
30327 const details::operator_type o1 = operation;
30329 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30330 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30332 details::free_node(*(expr_gen.node_allocator_),branch[0]);
30334 expression_node_ptr result = error_node();
30336 if (expr_gen.parser_->settings_.strength_reduction_enabled())
30338 // (c / v0) / v1 --> (covov) c / (v0 * v1)
30339 if ((details::e_div == o0) && (details::e_div == o1))
30341 const bool synthesis_result =
30342 synthesize_sf3ext_expression::
30343 template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", c, v0, v1, result);
30345 exprtk_debug(("(c / v0) / v1 --> (covov) c / (v0 * v1)\n"));
30347 return (synthesis_result) ? result : error_node();
30351 const bool synthesis_result =
30352 synthesize_sf3ext_expression::template compile<ctype, vtype, vtype>
30353 (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result);
30355 if (synthesis_result)
30356 return result;
30357 else if (!expr_gen.valid_operator(o0,f0))
30358 return error_node();
30359 else if (!expr_gen.valid_operator(o1,f1))
30360 return error_node();
30361 else
30362 return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1);
30365 static inline std::string id(expression_generator<Type>& expr_gen,
30366 const details::operator_type o0, const details::operator_type o1)
30368 return details::build_string()
30369 << "(t" << expr_gen.to_str(o0)
30370 << "t)" << expr_gen.to_str(o1)
30371 << "t";
30375 struct synthesize_covov_expression1
30377 typedef typename covov_t::type1 node_type;
30378 typedef typename covov_t::sf3_type sf3_type;
30380 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30381 const details::operator_type& operation,
30382 expression_node_ptr (&branch)[2])
30384 // (c) o0 (v0 o1 v1)
30385 const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
30386 const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
30387 const Type& v0 = vov->v0();
30388 const Type& v1 = vov->v1();
30389 const details::operator_type o0 = operation;
30390 const details::operator_type o1 = vov->operation();
30392 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30393 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30395 details::free_node(*(expr_gen.node_allocator_),branch[0]);
30396 details::free_node(*(expr_gen.node_allocator_),branch[1]);
30398 expression_node_ptr result = error_node();
30400 if (expr_gen.parser_->settings_.strength_reduction_enabled())
30402 // c / (v0 / v1) --> (covov) (c * v1) / v0
30403 if ((details::e_div == o0) && (details::e_div == o1))
30405 const bool synthesis_result =
30406 synthesize_sf3ext_expression::
30407 template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", c, v1, v0, result);
30409 exprtk_debug(("c / (v0 / v1) --> (covov) (c * v1) / v0\n"));
30411 return (synthesis_result) ? result : error_node();
30415 const bool synthesis_result =
30416 synthesize_sf3ext_expression::template compile<ctype, vtype, vtype>
30417 (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result);
30419 if (synthesis_result)
30420 return result;
30421 else if (!expr_gen.valid_operator(o0,f0))
30422 return error_node();
30423 else if (!expr_gen.valid_operator(o1,f1))
30424 return error_node();
30425 else
30426 return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1);
30429 static inline std::string id(expression_generator<Type>& expr_gen, const details::operator_type o0, const details::operator_type o1)
30431 return details::build_string()
30432 << "t" << expr_gen.to_str(o0)
30433 << "(t" << expr_gen.to_str(o1)
30434 << "t)";
30438 struct synthesize_covoc_expression0
30440 typedef typename covoc_t::type0 node_type;
30441 typedef typename covoc_t::sf3_type sf3_type;
30443 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30444 const details::operator_type& operation,
30445 expression_node_ptr (&branch)[2])
30447 // (c0 o0 v) o1 (c1)
30448 const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
30449 const Type c0 = cov->c();
30450 const Type& v = cov->v();
30451 const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
30452 const details::operator_type o0 = cov->operation();
30453 const details::operator_type o1 = operation;
30455 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30456 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30458 details::free_node(*(expr_gen.node_allocator_),branch[0]);
30459 details::free_node(*(expr_gen.node_allocator_),branch[1]);
30461 expression_node_ptr result = error_node();
30463 if (expr_gen.parser_->settings_.strength_reduction_enabled())
30465 // (c0 + v) + c1 --> (cov) (c0 + c1) + v
30466 if ((details::e_add == o0) && (details::e_add == o1))
30468 exprtk_debug(("(c0 + v) + c1 --> (cov) (c0 + c1) + v\n"));
30470 return expr_gen.node_allocator_->
30471 template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v);
30473 // (c0 + v) - c1 --> (cov) (c0 - c1) + v
30474 else if ((details::e_add == o0) && (details::e_sub == o1))
30476 exprtk_debug(("(c0 + v) - c1 --> (cov) (c0 - c1) + v\n"));
30478 return expr_gen.node_allocator_->
30479 template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v);
30481 // (c0 - v) + c1 --> (cov) (c0 + c1) - v
30482 else if ((details::e_sub == o0) && (details::e_add == o1))
30484 exprtk_debug(("(c0 - v) + c1 --> (cov) (c0 + c1) - v\n"));
30486 return expr_gen.node_allocator_->
30487 template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v);
30489 // (c0 - v) - c1 --> (cov) (c0 - c1) - v
30490 else if ((details::e_sub == o0) && (details::e_sub == o1))
30492 exprtk_debug(("(c0 - v) - c1 --> (cov) (c0 - c1) - v\n"));
30494 return expr_gen.node_allocator_->
30495 template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v);
30497 // (c0 * v) * c1 --> (cov) (c0 * c1) * v
30498 else if ((details::e_mul == o0) && (details::e_mul == o1))
30500 exprtk_debug(("(c0 * v) * c1 --> (cov) (c0 * c1) * v\n"));
30502 return expr_gen.node_allocator_->
30503 template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v);
30505 // (c0 * v) / c1 --> (cov) (c0 / c1) * v
30506 else if ((details::e_mul == o0) && (details::e_div == o1))
30508 exprtk_debug(("(c0 * v) / c1 --> (cov) (c0 / c1) * v\n"));
30510 return expr_gen.node_allocator_->
30511 template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v);
30513 // (c0 / v) * c1 --> (cov) (c0 * c1) / v
30514 else if ((details::e_div == o0) && (details::e_mul == o1))
30516 exprtk_debug(("(c0 / v) * c1 --> (cov) (c0 * c1) / v\n"));
30518 return expr_gen.node_allocator_->
30519 template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v);
30521 // (c0 / v) / c1 --> (cov) (c0 / c1) / v
30522 else if ((details::e_div == o0) && (details::e_div == o1))
30524 exprtk_debug(("(c0 / v) / c1 --> (cov) (c0 / c1) / v\n"));
30526 return expr_gen.node_allocator_->
30527 template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v);
30531 const bool synthesis_result =
30532 synthesize_sf3ext_expression::template compile<ctype, vtype, ctype>
30533 (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result);
30535 if (synthesis_result)
30536 return result;
30537 else if (!expr_gen.valid_operator(o0,f0))
30538 return error_node();
30539 else if (!expr_gen.valid_operator(o1,f1))
30540 return error_node();
30541 else
30542 return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1);
30545 static inline std::string id(expression_generator<Type>& expr_gen,
30546 const details::operator_type o0, const details::operator_type o1)
30548 return details::build_string()
30549 << "(t" << expr_gen.to_str(o0)
30550 << "t)" << expr_gen.to_str(o1)
30551 << "t";
30555 struct synthesize_covoc_expression1
30557 typedef typename covoc_t::type1 node_type;
30558 typedef typename covoc_t::sf3_type sf3_type;
30560 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30561 const details::operator_type& operation,
30562 expression_node_ptr (&branch)[2])
30564 // (c0) o0 (v o1 c1)
30565 const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);
30566 const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
30567 const Type& v = voc->v();
30568 const Type c1 = voc->c();
30569 const details::operator_type o0 = operation;
30570 const details::operator_type o1 = voc->operation();
30572 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30573 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30575 details::free_node(*(expr_gen.node_allocator_),branch[0]);
30576 details::free_node(*(expr_gen.node_allocator_),branch[1]);
30578 expression_node_ptr result = error_node();
30580 if (expr_gen.parser_->settings_.strength_reduction_enabled())
30582 // (c0) + (v + c1) --> (cov) (c0 + c1) + v
30583 if ((details::e_add == o0) && (details::e_add == o1))
30585 exprtk_debug(("(c0) + (v + c1) --> (cov) (c0 + c1) + v\n"));
30587 return expr_gen.node_allocator_->
30588 template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v);
30590 // (c0) + (v - c1) --> (cov) (c0 - c1) + v
30591 else if ((details::e_add == o0) && (details::e_sub == o1))
30593 exprtk_debug(("(c0) + (v - c1) --> (cov) (c0 - c1) + v\n"));
30595 return expr_gen.node_allocator_->
30596 template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v);
30598 // (c0) - (v + c1) --> (cov) (c0 - c1) - v
30599 else if ((details::e_sub == o0) && (details::e_add == o1))
30601 exprtk_debug(("(c0) - (v + c1) --> (cov) (c0 - c1) - v\n"));
30603 return expr_gen.node_allocator_->
30604 template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v);
30606 // (c0) - (v - c1) --> (cov) (c0 + c1) - v
30607 else if ((details::e_sub == o0) && (details::e_sub == o1))
30609 exprtk_debug(("(c0) - (v - c1) --> (cov) (c0 + c1) - v\n"));
30611 return expr_gen.node_allocator_->
30612 template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v);
30614 // (c0) * (v * c1) --> (voc) v * (c0 * c1)
30615 else if ((details::e_mul == o0) && (details::e_mul == o1))
30617 exprtk_debug(("(c0) * (v * c1) --> (voc) v * (c0 * c1)\n"));
30619 return expr_gen.node_allocator_->
30620 template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v);
30622 // (c0) * (v / c1) --> (cov) (c0 / c1) * v
30623 else if ((details::e_mul == o0) && (details::e_div == o1))
30625 exprtk_debug(("(c0) * (v / c1) --> (cov) (c0 / c1) * v\n"));
30627 return expr_gen.node_allocator_->
30628 template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v);
30630 // (c0) / (v * c1) --> (cov) (c0 / c1) / v
30631 else if ((details::e_div == o0) && (details::e_mul == o1))
30633 exprtk_debug(("(c0) / (v * c1) --> (cov) (c0 / c1) / v\n"));
30635 return expr_gen.node_allocator_->
30636 template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v);
30638 // (c0) / (v / c1) --> (cov) (c0 * c1) / v
30639 else if ((details::e_div == o0) && (details::e_div == o1))
30641 exprtk_debug(("(c0) / (v / c1) --> (cov) (c0 * c1) / v\n"));
30643 return expr_gen.node_allocator_->
30644 template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v);
30648 const bool synthesis_result =
30649 synthesize_sf3ext_expression::template compile<ctype, vtype, ctype>
30650 (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result);
30652 if (synthesis_result)
30653 return result;
30654 else if (!expr_gen.valid_operator(o0,f0))
30655 return error_node();
30656 else if (!expr_gen.valid_operator(o1,f1))
30657 return error_node();
30658 else
30659 return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1);
30662 static inline std::string id(expression_generator<Type>& expr_gen,
30663 const details::operator_type o0, const details::operator_type o1)
30665 return details::build_string()
30666 << "t" << expr_gen.to_str(o0)
30667 << "(t" << expr_gen.to_str(o1)
30668 << "t)";
30672 struct synthesize_cocov_expression0
30674 typedef typename cocov_t::type0 node_type;
30675 static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
30677 // (c0 o0 c1) o1 (v) - Not possible.
30678 return error_node();
30682 struct synthesize_cocov_expression1
30684 typedef typename cocov_t::type1 node_type;
30685 typedef typename cocov_t::sf3_type sf3_type;
30687 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30688 const details::operator_type& operation,
30689 expression_node_ptr (&branch)[2])
30691 // (c0) o0 (c1 o1 v)
30692 const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
30693 const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
30694 const Type c1 = cov->c();
30695 const Type& v = cov->v();
30696 const details::operator_type o0 = operation;
30697 const details::operator_type o1 = cov->operation();
30699 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30700 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30702 details::free_node(*(expr_gen.node_allocator_),branch[0]);
30703 details::free_node(*(expr_gen.node_allocator_),branch[1]);
30705 expression_node_ptr result = error_node();
30707 if (expr_gen.parser_->settings_.strength_reduction_enabled())
30709 // (c0) + (c1 + v) --> (cov) (c0 + c1) + v
30710 if ((details::e_add == o0) && (details::e_add == o1))
30712 exprtk_debug(("(c0) + (c1 + v) --> (cov) (c0 + c1) + v\n"));
30714 return expr_gen.node_allocator_->
30715 template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v);
30717 // (c0) + (c1 - v) --> (cov) (c0 + c1) - v
30718 else if ((details::e_add == o0) && (details::e_sub == o1))
30720 exprtk_debug(("(c0) + (c1 - v) --> (cov) (c0 + c1) - v\n"));
30722 return expr_gen.node_allocator_->
30723 template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v);
30725 // (c0) - (c1 + v) --> (cov) (c0 - c1) - v
30726 else if ((details::e_sub == o0) && (details::e_add == o1))
30728 exprtk_debug(("(c0) - (c1 + v) --> (cov) (c0 - c1) - v\n"));
30730 return expr_gen.node_allocator_->
30731 template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v);
30733 // (c0) - (c1 - v) --> (cov) (c0 - c1) + v
30734 else if ((details::e_sub == o0) && (details::e_sub == o1))
30736 exprtk_debug(("(c0) - (c1 - v) --> (cov) (c0 - c1) + v\n"));
30738 return expr_gen.node_allocator_->
30739 template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v);
30741 // (c0) * (c1 * v) --> (cov) (c0 * c1) * v
30742 else if ((details::e_mul == o0) && (details::e_mul == o1))
30744 exprtk_debug(("(c0) * (c1 * v) --> (cov) (c0 * c1) * v\n"));
30746 return expr_gen.node_allocator_->
30747 template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v);
30749 // (c0) * (c1 / v) --> (cov) (c0 * c1) / v
30750 else if ((details::e_mul == o0) && (details::e_div == o1))
30752 exprtk_debug(("(c0) * (c1 / v) --> (cov) (c0 * c1) / v\n"));
30754 return expr_gen.node_allocator_->
30755 template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v);
30757 // (c0) / (c1 * v) --> (cov) (c0 / c1) / v
30758 else if ((details::e_div == o0) && (details::e_mul == o1))
30760 exprtk_debug(("(c0) / (c1 * v) --> (cov) (c0 / c1) / v\n"));
30762 return expr_gen.node_allocator_->
30763 template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v);
30765 // (c0) / (c1 / v) --> (cov) (c0 / c1) * v
30766 else if ((details::e_div == o0) && (details::e_div == o1))
30768 exprtk_debug(("(c0) / (c1 / v) --> (cov) (c0 / c1) * v\n"));
30770 return expr_gen.node_allocator_->
30771 template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v);
30775 const bool synthesis_result =
30776 synthesize_sf3ext_expression::template compile<ctype, ctype, vtype>
30777 (expr_gen, id(expr_gen, o0, o1), c0, c1, v, result);
30779 if (synthesis_result)
30780 return result;
30781 else if (!expr_gen.valid_operator(o0,f0))
30782 return error_node();
30783 else if (!expr_gen.valid_operator(o1,f1))
30784 return error_node();
30785 else
30786 return node_type::allocate(*(expr_gen.node_allocator_), c0, c1, v, f0, f1);
30789 static inline std::string id(expression_generator<Type>& expr_gen, const details::operator_type o0, const details::operator_type o1)
30791 return details::build_string()
30792 << "t" << expr_gen.to_str(o0)
30793 << "(t" << expr_gen.to_str(o1)
30794 << "t)";
30798 struct synthesize_vococ_expression0
30800 typedef typename vococ_t::type0 node_type;
30801 typedef typename vococ_t::sf3_type sf3_type;
30803 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30804 const details::operator_type& operation,
30805 expression_node_ptr (&branch)[2])
30807 // (v o0 c0) o1 (c1)
30808 const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
30809 const Type& v = voc->v();
30810 const Type& c0 = voc->c();
30811 const Type& c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
30812 const details::operator_type o0 = voc->operation();
30813 const details::operator_type o1 = operation;
30815 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30816 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30818 details::free_node(*(expr_gen.node_allocator_),branch[0]);
30819 details::free_node(*(expr_gen.node_allocator_),branch[1]);
30821 expression_node_ptr result = error_node();
30823 if (expr_gen.parser_->settings_.strength_reduction_enabled())
30825 // (v + c0) + c1 --> (voc) v + (c0 + c1)
30826 if ((details::e_add == o0) && (details::e_add == o1))
30828 exprtk_debug(("(v + c0) + c1 --> (voc) v + (c0 + c1)\n"));
30830 return expr_gen.node_allocator_->
30831 template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c0 + c1);
30833 // (v + c0) - c1 --> (voc) v + (c0 - c1)
30834 else if ((details::e_add == o0) && (details::e_sub == o1))
30836 exprtk_debug(("(v + c0) - c1 --> (voc) v + (c0 - c1)\n"));
30838 return expr_gen.node_allocator_->
30839 template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c0 - c1);
30841 // (v - c0) + c1 --> (voc) v - (c0 + c1)
30842 else if ((details::e_sub == o0) && (details::e_add == o1))
30844 exprtk_debug(("(v - c0) + c1 --> (voc) v - (c0 + c1)\n"));
30846 return expr_gen.node_allocator_->
30847 template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c1 - c0);
30849 // (v - c0) - c1 --> (voc) v - (c0 + c1)
30850 else if ((details::e_sub == o0) && (details::e_sub == o1))
30852 exprtk_debug(("(v - c0) - c1 --> (voc) v - (c0 + c1)\n"));
30854 return expr_gen.node_allocator_->
30855 template allocate_rc<typename details::voc_node<Type,details::sub_op<Type> > >(v, c0 + c1);
30857 // (v * c0) * c1 --> (voc) v * (c0 * c1)
30858 else if ((details::e_mul == o0) && (details::e_mul == o1))
30860 exprtk_debug(("(v * c0) * c1 --> (voc) v * (c0 * c1)\n"));
30862 return expr_gen.node_allocator_->
30863 template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c0 * c1);
30865 // (v * c0) / c1 --> (voc) v * (c0 / c1)
30866 else if ((details::e_mul == o0) && (details::e_div == o1))
30868 exprtk_debug(("(v * c0) / c1 --> (voc) v * (c0 / c1)\n"));
30870 return expr_gen.node_allocator_->
30871 template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c0 / c1);
30873 // (v / c0) * c1 --> (voc) v * (c1 / c0)
30874 else if ((details::e_div == o0) && (details::e_mul == o1))
30876 exprtk_debug(("(v / c0) * c1 --> (voc) v * (c1 / c0)\n"));
30878 return expr_gen.node_allocator_->
30879 template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c1 / c0);
30881 // (v / c0) / c1 --> (voc) v / (c0 * c1)
30882 else if ((details::e_div == o0) && (details::e_div == o1))
30884 exprtk_debug(("(v / c0) / c1 --> (voc) v / (c0 * c1)\n"));
30886 return expr_gen.node_allocator_->
30887 template allocate_rc<typename details::voc_node<Type,details::div_op<Type> > >(v, c0 * c1);
30889 // (v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1)
30890 else if ((details::e_pow == o0) && (details::e_pow == o1))
30892 exprtk_debug(("(v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1)\n"));
30894 return expr_gen.node_allocator_->
30895 template allocate_rc<typename details::voc_node<Type,details::pow_op<Type> > >(v, c0 * c1);
30899 const bool synthesis_result =
30900 synthesize_sf3ext_expression::template compile<vtype, ctype, ctype>
30901 (expr_gen, id(expr_gen, o0, o1), v, c0, c1, result);
30903 if (synthesis_result)
30904 return result;
30905 else if (!expr_gen.valid_operator(o0,f0))
30906 return error_node();
30907 else if (!expr_gen.valid_operator(o1,f1))
30908 return error_node();
30909 else
30910 return node_type::allocate(*(expr_gen.node_allocator_), v, c0, c1, f0, f1);
30913 static inline std::string id(expression_generator<Type>& expr_gen,
30914 const details::operator_type o0, const details::operator_type o1)
30916 return details::build_string()
30917 << "(t" << expr_gen.to_str(o0)
30918 << "t)" << expr_gen.to_str(o1)
30919 << "t";
30923 struct synthesize_vococ_expression1
30925 typedef typename vococ_t::type0 node_type;
30927 static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
30929 // (v) o0 (c0 o1 c1) - Not possible.
30930 exprtk_debug(("(v) o0 (c0 o1 c1) - Not possible.\n"));
30931 return error_node();
30935 struct synthesize_vovovov_expression0
30937 typedef typename vovovov_t::type0 node_type;
30938 typedef typename vovovov_t::sf4_type sf4_type;
30939 typedef typename node_type::T0 T0;
30940 typedef typename node_type::T1 T1;
30941 typedef typename node_type::T2 T2;
30942 typedef typename node_type::T3 T3;
30944 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30945 const details::operator_type& operation,
30946 expression_node_ptr (&branch)[2])
30948 // (v0 o0 v1) o1 (v2 o2 v3)
30949 const details::vov_base_node<Type>* vov0 = static_cast<details::vov_base_node<Type>*>(branch[0]);
30950 const details::vov_base_node<Type>* vov1 = static_cast<details::vov_base_node<Type>*>(branch[1]);
30951 const Type& v0 = vov0->v0();
30952 const Type& v1 = vov0->v1();
30953 const Type& v2 = vov1->v0();
30954 const Type& v3 = vov1->v1();
30955 const details::operator_type o0 = vov0->operation();
30956 const details::operator_type o1 = operation;
30957 const details::operator_type o2 = vov1->operation();
30959 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30960 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30961 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
30963 details::free_node(*(expr_gen.node_allocator_),branch[0]);
30964 details::free_node(*(expr_gen.node_allocator_),branch[1]);
30966 expression_node_ptr result = error_node();
30968 if (expr_gen.parser_->settings_.strength_reduction_enabled())
30970 // (v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)
30971 if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
30973 const bool synthesis_result =
30974 synthesize_sf4ext_expression::
30975 template compile<vtype,vtype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, v3, result);
30977 exprtk_debug(("(v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)\n"));
30979 return (synthesis_result) ? result : error_node();
30981 // (v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)
30982 else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
30984 const bool synthesis_result =
30985 synthesize_sf4ext_expression::
30986 template compile<vtype,vtype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", v0, v3, v1, v2, result);
30988 exprtk_debug(("(v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)\n"));
30990 return (synthesis_result) ? result : error_node();
30992 // (v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)
30993 else if ((details::e_add == o0) && (details::e_div == o1) && (details::e_div == o2))
30995 const bool synthesis_result =
30996 synthesize_sf4ext_expression::
30997 template compile<vtype,vtype,vtype,vtype>(expr_gen, "(t+t)*(t/t)", v0, v1, v3, v2, result);
30999 exprtk_debug(("(v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)\n"));
31001 return (synthesis_result) ? result : error_node();
31003 // (v0 - v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)
31004 else if ((details::e_sub == o0) && (details::e_div == o1) && (details::e_div == o2))
31006 const bool synthesis_result =
31007 synthesize_sf4ext_expression::
31008 template compile<vtype,vtype,vtype,vtype>(expr_gen, "(t-t)*(t/t)", v0, v1, v3, v2, result);
31010 exprtk_debug(("(v0 - v1) / (v2 / v3) --> (vovovov) (v0 - v1) * (v3 / v2)\n"));
31012 return (synthesis_result) ? result : error_node();
31014 // (v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2
31015 else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
31017 const bool synthesis_result =
31018 synthesize_sf4ext_expression::
31019 template compile<vtype,vtype,vtype,vtype>(expr_gen, "((t*t)*t)/t", v0, v1, v3, v2, result);
31021 exprtk_debug(("(v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2\n"));
31023 return (synthesis_result) ? result : error_node();
31027 const bool synthesis_result =
31028 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
31029 (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
31031 if (synthesis_result)
31032 return result;
31033 else if (!expr_gen.valid_operator(o0,f0))
31034 return error_node();
31035 else if (!expr_gen.valid_operator(o1,f1))
31036 return error_node();
31037 else if (!expr_gen.valid_operator(o2,f2))
31038 return error_node();
31039 else
31040 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
31043 static inline std::string id(expression_generator<Type>& expr_gen,
31044 const details::operator_type o0,
31045 const details::operator_type o1,
31046 const details::operator_type o2)
31048 return details::build_string()
31049 << "(t" << expr_gen.to_str(o0)
31050 << "t)" << expr_gen.to_str(o1)
31051 << "(t" << expr_gen.to_str(o2)
31052 << "t)";
31056 struct synthesize_vovovoc_expression0
31058 typedef typename vovovoc_t::type0 node_type;
31059 typedef typename vovovoc_t::sf4_type sf4_type;
31060 typedef typename node_type::T0 T0;
31061 typedef typename node_type::T1 T1;
31062 typedef typename node_type::T2 T2;
31063 typedef typename node_type::T3 T3;
31065 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
31066 const details::operator_type& operation,
31067 expression_node_ptr (&branch)[2])
31069 // (v0 o0 v1) o1 (v2 o2 c)
31070 const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
31071 const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);
31072 const Type& v0 = vov->v0();
31073 const Type& v1 = vov->v1();
31074 const Type& v2 = voc->v ();
31075 const Type c = voc->c ();
31076 const details::operator_type o0 = vov->operation();
31077 const details::operator_type o1 = operation;
31078 const details::operator_type o2 = voc->operation();
31080 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31081 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31082 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
31084 details::free_node(*(expr_gen.node_allocator_),branch[0]);
31085 details::free_node(*(expr_gen.node_allocator_),branch[1]);
31087 expression_node_ptr result = error_node();
31089 if (expr_gen.parser_->settings_.strength_reduction_enabled())
31091 // (v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c)
31092 if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
31094 const bool synthesis_result =
31095 synthesize_sf4ext_expression::
31096 template compile<vtype,vtype,vtype,ctype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result);
31098 exprtk_debug(("(v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c)\n"));
31100 return (synthesis_result) ? result : error_node();
31102 // (v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2)
31103 if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
31105 const bool synthesis_result =
31106 synthesize_sf4ext_expression::
31107 template compile<vtype,ctype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result);
31109 exprtk_debug(("(v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2)\n"));
31111 return (synthesis_result) ? result : error_node();
31115 const bool synthesis_result =
31116 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
31117 (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
31119 if (synthesis_result)
31120 return result;
31121 else if (!expr_gen.valid_operator(o0,f0))
31122 return error_node();
31123 else if (!expr_gen.valid_operator(o1,f1))
31124 return error_node();
31125 else if (!expr_gen.valid_operator(o2,f2))
31126 return error_node();
31127 else
31128 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
31131 static inline std::string id(expression_generator<Type>& expr_gen,
31132 const details::operator_type o0,
31133 const details::operator_type o1,
31134 const details::operator_type o2)
31136 return details::build_string()
31137 << "(t" << expr_gen.to_str(o0)
31138 << "t)" << expr_gen.to_str(o1)
31139 << "(t" << expr_gen.to_str(o2)
31140 << "t)";
31144 struct synthesize_vovocov_expression0
31146 typedef typename vovocov_t::type0 node_type;
31147 typedef typename vovocov_t::sf4_type sf4_type;
31148 typedef typename node_type::T0 T0;
31149 typedef typename node_type::T1 T1;
31150 typedef typename node_type::T2 T2;
31151 typedef typename node_type::T3 T3;
31153 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
31154 const details::operator_type& operation,
31155 expression_node_ptr (&branch)[2])
31157 // (v0 o0 v1) o1 (c o2 v2)
31158 const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
31159 const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
31160 const Type& v0 = vov->v0();
31161 const Type& v1 = vov->v1();
31162 const Type& v2 = cov->v ();
31163 const Type c = cov->c ();
31164 const details::operator_type o0 = vov->operation();
31165 const details::operator_type o1 = operation;
31166 const details::operator_type o2 = cov->operation();
31168 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31169 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31170 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
31172 details::free_node(*(expr_gen.node_allocator_),branch[0]);
31173 details::free_node(*(expr_gen.node_allocator_),branch[1]);
31175 expression_node_ptr result = error_node();
31177 if (expr_gen.parser_->settings_.strength_reduction_enabled())
31179 // (v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2)
31180 if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
31182 const bool synthesis_result =
31183 synthesize_sf4ext_expression::
31184 template compile<vtype,ctype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result);
31186 exprtk_debug(("(v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2)\n"));
31188 return (synthesis_result) ? result : error_node();
31190 // (v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c)
31191 if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
31193 const bool synthesis_result =
31194 synthesize_sf4ext_expression::
31195 template compile<vtype,vtype,vtype,ctype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result);
31197 exprtk_debug(("(v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c)\n"));
31199 return (synthesis_result) ? result : error_node();
31203 const bool synthesis_result =
31204 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
31205 (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
31207 if (synthesis_result)
31208 return result;
31209 else if (!expr_gen.valid_operator(o0,f0))
31210 return error_node();
31211 else if (!expr_gen.valid_operator(o1,f1))
31212 return error_node();
31213 else if (!expr_gen.valid_operator(o2,f2))
31214 return error_node();
31215 else
31216 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
31219 static inline std::string id(expression_generator<Type>& expr_gen,
31220 const details::operator_type o0,
31221 const details::operator_type o1,
31222 const details::operator_type o2)
31224 return details::build_string()
31225 << "(t" << expr_gen.to_str(o0)
31226 << "t)" << expr_gen.to_str(o1)
31227 << "(t" << expr_gen.to_str(o2)
31228 << "t)";
31232 struct synthesize_vocovov_expression0
31234 typedef typename vocovov_t::type0 node_type;
31235 typedef typename vocovov_t::sf4_type sf4_type;
31236 typedef typename node_type::T0 T0;
31237 typedef typename node_type::T1 T1;
31238 typedef typename node_type::T2 T2;
31239 typedef typename node_type::T3 T3;
31241 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
31242 const details::operator_type& operation,
31243 expression_node_ptr (&branch)[2])
31245 // (v0 o0 c) o1 (v1 o2 v2)
31246 const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
31247 const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
31248 const Type c = voc->c ();
31249 const Type& v0 = voc->v ();
31250 const Type& v1 = vov->v0();
31251 const Type& v2 = vov->v1();
31252 const details::operator_type o0 = voc->operation();
31253 const details::operator_type o1 = operation;
31254 const details::operator_type o2 = vov->operation();
31256 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31257 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31258 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
31260 details::free_node(*(expr_gen.node_allocator_),branch[0]);
31261 details::free_node(*(expr_gen.node_allocator_),branch[1]);
31263 expression_node_ptr result = error_node();
31265 if (expr_gen.parser_->settings_.strength_reduction_enabled())
31267 // (v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2)
31268 if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
31270 const bool synthesis_result =
31271 synthesize_sf4ext_expression::
31272 template compile<vtype,vtype,ctype,vtype>(expr_gen, "(t*t)/(t*t)", v0, v1, c, v2, result);
31274 exprtk_debug(("(v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2)\n"));
31276 return (synthesis_result) ? result : error_node();
31278 // (v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1)
31279 if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
31281 const bool synthesis_result =
31282 synthesize_sf4ext_expression::
31283 template compile<vtype,vtype,ctype,vtype>(expr_gen, "(t*t)/(t*t)", v0, v2, c, v1, result);
31285 exprtk_debug(("(v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1)\n"));
31287 return (synthesis_result) ? result : error_node();
31291 const bool synthesis_result =
31292 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
31293 (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
31295 if (synthesis_result)
31296 return result;
31297 else if (!expr_gen.valid_operator(o0,f0))
31298 return error_node();
31299 else if (!expr_gen.valid_operator(o1,f1))
31300 return error_node();
31301 else if (!expr_gen.valid_operator(o2,f2))
31302 return error_node();
31303 else
31304 return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
31307 static inline std::string id(expression_generator<Type>& expr_gen,
31308 const details::operator_type o0,
31309 const details::operator_type o1,
31310 const details::operator_type o2)
31312 return details::build_string()
31313 << "(t" << expr_gen.to_str(o0)
31314 << "t)" << expr_gen.to_str(o1)
31315 << "(t" << expr_gen.to_str(o2)
31316 << "t)";
31320 struct synthesize_covovov_expression0
31322 typedef typename covovov_t::type0 node_type;
31323 typedef typename covovov_t::sf4_type sf4_type;
31324 typedef typename node_type::T0 T0;
31325 typedef typename node_type::T1 T1;
31326 typedef typename node_type::T2 T2;
31327 typedef typename node_type::T3 T3;
31329 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
31330 const details::operator_type& operation,
31331 expression_node_ptr (&branch)[2])
31333 // (c o0 v0) o1 (v1 o2 v2)
31334 const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
31335 const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
31336 const Type c = cov->c ();
31337 const Type& v0 = cov->v ();
31338 const Type& v1 = vov->v0();
31339 const Type& v2 = vov->v1();
31340 const details::operator_type o0 = cov->operation();
31341 const details::operator_type o1 = operation;
31342 const details::operator_type o2 = vov->operation();
31344 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31345 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31346 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
31348 details::free_node(*(expr_gen.node_allocator_),branch[0]);
31349 details::free_node(*(expr_gen.node_allocator_),branch[1]);
31351 expression_node_ptr result = error_node();
31353 if (expr_gen.parser_->settings_.strength_reduction_enabled())
31355 // (c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2)
31356 if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
31358 const bool synthesis_result =
31359 synthesize_sf4ext_expression::
31360 template compile<ctype,vtype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", c, v1, v0, v2, result);
31362 exprtk_debug(("(c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2)\n"));
31364 return (synthesis_result) ? result : error_node();
31366 // (c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1)
31367 if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
31369 const bool synthesis_result =
31370 synthesize_sf4ext_expression::
31371 template compile<ctype,vtype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", c, v2, v0, v1, result);
31373 exprtk_debug(("(c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1)\n"));
31375 return (synthesis_result) ? result : error_node();
31379 const bool synthesis_result =
31380 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
31381 (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
31383 if (synthesis_result)
31384 return result;
31385 else if (!expr_gen.valid_operator(o0,f0))
31386 return error_node();
31387 else if (!expr_gen.valid_operator(o1,f1))
31388 return error_node();
31389 else if (!expr_gen.valid_operator(o2,f2))
31390 return error_node();
31391 else
31392 return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
31395 static inline std::string id(expression_generator<Type>& expr_gen,
31396 const details::operator_type o0,
31397 const details::operator_type o1,
31398 const details::operator_type o2)
31400 return details::build_string()
31401 << "(t" << expr_gen.to_str(o0)
31402 << "t)" << expr_gen.to_str(o1)
31403 << "(t" << expr_gen.to_str(o2)
31404 << "t)";
31408 struct synthesize_covocov_expression0
31410 typedef typename covocov_t::type0 node_type;
31411 typedef typename covocov_t::sf4_type sf4_type;
31412 typedef typename node_type::T0 T0;
31413 typedef typename node_type::T1 T1;
31414 typedef typename node_type::T2 T2;
31415 typedef typename node_type::T3 T3;
31417 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
31418 const details::operator_type& operation,
31419 expression_node_ptr (&branch)[2])
31421 // (c0 o0 v0) o1 (c1 o2 v1)
31422 const details::cov_base_node<Type>* cov0 = static_cast<details::cov_base_node<Type>*>(branch[0]);
31423 const details::cov_base_node<Type>* cov1 = static_cast<details::cov_base_node<Type>*>(branch[1]);
31424 const Type c0 = cov0->c();
31425 const Type& v0 = cov0->v();
31426 const Type c1 = cov1->c();
31427 const Type& v1 = cov1->v();
31428 const details::operator_type o0 = cov0->operation();
31429 const details::operator_type o1 = operation;
31430 const details::operator_type o2 = cov1->operation();
31432 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31433 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31434 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
31436 details::free_node(*(expr_gen.node_allocator_),branch[0]);
31437 details::free_node(*(expr_gen.node_allocator_),branch[1]);
31439 expression_node_ptr result = error_node();
31441 if (expr_gen.parser_->settings_.strength_reduction_enabled())
31443 // (c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1
31444 if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
31446 const bool synthesis_result =
31447 synthesize_sf3ext_expression::
31448 template compile<ctype,vtype,vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
31450 exprtk_debug(("(c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n"));
31452 return (synthesis_result) ? result : error_node();
31454 // (c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1
31455 else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
31457 const bool synthesis_result =
31458 synthesize_sf3ext_expression::
31459 template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
31461 exprtk_debug(("(c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n"));
31463 return (synthesis_result) ? result : error_node();
31465 // (c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1
31466 else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
31468 const bool synthesis_result =
31469 synthesize_sf3ext_expression::
31470 template compile<ctype,vtype,vtype>(expr_gen, "(t-t)+t", (c0 - c1), v0, v1, result);
31472 exprtk_debug(("(c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1\n"));
31474 return (synthesis_result) ? result : error_node();
31476 // (c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1
31477 else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
31479 const bool synthesis_result =
31480 synthesize_sf3ext_expression::
31481 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
31483 exprtk_debug(("(c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n"));
31485 return (synthesis_result) ? result : error_node();
31487 // (c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)
31488 else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
31490 const bool synthesis_result =
31491 synthesize_sf3ext_expression::
31492 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
31494 exprtk_debug(("(c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
31496 return (synthesis_result) ? result : error_node();
31498 // (c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)
31499 else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
31501 const bool synthesis_result =
31502 synthesize_sf3ext_expression::
31503 template compile<ctype,vtype,vtype>(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result);
31505 exprtk_debug(("(c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)\n"));
31507 return (synthesis_result) ? result : error_node();
31509 // (c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0
31510 else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
31512 const bool synthesis_result =
31513 synthesize_sf3ext_expression::
31514 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v1, v0, result);
31516 exprtk_debug(("(c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0\n"));
31518 return (synthesis_result) ? result : error_node();
31520 // (c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)
31521 else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
31523 const bool synthesis_result =
31524 synthesize_sf3ext_expression::
31525 template compile<ctype,vtype,vtype>(expr_gen, "t*(t*t)", (c0 / c1), v0, v1, result);
31527 exprtk_debug(("(c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
31529 return (synthesis_result) ? result : error_node();
31531 // (c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)
31532 else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
31534 const bool synthesis_result =
31535 synthesize_sf3ext_expression::
31536 template compile<ctype,vtype,vtype>(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result);
31538 exprtk_debug(("(c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)\n"));
31540 return (synthesis_result) ? result : error_node();
31542 // (c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1)
31543 else if (
31544 (std::equal_to<T>()(c0,c1)) &&
31545 (details::e_mul == o0) &&
31546 (details::e_mul == o2) &&
31548 (details::e_add == o1) ||
31549 (details::e_sub == o1)
31553 std::string specfunc;
31555 switch (o1)
31557 case details::e_add : specfunc = "t*(t+t)"; break;
31558 case details::e_sub : specfunc = "t*(t-t)"; break;
31559 default : return error_node();
31562 const bool synthesis_result =
31563 synthesize_sf3ext_expression::
31564 template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result);
31566 exprtk_debug(("(c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n"));
31568 return (synthesis_result) ? result : error_node();
31572 const bool synthesis_result =
31573 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
31574 (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
31576 if (synthesis_result)
31577 return result;
31578 else if (!expr_gen.valid_operator(o0,f0))
31579 return error_node();
31580 else if (!expr_gen.valid_operator(o1,f1))
31581 return error_node();
31582 else if (!expr_gen.valid_operator(o2,f2))
31583 return error_node();
31584 else
31585 return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
31588 static inline std::string id(expression_generator<Type>& expr_gen,
31589 const details::operator_type o0,
31590 const details::operator_type o1,
31591 const details::operator_type o2)
31593 return details::build_string()
31594 << "(t" << expr_gen.to_str(o0)
31595 << "t)" << expr_gen.to_str(o1)
31596 << "(t" << expr_gen.to_str(o2)
31597 << "t)";
31601 struct synthesize_vocovoc_expression0
31603 typedef typename vocovoc_t::type0 node_type;
31604 typedef typename vocovoc_t::sf4_type sf4_type;
31605 typedef typename node_type::T0 T0;
31606 typedef typename node_type::T1 T1;
31607 typedef typename node_type::T2 T2;
31608 typedef typename node_type::T3 T3;
31610 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
31611 const details::operator_type& operation,
31612 expression_node_ptr (&branch)[2])
31614 // (v0 o0 c0) o1 (v1 o2 c1)
31615 const details::voc_base_node<Type>* voc0 = static_cast<details::voc_base_node<Type>*>(branch[0]);
31616 const details::voc_base_node<Type>* voc1 = static_cast<details::voc_base_node<Type>*>(branch[1]);
31617 const Type c0 = voc0->c();
31618 const Type& v0 = voc0->v();
31619 const Type c1 = voc1->c();
31620 const Type& v1 = voc1->v();
31621 const details::operator_type o0 = voc0->operation();
31622 const details::operator_type o1 = operation;
31623 const details::operator_type o2 = voc1->operation();
31625 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31626 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31627 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
31629 details::free_node(*(expr_gen.node_allocator_),branch[0]);
31630 details::free_node(*(expr_gen.node_allocator_),branch[1]);
31632 expression_node_ptr result = error_node();
31634 if (expr_gen.parser_->settings_.strength_reduction_enabled())
31636 // (v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1
31637 if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
31639 const bool synthesis_result =
31640 synthesize_sf3ext_expression::
31641 template compile<ctype,vtype,vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
31643 exprtk_debug(("(v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n"));
31645 return (synthesis_result) ? result : error_node();
31647 // (v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1
31648 else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
31650 const bool synthesis_result =
31651 synthesize_sf3ext_expression::
31652 template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
31654 exprtk_debug(("(v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n"));
31656 return (synthesis_result) ? result : error_node();
31658 // (v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1
31659 else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
31661 const bool synthesis_result =
31662 synthesize_sf3ext_expression::
31663 template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c1 - c0), v0, v1, result);
31665 exprtk_debug(("(v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1\n"));
31667 return (synthesis_result) ? result : error_node();
31669 // (v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1
31670 else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
31672 const bool synthesis_result =
31673 synthesize_sf3ext_expression::
31674 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
31676 exprtk_debug(("(v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n"));
31678 return (synthesis_result) ? result : error_node();
31680 // (v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)
31681 else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
31683 const bool synthesis_result =
31684 synthesize_sf3ext_expression::
31685 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
31687 exprtk_debug(("(v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
31689 return (synthesis_result) ? result : error_node();
31691 // (v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1
31692 else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
31694 const bool synthesis_result =
31695 synthesize_sf3ext_expression::
31696 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", Type(1) / (c0 * c1), v0, v1, result);
31698 exprtk_debug(("(v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1\n"));
31700 return (synthesis_result) ? result : error_node();
31702 // (v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1
31703 else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
31705 const bool synthesis_result =
31706 synthesize_sf3ext_expression::
31707 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result);
31709 exprtk_debug(("(v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1\n"));
31711 return (synthesis_result) ? result : error_node();
31713 // (v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)
31714 else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
31716 const bool synthesis_result =
31717 synthesize_sf3ext_expression::
31718 template compile<ctype,vtype,vtype>(expr_gen, "t*(t/t)", (c0 * c1), v0, v1, result);
31720 exprtk_debug(("(v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n"));
31722 return (synthesis_result) ? result : error_node();
31724 // (v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1
31725 else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
31727 const bool synthesis_result =
31728 synthesize_sf3ext_expression::
31729 template compile<ctype,vtype,vtype>(expr_gen, "t*(t/t)", Type(1) / (c0 * c1), v0, v1, result);
31731 exprtk_debug(("(v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1\n"));
31733 return (synthesis_result) ? result : error_node();
31735 // (v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1)
31736 else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_add == o2))
31738 const bool synthesis_result =
31739 synthesize_sf4ext_expression::
31740 template compile<vtype,ctype,vtype,ctype>(expr_gen, "(t*t)*(t+t)", v0, T(1) / c0, v1, c1, result);
31742 exprtk_debug(("(v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1)\n"));
31744 return (synthesis_result) ? result : error_node();
31746 // (v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1)
31747 else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_sub == o2))
31749 const bool synthesis_result =
31750 synthesize_sf4ext_expression::
31751 template compile<vtype,ctype,vtype,ctype>(expr_gen, "(t*t)*(t-t)", v0, T(1) / c0, v1, c1, result);
31753 exprtk_debug(("(v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1)\n"));
31755 return (synthesis_result) ? result : error_node();
31757 // (v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)
31758 else if (
31759 (std::equal_to<T>()(c0,c1)) &&
31760 (details::e_mul == o0) &&
31761 (details::e_mul == o2) &&
31763 (details::e_add == o1) ||
31764 (details::e_sub == o1)
31768 std::string specfunc;
31770 switch (o1)
31772 case details::e_add : specfunc = "t*(t+t)"; break;
31773 case details::e_sub : specfunc = "t*(t-t)"; break;
31774 default : return error_node();
31777 const bool synthesis_result =
31778 synthesize_sf3ext_expression::
31779 template compile<ctype,vtype,vtype>(expr_gen, specfunc, c0, v0, v1, result);
31781 exprtk_debug(("(v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n"));
31783 return (synthesis_result) ? result : error_node();
31785 // (v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c
31786 else if (
31787 (std::equal_to<T>()(c0,c1)) &&
31788 (details::e_div == o0) &&
31789 (details::e_div == o2) &&
31791 (details::e_add == o1) ||
31792 (details::e_sub == o1)
31796 std::string specfunc;
31798 switch (o1)
31800 case details::e_add : specfunc = "(t+t)/t"; break;
31801 case details::e_sub : specfunc = "(t-t)/t"; break;
31802 default : return error_node();
31805 const bool synthesis_result =
31806 synthesize_sf3ext_expression::
31807 template compile<vtype,vtype,ctype>(expr_gen, specfunc, v0, v1, c0, result);
31809 exprtk_debug(("(v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c\n"));
31811 return (synthesis_result) ? result : error_node();
31815 const bool synthesis_result =
31816 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
31817 (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
31819 if (synthesis_result)
31820 return result;
31821 else if (!expr_gen.valid_operator(o0,f0))
31822 return error_node();
31823 else if (!expr_gen.valid_operator(o1,f1))
31824 return error_node();
31825 else if (!expr_gen.valid_operator(o2,f2))
31826 return error_node();
31827 else
31828 return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
31831 static inline std::string id(expression_generator<Type>& expr_gen,
31832 const details::operator_type o0,
31833 const details::operator_type o1,
31834 const details::operator_type o2)
31836 return details::build_string()
31837 << "(t" << expr_gen.to_str(o0)
31838 << "t)" << expr_gen.to_str(o1)
31839 << "(t" << expr_gen.to_str(o2)
31840 << "t)";
31844 struct synthesize_covovoc_expression0
31846 typedef typename covovoc_t::type0 node_type;
31847 typedef typename covovoc_t::sf4_type sf4_type;
31848 typedef typename node_type::T0 T0;
31849 typedef typename node_type::T1 T1;
31850 typedef typename node_type::T2 T2;
31851 typedef typename node_type::T3 T3;
31853 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
31854 const details::operator_type& operation,
31855 expression_node_ptr (&branch)[2])
31857 // (c0 o0 v0) o1 (v1 o2 c1)
31858 const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
31859 const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);
31860 const Type c0 = cov->c();
31861 const Type& v0 = cov->v();
31862 const Type c1 = voc->c();
31863 const Type& v1 = voc->v();
31864 const details::operator_type o0 = cov->operation();
31865 const details::operator_type o1 = operation;
31866 const details::operator_type o2 = voc->operation();
31868 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31869 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31870 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
31872 details::free_node(*(expr_gen.node_allocator_),branch[0]);
31873 details::free_node(*(expr_gen.node_allocator_),branch[1]);
31875 expression_node_ptr result = error_node();
31877 if (expr_gen.parser_->settings_.strength_reduction_enabled())
31879 // (c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1
31880 if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
31882 const bool synthesis_result =
31883 synthesize_sf3ext_expression::
31884 template compile<ctype,vtype,vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
31886 exprtk_debug(("(c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n"));
31888 return (synthesis_result) ? result : error_node();
31890 // (c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1
31891 else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
31893 const bool synthesis_result =
31894 synthesize_sf3ext_expression::
31895 template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
31897 exprtk_debug(("(c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n"));
31899 return (synthesis_result) ? result : error_node();
31901 // (c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1
31902 else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
31904 const bool synthesis_result =
31905 synthesize_sf3ext_expression::
31906 template compile<ctype,vtype,vtype>(expr_gen, "t-(t+t)", (c0 + c1), v0, v1, result);
31908 exprtk_debug(("(c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1\n"));
31910 return (synthesis_result) ? result : error_node();
31912 // (c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1
31913 else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
31915 const bool synthesis_result =
31916 synthesize_sf3ext_expression::
31917 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
31919 exprtk_debug(("(c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n"));
31921 return (synthesis_result) ? result : error_node();
31923 // (c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)
31924 else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
31926 const bool synthesis_result =
31927 synthesize_sf3ext_expression::
31928 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
31930 exprtk_debug(("(c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
31932 return (synthesis_result) ? result : error_node();
31934 // (c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)
31935 else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
31937 const bool synthesis_result =
31938 synthesize_sf3ext_expression::
31939 template compile<ctype,vtype,vtype>(expr_gen, "t*(t/t)", (c0 / c1), v1, v0, result);
31941 exprtk_debug(("(c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)\n"));
31943 return (synthesis_result) ? result : error_node();
31945 // (c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1)
31946 else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
31948 const bool synthesis_result =
31949 synthesize_sf3ext_expression::
31950 template compile<ctype,vtype,vtype>(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result);
31952 exprtk_debug(("(c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1)\n"));
31954 return (synthesis_result) ? result : error_node();
31956 // (c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)
31957 else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
31959 const bool synthesis_result =
31960 synthesize_sf3ext_expression::
31961 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 * c1), v0, v1, result);
31963 exprtk_debug(("(c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n"));
31965 return (synthesis_result) ? result : error_node();
31967 // (c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)
31968 else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
31970 const bool synthesis_result =
31971 synthesize_sf3ext_expression::
31972 template compile<ctype,vtype,vtype>(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result);
31974 exprtk_debug(("(c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)\n"));
31976 return (synthesis_result) ? result : error_node();
31978 // (c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)
31979 else if (
31980 (std::equal_to<T>()(c0,c1)) &&
31981 (details::e_mul == o0) &&
31982 (details::e_mul == o2) &&
31984 (details::e_add == o1) ||
31985 (details::e_sub == o1)
31989 std::string specfunc;
31991 switch (o1)
31993 case details::e_add : specfunc = "t*(t+t)"; break;
31994 case details::e_sub : specfunc = "t*(t-t)"; break;
31995 default : return error_node();
31998 const bool synthesis_result =
31999 synthesize_sf3ext_expression::
32000 template compile<ctype,vtype,vtype>(expr_gen,specfunc, c0, v0, v1, result);
32002 exprtk_debug(("(c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n"));
32004 return (synthesis_result) ? result : error_node();
32008 const bool synthesis_result =
32009 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32010 (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
32012 if (synthesis_result)
32013 return result;
32014 else if (!expr_gen.valid_operator(o0,f0))
32015 return error_node();
32016 else if (!expr_gen.valid_operator(o1,f1))
32017 return error_node();
32018 else if (!expr_gen.valid_operator(o2,f2))
32019 return error_node();
32020 else
32021 return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
32024 static inline std::string id(expression_generator<Type>& expr_gen,
32025 const details::operator_type o0,
32026 const details::operator_type o1,
32027 const details::operator_type o2)
32029 return details::build_string()
32030 << "(t" << expr_gen.to_str(o0)
32031 << "t)" << expr_gen.to_str(o1)
32032 << "(t" << expr_gen.to_str(o2)
32033 << "t)";
32037 struct synthesize_vococov_expression0
32039 typedef typename vococov_t::type0 node_type;
32040 typedef typename vococov_t::sf4_type sf4_type;
32041 typedef typename node_type::T0 T0;
32042 typedef typename node_type::T1 T1;
32043 typedef typename node_type::T2 T2;
32044 typedef typename node_type::T3 T3;
32046 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32047 const details::operator_type& operation,
32048 expression_node_ptr (&branch)[2])
32050 // (v0 o0 c0) o1 (c1 o2 v1)
32051 const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
32052 const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
32053 const Type c0 = voc->c();
32054 const Type& v0 = voc->v();
32055 const Type c1 = cov->c();
32056 const Type& v1 = cov->v();
32057 const details::operator_type o0 = voc->operation();
32058 const details::operator_type o1 = operation;
32059 const details::operator_type o2 = cov->operation();
32061 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32062 binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
32063 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
32065 details::free_node(*(expr_gen.node_allocator_),branch[0]);
32066 details::free_node(*(expr_gen.node_allocator_),branch[1]);
32068 expression_node_ptr result = error_node();
32070 if (expr_gen.parser_->settings_.strength_reduction_enabled())
32072 // (v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1
32073 if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
32075 const bool synthesis_result =
32076 synthesize_sf3ext_expression::
32077 template compile<ctype,vtype,vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
32079 exprtk_debug(("(v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n"));
32081 return (synthesis_result) ? result : error_node();
32083 // (v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1
32084 else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
32086 const bool synthesis_result =
32087 synthesize_sf3ext_expression::
32088 template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
32090 exprtk_debug(("(v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n"));
32092 return (synthesis_result) ? result : error_node();
32094 // (v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)
32095 else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
32097 const bool synthesis_result =
32098 synthesize_sf3ext_expression::
32099 template compile<vtype,vtype,ctype>(expr_gen, "(t+t)-t", v0, v1, (c1 + c0), result);
32101 exprtk_debug(("(v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)\n"));
32103 return (synthesis_result) ? result : error_node();
32105 // (v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1
32106 else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
32108 const bool synthesis_result =
32109 synthesize_sf3ext_expression::
32110 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
32112 exprtk_debug(("(v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n"));
32114 return (synthesis_result) ? result : error_node();
32116 // (v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)
32117 else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
32119 const bool synthesis_result =
32120 synthesize_sf3ext_expression::
32121 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
32123 exprtk_debug(("(v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
32125 return (synthesis_result) ? result : error_node();
32127 // (v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)
32128 else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
32130 const bool synthesis_result =
32131 synthesize_sf3ext_expression::
32132 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result);
32134 exprtk_debug(("(v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)\n"));
32136 return (synthesis_result) ? result : error_node();
32138 // (v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)
32139 else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
32141 const bool synthesis_result =
32142 synthesize_sf3ext_expression::
32143 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 / c1), v0, v1, result);
32145 exprtk_debug(("(v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
32147 return (synthesis_result) ? result : error_node();
32149 // (v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)
32150 else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
32152 const bool synthesis_result =
32153 synthesize_sf3ext_expression::
32154 template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", Type(1) / (c0 * c1), v0, v1, result);
32156 exprtk_debug(("(v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)\n"));
32158 return (synthesis_result) ? result : error_node();
32160 // (v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1))
32161 else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
32163 const bool synthesis_result =
32164 synthesize_sf3ext_expression::
32165 template compile<vtype,vtype,ctype>(expr_gen, "(t*t)*t", v0, v1, Type(1) / (c0 * c1), result);
32167 exprtk_debug(("(v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1))\n"));
32169 return (synthesis_result) ? result : error_node();
32171 // (v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)
32172 else if (
32173 (std::equal_to<T>()(c0,c1)) &&
32174 (details::e_mul == o0) &&
32175 (details::e_mul == o2) &&
32177 (details::e_add == o1) || (details::e_sub == o1)
32181 std::string specfunc;
32183 switch (o1)
32185 case details::e_add : specfunc = "t*(t+t)"; break;
32186 case details::e_sub : specfunc = "t*(t-t)"; break;
32187 default : return error_node();
32190 const bool synthesis_result =
32191 synthesize_sf3ext_expression::
32192 template compile<ctype,vtype,vtype>(expr_gen, specfunc, c0, v0, v1, result);
32194 exprtk_debug(("(v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n"));
32196 return (synthesis_result) ? result : error_node();
32200 const bool synthesis_result =
32201 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32202 (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result);
32204 if (synthesis_result)
32205 return result;
32206 else if (!expr_gen.valid_operator(o0,f0))
32207 return error_node();
32208 else if (!expr_gen.valid_operator(o1,f1))
32209 return error_node();
32210 else if (!expr_gen.valid_operator(o2,f2))
32211 return error_node();
32212 else
32213 return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2);
32216 static inline std::string id(expression_generator<Type>& expr_gen,
32217 const details::operator_type o0,
32218 const details::operator_type o1,
32219 const details::operator_type o2)
32221 return details::build_string()
32222 << "(t" << expr_gen.to_str(o0)
32223 << "t)" << expr_gen.to_str(o1)
32224 << "(t" << expr_gen.to_str(o2)
32225 << "t)";
32229 struct synthesize_vovovov_expression1
32231 typedef typename vovovov_t::type1 node_type;
32232 typedef typename vovovov_t::sf4_type sf4_type;
32233 typedef typename node_type::T0 T0;
32234 typedef typename node_type::T1 T1;
32235 typedef typename node_type::T2 T2;
32236 typedef typename node_type::T3 T3;
32238 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32239 const details::operator_type& operation,
32240 expression_node_ptr (&branch)[2])
32242 // v0 o0 (v1 o1 (v2 o2 v3))
32243 typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
32245 const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
32246 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
32247 const Type& v1 = vovov->t0();
32248 const Type& v2 = vovov->t1();
32249 const Type& v3 = vovov->t2();
32250 const details::operator_type o0 = operation;
32251 const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
32252 const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
32254 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32255 binary_functor_t f1 = vovov->f0();
32256 binary_functor_t f2 = vovov->f1();
32258 details::free_node(*(expr_gen.node_allocator_),branch[1]);
32260 expression_node_ptr result = error_node();
32262 if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result))
32263 return result;
32264 else if (!expr_gen.valid_operator(o0,f0))
32265 return error_node();
32267 exprtk_debug(("v0 o0 (v1 o1 (v2 o2 v3))\n"));
32269 return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2);
32272 static inline std::string id(expression_generator<Type>& expr_gen,
32273 const details::operator_type o0,
32274 const details::operator_type o1,
32275 const details::operator_type o2)
32277 return details::build_string()
32278 << "t" << expr_gen.to_str(o0)
32279 << "(t" << expr_gen.to_str(o1)
32280 << "(t" << expr_gen.to_str(o2)
32281 << "t))";
32285 struct synthesize_vovovoc_expression1
32287 typedef typename vovovoc_t::type1 node_type;
32288 typedef typename vovovoc_t::sf4_type sf4_type;
32289 typedef typename node_type::T0 T0;
32290 typedef typename node_type::T1 T1;
32291 typedef typename node_type::T2 T2;
32292 typedef typename node_type::T3 T3;
32294 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32295 const details::operator_type& operation,
32296 expression_node_ptr (&branch)[2])
32298 // v0 o0 (v1 o1 (v2 o2 c))
32299 typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t;
32301 const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
32302 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
32303 const Type& v1 = vovoc->t0();
32304 const Type& v2 = vovoc->t1();
32305 const Type c = vovoc->t2();
32306 const details::operator_type o0 = operation;
32307 const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
32308 const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
32310 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32311 binary_functor_t f1 = vovoc->f0();
32312 binary_functor_t f2 = vovoc->f1();
32314 details::free_node(*(expr_gen.node_allocator_),branch[1]);
32316 expression_node_ptr result = error_node();
32318 const bool synthesis_result =
32319 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32320 (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
32322 if (synthesis_result)
32323 return result;
32324 else if (!expr_gen.valid_operator(o0,f0))
32325 return error_node();
32327 exprtk_debug(("v0 o0 (v1 o1 (v2 o2 c))\n"));
32329 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
32332 static inline std::string id(expression_generator<Type>& expr_gen,
32333 const details::operator_type o0,
32334 const details::operator_type o1,
32335 const details::operator_type o2)
32337 return details::build_string()
32338 << "t" << expr_gen.to_str(o0)
32339 << "(t" << expr_gen.to_str(o1)
32340 << "(t" << expr_gen.to_str(o2)
32341 << "t))";
32345 struct synthesize_vovocov_expression1
32347 typedef typename vovocov_t::type1 node_type;
32348 typedef typename vovocov_t::sf4_type sf4_type;
32349 typedef typename node_type::T0 T0;
32350 typedef typename node_type::T1 T1;
32351 typedef typename node_type::T2 T2;
32352 typedef typename node_type::T3 T3;
32354 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32355 const details::operator_type& operation,
32356 expression_node_ptr (&branch)[2])
32358 // v0 o0 (v1 o1 (c o2 v2))
32359 typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
32361 const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
32362 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
32363 const Type& v1 = vocov->t0();
32364 const Type c = vocov->t1();
32365 const Type& v2 = vocov->t2();
32366 const details::operator_type o0 = operation;
32367 const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
32368 const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
32370 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32371 binary_functor_t f1 = vocov->f0();
32372 binary_functor_t f2 = vocov->f1();
32374 details::free_node(*(expr_gen.node_allocator_),branch[1]);
32376 expression_node_ptr result = error_node();
32378 const bool synthesis_result =
32379 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32380 (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
32382 if (synthesis_result)
32383 return result;
32384 if (!expr_gen.valid_operator(o0,f0))
32385 return error_node();
32387 exprtk_debug(("v0 o0 (v1 o1 (c o2 v2))\n"));
32389 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
32392 static inline std::string id(expression_generator<Type>& expr_gen,
32393 const details::operator_type o0,
32394 const details::operator_type o1,
32395 const details::operator_type o2)
32397 return details::build_string()
32398 << "t" << expr_gen.to_str(o0)
32399 << "(t" << expr_gen.to_str(o1)
32400 << "(t" << expr_gen.to_str(o2)
32401 << "t))";
32405 struct synthesize_vocovov_expression1
32407 typedef typename vocovov_t::type1 node_type;
32408 typedef typename vocovov_t::sf4_type sf4_type;
32409 typedef typename node_type::T0 T0;
32410 typedef typename node_type::T1 T1;
32411 typedef typename node_type::T2 T2;
32412 typedef typename node_type::T3 T3;
32414 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32415 const details::operator_type& operation,
32416 expression_node_ptr (&branch)[2])
32418 // v0 o0 (c o1 (v1 o2 v2))
32419 typedef typename synthesize_covov_expression1::node_type lcl_covov_t;
32421 const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]);
32422 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
32423 const Type c = covov->t0();
32424 const Type& v1 = covov->t1();
32425 const Type& v2 = covov->t2();
32426 const details::operator_type o0 = operation;
32427 const details::operator_type o1 = expr_gen.get_operator(covov->f0());
32428 const details::operator_type o2 = expr_gen.get_operator(covov->f1());
32430 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32431 binary_functor_t f1 = covov->f0();
32432 binary_functor_t f2 = covov->f1();
32434 details::free_node(*(expr_gen.node_allocator_),branch[1]);
32436 expression_node_ptr result = error_node();
32438 const bool synthesis_result =
32439 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32440 (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
32442 if (synthesis_result)
32443 return result;
32444 else if (!expr_gen.valid_operator(o0,f0))
32445 return error_node();
32447 exprtk_debug(("v0 o0 (c o1 (v1 o2 v2))\n"));
32449 return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
32452 static inline std::string id(expression_generator<Type>& expr_gen,
32453 const details::operator_type o0,
32454 const details::operator_type o1,
32455 const details::operator_type o2)
32457 return details::build_string()
32458 << "t" << expr_gen.to_str(o0)
32459 << "(t" << expr_gen.to_str(o1)
32460 << "(t" << expr_gen.to_str(o2)
32461 << "t))";
32465 struct synthesize_covovov_expression1
32467 typedef typename covovov_t::type1 node_type;
32468 typedef typename covovov_t::sf4_type sf4_type;
32469 typedef typename node_type::T0 T0;
32470 typedef typename node_type::T1 T1;
32471 typedef typename node_type::T2 T2;
32472 typedef typename node_type::T3 T3;
32474 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32475 const details::operator_type& operation,
32476 expression_node_ptr (&branch)[2])
32478 // c o0 (v0 o1 (v1 o2 v2))
32479 typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
32481 const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
32482 const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
32483 const Type& v0 = vovov->t0();
32484 const Type& v1 = vovov->t1();
32485 const Type& v2 = vovov->t2();
32486 const details::operator_type o0 = operation;
32487 const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
32488 const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
32490 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32491 binary_functor_t f1 = vovov->f0();
32492 binary_functor_t f2 = vovov->f1();
32494 details::free_node(*(expr_gen.node_allocator_),branch[0]);
32495 details::free_node(*(expr_gen.node_allocator_),branch[1]);
32497 expression_node_ptr result = error_node();
32499 const bool synthesis_result =
32500 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32501 (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
32503 if (synthesis_result)
32504 return result;
32505 if (!expr_gen.valid_operator(o0,f0))
32506 return error_node();
32508 exprtk_debug(("c o0 (v0 o1 (v1 o2 v2))\n"));
32510 return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
32513 static inline std::string id(expression_generator<Type>& expr_gen,
32514 const details::operator_type o0,
32515 const details::operator_type o1,
32516 const details::operator_type o2)
32518 return details::build_string()
32519 << "t" << expr_gen.to_str(o0)
32520 << "(t" << expr_gen.to_str(o1)
32521 << "(t" << expr_gen.to_str(o2)
32522 << "t))";
32526 struct synthesize_covocov_expression1
32528 typedef typename covocov_t::type1 node_type;
32529 typedef typename covocov_t::sf4_type sf4_type;
32530 typedef typename node_type::T0 T0;
32531 typedef typename node_type::T1 T1;
32532 typedef typename node_type::T2 T2;
32533 typedef typename node_type::T3 T3;
32535 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32536 const details::operator_type& operation,
32537 expression_node_ptr (&branch)[2])
32539 // c0 o0 (v0 o1 (c1 o2 v1))
32540 typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
32542 const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
32543 const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
32544 const Type& v0 = vocov->t0();
32545 const Type c1 = vocov->t1();
32546 const Type& v1 = vocov->t2();
32547 const details::operator_type o0 = operation;
32548 const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
32549 const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
32551 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32552 binary_functor_t f1 = vocov->f0();
32553 binary_functor_t f2 = vocov->f1();
32555 details::free_node(*(expr_gen.node_allocator_),branch[0]);
32556 details::free_node(*(expr_gen.node_allocator_),branch[1]);
32558 expression_node_ptr result = error_node();
32560 const bool synthesis_result =
32561 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32562 (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
32564 if (synthesis_result)
32565 return result;
32566 else if (!expr_gen.valid_operator(o0,f0))
32567 return error_node();
32569 exprtk_debug(("c0 o0 (v0 o1 (c1 o2 v1))\n"));
32571 return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
32574 static inline std::string id(expression_generator<Type>& expr_gen,
32575 const details::operator_type o0,
32576 const details::operator_type o1,
32577 const details::operator_type o2)
32579 return details::build_string()
32580 << "t" << expr_gen.to_str(o0)
32581 << "(t" << expr_gen.to_str(o1)
32582 << "(t" << expr_gen.to_str(o2)
32583 << "t))";
32587 struct synthesize_vocovoc_expression1
32589 typedef typename vocovoc_t::type1 node_type;
32590 typedef typename vocovoc_t::sf4_type sf4_type;
32591 typedef typename node_type::T0 T0;
32592 typedef typename node_type::T1 T1;
32593 typedef typename node_type::T2 T2;
32594 typedef typename node_type::T3 T3;
32596 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32597 const details::operator_type& operation,
32598 expression_node_ptr (&branch)[2])
32600 // v0 o0 (c0 o1 (v1 o2 c2))
32601 typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t;
32603 const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]);
32604 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
32605 const Type c0 = covoc->t0();
32606 const Type& v1 = covoc->t1();
32607 const Type c1 = covoc->t2();
32608 const details::operator_type o0 = operation;
32609 const details::operator_type o1 = expr_gen.get_operator(covoc->f0());
32610 const details::operator_type o2 = expr_gen.get_operator(covoc->f1());
32612 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32613 binary_functor_t f1 = covoc->f0();
32614 binary_functor_t f2 = covoc->f1();
32616 details::free_node(*(expr_gen.node_allocator_),branch[1]);
32618 expression_node_ptr result = error_node();
32620 const bool synthesis_result =
32621 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32622 (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
32624 if (synthesis_result)
32625 return result;
32626 else if (!expr_gen.valid_operator(o0,f0))
32627 return error_node();
32629 exprtk_debug(("v0 o0 (c0 o1 (v1 o2 c2))\n"));
32631 return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
32634 static inline std::string id(expression_generator<Type>& expr_gen,
32635 const details::operator_type o0,
32636 const details::operator_type o1,
32637 const details::operator_type o2)
32639 return details::build_string()
32640 << "t" << expr_gen.to_str(o0)
32641 << "(t" << expr_gen.to_str(o1)
32642 << "(t" << expr_gen.to_str(o2)
32643 << "t))";
32647 struct synthesize_covovoc_expression1
32649 typedef typename covovoc_t::type1 node_type;
32650 typedef typename covovoc_t::sf4_type sf4_type;
32651 typedef typename node_type::T0 T0;
32652 typedef typename node_type::T1 T1;
32653 typedef typename node_type::T2 T2;
32654 typedef typename node_type::T3 T3;
32655 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32656 const details::operator_type& operation,
32657 expression_node_ptr (&branch)[2])
32659 // c0 o0 (v0 o1 (v1 o2 c1))
32660 typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t;
32662 const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
32663 const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
32664 const Type& v0 = vovoc->t0();
32665 const Type& v1 = vovoc->t1();
32666 const Type c1 = vovoc->t2();
32667 const details::operator_type o0 = operation;
32668 const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
32669 const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
32671 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32672 binary_functor_t f1 = vovoc->f0();
32673 binary_functor_t f2 = vovoc->f1();
32675 details::free_node(*(expr_gen.node_allocator_),branch[0]);
32676 details::free_node(*(expr_gen.node_allocator_),branch[1]);
32678 expression_node_ptr result = error_node();
32680 const bool synthesis_result =
32681 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32682 (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
32684 if (synthesis_result)
32685 return result;
32686 else if (!expr_gen.valid_operator(o0,f0))
32687 return error_node();
32689 exprtk_debug(("c0 o0 (v0 o1 (v1 o2 c1))\n"));
32691 return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
32694 static inline std::string id(expression_generator<Type>& expr_gen,
32695 const details::operator_type o0,
32696 const details::operator_type o1,
32697 const details::operator_type o2)
32699 return details::build_string()
32700 << "t" << expr_gen.to_str(o0)
32701 << "(t" << expr_gen.to_str(o1)
32702 << "(t" << expr_gen.to_str(o2)
32703 << "t))";
32707 struct synthesize_vococov_expression1
32709 typedef typename vococov_t::type1 node_type;
32710 typedef typename vococov_t::sf4_type sf4_type;
32711 typedef typename node_type::T0 T0;
32712 typedef typename node_type::T1 T1;
32713 typedef typename node_type::T2 T2;
32714 typedef typename node_type::T3 T3;
32716 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32717 const details::operator_type& operation,
32718 expression_node_ptr (&branch)[2])
32720 // v0 o0 (c0 o1 (c1 o2 v1))
32721 typedef typename synthesize_cocov_expression1::node_type lcl_cocov_t;
32723 const lcl_cocov_t* cocov = static_cast<const lcl_cocov_t*>(branch[1]);
32724 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
32725 const Type c0 = cocov->t0();
32726 const Type c1 = cocov->t1();
32727 const Type& v1 = cocov->t2();
32728 const details::operator_type o0 = operation;
32729 const details::operator_type o1 = expr_gen.get_operator(cocov->f0());
32730 const details::operator_type o2 = expr_gen.get_operator(cocov->f1());
32732 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32733 binary_functor_t f1 = cocov->f0();
32734 binary_functor_t f2 = cocov->f1();
32736 details::free_node(*(expr_gen.node_allocator_),branch[1]);
32738 expression_node_ptr result = error_node();
32740 const bool synthesis_result =
32741 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32742 (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result);
32744 if (synthesis_result)
32745 return result;
32746 else if (!expr_gen.valid_operator(o0,f0))
32747 return error_node();
32749 exprtk_debug(("v0 o0 (c0 o1 (c1 o2 v1))\n"));
32751 return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2);
32754 static inline std::string id(expression_generator<Type>& expr_gen,
32755 const details::operator_type o0,
32756 const details::operator_type o1,
32757 const details::operator_type o2)
32759 return details::build_string()
32760 << "t" << expr_gen.to_str(o0)
32761 << "(t" << expr_gen.to_str(o1)
32762 << "(t" << expr_gen.to_str(o2)
32763 << "t))";
32767 struct synthesize_vovovov_expression2
32769 typedef typename vovovov_t::type2 node_type;
32770 typedef typename vovovov_t::sf4_type sf4_type;
32771 typedef typename node_type::T0 T0;
32772 typedef typename node_type::T1 T1;
32773 typedef typename node_type::T2 T2;
32774 typedef typename node_type::T3 T3;
32776 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32777 const details::operator_type& operation,
32778 expression_node_ptr (&branch)[2])
32780 // v0 o0 ((v1 o1 v2) o2 v3)
32781 typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
32783 const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
32784 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
32785 const Type& v1 = vovov->t0();
32786 const Type& v2 = vovov->t1();
32787 const Type& v3 = vovov->t2();
32788 const details::operator_type o0 = operation;
32789 const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
32790 const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
32792 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32793 binary_functor_t f1 = vovov->f0();
32794 binary_functor_t f2 = vovov->f1();
32796 details::free_node(*(expr_gen.node_allocator_),branch[1]);
32798 expression_node_ptr result = error_node();
32800 const bool synthesis_result =
32801 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32802 (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
32804 if (synthesis_result)
32805 return result;
32806 else if (!expr_gen.valid_operator(o0,f0))
32807 return error_node();
32809 exprtk_debug(("v0 o0 ((v1 o1 v2) o2 v3)\n"));
32811 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
32814 static inline std::string id(expression_generator<Type>& expr_gen,
32815 const details::operator_type o0,
32816 const details::operator_type o1,
32817 const details::operator_type o2)
32819 return details::build_string()
32820 << "t" << expr_gen.to_str(o0)
32821 << "((t" << expr_gen.to_str(o1)
32822 << "t)" << expr_gen.to_str(o2)
32823 << "t)";
32827 struct synthesize_vovovoc_expression2
32829 typedef typename vovovoc_t::type2 node_type;
32830 typedef typename vovovoc_t::sf4_type sf4_type;
32831 typedef typename node_type::T0 T0;
32832 typedef typename node_type::T1 T1;
32833 typedef typename node_type::T2 T2;
32834 typedef typename node_type::T3 T3;
32836 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32837 const details::operator_type& operation,
32838 expression_node_ptr (&branch)[2])
32840 // v0 o0 ((v1 o1 v2) o2 c)
32841 typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t;
32843 const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
32844 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
32845 const Type& v1 = vovoc->t0();
32846 const Type& v2 = vovoc->t1();
32847 const Type c = vovoc->t2();
32848 const details::operator_type o0 = operation;
32849 const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
32850 const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
32852 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32853 binary_functor_t f1 = vovoc->f0();
32854 binary_functor_t f2 = vovoc->f1();
32856 details::free_node(*(expr_gen.node_allocator_),branch[1]);
32858 expression_node_ptr result = error_node();
32860 const bool synthesis_result =
32861 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32862 (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
32864 if (synthesis_result)
32865 return result;
32866 else if (!expr_gen.valid_operator(o0,f0))
32867 return error_node();
32869 exprtk_debug(("v0 o0 ((v1 o1 v2) o2 c)\n"));
32871 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
32874 static inline std::string id(expression_generator<Type>& expr_gen,
32875 const details::operator_type o0,
32876 const details::operator_type o1,
32877 const details::operator_type o2)
32879 return details::build_string()
32880 << "t" << expr_gen.to_str(o0)
32881 << "((t" << expr_gen.to_str(o1)
32882 << "t)" << expr_gen.to_str(o2)
32883 << "t)";
32887 struct synthesize_vovocov_expression2
32889 typedef typename vovocov_t::type2 node_type;
32890 typedef typename vovocov_t::sf4_type sf4_type;
32891 typedef typename node_type::T0 T0;
32892 typedef typename node_type::T1 T1;
32893 typedef typename node_type::T2 T2;
32894 typedef typename node_type::T3 T3;
32896 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32897 const details::operator_type& operation,
32898 expression_node_ptr (&branch)[2])
32900 // v0 o0 ((v1 o1 c) o2 v2)
32901 typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
32903 const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
32904 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
32905 const Type& v1 = vocov->t0();
32906 const Type c = vocov->t1();
32907 const Type& v2 = vocov->t2();
32908 const details::operator_type o0 = operation;
32909 const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
32910 const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
32912 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32913 binary_functor_t f1 = vocov->f0();
32914 binary_functor_t f2 = vocov->f1();
32916 details::free_node(*(expr_gen.node_allocator_),branch[1]);
32918 expression_node_ptr result = error_node();
32920 const bool synthesis_result =
32921 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32922 (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
32924 if (synthesis_result)
32925 return result;
32926 else if (!expr_gen.valid_operator(o0,f0))
32927 return error_node();
32929 exprtk_debug(("v0 o0 ((v1 o1 c) o2 v2)\n"));
32931 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
32934 static inline std::string id(expression_generator<Type>& expr_gen,
32935 const details::operator_type o0,
32936 const details::operator_type o1,
32937 const details::operator_type o2)
32939 return details::build_string()
32940 << "t" << expr_gen.to_str(o0)
32941 << "((t" << expr_gen.to_str(o1)
32942 << "t)" << expr_gen.to_str(o2)
32943 << "t)";
32947 struct synthesize_vocovov_expression2
32949 typedef typename vocovov_t::type2 node_type;
32950 typedef typename vocovov_t::sf4_type sf4_type;
32951 typedef typename node_type::T0 T0;
32952 typedef typename node_type::T1 T1;
32953 typedef typename node_type::T2 T2;
32954 typedef typename node_type::T3 T3;
32956 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32957 const details::operator_type& operation,
32958 expression_node_ptr (&branch)[2])
32960 // v0 o0 ((c o1 v1) o2 v2)
32961 typedef typename synthesize_covov_expression0::node_type lcl_covov_t;
32963 const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]);
32964 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
32965 const Type c = covov->t0();
32966 const Type& v1 = covov->t1();
32967 const Type& v2 = covov->t2();
32968 const details::operator_type o0 = operation;
32969 const details::operator_type o1 = expr_gen.get_operator(covov->f0());
32970 const details::operator_type o2 = expr_gen.get_operator(covov->f1());
32972 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32973 binary_functor_t f1 = covov->f0();
32974 binary_functor_t f2 = covov->f1();
32976 details::free_node(*(expr_gen.node_allocator_),branch[1]);
32978 expression_node_ptr result = error_node();
32980 const bool synthesis_result =
32981 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32982 (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
32984 if (synthesis_result)
32985 return result;
32986 else if (!expr_gen.valid_operator(o0,f0))
32987 return error_node();
32989 exprtk_debug(("v0 o0 ((c o1 v1) o2 v2)\n"));
32991 return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
32994 static inline std::string id(expression_generator<Type>& expr_gen,
32995 const details::operator_type o0,
32996 const details::operator_type o1,
32997 const details::operator_type o2)
32999 return details::build_string()
33000 << "t" << expr_gen.to_str(o0)
33001 << "((t" << expr_gen.to_str(o1)
33002 << "t)" << expr_gen.to_str(o2)
33003 << "t)";
33007 struct synthesize_covovov_expression2
33009 typedef typename covovov_t::type2 node_type;
33010 typedef typename covovov_t::sf4_type sf4_type;
33011 typedef typename node_type::T0 T0;
33012 typedef typename node_type::T1 T1;
33013 typedef typename node_type::T2 T2;
33014 typedef typename node_type::T3 T3;
33016 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33017 const details::operator_type& operation,
33018 expression_node_ptr (&branch)[2])
33020 // c o0 ((v1 o1 v2) o2 v3)
33021 typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
33023 const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
33024 const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
33025 const Type& v0 = vovov->t0();
33026 const Type& v1 = vovov->t1();
33027 const Type& v2 = vovov->t2();
33028 const details::operator_type o0 = operation;
33029 const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
33030 const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
33032 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
33033 binary_functor_t f1 = vovov->f0();
33034 binary_functor_t f2 = vovov->f1();
33036 details::free_node(*(expr_gen.node_allocator_),branch[0]);
33037 details::free_node(*(expr_gen.node_allocator_),branch[1]);
33039 expression_node_ptr result = error_node();
33041 const bool synthesis_result =
33042 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33043 (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
33045 if (synthesis_result)
33046 return result;
33047 else if (!expr_gen.valid_operator(o0,f0))
33048 return error_node();
33050 exprtk_debug(("c o0 ((v1 o1 v2) o2 v3)\n"));
33052 return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
33055 static inline std::string id(expression_generator<Type>& expr_gen,
33056 const details::operator_type o0,
33057 const details::operator_type o1,
33058 const details::operator_type o2)
33060 return details::build_string()
33061 << "t" << expr_gen.to_str(o0)
33062 << "((t" << expr_gen.to_str(o1)
33063 << "t)" << expr_gen.to_str(o2)
33064 << "t)";
33068 struct synthesize_covocov_expression2
33070 typedef typename covocov_t::type2 node_type;
33071 typedef typename covocov_t::sf4_type sf4_type;
33072 typedef typename node_type::T0 T0;
33073 typedef typename node_type::T1 T1;
33074 typedef typename node_type::T2 T2;
33075 typedef typename node_type::T3 T3;
33077 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33078 const details::operator_type& operation,
33079 expression_node_ptr (&branch)[2])
33081 // c0 o0 ((v0 o1 c1) o2 v1)
33082 typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
33084 const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
33085 const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
33086 const Type& v0 = vocov->t0();
33087 const Type c1 = vocov->t1();
33088 const Type& v1 = vocov->t2();
33089 const details::operator_type o0 = operation;
33090 const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
33091 const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
33093 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
33094 binary_functor_t f1 = vocov->f0();
33095 binary_functor_t f2 = vocov->f1();
33097 details::free_node(*(expr_gen.node_allocator_),branch[0]);
33098 details::free_node(*(expr_gen.node_allocator_),branch[1]);
33100 expression_node_ptr result = error_node();
33102 const bool synthesis_result =
33103 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33104 (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
33106 if (synthesis_result)
33107 return result;
33108 else if (!expr_gen.valid_operator(o0,f0))
33109 return error_node();
33111 exprtk_debug(("c0 o0 ((v0 o1 c1) o2 v1)\n"));
33113 return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
33116 static inline std::string id(expression_generator<Type>& expr_gen,
33117 const details::operator_type o0,
33118 const details::operator_type o1,
33119 const details::operator_type o2)
33121 return details::build_string()
33122 << "t" << expr_gen.to_str(o0)
33123 << "((t" << expr_gen.to_str(o1)
33124 << "t)" << expr_gen.to_str(o2)
33125 << "t)";
33129 struct synthesize_vocovoc_expression2
33131 typedef typename vocovoc_t::type2 node_type;
33132 typedef typename vocovoc_t::sf4_type sf4_type;
33133 typedef typename node_type::T0 T0;
33134 typedef typename node_type::T1 T1;
33135 typedef typename node_type::T2 T2;
33136 typedef typename node_type::T3 T3;
33138 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33139 const details::operator_type& operation,
33140 expression_node_ptr (&branch)[2])
33142 // v0 o0 ((c0 o1 v1) o2 c1)
33143 typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t;
33145 const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]);
33146 const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
33147 const Type c0 = covoc->t0();
33148 const Type& v1 = covoc->t1();
33149 const Type c1 = covoc->t2();
33150 const details::operator_type o0 = operation;
33151 const details::operator_type o1 = expr_gen.get_operator(covoc->f0());
33152 const details::operator_type o2 = expr_gen.get_operator(covoc->f1());
33154 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
33155 binary_functor_t f1 = covoc->f0();
33156 binary_functor_t f2 = covoc->f1();
33158 details::free_node(*(expr_gen.node_allocator_),branch[1]);
33160 expression_node_ptr result = error_node();
33162 const bool synthesis_result =
33163 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33164 (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
33166 if (synthesis_result)
33167 return result;
33168 else if (!expr_gen.valid_operator(o0,f0))
33169 return error_node();
33171 exprtk_debug(("v0 o0 ((c0 o1 v1) o2 c1)\n"));
33173 return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
33176 static inline std::string id(expression_generator<Type>& expr_gen,
33177 const details::operator_type o0,
33178 const details::operator_type o1,
33179 const details::operator_type o2)
33181 return details::build_string()
33182 << "t" << expr_gen.to_str(o0)
33183 << "((t" << expr_gen.to_str(o1)
33184 << "t)" << expr_gen.to_str(o2)
33185 << "t)";
33189 struct synthesize_covovoc_expression2
33191 typedef typename covovoc_t::type2 node_type;
33192 typedef typename covovoc_t::sf4_type sf4_type;
33193 typedef typename node_type::T0 T0;
33194 typedef typename node_type::T1 T1;
33195 typedef typename node_type::T2 T2;
33196 typedef typename node_type::T3 T3;
33198 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33199 const details::operator_type& operation,
33200 expression_node_ptr (&branch)[2])
33202 // c0 o0 ((v0 o1 v1) o2 c1)
33203 typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t;
33205 const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
33206 const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
33207 const Type& v0 = vovoc->t0();
33208 const Type& v1 = vovoc->t1();
33209 const Type c1 = vovoc->t2();
33210 const details::operator_type o0 = operation;
33211 const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
33212 const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
33214 binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
33215 binary_functor_t f1 = vovoc->f0();
33216 binary_functor_t f2 = vovoc->f1();
33218 details::free_node(*(expr_gen.node_allocator_),branch[0]);
33219 details::free_node(*(expr_gen.node_allocator_),branch[1]);
33221 expression_node_ptr result = error_node();
33223 const bool synthesis_result =
33224 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33225 (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
33227 if (synthesis_result)
33228 return result;
33229 else if (!expr_gen.valid_operator(o0,f0))
33230 return error_node();
33232 exprtk_debug(("c0 o0 ((v0 o1 v1) o2 c1)\n"));
33234 return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
33237 static inline std::string id(expression_generator<Type>& expr_gen,
33238 const details::operator_type o0,
33239 const details::operator_type o1,
33240 const details::operator_type o2)
33242 return details::build_string()
33243 << "t" << expr_gen.to_str(o0)
33244 << "((t" << expr_gen.to_str(o1)
33245 << "t)" << expr_gen.to_str(o2)
33246 << "t)";
33250 struct synthesize_vococov_expression2
33252 typedef typename vococov_t::type2 node_type;
33253 static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
33255 // v0 o0 ((c0 o1 c1) o2 v1) - Not possible
33256 exprtk_debug(("v0 o0 ((c0 o1 c1) o2 v1) - Not possible\n"));
33257 return error_node();
33260 static inline std::string id(expression_generator<Type>&,
33261 const details::operator_type, const details::operator_type, const details::operator_type)
33263 return "INVALID";
33267 struct synthesize_vovovov_expression3
33269 typedef typename vovovov_t::type3 node_type;
33270 typedef typename vovovov_t::sf4_type sf4_type;
33271 typedef typename node_type::T0 T0;
33272 typedef typename node_type::T1 T1;
33273 typedef typename node_type::T2 T2;
33274 typedef typename node_type::T3 T3;
33276 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33277 const details::operator_type& operation,
33278 expression_node_ptr (&branch)[2])
33280 // ((v0 o0 v1) o1 v2) o2 v3
33281 typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
33283 const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
33284 const Type& v0 = vovov->t0();
33285 const Type& v1 = vovov->t1();
33286 const Type& v2 = vovov->t2();
33287 const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
33288 const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
33289 const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
33290 const details::operator_type o2 = operation;
33292 binary_functor_t f0 = vovov->f0();
33293 binary_functor_t f1 = vovov->f1();
33294 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33296 details::free_node(*(expr_gen.node_allocator_),branch[0]);
33298 expression_node_ptr result = error_node();
33300 const bool synthesis_result =
33301 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33302 (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
33304 if (synthesis_result)
33305 return result;
33306 else if (!expr_gen.valid_operator(o2,f2))
33307 return error_node();
33309 exprtk_debug(("((v0 o0 v1) o1 v2) o2 v3\n"));
33311 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
33314 static inline std::string id(expression_generator<Type>& expr_gen,
33315 const details::operator_type o0,
33316 const details::operator_type o1,
33317 const details::operator_type o2)
33319 return details::build_string()
33320 << "((t" << expr_gen.to_str(o0)
33321 << "t)" << expr_gen.to_str(o1)
33322 << "t)" << expr_gen.to_str(o2)
33323 << "t";
33327 struct synthesize_vovovoc_expression3
33329 typedef typename vovovoc_t::type3 node_type;
33330 typedef typename vovovoc_t::sf4_type sf4_type;
33331 typedef typename node_type::T0 T0;
33332 typedef typename node_type::T1 T1;
33333 typedef typename node_type::T2 T2;
33334 typedef typename node_type::T3 T3;
33336 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33337 const details::operator_type& operation,
33338 expression_node_ptr (&branch)[2])
33340 // ((v0 o0 v1) o1 v2) o2 c
33341 typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
33343 const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
33344 const Type& v0 = vovov->t0();
33345 const Type& v1 = vovov->t1();
33346 const Type& v2 = vovov->t2();
33347 const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
33348 const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
33349 const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
33350 const details::operator_type o2 = operation;
33352 binary_functor_t f0 = vovov->f0();
33353 binary_functor_t f1 = vovov->f1();
33354 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33356 details::free_node(*(expr_gen.node_allocator_),branch[0]);
33357 details::free_node(*(expr_gen.node_allocator_),branch[1]);
33359 expression_node_ptr result = error_node();
33361 const bool synthesis_result =
33362 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33363 (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
33365 if (synthesis_result)
33366 return result;
33367 else if (!expr_gen.valid_operator(o2,f2))
33368 return error_node();
33370 exprtk_debug(("((v0 o0 v1) o1 v2) o2 c\n"));
33372 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
33375 static inline std::string id(expression_generator<Type>& expr_gen,
33376 const details::operator_type o0,
33377 const details::operator_type o1,
33378 const details::operator_type o2)
33380 return details::build_string()
33381 << "((t" << expr_gen.to_str(o0)
33382 << "t)" << expr_gen.to_str(o1)
33383 << "t)" << expr_gen.to_str(o2)
33384 << "t";
33388 struct synthesize_vovocov_expression3
33390 typedef typename vovocov_t::type3 node_type;
33391 typedef typename vovocov_t::sf4_type sf4_type;
33392 typedef typename node_type::T0 T0;
33393 typedef typename node_type::T1 T1;
33394 typedef typename node_type::T2 T2;
33395 typedef typename node_type::T3 T3;
33397 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33398 const details::operator_type& operation,
33399 expression_node_ptr (&branch)[2])
33401 // ((v0 o0 v1) o1 c) o2 v2
33402 typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t;
33404 const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]);
33405 const Type& v0 = vovoc->t0();
33406 const Type& v1 = vovoc->t1();
33407 const Type c = vovoc->t2();
33408 const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
33409 const details::operator_type o0 = expr_gen.get_operator(vovoc->f0());
33410 const details::operator_type o1 = expr_gen.get_operator(vovoc->f1());
33411 const details::operator_type o2 = operation;
33413 binary_functor_t f0 = vovoc->f0();
33414 binary_functor_t f1 = vovoc->f1();
33415 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33417 details::free_node(*(expr_gen.node_allocator_),branch[0]);
33419 expression_node_ptr result = error_node();
33421 const bool synthesis_result =
33422 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33423 (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
33425 if (synthesis_result)
33426 return result;
33427 else if (!expr_gen.valid_operator(o2,f2))
33428 return error_node();
33430 exprtk_debug(("((v0 o0 v1) o1 c) o2 v2\n"));
33432 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
33435 static inline std::string id(expression_generator<Type>& expr_gen,
33436 const details::operator_type o0,
33437 const details::operator_type o1,
33438 const details::operator_type o2)
33440 return details::build_string()
33441 << "((t" << expr_gen.to_str(o0)
33442 << "t)" << expr_gen.to_str(o1)
33443 << "t)" << expr_gen.to_str(o2)
33444 << "t";
33448 struct synthesize_vocovov_expression3
33450 typedef typename vocovov_t::type3 node_type;
33451 typedef typename vocovov_t::sf4_type sf4_type;
33452 typedef typename node_type::T0 T0;
33453 typedef typename node_type::T1 T1;
33454 typedef typename node_type::T2 T2;
33455 typedef typename node_type::T3 T3;
33457 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33458 const details::operator_type& operation,
33459 expression_node_ptr (&branch)[2])
33461 // ((v0 o0 c) o1 v1) o2 v2
33462 typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
33464 const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
33465 const Type& v0 = vocov->t0();
33466 const Type c = vocov->t1();
33467 const Type& v1 = vocov->t2();
33468 const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
33469 const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
33470 const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
33471 const details::operator_type o2 = operation;
33473 binary_functor_t f0 = vocov->f0();
33474 binary_functor_t f1 = vocov->f1();
33475 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33477 details::free_node(*(expr_gen.node_allocator_),branch[0]);
33479 expression_node_ptr result = error_node();
33481 const bool synthesis_result =
33482 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33483 (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
33485 if (synthesis_result)
33486 return result;
33487 else if (!expr_gen.valid_operator(o2,f2))
33488 return error_node();
33490 exprtk_debug(("((v0 o0 c) o1 v1) o2 v2\n"));
33492 return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
33495 static inline std::string id(expression_generator<Type>& expr_gen,
33496 const details::operator_type o0,
33497 const details::operator_type o1,
33498 const details::operator_type o2)
33500 return details::build_string()
33501 << "((t" << expr_gen.to_str(o0)
33502 << "t)" << expr_gen.to_str(o1)
33503 << "t)" << expr_gen.to_str(o2)
33504 << "t";
33508 struct synthesize_covovov_expression3
33510 typedef typename covovov_t::type3 node_type;
33511 typedef typename covovov_t::sf4_type sf4_type;
33512 typedef typename node_type::T0 T0;
33513 typedef typename node_type::T1 T1;
33514 typedef typename node_type::T2 T2;
33515 typedef typename node_type::T3 T3;
33517 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33518 const details::operator_type& operation,
33519 expression_node_ptr (&branch)[2])
33521 // ((c o0 v0) o1 v1) o2 v2
33522 typedef typename synthesize_covov_expression0::node_type lcl_covov_t;
33524 const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
33525 const Type c = covov->t0();
33526 const Type& v0 = covov->t1();
33527 const Type& v1 = covov->t2();
33528 const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
33529 const details::operator_type o0 = expr_gen.get_operator(covov->f0());
33530 const details::operator_type o1 = expr_gen.get_operator(covov->f1());
33531 const details::operator_type o2 = operation;
33533 binary_functor_t f0 = covov->f0();
33534 binary_functor_t f1 = covov->f1();
33535 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33537 details::free_node(*(expr_gen.node_allocator_),branch[0]);
33539 expression_node_ptr result = error_node();
33541 const bool synthesis_result =
33542 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33543 (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
33545 if (synthesis_result)
33546 return result;
33547 else if (!expr_gen.valid_operator(o2,f2))
33548 return error_node();
33550 exprtk_debug(("((c o0 v0) o1 v1) o2 v2\n"));
33552 return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
33555 static inline std::string id(expression_generator<Type>& expr_gen,
33556 const details::operator_type o0,
33557 const details::operator_type o1,
33558 const details::operator_type o2)
33560 return details::build_string()
33561 << "((t" << expr_gen.to_str(o0)
33562 << "t)" << expr_gen.to_str(o1)
33563 << "t)" << expr_gen.to_str(o2)
33564 << "t";
33568 struct synthesize_covocov_expression3
33570 typedef typename covocov_t::type3 node_type;
33571 typedef typename covocov_t::sf4_type sf4_type;
33572 typedef typename node_type::T0 T0;
33573 typedef typename node_type::T1 T1;
33574 typedef typename node_type::T2 T2;
33575 typedef typename node_type::T3 T3;
33577 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33578 const details::operator_type& operation,
33579 expression_node_ptr (&branch)[2])
33581 // ((c0 o0 v0) o1 c1) o2 v1
33582 typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t;
33584 const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]);
33585 const Type c0 = covoc->t0();
33586 const Type& v0 = covoc->t1();
33587 const Type c1 = covoc->t2();
33588 const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
33589 const details::operator_type o0 = expr_gen.get_operator(covoc->f0());
33590 const details::operator_type o1 = expr_gen.get_operator(covoc->f1());
33591 const details::operator_type o2 = operation;
33593 binary_functor_t f0 = covoc->f0();
33594 binary_functor_t f1 = covoc->f1();
33595 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33597 details::free_node(*(expr_gen.node_allocator_),branch[0]);
33599 expression_node_ptr result = error_node();
33601 const bool synthesis_result =
33602 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33603 (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
33605 if (synthesis_result)
33606 return result;
33607 else if (!expr_gen.valid_operator(o2,f2))
33608 return error_node();
33610 exprtk_debug(("((c0 o0 v0) o1 c1) o2 v1\n"));
33612 return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
33615 static inline std::string id(expression_generator<Type>& expr_gen,
33616 const details::operator_type o0,
33617 const details::operator_type o1,
33618 const details::operator_type o2)
33620 return details::build_string()
33621 << "((t" << expr_gen.to_str(o0)
33622 << "t)" << expr_gen.to_str(o1)
33623 << "t)" << expr_gen.to_str(o2)
33624 << "t";
33628 struct synthesize_vocovoc_expression3
33630 typedef typename vocovoc_t::type3 node_type;
33631 typedef typename vocovoc_t::sf4_type sf4_type;
33632 typedef typename node_type::T0 T0;
33633 typedef typename node_type::T1 T1;
33634 typedef typename node_type::T2 T2;
33635 typedef typename node_type::T3 T3;
33637 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33638 const details::operator_type& operation,
33639 expression_node_ptr (&branch)[2])
33641 // ((v0 o0 c0) o1 v1) o2 c1
33642 typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
33644 const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
33645 const Type& v0 = vocov->t0();
33646 const Type c0 = vocov->t1();
33647 const Type& v1 = vocov->t2();
33648 const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
33649 const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
33650 const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
33651 const details::operator_type o2 = operation;
33653 binary_functor_t f0 = vocov->f0();
33654 binary_functor_t f1 = vocov->f1();
33655 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33657 details::free_node(*(expr_gen.node_allocator_),branch[0]);
33658 details::free_node(*(expr_gen.node_allocator_),branch[1]);
33660 expression_node_ptr result = error_node();
33662 const bool synthesis_result =
33663 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33664 (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
33666 if (synthesis_result)
33667 return result;
33668 else if (!expr_gen.valid_operator(o2,f2))
33669 return error_node();
33671 exprtk_debug(("((v0 o0 c0) o1 v1) o2 c1\n"));
33673 return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
33676 static inline std::string id(expression_generator<Type>& expr_gen,
33677 const details::operator_type o0,
33678 const details::operator_type o1,
33679 const details::operator_type o2)
33681 return details::build_string()
33682 << "((t" << expr_gen.to_str(o0)
33683 << "t)" << expr_gen.to_str(o1)
33684 << "t)" << expr_gen.to_str(o2)
33685 << "t";
33689 struct synthesize_covovoc_expression3
33691 typedef typename covovoc_t::type3 node_type;
33692 typedef typename covovoc_t::sf4_type sf4_type;
33693 typedef typename node_type::T0 T0;
33694 typedef typename node_type::T1 T1;
33695 typedef typename node_type::T2 T2;
33696 typedef typename node_type::T3 T3;
33698 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33699 const details::operator_type& operation,
33700 expression_node_ptr (&branch)[2])
33702 // ((c0 o0 v0) o1 v1) o2 c1
33703 typedef typename synthesize_covov_expression0::node_type lcl_covov_t;
33705 const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
33706 const Type c0 = covov->t0();
33707 const Type& v0 = covov->t1();
33708 const Type& v1 = covov->t2();
33709 const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
33710 const details::operator_type o0 = expr_gen.get_operator(covov->f0());
33711 const details::operator_type o1 = expr_gen.get_operator(covov->f1());
33712 const details::operator_type o2 = operation;
33714 binary_functor_t f0 = covov->f0();
33715 binary_functor_t f1 = covov->f1();
33716 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33718 details::free_node(*(expr_gen.node_allocator_),branch[0]);
33719 details::free_node(*(expr_gen.node_allocator_),branch[1]);
33721 expression_node_ptr result = error_node();
33723 const bool synthesis_result =
33724 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33725 (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
33727 if (synthesis_result)
33728 return result;
33729 else if (!expr_gen.valid_operator(o2,f2))
33730 return error_node();
33732 exprtk_debug(("((c0 o0 v0) o1 v1) o2 c1\n"));
33734 return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
33737 static inline std::string id(expression_generator<Type>& expr_gen,
33738 const details::operator_type o0,
33739 const details::operator_type o1,
33740 const details::operator_type o2)
33742 return details::build_string()
33743 << "((t" << expr_gen.to_str(o0)
33744 << "t)" << expr_gen.to_str(o1)
33745 << "t)" << expr_gen.to_str(o2)
33746 << "t";
33750 struct synthesize_vococov_expression3
33752 typedef typename vococov_t::type3 node_type;
33753 typedef typename vococov_t::sf4_type sf4_type;
33754 typedef typename node_type::T0 T0;
33755 typedef typename node_type::T1 T1;
33756 typedef typename node_type::T2 T2;
33757 typedef typename node_type::T3 T3;
33759 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33760 const details::operator_type& operation,
33761 expression_node_ptr (&branch)[2])
33763 // ((v0 o0 c0) o1 c1) o2 v1
33764 typedef typename synthesize_vococ_expression0::node_type lcl_vococ_t;
33766 const lcl_vococ_t* vococ = static_cast<const lcl_vococ_t*>(branch[0]);
33767 const Type& v0 = vococ->t0();
33768 const Type c0 = vococ->t1();
33769 const Type c1 = vococ->t2();
33770 const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
33771 const details::operator_type o0 = expr_gen.get_operator(vococ->f0());
33772 const details::operator_type o1 = expr_gen.get_operator(vococ->f1());
33773 const details::operator_type o2 = operation;
33775 binary_functor_t f0 = vococ->f0();
33776 binary_functor_t f1 = vococ->f1();
33777 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33779 details::free_node(*(expr_gen.node_allocator_),branch[0]);
33781 expression_node_ptr result = error_node();
33783 const bool synthesis_result =
33784 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33785 (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result);
33787 if (synthesis_result)
33788 return result;
33789 else if (!expr_gen.valid_operator(o2,f2))
33790 return error_node();
33792 exprtk_debug(("((v0 o0 c0) o1 c1) o2 v1\n"));
33794 return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2);
33797 static inline std::string id(expression_generator<Type>& expr_gen,
33798 const details::operator_type o0,
33799 const details::operator_type o1,
33800 const details::operator_type o2)
33802 return details::build_string()
33803 << "((t" << expr_gen.to_str(o0)
33804 << "t)" << expr_gen.to_str(o1)
33805 << "t)" << expr_gen.to_str(o2)
33806 << "t";
33810 struct synthesize_vovovov_expression4
33812 typedef typename vovovov_t::type4 node_type;
33813 typedef typename vovovov_t::sf4_type sf4_type;
33814 typedef typename node_type::T0 T0;
33815 typedef typename node_type::T1 T1;
33816 typedef typename node_type::T2 T2;
33817 typedef typename node_type::T3 T3;
33819 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33820 const details::operator_type& operation,
33821 expression_node_ptr (&branch)[2])
33823 // (v0 o0 (v1 o1 v2)) o2 v3
33824 typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
33826 const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
33827 const Type& v0 = vovov->t0();
33828 const Type& v1 = vovov->t1();
33829 const Type& v2 = vovov->t2();
33830 const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
33831 const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
33832 const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
33833 const details::operator_type o2 = operation;
33835 binary_functor_t f0 = vovov->f0();
33836 binary_functor_t f1 = vovov->f1();
33837 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33839 details::free_node(*(expr_gen.node_allocator_),branch[0]);
33841 expression_node_ptr result = error_node();
33843 const bool synthesis_result =
33844 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33845 (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
33847 if (synthesis_result)
33848 return result;
33849 else if (!expr_gen.valid_operator(o2,f2))
33850 return error_node();
33852 exprtk_debug(("(v0 o0 (v1 o1 v2)) o2 v3\n"));
33854 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
33857 static inline std::string id(expression_generator<Type>& expr_gen,
33858 const details::operator_type o0,
33859 const details::operator_type o1,
33860 const details::operator_type o2)
33862 return details::build_string()
33863 << "(t" << expr_gen.to_str(o0)
33864 << "(t" << expr_gen.to_str(o1)
33865 << "t)" << expr_gen.to_str(o2)
33866 << "t";
33870 struct synthesize_vovovoc_expression4
33872 typedef typename vovovoc_t::type4 node_type;
33873 typedef typename vovovoc_t::sf4_type sf4_type;
33874 typedef typename node_type::T0 T0;
33875 typedef typename node_type::T1 T1;
33876 typedef typename node_type::T2 T2;
33877 typedef typename node_type::T3 T3;
33879 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33880 const details::operator_type& operation,
33881 expression_node_ptr (&branch)[2])
33883 // ((v0 o0 (v1 o1 v2)) o2 c)
33884 typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
33886 const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
33887 const Type& v0 = vovov->t0();
33888 const Type& v1 = vovov->t1();
33889 const Type& v2 = vovov->t2();
33890 const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
33891 const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
33892 const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
33893 const details::operator_type o2 = operation;
33895 binary_functor_t f0 = vovov->f0();
33896 binary_functor_t f1 = vovov->f1();
33897 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33899 details::free_node(*(expr_gen.node_allocator_),branch[0]);
33900 details::free_node(*(expr_gen.node_allocator_),branch[1]);
33902 expression_node_ptr result = error_node();
33904 const bool synthesis_result =
33905 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33906 (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
33908 if (synthesis_result)
33909 return result;
33910 else if (!expr_gen.valid_operator(o2,f2))
33911 return error_node();
33913 exprtk_debug(("((v0 o0 (v1 o1 v2)) o2 c)\n"));
33915 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
33918 static inline std::string id(expression_generator<Type>& expr_gen,
33919 const details::operator_type o0,
33920 const details::operator_type o1,
33921 const details::operator_type o2)
33923 return details::build_string()
33924 << "(t" << expr_gen.to_str(o0)
33925 << "(t" << expr_gen.to_str(o1)
33926 << "t)" << expr_gen.to_str(o2)
33927 << "t";
33931 struct synthesize_vovocov_expression4
33933 typedef typename vovocov_t::type4 node_type;
33934 typedef typename vovocov_t::sf4_type sf4_type;
33935 typedef typename node_type::T0 T0;
33936 typedef typename node_type::T1 T1;
33937 typedef typename node_type::T2 T2;
33938 typedef typename node_type::T3 T3;
33940 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33941 const details::operator_type& operation,
33942 expression_node_ptr (&branch)[2])
33944 // ((v0 o0 (v1 o1 c)) o2 v1)
33945 typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t;
33947 const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]);
33948 const Type& v0 = vovoc->t0();
33949 const Type& v1 = vovoc->t1();
33950 const Type c = vovoc->t2();
33951 const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
33952 const details::operator_type o0 = expr_gen.get_operator(vovoc->f0());
33953 const details::operator_type o1 = expr_gen.get_operator(vovoc->f1());
33954 const details::operator_type o2 = operation;
33956 binary_functor_t f0 = vovoc->f0();
33957 binary_functor_t f1 = vovoc->f1();
33958 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33960 details::free_node(*(expr_gen.node_allocator_),branch[0]);
33962 expression_node_ptr result = error_node();
33964 const bool synthesis_result =
33965 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33966 (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
33968 if (synthesis_result)
33969 return result;
33970 else if (!expr_gen.valid_operator(o2,f2))
33971 return error_node();
33973 exprtk_debug(("((v0 o0 (v1 o1 c)) o2 v1)\n"));
33975 return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
33978 static inline std::string id(expression_generator<Type>& expr_gen,
33979 const details::operator_type o0,
33980 const details::operator_type o1,
33981 const details::operator_type o2)
33983 return details::build_string()
33984 << "(t" << expr_gen.to_str(o0)
33985 << "(t" << expr_gen.to_str(o1)
33986 << "t)" << expr_gen.to_str(o2)
33987 << "t";
33991 struct synthesize_vocovov_expression4
33993 typedef typename vocovov_t::type4 node_type;
33994 typedef typename vocovov_t::sf4_type sf4_type;
33995 typedef typename node_type::T0 T0;
33996 typedef typename node_type::T1 T1;
33997 typedef typename node_type::T2 T2;
33998 typedef typename node_type::T3 T3;
34000 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34001 const details::operator_type& operation,
34002 expression_node_ptr (&branch)[2])
34004 // ((v0 o0 (c o1 v1)) o2 v2)
34005 typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
34007 const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
34008 const Type& v0 = vocov->t0();
34009 const Type c = vocov->t1();
34010 const Type& v1 = vocov->t2();
34011 const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
34012 const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
34013 const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
34014 const details::operator_type o2 = operation;
34016 binary_functor_t f0 = vocov->f0();
34017 binary_functor_t f1 = vocov->f1();
34018 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34020 details::free_node(*(expr_gen.node_allocator_),branch[0]);
34021 expression_node_ptr result = error_node();
34023 const bool synthesis_result =
34024 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34025 (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
34027 if (synthesis_result)
34028 return result;
34029 else if (!expr_gen.valid_operator(o2,f2))
34030 return error_node();
34032 exprtk_debug(("((v0 o0 (c o1 v1)) o2 v2)\n"));
34034 return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
34037 static inline std::string id(expression_generator<Type>& expr_gen,
34038 const details::operator_type o0,
34039 const details::operator_type o1,
34040 const details::operator_type o2)
34042 return details::build_string()
34043 << "(t" << expr_gen.to_str(o0)
34044 << "(t" << expr_gen.to_str(o1)
34045 << "t)" << expr_gen.to_str(o2)
34046 << "t";
34050 struct synthesize_covovov_expression4
34052 typedef typename covovov_t::type4 node_type;
34053 typedef typename covovov_t::sf4_type sf4_type;
34054 typedef typename node_type::T0 T0;
34055 typedef typename node_type::T1 T1;
34056 typedef typename node_type::T2 T2;
34057 typedef typename node_type::T3 T3;
34059 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34060 const details::operator_type& operation,
34061 expression_node_ptr (&branch)[2])
34063 // ((c o0 (v0 o1 v1)) o2 v2)
34064 typedef typename synthesize_covov_expression1::node_type lcl_covov_t;
34066 const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
34067 const Type c = covov->t0();
34068 const Type& v0 = covov->t1();
34069 const Type& v1 = covov->t2();
34070 const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
34071 const details::operator_type o0 = expr_gen.get_operator(covov->f0());
34072 const details::operator_type o1 = expr_gen.get_operator(covov->f1());
34073 const details::operator_type o2 = operation;
34075 binary_functor_t f0 = covov->f0();
34076 binary_functor_t f1 = covov->f1();
34077 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34079 details::free_node(*(expr_gen.node_allocator_),branch[0]);
34081 expression_node_ptr result = error_node();
34083 const bool synthesis_result =
34084 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34085 (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
34087 if (synthesis_result)
34088 return result;
34089 else if (!expr_gen.valid_operator(o2,f2))
34090 return error_node();
34092 exprtk_debug(("((c o0 (v0 o1 v1)) o2 v2)\n"));
34094 return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
34097 static inline std::string id(expression_generator<Type>& expr_gen,
34098 const details::operator_type o0,
34099 const details::operator_type o1,
34100 const details::operator_type o2)
34102 return details::build_string()
34103 << "(t" << expr_gen.to_str(o0)
34104 << "(t" << expr_gen.to_str(o1)
34105 << "t)" << expr_gen.to_str(o2)
34106 << "t";
34110 struct synthesize_covocov_expression4
34112 typedef typename covocov_t::type4 node_type;
34113 typedef typename covocov_t::sf4_type sf4_type;
34114 typedef typename node_type::T0 T0;
34115 typedef typename node_type::T1 T1;
34116 typedef typename node_type::T2 T2;
34117 typedef typename node_type::T3 T3;
34119 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34120 const details::operator_type& operation,
34121 expression_node_ptr (&branch)[2])
34123 // ((c0 o0 (v0 o1 c1)) o2 v1)
34124 typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t;
34126 const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]);
34127 const Type c0 = covoc->t0();
34128 const Type& v0 = covoc->t1();
34129 const Type c1 = covoc->t2();
34130 const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
34131 const details::operator_type o0 = expr_gen.get_operator(covoc->f0());
34132 const details::operator_type o1 = expr_gen.get_operator(covoc->f1());
34133 const details::operator_type o2 = operation;
34135 binary_functor_t f0 = covoc->f0();
34136 binary_functor_t f1 = covoc->f1();
34137 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34139 details::free_node(*(expr_gen.node_allocator_),branch[0]);
34141 expression_node_ptr result = error_node();
34143 const bool synthesis_result =
34144 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34145 (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
34147 if (synthesis_result)
34148 return result;
34149 else if (!expr_gen.valid_operator(o2,f2))
34150 return error_node();
34152 exprtk_debug(("((c0 o0 (v0 o1 c1)) o2 v1)\n"));
34154 return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
34157 static inline std::string id(expression_generator<Type>& expr_gen,
34158 const details::operator_type o0,
34159 const details::operator_type o1,
34160 const details::operator_type o2)
34162 return details::build_string()
34163 << "(t" << expr_gen.to_str(o0)
34164 << "(t" << expr_gen.to_str(o1)
34165 << "t)" << expr_gen.to_str(o2)
34166 << "t";
34170 struct synthesize_vocovoc_expression4
34172 typedef typename vocovoc_t::type4 node_type;
34173 typedef typename vocovoc_t::sf4_type sf4_type;
34174 typedef typename node_type::T0 T0;
34175 typedef typename node_type::T1 T1;
34176 typedef typename node_type::T2 T2;
34177 typedef typename node_type::T3 T3;
34179 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34180 const details::operator_type& operation,
34181 expression_node_ptr (&branch)[2])
34183 // ((v0 o0 (c0 o1 v1)) o2 c1)
34184 typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
34186 const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
34187 const Type& v0 = vocov->t0();
34188 const Type c0 = vocov->t1();
34189 const Type& v1 = vocov->t2();
34190 const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
34191 const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
34192 const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
34193 const details::operator_type o2 = operation;
34195 binary_functor_t f0 = vocov->f0();
34196 binary_functor_t f1 = vocov->f1();
34197 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34199 details::free_node(*(expr_gen.node_allocator_),branch[0]);
34200 details::free_node(*(expr_gen.node_allocator_),branch[1]);
34202 expression_node_ptr result = error_node();
34204 const bool synthesis_result =
34205 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34206 (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
34208 if (synthesis_result)
34209 return result;
34210 else if (!expr_gen.valid_operator(o2,f2))
34211 return error_node();
34213 exprtk_debug(("((v0 o0 (c0 o1 v1)) o2 c1)\n"));
34215 return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
34218 static inline std::string id(expression_generator<Type>& expr_gen,
34219 const details::operator_type o0,
34220 const details::operator_type o1,
34221 const details::operator_type o2)
34223 return details::build_string()
34224 << "(t" << expr_gen.to_str(o0)
34225 << "(t" << expr_gen.to_str(o1)
34226 << "t)" << expr_gen.to_str(o2)
34227 << "t";
34231 struct synthesize_covovoc_expression4
34233 typedef typename covovoc_t::type4 node_type;
34234 typedef typename covovoc_t::sf4_type sf4_type;
34235 typedef typename node_type::T0 T0;
34236 typedef typename node_type::T1 T1;
34237 typedef typename node_type::T2 T2;
34238 typedef typename node_type::T3 T3;
34240 static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34241 const details::operator_type& operation,
34242 expression_node_ptr (&branch)[2])
34244 // ((c0 o0 (v0 o1 v1)) o2 c1)
34245 typedef typename synthesize_covov_expression1::node_type lcl_covov_t;
34247 const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
34248 const Type c0 = covov->t0();
34249 const Type& v0 = covov->t1();
34250 const Type& v1 = covov->t2();
34251 const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
34252 const details::operator_type o0 = expr_gen.get_operator(covov->f0());
34253 const details::operator_type o1 = expr_gen.get_operator(covov->f1());
34254 const details::operator_type o2 = operation;
34256 binary_functor_t f0 = covov->f0();
34257 binary_functor_t f1 = covov->f1();
34258 binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34260 details::free_node(*(expr_gen.node_allocator_),branch[0]);
34261 details::free_node(*(expr_gen.node_allocator_),branch[1]);
34263 expression_node_ptr result = error_node();
34265 const bool synthesis_result =
34266 synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34267 (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
34269 if (synthesis_result)
34270 return result;
34271 else if (!expr_gen.valid_operator(o2,f2))
34272 return error_node();
34274 exprtk_debug(("((c0 o0 (v0 o1 v1)) o2 c1)\n"));
34276 return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
34279 static inline std::string id(expression_generator<Type>& expr_gen,
34280 const details::operator_type o0,
34281 const details::operator_type o1,
34282 const details::operator_type o2)
34284 return details::build_string()
34285 << "(t" << expr_gen.to_str(o0)
34286 << "(t" << expr_gen.to_str(o1)
34287 << "t)" << expr_gen.to_str(o2)
34288 << "t";
34292 struct synthesize_vococov_expression4
34294 typedef typename vococov_t::type4 node_type;
34295 static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
34297 // ((v0 o0 (c0 o1 c1)) o2 v1) - Not possible
34298 exprtk_debug(("((v0 o0 (c0 o1 c1)) o2 v1) - Not possible\n"));
34299 return error_node();
34302 static inline std::string id(expression_generator<Type>&,
34303 const details::operator_type, const details::operator_type, const details::operator_type)
34305 return "INVALID";
34308 #endif
34310 inline expression_node_ptr synthesize_uvouv_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
34312 // Definition: uv o uv
34313 details::operator_type o0 = static_cast<details::uv_base_node<Type>*>(branch[0])->operation();
34314 details::operator_type o1 = static_cast<details::uv_base_node<Type>*>(branch[1])->operation();
34315 const Type& v0 = static_cast<details::uv_base_node<Type>*>(branch[0])->v();
34316 const Type& v1 = static_cast<details::uv_base_node<Type>*>(branch[1])->v();
34317 unary_functor_t u0 = reinterpret_cast<unary_functor_t> (0);
34318 unary_functor_t u1 = reinterpret_cast<unary_functor_t> (0);
34319 binary_functor_t f = reinterpret_cast<binary_functor_t>(0);
34321 if (!valid_operator(o0,u0))
34322 return error_node();
34323 else if (!valid_operator(o1,u1))
34324 return error_node();
34325 else if (!valid_operator(operation,f))
34326 return error_node();
34328 expression_node_ptr result = error_node();
34330 if (
34331 (details::e_neg == o0) &&
34332 (details::e_neg == o1)
34335 switch (operation)
34337 // (-v0 + -v1) --> -(v0 + v1)
34338 case details::e_add : result = (*this)(details::e_neg,
34339 node_allocator_->
34340 allocate_rr<typename details::
34341 vov_node<Type,details::add_op<Type> > >(v0, v1));
34342 exprtk_debug(("(-v0 + -v1) --> -(v0 + v1)\n"));
34343 break;
34345 // (-v0 - -v1) --> (v1 - v0)
34346 case details::e_sub : result = node_allocator_->
34347 allocate_rr<typename details::
34348 vov_node<Type,details::sub_op<Type> > >(v1, v0);
34349 exprtk_debug(("(-v0 - -v1) --> (v1 - v0)\n"));
34350 break;
34352 // (-v0 * -v1) --> (v0 * v1)
34353 case details::e_mul : result = node_allocator_->
34354 allocate_rr<typename details::
34355 vov_node<Type,details::mul_op<Type> > >(v0, v1);
34356 exprtk_debug(("(-v0 * -v1) --> (v0 * v1)\n"));
34357 break;
34359 // (-v0 / -v1) --> (v0 / v1)
34360 case details::e_div : result = node_allocator_->
34361 allocate_rr<typename details::
34362 vov_node<Type,details::div_op<Type> > >(v0, v1);
34363 exprtk_debug(("(-v0 / -v1) --> (v0 / v1)\n"));
34364 break;
34366 default : break;
34370 if (0 == result)
34372 result = node_allocator_->
34373 allocate_rrrrr<typename details::uvouv_node<Type> >(v0, v1, u0, u1, f);
34376 details::free_all_nodes(*node_allocator_,branch);
34377 return result;
34380 #undef basic_opr_switch_statements
34381 #undef extended_opr_switch_statements
34382 #undef unary_opr_switch_statements
34384 #ifndef exprtk_disable_string_capabilities
34386 #define string_opr_switch_statements \
34387 case_stmt(details:: e_lt ,details:: lt_op) \
34388 case_stmt(details:: e_lte ,details:: lte_op) \
34389 case_stmt(details:: e_gt ,details:: gt_op) \
34390 case_stmt(details:: e_gte ,details:: gte_op) \
34391 case_stmt(details:: e_eq ,details:: eq_op) \
34392 case_stmt(details:: e_ne ,details:: ne_op) \
34393 case_stmt(details::e_in ,details:: in_op) \
34394 case_stmt(details::e_like ,details:: like_op) \
34395 case_stmt(details::e_ilike,details::ilike_op) \
34397 template <typename T0, typename T1>
34398 inline expression_node_ptr synthesize_str_xrox_expression_impl(const details::operator_type& opr,
34399 T0 s0, T1 s1,
34400 range_t rp0)
34402 switch (opr)
34404 #define case_stmt(op0,op1) \
34405 case op0 : return node_allocator_-> \
34406 allocate_ttt<typename details::str_xrox_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \
34407 (s0, s1, rp0); \
34409 string_opr_switch_statements
34410 #undef case_stmt
34411 default : return error_node();
34415 template <typename T0, typename T1>
34416 inline expression_node_ptr synthesize_str_xoxr_expression_impl(const details::operator_type& opr,
34417 T0 s0, T1 s1,
34418 range_t rp1)
34420 switch (opr)
34422 #define case_stmt(op0,op1) \
34423 case op0 : return node_allocator_-> \
34424 allocate_ttt<typename details::str_xoxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \
34425 (s0, s1, rp1); \
34427 string_opr_switch_statements
34428 #undef case_stmt
34429 default : return error_node();
34433 template <typename T0, typename T1>
34434 inline expression_node_ptr synthesize_str_xroxr_expression_impl(const details::operator_type& opr,
34435 T0 s0, T1 s1,
34436 range_t rp0, range_t rp1)
34438 switch (opr)
34440 #define case_stmt(op0,op1) \
34441 case op0 : return node_allocator_-> \
34442 allocate_tttt<typename details::str_xroxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \
34443 (s0, s1, rp0, rp1); \
34445 string_opr_switch_statements
34446 #undef case_stmt
34447 default : return error_node();
34451 template <typename T0, typename T1>
34452 inline expression_node_ptr synthesize_sos_expression_impl(const details::operator_type& opr, T0 s0, T1 s1)
34454 switch (opr)
34456 #define case_stmt(op0,op1) \
34457 case op0 : return node_allocator_-> \
34458 allocate_tt<typename details::sos_node<Type,T0,T1,op1<Type> >,T0,T1>(s0, s1); \
34460 string_opr_switch_statements
34461 #undef case_stmt
34462 default : return error_node();
34466 inline expression_node_ptr synthesize_sos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34468 std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref();
34469 std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref();
34471 return synthesize_sos_expression_impl<std::string&,std::string&>(opr, s0, s1);
34474 inline expression_node_ptr synthesize_sros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34476 std::string& s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref ();
34477 std::string& s1 = static_cast<details::stringvar_node<Type>*> (branch[1])->ref ();
34478 range_t rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range();
34480 static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();
34482 free_node(*node_allocator_,branch[0]);
34484 return synthesize_str_xrox_expression_impl<std::string&,std::string&>(opr, s0, s1, rp0);
34487 inline expression_node_ptr synthesize_sosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34489 std::string& s0 = static_cast<details::stringvar_node<Type>*> (branch[0])->ref ();
34490 std::string& s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref ();
34491 range_t rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range();
34493 static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();
34495 free_node(*node_allocator_,branch[1]);
34497 return synthesize_str_xoxr_expression_impl<std::string&,std::string&>(opr, s0, s1, rp1);
34500 inline expression_node_ptr synthesize_socsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34502 std::string& s0 = static_cast<details::stringvar_node<Type>*> (branch[0])->ref ();
34503 std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str ();
34504 range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
34506 static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
34508 free_node(*node_allocator_,branch[1]);
34510 return synthesize_str_xoxr_expression_impl<std::string&, const std::string>(opr, s0, s1, rp1);
34513 inline expression_node_ptr synthesize_srosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34515 std::string& s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref ();
34516 std::string& s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref ();
34517 range_t rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range();
34518 range_t rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range();
34520 static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();
34521 static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();
34523 details::free_node(*node_allocator_,branch[0]);
34524 details::free_node(*node_allocator_,branch[1]);
34526 return synthesize_str_xroxr_expression_impl<std::string&,std::string&>(opr, s0, s1, rp0, rp1);
34529 inline expression_node_ptr synthesize_socs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34531 std::string& s0 = static_cast< details::stringvar_node<Type>*>(branch[0])->ref();
34532 std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
34534 details::free_node(*node_allocator_,branch[1]);
34536 return synthesize_sos_expression_impl<std::string&, const std::string>(opr, s0, s1);
34539 inline expression_node_ptr synthesize_csos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34541 std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
34542 std::string& s1 = static_cast< details::stringvar_node<Type>*>(branch[1])->ref();
34544 details::free_node(*node_allocator_,branch[0]);
34546 return synthesize_sos_expression_impl<const std::string,std::string&>(opr, s0, s1);
34549 inline expression_node_ptr synthesize_csosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34551 std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str ();
34552 std::string& s1 = static_cast<details::string_range_node<Type>*> (branch[1])->ref ();
34553 range_t rp1 = static_cast<details::string_range_node<Type>*> (branch[1])->range();
34555 static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();
34557 details::free_node(*node_allocator_,branch[0]);
34558 details::free_node(*node_allocator_,branch[1]);
34560 return synthesize_str_xoxr_expression_impl<const std::string,std::string&>(opr, s0, s1, rp1);
34563 inline expression_node_ptr synthesize_srocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34565 std::string& s0 = static_cast<details::string_range_node<Type>*> (branch[0])->ref ();
34566 std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str ();
34567 range_t rp0 = static_cast<details::string_range_node<Type>*> (branch[0])->range();
34569 static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();
34571 details::free_node(*node_allocator_,branch[0]);
34572 details::free_node(*node_allocator_,branch[1]);
34574 return synthesize_str_xrox_expression_impl<std::string&, const std::string>(opr, s0, s1, rp0);
34577 inline expression_node_ptr synthesize_srocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34579 std::string& s0 = static_cast<details::string_range_node<Type>*> (branch[0])->ref ();
34580 std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str ();
34581 range_t rp0 = static_cast<details::string_range_node<Type>*> (branch[0])->range();
34582 range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
34584 static_cast<details::string_range_node<Type>*> (branch[0])->range_ref().clear();
34585 static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
34587 details::free_node(*node_allocator_,branch[0]);
34588 details::free_node(*node_allocator_,branch[1]);
34590 return synthesize_str_xroxr_expression_impl<std::string&, const std::string>(opr, s0, s1, rp0, rp1);
34593 inline expression_node_ptr synthesize_csocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34595 const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
34596 const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
34598 expression_node_ptr result = error_node();
34600 if (details::e_add == opr)
34601 result = node_allocator_->allocate_c<details::string_literal_node<Type> >(s0 + s1);
34602 else if (details::e_in == opr)
34603 result = node_allocator_->allocate_c<details::literal_node<Type> >(details::in_op <Type>::process(s0,s1));
34604 else if (details::e_like == opr)
34605 result = node_allocator_->allocate_c<details::literal_node<Type> >(details::like_op <Type>::process(s0,s1));
34606 else if (details::e_ilike == opr)
34607 result = node_allocator_->allocate_c<details::literal_node<Type> >(details::ilike_op<Type>::process(s0,s1));
34608 else
34610 expression_node_ptr temp = synthesize_sos_expression_impl<const std::string, const std::string>(opr, s0, s1);
34612 const Type v = temp->value();
34614 details::free_node(*node_allocator_,temp);
34616 result = node_allocator_->allocate<literal_node_t>(v);
34619 details::free_all_nodes(*node_allocator_,branch);
34621 return result;
34624 inline expression_node_ptr synthesize_csocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34626 const std::string s0 = static_cast<details::string_literal_node<Type>*> (branch[0])->str ();
34627 std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str ();
34628 range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
34630 static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
34632 free_node(*node_allocator_,branch[0]);
34633 free_node(*node_allocator_,branch[1]);
34635 return synthesize_str_xoxr_expression_impl<const std::string, const std::string>(opr, s0, s1, rp1);
34638 inline expression_node_ptr synthesize_csros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34640 std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str ();
34641 std::string& s1 = static_cast<details::stringvar_node<Type>*> (branch[1])->ref ();
34642 range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
34644 static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
34646 free_node(*node_allocator_,branch[0]);
34648 return synthesize_str_xrox_expression_impl<const std::string,std::string&>(opr, s0, s1, rp0);
34651 inline expression_node_ptr synthesize_csrosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34653 const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str ();
34654 std::string& s1 = static_cast<details::string_range_node<Type>*> (branch[1])->ref ();
34655 const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
34656 const range_t rp1 = static_cast<details::string_range_node<Type>*> (branch[1])->range();
34658 static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
34659 static_cast<details::string_range_node<Type>*> (branch[1])->range_ref().clear();
34661 free_node(*node_allocator_,branch[0]);
34662 free_node(*node_allocator_,branch[1]);
34664 return synthesize_str_xroxr_expression_impl<const std::string,std::string&>(opr, s0, s1, rp0, rp1);
34667 inline expression_node_ptr synthesize_csrocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34669 const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str ();
34670 const std::string s1 = static_cast<details::string_literal_node<Type>*> (branch[1])->str ();
34671 const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
34673 static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
34675 details::free_all_nodes(*node_allocator_,branch);
34677 return synthesize_str_xrox_expression_impl<const std::string,std::string>(opr, s0, s1, rp0);
34680 inline expression_node_ptr synthesize_csrocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34682 const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str ();
34683 const std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str ();
34684 const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
34685 const range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
34687 static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
34688 static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
34690 details::free_all_nodes(*node_allocator_,branch);
34692 return synthesize_str_xroxr_expression_impl<const std::string, const std::string>(opr, s0, s1, rp0, rp1);
34695 inline expression_node_ptr synthesize_strogen_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34697 switch (opr)
34699 #define case_stmt(op0,op1) \
34700 case op0 : return node_allocator_-> \
34701 allocate_ttt<typename details::str_sogens_node<Type,op1<Type> > > \
34702 (opr, branch[0], branch[1]); \
34704 string_opr_switch_statements
34705 #undef case_stmt
34706 default : return error_node();
34709 #endif
34711 #ifndef exprtk_disable_string_capabilities
34712 inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34714 if ((0 == branch[0]) || (0 == branch[1]))
34716 details::free_all_nodes(*node_allocator_,branch);
34718 return error_node();
34721 const bool b0_is_s = details::is_string_node (branch[0]);
34722 const bool b0_is_cs = details::is_const_string_node (branch[0]);
34723 const bool b0_is_sr = details::is_string_range_node (branch[0]);
34724 const bool b0_is_csr = details::is_const_string_range_node(branch[0]);
34726 const bool b1_is_s = details::is_string_node (branch[1]);
34727 const bool b1_is_cs = details::is_const_string_node (branch[1]);
34728 const bool b1_is_sr = details::is_string_range_node (branch[1]);
34729 const bool b1_is_csr = details::is_const_string_range_node(branch[1]);
34731 const bool b0_is_gen = details::is_string_assignment_node (branch[0]) ||
34732 details::is_genricstring_range_node(branch[0]) ||
34733 details::is_string_concat_node (branch[0]) ||
34734 details::is_string_function_node (branch[0]) ||
34735 details::is_string_condition_node (branch[0]) ||
34736 details::is_string_ccondition_node (branch[0]) ||
34737 details::is_string_vararg_node (branch[0]) ;
34739 const bool b1_is_gen = details::is_string_assignment_node (branch[1]) ||
34740 details::is_genricstring_range_node(branch[1]) ||
34741 details::is_string_concat_node (branch[1]) ||
34742 details::is_string_function_node (branch[1]) ||
34743 details::is_string_condition_node (branch[1]) ||
34744 details::is_string_ccondition_node (branch[1]) ||
34745 details::is_string_vararg_node (branch[1]) ;
34747 if (details::e_add == opr)
34749 if (!b0_is_cs || !b1_is_cs)
34751 return synthesize_expression<string_concat_node_t,2>(opr,branch);
34755 if (b0_is_gen || b1_is_gen)
34757 return synthesize_strogen_expression(opr,branch);
34759 else if (b0_is_s)
34761 if (b1_is_s ) return synthesize_sos_expression (opr,branch);
34762 else if (b1_is_cs ) return synthesize_socs_expression (opr,branch);
34763 else if (b1_is_sr ) return synthesize_sosr_expression (opr,branch);
34764 else if (b1_is_csr) return synthesize_socsr_expression (opr,branch);
34766 else if (b0_is_cs)
34768 if (b1_is_s ) return synthesize_csos_expression (opr,branch);
34769 else if (b1_is_cs ) return synthesize_csocs_expression (opr,branch);
34770 else if (b1_is_sr ) return synthesize_csosr_expression (opr,branch);
34771 else if (b1_is_csr) return synthesize_csocsr_expression(opr,branch);
34773 else if (b0_is_sr)
34775 if (b1_is_s ) return synthesize_sros_expression (opr,branch);
34776 else if (b1_is_sr ) return synthesize_srosr_expression (opr,branch);
34777 else if (b1_is_cs ) return synthesize_srocs_expression (opr,branch);
34778 else if (b1_is_csr) return synthesize_srocsr_expression(opr,branch);
34780 else if (b0_is_csr)
34782 if (b1_is_s ) return synthesize_csros_expression (opr,branch);
34783 else if (b1_is_sr ) return synthesize_csrosr_expression (opr,branch);
34784 else if (b1_is_cs ) return synthesize_csrocs_expression (opr,branch);
34785 else if (b1_is_csr) return synthesize_csrocsr_expression(opr,branch);
34788 return error_node();
34790 #else
34791 inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[2])
34793 details::free_all_nodes(*node_allocator_,branch);
34794 return error_node();
34796 #endif
34798 #ifndef exprtk_disable_string_capabilities
34799 inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[3])
34801 if (details::e_inrange != opr)
34802 return error_node();
34803 else if ((0 == branch[0]) || (0 == branch[1]) || (0 == branch[2]))
34805 details::free_all_nodes(*node_allocator_,branch);
34807 return error_node();
34809 else if (
34810 details::is_const_string_node(branch[0]) &&
34811 details::is_const_string_node(branch[1]) &&
34812 details::is_const_string_node(branch[2])
34815 const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
34816 const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
34817 const std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();
34819 const Type v = (((s0 <= s1) && (s1 <= s2)) ? Type(1) : Type(0));
34821 details::free_all_nodes(*node_allocator_,branch);
34823 return node_allocator_->allocate_c<details::literal_node<Type> >(v);
34825 else if (
34826 details::is_string_node(branch[0]) &&
34827 details::is_string_node(branch[1]) &&
34828 details::is_string_node(branch[2])
34831 std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref();
34832 std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref();
34833 std::string& s2 = static_cast<details::stringvar_node<Type>*>(branch[2])->ref();
34835 typedef typename details::sosos_node<Type, std::string&, std::string&, std::string&, details::inrange_op<Type> > inrange_t;
34837 return node_allocator_->allocate_type<inrange_t, std::string&, std::string&, std::string&>(s0, s1, s2);
34839 else if (
34840 details::is_const_string_node(branch[0]) &&
34841 details::is_string_node(branch[1]) &&
34842 details::is_const_string_node(branch[2])
34845 std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
34846 std::string& s1 = static_cast< details::stringvar_node<Type>*>(branch[1])->ref();
34847 std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();
34849 typedef typename details::sosos_node<Type, std::string, std::string&, std::string, details::inrange_op<Type> > inrange_t;
34851 details::free_node(*node_allocator_,branch[0]);
34852 details::free_node(*node_allocator_,branch[2]);
34854 return node_allocator_->allocate_type<inrange_t, std::string, std::string&, std::string>(s0, s1, s2);
34856 else if (
34857 details::is_string_node(branch[0]) &&
34858 details::is_const_string_node(branch[1]) &&
34859 details::is_string_node(branch[2])
34862 std::string& s0 = static_cast< details::stringvar_node<Type>*>(branch[0])->ref();
34863 std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
34864 std::string& s2 = static_cast< details::stringvar_node<Type>*>(branch[2])->ref();
34866 typedef typename details::sosos_node<Type, std::string&, std::string, std::string&, details::inrange_op<Type> > inrange_t;
34868 details::free_node(*node_allocator_,branch[1]);
34870 return node_allocator_->allocate_type<inrange_t, std::string&, std::string, std::string&>(s0, s1, s2);
34872 else if (
34873 details::is_string_node(branch[0]) &&
34874 details::is_string_node(branch[1]) &&
34875 details::is_const_string_node(branch[2])
34878 std::string& s0 = static_cast< details::stringvar_node<Type>*>(branch[0])->ref();
34879 std::string& s1 = static_cast< details::stringvar_node<Type>*>(branch[1])->ref();
34880 std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();
34882 typedef typename details::sosos_node<Type, std::string&, std::string&, std::string, details::inrange_op<Type> > inrange_t;
34884 details::free_node(*node_allocator_,branch[2]);
34886 return node_allocator_->allocate_type<inrange_t, std::string&, std::string&, std::string>(s0, s1, s2);
34888 else if (
34889 details::is_const_string_node(branch[0]) &&
34890 details:: is_string_node(branch[1]) &&
34891 details:: is_string_node(branch[2])
34894 std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
34895 std::string& s1 = static_cast< details::stringvar_node<Type>*>(branch[1])->ref();
34896 std::string& s2 = static_cast< details::stringvar_node<Type>*>(branch[2])->ref();
34898 typedef typename details::sosos_node<Type, std::string, std::string&, std::string&, details::inrange_op<Type> > inrange_t;
34900 details::free_node(*node_allocator_,branch[0]);
34902 return node_allocator_->allocate_type<inrange_t, std::string, std::string&, std::string&>(s0, s1, s2);
34904 else
34905 return error_node();
34907 #else
34908 inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[3])
34910 details::free_all_nodes(*node_allocator_,branch);
34911 return error_node();
34913 #endif
34915 inline expression_node_ptr synthesize_null_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
34918 Note: The following are the type promotion rules
34919 that relate to operations that include 'null':
34920 0. null ==/!= null --> true false
34921 1. null operation null --> null
34922 2. x ==/!= null --> true/false
34923 3. null ==/!= x --> true/false
34924 4. x operation null --> x
34925 5. null operation x --> x
34928 typedef typename details::null_eq_node<T> nulleq_node_t;
34930 const bool b0_null = details::is_null_node(branch[0]);
34931 const bool b1_null = details::is_null_node(branch[1]);
34933 if (b0_null && b1_null)
34935 expression_node_ptr result = error_node();
34937 if (details::e_eq == operation)
34938 result = node_allocator_->allocate_c<literal_node_t>(T(1));
34939 else if (details::e_ne == operation)
34940 result = node_allocator_->allocate_c<literal_node_t>(T(0));
34942 if (result)
34944 details::free_node(*node_allocator_,branch[0]);
34945 details::free_node(*node_allocator_,branch[1]);
34947 return result;
34950 details::free_node(*node_allocator_,branch[1]);
34952 return branch[0];
34954 else if (details::e_eq == operation)
34956 expression_node_ptr result = node_allocator_->
34957 allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],true);
34959 details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]);
34961 return result;
34963 else if (details::e_ne == operation)
34965 expression_node_ptr result = node_allocator_->
34966 allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],false);
34968 details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]);
34970 return result;
34972 else if (b0_null)
34974 details::free_node(*node_allocator_,branch[0]);
34975 branch[0] = branch[1];
34976 branch[1] = error_node();
34978 else if (b1_null)
34980 details::free_node(*node_allocator_,branch[1]);
34981 branch[1] = error_node();
34984 if (
34985 (details::e_add == operation) || (details::e_sub == operation) ||
34986 (details::e_mul == operation) || (details::e_div == operation) ||
34987 (details::e_mod == operation) || (details::e_pow == operation)
34990 return branch[0];
34992 else if (
34993 (details::e_lt == operation) || (details::e_lte == operation) ||
34994 (details::e_gt == operation) || (details::e_gte == operation) ||
34995 (details::e_and == operation) || (details::e_nand == operation) ||
34996 (details::e_or == operation) || (details::e_nor == operation) ||
34997 (details::e_xor == operation) || (details::e_xnor == operation) ||
34998 (details::e_in == operation) || (details::e_like == operation) ||
34999 (details::e_ilike == operation)
35002 return node_allocator_->allocate_c<literal_node_t>(T(0));
35005 details::free_node(*node_allocator_,branch[0]);
35007 return node_allocator_->allocate<details::null_node<Type> >();
35010 template <typename NodeType, std::size_t N>
35011 inline expression_node_ptr synthesize_expression(const details::operator_type& operation, expression_node_ptr (&branch)[N])
35013 if (
35014 (details::e_in == operation) ||
35015 (details::e_like == operation) ||
35016 (details::e_ilike == operation)
35019 free_all_nodes(*node_allocator_,branch);
35021 return error_node();
35023 else if (!details::all_nodes_valid<N>(branch))
35025 free_all_nodes(*node_allocator_,branch);
35027 return error_node();
35029 else if ((details::e_default != operation))
35031 // Attempt simple constant folding optimisation.
35032 expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(operation,branch);
35034 if (is_constant_foldable<N>(branch))
35036 const Type v = expression_point->value();
35037 details::free_node(*node_allocator_,expression_point);
35039 return node_allocator_->allocate<literal_node_t>(v);
35041 else
35042 return expression_point;
35044 else
35045 return error_node();
35048 template <typename NodeType, std::size_t N>
35049 inline expression_node_ptr synthesize_expression(F* f, expression_node_ptr (&branch)[N])
35051 if (!details::all_nodes_valid<N>(branch))
35053 free_all_nodes(*node_allocator_,branch);
35055 return error_node();
35058 typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t;
35060 // Attempt simple constant folding optimisation.
35062 expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(f);
35063 function_N_node_t* func_node_ptr = dynamic_cast<function_N_node_t*>(expression_point);
35065 if (0 == func_node_ptr)
35067 free_all_nodes(*node_allocator_,branch);
35069 return error_node();
35071 else
35072 func_node_ptr->init_branches(branch);
35074 if (is_constant_foldable<N>(branch) && !f->has_side_effects())
35076 Type v = expression_point->value();
35077 details::free_node(*node_allocator_,expression_point);
35079 return node_allocator_->allocate<literal_node_t>(v);
35082 parser_->state_.activate_side_effect("synthesize_expression(function<NT,N>)");
35084 return expression_point;
35087 bool strength_reduction_enabled_;
35088 details::node_allocator* node_allocator_;
35089 synthesize_map_t synthesize_map_;
35090 unary_op_map_t* unary_op_map_;
35091 binary_op_map_t* binary_op_map_;
35092 inv_binary_op_map_t* inv_binary_op_map_;
35093 sf3_map_t* sf3_map_;
35094 sf4_map_t* sf4_map_;
35095 parser_t* parser_;
35098 inline void set_error(const parser_error::type& error_type)
35100 error_list_.push_back(error_type);
35103 inline void remove_last_error()
35105 if (!error_list_.empty())
35107 error_list_.pop_back();
35111 inline void set_synthesis_error(const std::string& synthesis_error_message)
35113 if (synthesis_error_.empty())
35115 synthesis_error_ = synthesis_error_message;
35119 inline void register_local_vars(expression<T>& e)
35121 for (std::size_t i = 0; i < sem_.size(); ++i)
35123 scope_element& se = sem_.get_element(i);
35125 if (
35126 (scope_element::e_variable == se.type) ||
35127 (scope_element::e_vecelem == se.type)
35130 if (se.var_node)
35132 e.register_local_var(se.var_node);
35135 if (se.data)
35137 e.register_local_data(se.data, 1, 0);
35140 else if (scope_element::e_vector == se.type)
35142 if (se.vec_node)
35144 e.register_local_var(se.vec_node);
35147 if (se.data)
35149 e.register_local_data(se.data, se.size, 1);
35152 #ifndef exprtk_disable_string_capabilities
35153 else if (scope_element::e_string == se.type)
35155 if (se.str_node)
35157 e.register_local_var(se.str_node);
35160 if (se.data)
35162 e.register_local_data(se.data, se.size, 2);
35165 #endif
35167 se.var_node = 0;
35168 se.vec_node = 0;
35169 #ifndef exprtk_disable_string_capabilities
35170 se.str_node = 0;
35171 #endif
35172 se.data = 0;
35173 se.ref_count = 0;
35174 se.active = false;
35178 inline void register_return_results(expression<T>& e)
35180 e.register_return_results(results_context_);
35181 results_context_ = 0;
35184 inline void load_unary_operations_map(unary_op_map_t& m)
35186 #define register_unary_op(Op,UnaryFunctor) \
35187 m.insert(std::make_pair(Op,UnaryFunctor<T>::process)); \
35189 register_unary_op(details:: e_abs, details:: abs_op)
35190 register_unary_op(details:: e_acos, details:: acos_op)
35191 register_unary_op(details::e_acosh, details::acosh_op)
35192 register_unary_op(details:: e_asin, details:: asin_op)
35193 register_unary_op(details::e_asinh, details::asinh_op)
35194 register_unary_op(details::e_atanh, details::atanh_op)
35195 register_unary_op(details:: e_ceil, details:: ceil_op)
35196 register_unary_op(details:: e_cos, details:: cos_op)
35197 register_unary_op(details:: e_cosh, details:: cosh_op)
35198 register_unary_op(details:: e_exp, details:: exp_op)
35199 register_unary_op(details::e_expm1, details::expm1_op)
35200 register_unary_op(details::e_floor, details::floor_op)
35201 register_unary_op(details:: e_log, details:: log_op)
35202 register_unary_op(details::e_log10, details::log10_op)
35203 register_unary_op(details:: e_log2, details:: log2_op)
35204 register_unary_op(details::e_log1p, details::log1p_op)
35205 register_unary_op(details:: e_neg, details:: neg_op)
35206 register_unary_op(details:: e_pos, details:: pos_op)
35207 register_unary_op(details::e_round, details::round_op)
35208 register_unary_op(details:: e_sin, details:: sin_op)
35209 register_unary_op(details:: e_sinc, details:: sinc_op)
35210 register_unary_op(details:: e_sinh, details:: sinh_op)
35211 register_unary_op(details:: e_sqrt, details:: sqrt_op)
35212 register_unary_op(details:: e_tan, details:: tan_op)
35213 register_unary_op(details:: e_tanh, details:: tanh_op)
35214 register_unary_op(details:: e_cot, details:: cot_op)
35215 register_unary_op(details:: e_sec, details:: sec_op)
35216 register_unary_op(details:: e_csc, details:: csc_op)
35217 register_unary_op(details:: e_r2d, details:: r2d_op)
35218 register_unary_op(details:: e_d2r, details:: d2r_op)
35219 register_unary_op(details:: e_d2g, details:: d2g_op)
35220 register_unary_op(details:: e_g2d, details:: g2d_op)
35221 register_unary_op(details:: e_notl, details:: notl_op)
35222 register_unary_op(details:: e_sgn, details:: sgn_op)
35223 register_unary_op(details:: e_erf, details:: erf_op)
35224 register_unary_op(details:: e_erfc, details:: erfc_op)
35225 register_unary_op(details:: e_ncdf, details:: ncdf_op)
35226 register_unary_op(details:: e_frac, details:: frac_op)
35227 register_unary_op(details::e_trunc, details::trunc_op)
35228 #undef register_unary_op
35231 inline void load_binary_operations_map(binary_op_map_t& m)
35233 typedef typename binary_op_map_t::value_type value_type;
35235 #define register_binary_op(Op,BinaryFunctor) \
35236 m.insert(value_type(Op,BinaryFunctor<T>::process)); \
35238 register_binary_op(details:: e_add, details:: add_op)
35239 register_binary_op(details:: e_sub, details:: sub_op)
35240 register_binary_op(details:: e_mul, details:: mul_op)
35241 register_binary_op(details:: e_div, details:: div_op)
35242 register_binary_op(details:: e_mod, details:: mod_op)
35243 register_binary_op(details:: e_pow, details:: pow_op)
35244 register_binary_op(details:: e_lt, details:: lt_op)
35245 register_binary_op(details:: e_lte, details:: lte_op)
35246 register_binary_op(details:: e_gt, details:: gt_op)
35247 register_binary_op(details:: e_gte, details:: gte_op)
35248 register_binary_op(details:: e_eq, details:: eq_op)
35249 register_binary_op(details:: e_ne, details:: ne_op)
35250 register_binary_op(details:: e_and, details:: and_op)
35251 register_binary_op(details::e_nand, details::nand_op)
35252 register_binary_op(details:: e_or, details:: or_op)
35253 register_binary_op(details:: e_nor, details:: nor_op)
35254 register_binary_op(details:: e_xor, details:: xor_op)
35255 register_binary_op(details::e_xnor, details::xnor_op)
35256 #undef register_binary_op
35259 inline void load_inv_binary_operations_map(inv_binary_op_map_t& m)
35261 typedef typename inv_binary_op_map_t::value_type value_type;
35263 #define register_binary_op(Op,BinaryFunctor) \
35264 m.insert(value_type(BinaryFunctor<T>::process,Op)); \
35266 register_binary_op(details:: e_add, details:: add_op)
35267 register_binary_op(details:: e_sub, details:: sub_op)
35268 register_binary_op(details:: e_mul, details:: mul_op)
35269 register_binary_op(details:: e_div, details:: div_op)
35270 register_binary_op(details:: e_mod, details:: mod_op)
35271 register_binary_op(details:: e_pow, details:: pow_op)
35272 register_binary_op(details:: e_lt, details:: lt_op)
35273 register_binary_op(details:: e_lte, details:: lte_op)
35274 register_binary_op(details:: e_gt, details:: gt_op)
35275 register_binary_op(details:: e_gte, details:: gte_op)
35276 register_binary_op(details:: e_eq, details:: eq_op)
35277 register_binary_op(details:: e_ne, details:: ne_op)
35278 register_binary_op(details:: e_and, details:: and_op)
35279 register_binary_op(details::e_nand, details::nand_op)
35280 register_binary_op(details:: e_or, details:: or_op)
35281 register_binary_op(details:: e_nor, details:: nor_op)
35282 register_binary_op(details:: e_xor, details:: xor_op)
35283 register_binary_op(details::e_xnor, details::xnor_op)
35284 #undef register_binary_op
35287 inline void load_sf3_map(sf3_map_t& sf3_map)
35289 typedef std::pair<trinary_functor_t,details::operator_type> pair_t;
35291 #define register_sf3(Op) \
35292 sf3_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \
35294 register_sf3(00) register_sf3(01) register_sf3(02) register_sf3(03)
35295 register_sf3(04) register_sf3(05) register_sf3(06) register_sf3(07)
35296 register_sf3(08) register_sf3(09) register_sf3(10) register_sf3(11)
35297 register_sf3(12) register_sf3(13) register_sf3(14) register_sf3(15)
35298 register_sf3(16) register_sf3(17) register_sf3(18) register_sf3(19)
35299 register_sf3(20) register_sf3(21) register_sf3(22) register_sf3(23)
35300 register_sf3(24) register_sf3(25) register_sf3(26) register_sf3(27)
35301 register_sf3(28) register_sf3(29) register_sf3(30)
35302 #undef register_sf3
35304 #define register_sf3_extid(Id, Op) \
35305 sf3_map[Id] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \
35307 register_sf3_extid("(t-t)-t",23) // (t-t)-t --> t-(t+t)
35308 #undef register_sf3_extid
35311 inline void load_sf4_map(sf4_map_t& sf4_map)
35313 typedef std::pair<quaternary_functor_t,details::operator_type> pair_t;
35315 #define register_sf4(Op) \
35316 sf4_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \
35318 register_sf4(48) register_sf4(49) register_sf4(50) register_sf4(51)
35319 register_sf4(52) register_sf4(53) register_sf4(54) register_sf4(55)
35320 register_sf4(56) register_sf4(57) register_sf4(58) register_sf4(59)
35321 register_sf4(60) register_sf4(61) register_sf4(62) register_sf4(63)
35322 register_sf4(64) register_sf4(65) register_sf4(66) register_sf4(67)
35323 register_sf4(68) register_sf4(69) register_sf4(70) register_sf4(71)
35324 register_sf4(72) register_sf4(73) register_sf4(74) register_sf4(75)
35325 register_sf4(76) register_sf4(77) register_sf4(78) register_sf4(79)
35326 register_sf4(80) register_sf4(81) register_sf4(82) register_sf4(83)
35327 #undef register_sf4
35329 #define register_sf4ext(Op) \
35330 sf4_map[details::sfext##Op##_op<T>::id()] = pair_t(details::sfext##Op##_op<T>::process,details::e_sf4ext##Op); \
35332 register_sf4ext(00) register_sf4ext(01) register_sf4ext(02) register_sf4ext(03)
35333 register_sf4ext(04) register_sf4ext(05) register_sf4ext(06) register_sf4ext(07)
35334 register_sf4ext(08) register_sf4ext(09) register_sf4ext(10) register_sf4ext(11)
35335 register_sf4ext(12) register_sf4ext(13) register_sf4ext(14) register_sf4ext(15)
35336 register_sf4ext(16) register_sf4ext(17) register_sf4ext(18) register_sf4ext(19)
35337 register_sf4ext(20) register_sf4ext(21) register_sf4ext(22) register_sf4ext(23)
35338 register_sf4ext(24) register_sf4ext(25) register_sf4ext(26) register_sf4ext(27)
35339 register_sf4ext(28) register_sf4ext(29) register_sf4ext(30) register_sf4ext(31)
35340 register_sf4ext(32) register_sf4ext(33) register_sf4ext(34) register_sf4ext(35)
35341 register_sf4ext(36) register_sf4ext(36) register_sf4ext(38) register_sf4ext(39)
35342 register_sf4ext(40) register_sf4ext(41) register_sf4ext(42) register_sf4ext(43)
35343 register_sf4ext(44) register_sf4ext(45) register_sf4ext(46) register_sf4ext(47)
35344 register_sf4ext(48) register_sf4ext(49) register_sf4ext(50) register_sf4ext(51)
35345 register_sf4ext(52) register_sf4ext(53) register_sf4ext(54) register_sf4ext(55)
35346 register_sf4ext(56) register_sf4ext(57) register_sf4ext(58) register_sf4ext(59)
35347 register_sf4ext(60) register_sf4ext(61)
35348 #undef register_sf4ext
35351 inline results_context_t& results_ctx()
35353 if (0 == results_context_)
35355 results_context_ = new results_context_t();
35358 return (*results_context_);
35361 inline void return_cleanup()
35363 #ifndef exprtk_disable_return_statement
35364 if (results_context_)
35366 delete results_context_;
35367 results_context_ = 0;
35370 state_.return_stmt_present = false;
35371 #endif
35374 private:
35376 parser(const parser<T>&);
35377 parser<T>& operator=(const parser<T>&);
35379 settings_store settings_;
35380 expression_generator<T> expression_generator_;
35381 details::node_allocator node_allocator_;
35382 symtab_store symtab_store_;
35383 dependent_entity_collector dec_;
35384 std::deque<parser_error::type> error_list_;
35385 std::deque<bool> brkcnt_list_;
35386 parser_state state_;
35387 bool resolve_unknown_symbol_;
35388 results_context_t* results_context_;
35389 unknown_symbol_resolver* unknown_symbol_resolver_;
35390 unknown_symbol_resolver default_usr_;
35391 base_ops_map_t base_ops_map_;
35392 unary_op_map_t unary_op_map_;
35393 binary_op_map_t binary_op_map_;
35394 inv_binary_op_map_t inv_binary_op_map_;
35395 sf3_map_t sf3_map_;
35396 sf4_map_t sf4_map_;
35397 std::string synthesis_error_;
35398 scope_element_manager sem_;
35400 lexer::helper::helper_assembly helper_assembly_;
35402 lexer::helper::commutative_inserter commutative_inserter_;
35403 lexer::helper::operator_joiner operator_joiner_2_;
35404 lexer::helper::operator_joiner operator_joiner_3_;
35405 lexer::helper::symbol_replacer symbol_replacer_;
35406 lexer::helper::bracket_checker bracket_checker_;
35407 lexer::helper::numeric_checker numeric_checker_;
35408 lexer::helper::sequence_validator sequence_validator_;
35409 lexer::helper::sequence_validator_3tokens sequence_validator_3tkns_;
35411 template <typename ParserType>
35412 friend void details::disable_type_checking(ParserType& p);
35415 namespace details
35417 template <typename T>
35418 struct collector_helper
35420 typedef exprtk::symbol_table<T> symbol_table_t;
35421 typedef exprtk::expression<T> expression_t;
35422 typedef exprtk::parser<T> parser_t;
35423 typedef typename parser_t::dependent_entity_collector::symbol_t symbol_t;
35424 typedef typename parser_t::unknown_symbol_resolver usr_t;
35426 struct resolve_as_vector : public parser_t::unknown_symbol_resolver
35428 typedef exprtk::parser<T> parser_t;
35430 resolve_as_vector()
35431 : usr_t(usr_t::e_usrmode_extended)
35434 virtual bool process(const std::string& unknown_symbol,
35435 symbol_table_t& symbol_table,
35436 std::string&)
35438 static T v[1];
35439 symbol_table.add_vector(unknown_symbol,v);
35440 return true;
35444 static inline bool collection_pass(const std::string& expression_string,
35445 std::set<std::string>& symbol_set,
35446 const bool collect_variables,
35447 const bool collect_functions,
35448 const bool vector_pass,
35449 symbol_table_t& ext_symbol_table)
35451 symbol_table_t symbol_table;
35452 expression_t expression;
35453 parser_t parser;
35455 resolve_as_vector vect_resolver;
35457 expression.register_symbol_table(symbol_table );
35458 expression.register_symbol_table(ext_symbol_table);
35460 if (vector_pass)
35461 parser.enable_unknown_symbol_resolver(&vect_resolver);
35462 else
35463 parser.enable_unknown_symbol_resolver();
35465 if (collect_variables)
35466 parser.dec().collect_variables() = true;
35468 if (collect_functions)
35469 parser.dec().collect_functions() = true;
35471 bool pass_result = false;
35473 details::disable_type_checking(parser);
35475 if (parser.compile(expression_string, expression))
35477 pass_result = true;
35479 std::deque<symbol_t> symb_list;
35480 parser.dec().symbols(symb_list);
35482 for (std::size_t i = 0; i < symb_list.size(); ++i)
35484 symbol_set.insert(symb_list[i].first);
35488 return pass_result;
35493 template <typename Allocator,
35494 template <typename, typename> class Sequence>
35495 inline bool collect_variables(const std::string& expression,
35496 Sequence<std::string, Allocator>& symbol_list)
35498 typedef double T;
35499 typedef details::collector_helper<T> collect_t;
35501 collect_t::symbol_table_t null_symbol_table;
35503 std::set<std::string> symbol_set;
35505 const bool variable_pass = collect_t::collection_pass
35506 (expression, symbol_set, true, false, false, null_symbol_table);
35507 const bool vector_pass = collect_t::collection_pass
35508 (expression, symbol_set, true, false, true, null_symbol_table);
35510 if (!variable_pass && !vector_pass)
35511 return false;
35513 std::set<std::string>::iterator itr = symbol_set.begin();
35515 while (symbol_set.end() != itr)
35517 symbol_list.push_back(*itr);
35518 ++itr;
35521 return true;
35524 template <typename T,
35525 typename Allocator,
35526 template <typename, typename> class Sequence>
35527 inline bool collect_variables(const std::string& expression,
35528 exprtk::symbol_table<T>& extrnl_symbol_table,
35529 Sequence<std::string, Allocator>& symbol_list)
35531 typedef details::collector_helper<T> collect_t;
35533 std::set<std::string> symbol_set;
35535 const bool variable_pass = collect_t::collection_pass
35536 (expression, symbol_set, true, false, false, extrnl_symbol_table);
35537 const bool vector_pass = collect_t::collection_pass
35538 (expression, symbol_set, true, false, true, extrnl_symbol_table);
35540 if (!variable_pass && !vector_pass)
35541 return false;
35543 std::set<std::string>::iterator itr = symbol_set.begin();
35545 while (symbol_set.end() != itr)
35547 symbol_list.push_back(*itr);
35548 ++itr;
35551 return true;
35554 template <typename Allocator,
35555 template <typename, typename> class Sequence>
35556 inline bool collect_functions(const std::string& expression,
35557 Sequence<std::string, Allocator>& symbol_list)
35559 typedef double T;
35560 typedef details::collector_helper<T> collect_t;
35562 collect_t::symbol_table_t null_symbol_table;
35564 std::set<std::string> symbol_set;
35566 const bool variable_pass = collect_t::collection_pass
35567 (expression, symbol_set, false, true, false, null_symbol_table);
35568 const bool vector_pass = collect_t::collection_pass
35569 (expression, symbol_set, false, true, true, null_symbol_table);
35571 if (!variable_pass && !vector_pass)
35572 return false;
35574 std::set<std::string>::iterator itr = symbol_set.begin();
35576 while (symbol_set.end() != itr)
35578 symbol_list.push_back(*itr);
35579 ++itr;
35582 return true;
35585 template <typename T,
35586 typename Allocator,
35587 template <typename, typename> class Sequence>
35588 inline bool collect_functions(const std::string& expression,
35589 exprtk::symbol_table<T>& extrnl_symbol_table,
35590 Sequence<std::string, Allocator>& symbol_list)
35592 typedef details::collector_helper<T> collect_t;
35594 std::set<std::string> symbol_set;
35596 const bool variable_pass = collect_t::collection_pass
35597 (expression, symbol_set, false, true, false, extrnl_symbol_table);
35598 const bool vector_pass = collect_t::collection_pass
35599 (expression, symbol_set, false, true, true, extrnl_symbol_table);
35601 if (!variable_pass && !vector_pass)
35602 return false;
35604 std::set<std::string>::iterator itr = symbol_set.begin();
35606 while (symbol_set.end() != itr)
35608 symbol_list.push_back(*itr);
35609 ++itr;
35612 return true;
35615 template <typename T>
35616 inline T integrate(const expression<T>& e,
35617 T& x,
35618 const T& r0, const T& r1,
35619 const std::size_t number_of_intervals = 1000000)
35621 if (r0 > r1)
35622 return T(0);
35624 const T h = (r1 - r0) / (T(2) * number_of_intervals);
35625 T total_area = T(0);
35627 for (std::size_t i = 0; i < number_of_intervals; ++i)
35629 x = r0 + T(2) * i * h;
35630 const T y0 = e.value(); x += h;
35631 const T y1 = e.value(); x += h;
35632 const T y2 = e.value(); x += h;
35633 total_area += h * (y0 + T(4) * y1 + y2) / T(3);
35636 return total_area;
35639 template <typename T>
35640 inline T integrate(const expression<T>& e,
35641 const std::string& variable_name,
35642 const T& r0, const T& r1,
35643 const std::size_t number_of_intervals = 1000000)
35645 const symbol_table<T>& sym_table = e.get_symbol_table();
35647 if (!sym_table.valid())
35648 return std::numeric_limits<T>::quiet_NaN();
35650 details::variable_node<T>* var = sym_table.get_variable(variable_name);
35652 if (var)
35654 T& x = var->ref();
35655 T x_original = x;
35656 T result = integrate(e, x, r0, r1, number_of_intervals);
35657 x = x_original;
35659 return result;
35661 else
35662 return std::numeric_limits<T>::quiet_NaN();
35665 template <typename T>
35666 inline T derivative(const expression<T>& e,
35667 T& x,
35668 const T& h = T(0.00000001))
35670 const T x_init = x;
35671 const T _2h = T(2) * h;
35673 x = x_init + _2h;
35674 const T y0 = e.value();
35675 x = x_init + h;
35676 const T y1 = e.value();
35677 x = x_init - h;
35678 const T y2 = e.value();
35679 x = x_init - _2h;
35680 const T y3 = e.value();
35681 x = x_init;
35683 return (-y0 + T(8) * (y1 - y2) + y3) / (T(12) * h);
35686 template <typename T>
35687 inline T second_derivative(const expression<T>& e,
35688 T& x,
35689 const T& h = T(0.00001))
35691 const T x_init = x;
35692 const T _2h = T(2) * h;
35694 const T y = e.value();
35695 x = x_init + _2h;
35696 const T y0 = e.value();
35697 x = x_init + h;
35698 const T y1 = e.value();
35699 x = x_init - h;
35700 const T y2 = e.value();
35701 x = x_init - _2h;
35702 const T y3 = e.value();
35703 x = x_init;
35705 return (-y0 + T(16) * (y1 + y2) - T(30) * y - y3) / (T(12) * h * h);
35708 template <typename T>
35709 inline T third_derivative(const expression<T>& e,
35710 T& x,
35711 const T& h = T(0.0001))
35713 const T x_init = x;
35714 const T _2h = T(2) * h;
35716 x = x_init + _2h;
35717 const T y0 = e.value();
35718 x = x_init + h;
35719 const T y1 = e.value();
35720 x = x_init - h;
35721 const T y2 = e.value();
35722 x = x_init - _2h;
35723 const T y3 = e.value();
35724 x = x_init;
35726 return (y0 + T(2) * (y2 - y1) - y3) / (T(2) * h * h * h);
35729 template <typename T>
35730 inline T derivative(const expression<T>& e,
35731 const std::string& variable_name,
35732 const T& h = T(0.00000001))
35734 const symbol_table<T>& sym_table = e.get_symbol_table();
35736 if (!sym_table.valid())
35738 return std::numeric_limits<T>::quiet_NaN();
35741 details::variable_node<T>* var = sym_table.get_variable(variable_name);
35743 if (var)
35745 T& x = var->ref();
35746 T x_original = x;
35747 T result = derivative(e, x, h);
35748 x = x_original;
35750 return result;
35752 else
35753 return std::numeric_limits<T>::quiet_NaN();
35756 template <typename T>
35757 inline T second_derivative(const expression<T>& e,
35758 const std::string& variable_name,
35759 const T& h = T(0.00001))
35761 const symbol_table<T>& sym_table = e.get_symbol_table();
35763 if (!sym_table.valid())
35765 return std::numeric_limits<T>::quiet_NaN();
35768 details::variable_node<T>* var = sym_table.get_variable(variable_name);
35770 if (var)
35772 T& x = var->ref();
35773 const T x_original = x;
35774 const T result = second_derivative(e, x, h);
35775 x = x_original;
35777 return result;
35779 else
35780 return std::numeric_limits<T>::quiet_NaN();
35783 template <typename T>
35784 inline T third_derivative(const expression<T>& e,
35785 const std::string& variable_name,
35786 const T& h = T(0.0001))
35788 const symbol_table<T>& sym_table = e.get_symbol_table();
35790 if (!sym_table.valid())
35792 return std::numeric_limits<T>::quiet_NaN();
35795 details::variable_node<T>* var = sym_table.get_variable(variable_name);
35797 if (var)
35799 T& x = var->ref();
35800 const T x_original = x;
35801 const T result = third_derivative(e, x, h);
35802 x = x_original;
35804 return result;
35806 else
35807 return std::numeric_limits<T>::quiet_NaN();
35811 Note: The following 'compute' routines are simple helpers,
35812 for quickly setting up the required pieces of code in order
35813 to evaluate an expression. By virtue of how they operate
35814 there will be an overhead with regards to their setup and
35815 teardown and hence should not be used in time critical
35816 sections of code.
35817 Furthermore they only assume a small sub set of variables,
35818 no string variables or user defined functions.
35820 template <typename T>
35821 inline bool compute(const std::string& expression_string, T& result)
35823 // No variables
35824 symbol_table<T> symbol_table;
35825 symbol_table.add_constants();
35827 expression<T> expression;
35828 expression.register_symbol_table(symbol_table);
35830 parser<T> parser;
35832 if (parser.compile(expression_string,expression))
35834 result = expression.value();
35836 return true;
35838 else
35839 return false;
35842 template <typename T>
35843 inline bool compute(const std::string& expression_string,
35844 const T& x,
35845 T& result)
35847 // Only 'x'
35848 static const std::string x_var("x");
35850 symbol_table<T> symbol_table;
35851 symbol_table.add_constants();
35852 symbol_table.add_constant(x_var,x);
35854 expression<T> expression;
35855 expression.register_symbol_table(symbol_table);
35857 parser<T> parser;
35859 if (parser.compile(expression_string,expression))
35861 result = expression.value();
35863 return true;
35865 else
35866 return false;
35869 template <typename T>
35870 inline bool compute(const std::string& expression_string,
35871 const T&x, const T& y,
35872 T& result)
35874 // Only 'x' and 'y'
35875 static const std::string x_var("x");
35876 static const std::string y_var("y");
35878 symbol_table<T> symbol_table;
35879 symbol_table.add_constants();
35880 symbol_table.add_constant(x_var,x);
35881 symbol_table.add_constant(y_var,y);
35883 expression<T> expression;
35884 expression.register_symbol_table(symbol_table);
35886 parser<T> parser;
35888 if (parser.compile(expression_string,expression))
35890 result = expression.value();
35892 return true;
35894 else
35895 return false;
35898 template <typename T>
35899 inline bool compute(const std::string& expression_string,
35900 const T& x, const T& y, const T& z,
35901 T& result)
35903 // Only 'x', 'y' or 'z'
35904 static const std::string x_var("x");
35905 static const std::string y_var("y");
35906 static const std::string z_var("z");
35908 symbol_table<T> symbol_table;
35909 symbol_table.add_constants();
35910 symbol_table.add_constant(x_var,x);
35911 symbol_table.add_constant(y_var,y);
35912 symbol_table.add_constant(z_var,z);
35914 expression<T> expression;
35915 expression.register_symbol_table(symbol_table);
35917 parser<T> parser;
35919 if (parser.compile(expression_string,expression))
35921 result = expression.value();
35923 return true;
35925 else
35926 return false;
35929 template <typename T, std::size_t N>
35930 class polynomial : public ifunction<T>
35932 private:
35934 template <typename Type, std::size_t NumberOfCoefficients>
35935 struct poly_impl { };
35937 template <typename Type>
35938 struct poly_impl <Type,12>
35940 static inline T evaluate(const Type x,
35941 const Type c12, const Type c11, const Type c10, const Type c9, const Type c8,
35942 const Type c7, const Type c6, const Type c5, const Type c4, const Type c3,
35943 const Type c2, const Type c1, const Type c0)
35945 // p(x) = c_12x^12 + c_11x^11 + c_10x^10 + c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
35946 return ((((((((((((c12 * x + c11) * x + c10) * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
35950 template <typename Type>
35951 struct poly_impl <Type,11>
35953 static inline T evaluate(const Type x,
35954 const Type c11, const Type c10, const Type c9, const Type c8, const Type c7,
35955 const Type c6, const Type c5, const Type c4, const Type c3, const Type c2,
35956 const Type c1, const Type c0)
35958 // p(x) = c_11x^11 + c_10x^10 + c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
35959 return (((((((((((c11 * x + c10) * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
35963 template <typename Type>
35964 struct poly_impl <Type,10>
35966 static inline T evaluate(const Type x,
35967 const Type c10, const Type c9, const Type c8, const Type c7, const Type c6,
35968 const Type c5, const Type c4, const Type c3, const Type c2, const Type c1,
35969 const Type c0)
35971 // p(x) = c_10x^10 + c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
35972 return ((((((((((c10 * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
35976 template <typename Type>
35977 struct poly_impl <Type,9>
35979 static inline T evaluate(const Type x,
35980 const Type c9, const Type c8, const Type c7, const Type c6, const Type c5,
35981 const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
35983 // p(x) = c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
35984 return (((((((((c9 * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
35988 template <typename Type>
35989 struct poly_impl <Type,8>
35991 static inline T evaluate(const Type x,
35992 const Type c8, const Type c7, const Type c6, const Type c5, const Type c4,
35993 const Type c3, const Type c2, const Type c1, const Type c0)
35995 // p(x) = c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
35996 return ((((((((c8 * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
36000 template <typename Type>
36001 struct poly_impl <Type,7>
36003 static inline T evaluate(const Type x,
36004 const Type c7, const Type c6, const Type c5, const Type c4, const Type c3,
36005 const Type c2, const Type c1, const Type c0)
36007 // p(x) = c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
36008 return (((((((c7 * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
36012 template <typename Type>
36013 struct poly_impl <Type,6>
36015 static inline T evaluate(const Type x,
36016 const Type c6, const Type c5, const Type c4, const Type c3, const Type c2,
36017 const Type c1, const Type c0)
36019 // p(x) = c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
36020 return ((((((c6 * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
36024 template <typename Type>
36025 struct poly_impl <Type,5>
36027 static inline T evaluate(const Type x,
36028 const Type c5, const Type c4, const Type c3, const Type c2,
36029 const Type c1, const Type c0)
36031 // p(x) = c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
36032 return (((((c5 * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
36036 template <typename Type>
36037 struct poly_impl <Type,4>
36039 static inline T evaluate(const Type x, const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
36041 // p(x) = c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
36042 return ((((c4 * x + c3) * x + c2) * x + c1) * x + c0);
36046 template <typename Type>
36047 struct poly_impl <Type,3>
36049 static inline T evaluate(const Type x, const Type c3, const Type c2, const Type c1, const Type c0)
36051 // p(x) = c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
36052 return (((c3 * x + c2) * x + c1) * x + c0);
36056 template <typename Type>
36057 struct poly_impl <Type,2>
36059 static inline T evaluate(const Type x, const Type c2, const Type c1, const Type c0)
36061 // p(x) = c_2x^2 + c_1x^1 + c_0x^0
36062 return ((c2 * x + c1) * x + c0);
36066 template <typename Type>
36067 struct poly_impl <Type,1>
36069 static inline T evaluate(const Type x, const Type c1, const Type c0)
36071 // p(x) = c_1x^1 + c_0x^0
36072 return (c1 * x + c0);
36076 public:
36078 using ifunction<T>::operator();
36080 polynomial()
36081 : ifunction<T>((N+2 <= 20) ? (N + 2) : std::numeric_limits<std::size_t>::max())
36083 disable_has_side_effects(*this);
36086 virtual ~polynomial()
36089 #define poly_rtrn(NN) \
36090 return (NN != N) ? std::numeric_limits<T>::quiet_NaN() :
36092 inline virtual T operator() (const T& x, const T& c1, const T& c0)
36094 poly_rtrn(1) poly_impl<T,1>::evaluate(x, c1, c0);
36097 inline virtual T operator() (const T& x, const T& c2, const T& c1, const T& c0)
36099 poly_rtrn(2) poly_impl<T,2>::evaluate(x, c2, c1, c0);
36102 inline virtual T operator() (const T& x, const T& c3, const T& c2, const T& c1, const T& c0)
36104 poly_rtrn(3) poly_impl<T,3>::evaluate(x, c3, c2, c1, c0);
36107 inline virtual T operator() (const T& x, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
36109 poly_rtrn(4) poly_impl<T,4>::evaluate(x, c4, c3, c2, c1, c0);
36112 inline virtual T operator() (const T& x, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
36114 poly_rtrn(5) poly_impl<T,5>::evaluate(x, c5, c4, c3, c2, c1, c0);
36117 inline virtual T operator() (const T& x, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
36119 poly_rtrn(6) poly_impl<T,6>::evaluate(x, c6, c5, c4, c3, c2, c1, c0);
36122 inline virtual T operator() (const T& x, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
36124 poly_rtrn(7) poly_impl<T,7>::evaluate(x, c7, c6, c5, c4, c3, c2, c1, c0);
36127 inline virtual T operator() (const T& x, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
36129 poly_rtrn(8) poly_impl<T,8>::evaluate(x, c8, c7, c6, c5, c4, c3, c2, c1, c0);
36132 inline virtual T operator() (const T& x, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
36134 poly_rtrn(9) poly_impl<T,9>::evaluate(x, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0);
36137 inline virtual T operator() (const T& x, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
36139 poly_rtrn(10) poly_impl<T,10>::evaluate(x, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0);
36142 inline virtual T operator() (const T& x, const T& c11, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
36144 poly_rtrn(11) poly_impl<T,11>::evaluate(x, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0);
36147 inline virtual T operator() (const T& x, const T& c12, const T& c11, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
36149 poly_rtrn(12) poly_impl<T,12>::evaluate(x, c12, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0);
36152 #undef poly_rtrn
36154 inline virtual T operator() ()
36156 return std::numeric_limits<T>::quiet_NaN();
36159 inline virtual T operator() (const T&)
36161 return std::numeric_limits<T>::quiet_NaN();
36164 inline virtual T operator() (const T&, const T&)
36166 return std::numeric_limits<T>::quiet_NaN();
36170 template <typename T>
36171 class function_compositor
36173 public:
36175 typedef exprtk::expression<T> expression_t;
36176 typedef exprtk::symbol_table<T> symbol_table_t;
36177 typedef exprtk::parser<T> parser_t;
36178 typedef typename parser_t::settings_store settings_t;
36180 struct function
36182 function()
36185 function(const std::string& n)
36186 : name_(n)
36189 function(const std::string& name,
36190 const std::string& expression)
36191 : name_(name),
36192 expression_(expression)
36195 function(const std::string& name,
36196 const std::string& expression,
36197 const std::string& v0)
36198 : name_(name),
36199 expression_(expression)
36201 v_.push_back(v0);
36204 function(const std::string& name,
36205 const std::string& expression,
36206 const std::string& v0, const std::string& v1)
36207 : name_(name),
36208 expression_(expression)
36210 v_.push_back(v0); v_.push_back(v1);
36213 function(const std::string& name,
36214 const std::string& expression,
36215 const std::string& v0, const std::string& v1,
36216 const std::string& v2)
36217 : name_(name),
36218 expression_(expression)
36220 v_.push_back(v0); v_.push_back(v1);
36221 v_.push_back(v2);
36224 function(const std::string& name,
36225 const std::string& expression,
36226 const std::string& v0, const std::string& v1,
36227 const std::string& v2, const std::string& v3)
36228 : name_(name),
36229 expression_(expression)
36231 v_.push_back(v0); v_.push_back(v1);
36232 v_.push_back(v2); v_.push_back(v3);
36235 function(const std::string& name,
36236 const std::string& expression,
36237 const std::string& v0, const std::string& v1,
36238 const std::string& v2, const std::string& v3,
36239 const std::string& v4)
36240 : name_(name),
36241 expression_(expression)
36243 v_.push_back(v0); v_.push_back(v1);
36244 v_.push_back(v2); v_.push_back(v3);
36245 v_.push_back(v4);
36248 inline function& name(const std::string& n)
36250 name_ = n;
36251 return (*this);
36254 inline function& expression(const std::string& e)
36256 expression_ = e;
36257 return (*this);
36260 inline function& var(const std::string& v)
36262 v_.push_back(v);
36263 return (*this);
36266 std::string name_;
36267 std::string expression_;
36268 std::deque<std::string> v_;
36271 private:
36273 struct base_func : public exprtk::ifunction<T>
36275 typedef const T& type;
36276 typedef exprtk::ifunction<T> function_t;
36277 typedef std::vector<T*> varref_t;
36278 typedef std::vector<T> var_t;
36279 typedef std::pair<T*,std::size_t> lvarref_t;
36280 typedef std::vector<lvarref_t> lvr_vec_t;
36282 using exprtk::ifunction<T>::operator();
36284 base_func(const std::size_t& pc = 0)
36285 : exprtk::ifunction<T>(pc),
36286 local_var_stack_size(0),
36287 stack_depth(0)
36289 v.resize(pc);
36292 virtual ~base_func()
36295 inline void update(const T& v0)
36297 (*v[0]) = v0;
36300 inline void update(const T& v0, const T& v1)
36302 (*v[0]) = v0; (*v[1]) = v1;
36305 inline void update(const T& v0, const T& v1, const T& v2)
36307 (*v[0]) = v0; (*v[1]) = v1;
36308 (*v[2]) = v2;
36311 inline void update(const T& v0, const T& v1, const T& v2, const T& v3)
36313 (*v[0]) = v0; (*v[1]) = v1;
36314 (*v[2]) = v2; (*v[3]) = v3;
36317 inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4)
36319 (*v[0]) = v0; (*v[1]) = v1;
36320 (*v[2]) = v2; (*v[3]) = v3;
36321 (*v[4]) = v4;
36324 inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5)
36326 (*v[0]) = v0; (*v[1]) = v1;
36327 (*v[2]) = v2; (*v[3]) = v3;
36328 (*v[4]) = v4; (*v[5]) = v5;
36331 inline function_t& setup(expression_t& expr)
36333 expression = expr;
36335 typedef typename expression_t::control_block::local_data_list_t ldl_t;
36337 ldl_t ldl = expr.local_data_list();
36339 std::vector<std::size_t> index_list;
36341 for (std::size_t i = 0; i < ldl.size(); ++i)
36343 if (ldl[i].size)
36345 index_list.push_back(i);
36349 std::size_t input_param_count = 0;
36351 for (std::size_t i = 0; i < index_list.size(); ++i)
36353 const std::size_t index = index_list[i];
36355 if (i < (index_list.size() - v.size()))
36357 lv.push_back(
36358 std::make_pair(
36359 reinterpret_cast<T*>(ldl[index].pointer),
36360 ldl[index].size));
36362 local_var_stack_size += ldl[index].size;
36364 else
36365 v[input_param_count++] = reinterpret_cast<T*>(ldl[index].pointer);
36368 clear_stack();
36370 return (*this);
36373 inline void pre()
36375 if (stack_depth++)
36377 if (!v.empty())
36379 var_t var_stack(v.size(),T(0));
36380 copy(v,var_stack);
36381 param_stack.push_back(var_stack);
36384 if (!lv.empty())
36386 var_t local_var_stack(local_var_stack_size,T(0));
36387 copy(lv,local_var_stack);
36388 local_stack.push_back(local_var_stack);
36393 inline void post()
36395 if (--stack_depth)
36397 if (!v.empty())
36399 copy(param_stack.back(),v);
36400 param_stack.pop_back();
36403 if (!lv.empty())
36405 copy(local_stack.back(),lv);
36406 local_stack.pop_back();
36411 void copy(const varref_t& src_v, var_t& dest_v)
36413 for (std::size_t i = 0; i < src_v.size(); ++i)
36415 dest_v[i] = (*src_v[i]);
36419 void copy(const var_t& src_v, varref_t& dest_v)
36421 for (std::size_t i = 0; i < src_v.size(); ++i)
36423 (*dest_v[i]) = src_v[i];
36427 void copy(const lvr_vec_t& src_v, var_t& dest_v)
36429 typename var_t::iterator itr = dest_v.begin();
36430 typedef typename std::iterator_traits<typename var_t::iterator>::difference_type diff_t;
36432 for (std::size_t i = 0; i < src_v.size(); ++i)
36434 lvarref_t vr = src_v[i];
36436 if (1 == vr.second)
36437 *itr++ = (*vr.first);
36438 else
36440 std::copy(vr.first, vr.first + vr.second, itr);
36441 itr += static_cast<diff_t>(vr.second);
36446 void copy(const var_t& src_v, lvr_vec_t& dest_v)
36448 typename var_t::const_iterator itr = src_v.begin();
36449 typedef typename std::iterator_traits<typename var_t::iterator>::difference_type diff_t;
36451 for (std::size_t i = 0; i < src_v.size(); ++i)
36453 lvarref_t vr = dest_v[i];
36455 if (1 == vr.second)
36456 (*vr.first) = *itr++;
36457 else
36459 std::copy(itr, itr + static_cast<diff_t>(vr.second), vr.first);
36460 itr += static_cast<diff_t>(vr.second);
36465 inline void clear_stack()
36467 for (std::size_t i = 0; i < v.size(); ++i)
36469 (*v[i]) = 0;
36473 inline virtual T value(expression_t& e)
36475 return e.value();
36478 expression_t expression;
36479 varref_t v;
36480 lvr_vec_t lv;
36481 std::size_t local_var_stack_size;
36482 std::size_t stack_depth;
36483 std::deque<var_t> param_stack;
36484 std::deque<var_t> local_stack;
36487 typedef std::map<std::string,base_func*> funcparam_t;
36489 struct func_0param : public base_func
36491 using exprtk::ifunction<T>::operator();
36493 func_0param() : base_func(0) {}
36495 inline T operator() ()
36497 return this->value(base_func::expression);
36501 typedef const T& type;
36503 template <typename BaseFuncType>
36504 struct scoped_bft
36506 scoped_bft(BaseFuncType& bft) : bft_(bft) { bft_.pre (); }
36507 ~scoped_bft() { bft_.post(); }
36509 BaseFuncType& bft_;
36511 private:
36513 scoped_bft(scoped_bft&);
36514 scoped_bft& operator=(scoped_bft&);
36517 struct func_1param : public base_func
36519 using exprtk::ifunction<T>::operator();
36521 func_1param() : base_func(1) {}
36523 inline T operator() (type v0)
36525 scoped_bft<func_1param> sb(*this);
36526 base_func::update(v0);
36527 return this->value(base_func::expression);
36531 struct func_2param : public base_func
36533 using exprtk::ifunction<T>::operator();
36535 func_2param() : base_func(2) {}
36537 inline T operator() (type v0, type v1)
36539 scoped_bft<func_2param> sb(*this);
36540 base_func::update(v0, v1);
36541 return this->value(base_func::expression);
36545 struct func_3param : public base_func
36547 using exprtk::ifunction<T>::operator();
36549 func_3param() : base_func(3) {}
36551 inline T operator() (type v0, type v1, type v2)
36553 scoped_bft<func_3param> sb(*this);
36554 base_func::update(v0, v1, v2);
36555 return this->value(base_func::expression);
36559 struct func_4param : public base_func
36561 using exprtk::ifunction<T>::operator();
36563 func_4param() : base_func(4) {}
36565 inline T operator() (type v0, type v1, type v2, type v3)
36567 scoped_bft<func_4param> sb(*this);
36568 base_func::update(v0, v1, v2, v3);
36569 return this->value(base_func::expression);
36573 struct func_5param : public base_func
36575 using exprtk::ifunction<T>::operator();
36577 func_5param() : base_func(5) {}
36579 inline T operator() (type v0, type v1, type v2, type v3, type v4)
36581 scoped_bft<func_5param> sb(*this);
36582 base_func::update(v0, v1, v2, v3, v4);
36583 return this->value(base_func::expression);
36587 struct func_6param : public base_func
36589 using exprtk::ifunction<T>::operator();
36591 func_6param() : base_func(6) {}
36593 inline T operator() (type v0, type v1, type v2, type v3, type v4, type v5)
36595 scoped_bft<func_6param> sb(*this);
36596 base_func::update(v0, v1, v2, v3, v4, v5);
36597 return this->value(base_func::expression);
36601 static T return_value(expression_t& e)
36603 typedef exprtk::results_context<T> results_context_t;
36604 typedef typename results_context_t::type_store_t type_t;
36605 typedef typename type_t::scalar_view scalar_t;
36607 T result = e.value();
36609 if (e.return_invoked())
36611 // Due to the post compilation checks, it can be safely
36612 // assumed that there will be at least one parameter
36613 // and that the first parameter will always be scalar.
36614 return scalar_t(e.results()[0])();
36617 return result;
36620 #define def_fp_retval(N) \
36621 struct func_##N##param_retval : public func_##N##param \
36623 inline T value(expression_t& e) \
36625 return return_value(e); \
36627 }; \
36629 def_fp_retval(0)
36630 def_fp_retval(1)
36631 def_fp_retval(2)
36632 def_fp_retval(3)
36633 def_fp_retval(4)
36634 def_fp_retval(5)
36635 def_fp_retval(6)
36637 template <typename Allocator,
36638 template <typename, typename> class Sequence>
36639 inline bool add(const std::string& name,
36640 const std::string& expression,
36641 const Sequence<std::string,Allocator>& var_list,
36642 const bool override = false)
36644 const typename std::map<std::string,expression_t>::iterator itr = expr_map_.find(name);
36646 if (expr_map_.end() != itr)
36648 if (!override)
36650 exprtk_debug(("Compositor error(add): function '%s' already defined\n",
36651 name.c_str()));
36653 return false;
36656 remove(name, var_list.size());
36659 if (compile_expression(name,expression,var_list))
36661 const std::size_t n = var_list.size();
36663 fp_map_[n][name]->setup(expr_map_[name]);
36665 return true;
36667 else
36669 exprtk_debug(("Compositor error(add): Failed to compile function '%s'\n",
36670 name.c_str()));
36672 return false;
36676 public:
36678 function_compositor()
36679 : parser_(settings_t::compile_all_opts +
36680 settings_t::e_disable_zero_return),
36681 fp_map_(7)
36684 function_compositor(const symbol_table_t& st)
36685 : symbol_table_(st),
36686 parser_(settings_t::compile_all_opts +
36687 settings_t::e_disable_zero_return),
36688 fp_map_(7)
36691 ~function_compositor()
36693 clear();
36696 inline symbol_table_t& symbol_table()
36698 return symbol_table_;
36701 inline void add_auxiliary_symtab(symbol_table_t& symtab)
36703 auxiliary_symtab_list_.push_back(&symtab);
36706 void clear()
36708 symbol_table_.clear();
36709 expr_map_ .clear();
36711 for (std::size_t i = 0; i < fp_map_.size(); ++i)
36713 typename funcparam_t::iterator itr = fp_map_[i].begin();
36714 typename funcparam_t::iterator end = fp_map_[i].end ();
36716 while (itr != end)
36718 delete itr->second;
36719 ++itr;
36722 fp_map_[i].clear();
36726 inline bool add(const function& f, const bool override = false)
36728 return add(f.name_, f.expression_, f.v_,override);
36731 private:
36733 template <typename Allocator,
36734 template <typename, typename> class Sequence>
36735 bool compile_expression(const std::string& name,
36736 const std::string& expression,
36737 const Sequence<std::string,Allocator>& input_var_list,
36738 bool return_present = false)
36740 expression_t compiled_expression;
36741 symbol_table_t local_symbol_table;
36743 local_symbol_table.load_from(symbol_table_);
36744 local_symbol_table.add_constants();
36746 if (!valid(name,input_var_list.size()))
36747 return false;
36749 if (!forward(name,
36750 input_var_list.size(),
36751 local_symbol_table,
36752 return_present))
36753 return false;
36755 compiled_expression.register_symbol_table(local_symbol_table);
36757 for (std::size_t i = 0; i < auxiliary_symtab_list_.size(); ++i)
36759 compiled_expression.register_symbol_table((*auxiliary_symtab_list_[i]));
36762 std::string mod_expression;
36764 for (std::size_t i = 0; i < input_var_list.size(); ++i)
36766 mod_expression += " var " + input_var_list[i] + "{};\n";
36769 if (
36770 ('{' == details::front(expression)) &&
36771 ('}' == details::back (expression))
36773 mod_expression += "~" + expression + ";";
36774 else
36775 mod_expression += "~{" + expression + "};";
36777 if (!parser_.compile(mod_expression,compiled_expression))
36779 exprtk_debug(("Compositor Error: %s\n",parser_.error().c_str()));
36780 exprtk_debug(("Compositor modified expression: \n%s\n",mod_expression.c_str()));
36782 remove(name,input_var_list.size());
36784 return false;
36787 if (!return_present && parser_.dec().return_present())
36789 remove(name,input_var_list.size());
36791 return compile_expression(name, expression, input_var_list, true);
36794 // Make sure every return point has a scalar as its first parameter
36795 if (parser_.dec().return_present())
36797 typedef std::vector<std::string> str_list_t;
36799 str_list_t ret_param_list = parser_.dec().return_param_type_list();
36801 for (std::size_t i = 0; i < ret_param_list.size(); ++i)
36803 const std::string& params = ret_param_list[i];
36805 if (params.empty() || ('T' != params[0]))
36807 exprtk_debug(("Compositor Error: Return statement in function '%s' is invalid\n",
36808 name.c_str()));
36810 remove(name,input_var_list.size());
36812 return false;
36817 expr_map_[name] = compiled_expression;
36819 exprtk::ifunction<T>& ifunc = (*(fp_map_[input_var_list.size()])[name]);
36821 if (symbol_table_.add_function(name,ifunc))
36822 return true;
36823 else
36825 exprtk_debug(("Compositor Error: Failed to add function '%s' to symbol table\n",
36826 name.c_str()));
36827 return false;
36831 inline bool symbol_used(const std::string& symbol) const
36833 return (
36834 symbol_table_.is_variable (symbol) ||
36835 symbol_table_.is_stringvar (symbol) ||
36836 symbol_table_.is_function (symbol) ||
36837 symbol_table_.is_vector (symbol) ||
36838 symbol_table_.is_vararg_function(symbol)
36842 inline bool valid(const std::string& name,
36843 const std::size_t& arg_count) const
36845 if (arg_count > 6)
36846 return false;
36847 else if (symbol_used(name))
36848 return false;
36849 else if (fp_map_[arg_count].end() != fp_map_[arg_count].find(name))
36850 return false;
36851 else
36852 return true;
36855 inline bool forward(const std::string& name,
36856 const std::size_t& arg_count,
36857 symbol_table_t& sym_table,
36858 const bool ret_present = false)
36860 switch (arg_count)
36862 #define case_stmt(N) \
36863 case N : (fp_map_[arg_count])[name] = \
36864 (!ret_present) ? static_cast<base_func*> \
36865 (new func_##N##param) : \
36866 static_cast<base_func*> \
36867 (new func_##N##param_retval) ; \
36868 break; \
36870 case_stmt(0) case_stmt(1) case_stmt(2)
36871 case_stmt(3) case_stmt(4) case_stmt(5)
36872 case_stmt(6)
36873 #undef case_stmt
36876 exprtk::ifunction<T>& ifunc = (*(fp_map_[arg_count])[name]);
36878 return sym_table.add_function(name,ifunc);
36881 inline void remove(const std::string& name, const std::size_t& arg_count)
36883 if (arg_count > 6)
36884 return;
36886 const typename std::map<std::string,expression_t>::iterator em_itr = expr_map_.find(name);
36888 if (expr_map_.end() != em_itr)
36890 expr_map_.erase(em_itr);
36893 const typename funcparam_t::iterator fp_itr = fp_map_[arg_count].find(name);
36895 if (fp_map_[arg_count].end() != fp_itr)
36897 delete fp_itr->second;
36898 fp_map_[arg_count].erase(fp_itr);
36901 symbol_table_.remove_function(name);
36904 private:
36906 symbol_table_t symbol_table_;
36907 parser_t parser_;
36908 std::map<std::string,expression_t> expr_map_;
36909 std::vector<funcparam_t> fp_map_;
36910 std::vector<symbol_table_t*> auxiliary_symtab_list_;
36913 template <typename T>
36914 inline bool pgo_primer()
36916 static const std::string expression_list[] =
36918 "(y + x)",
36919 "2 * (y + x)",
36920 "(2 * y + 2 * x)",
36921 "(y + x / y) * (x - y / x)",
36922 "x / ((x + y) * (x - y)) / y",
36923 "1 - ((x * y) + (y / x)) - 3",
36924 "sin(2 * x) + cos(pi / y)",
36925 "1 - sin(2 * x) + cos(pi / y)",
36926 "sqrt(1 - sin(2 * x) + cos(pi / y) / 3)",
36927 "(x^2 / sin(2 * pi / y)) -x / 2",
36928 "x + (cos(y - sin(2 / x * pi)) - sin(x - cos(2 * y / pi))) - y",
36929 "clamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)",
36930 "iclamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)",
36931 "max(3.33, min(sqrt(1 - sin(2 * x) + cos(pi / y) / 3), 1.11))",
36932 "if(avg(x,y) <= x + y, x - y, x * y) + 2 * pi / x",
36933 "1.1x^1 + 2.2y^2 - 3.3x^3 + 4.4y^4 - 5.5x^5 + 6.6y^6 - 7.7x^27 + 8.8y^55",
36934 "(yy + xx)",
36935 "2 * (yy + xx)",
36936 "(2 * yy + 2 * xx)",
36937 "(yy + xx / yy) * (xx - yy / xx)",
36938 "xx / ((xx + yy) * (xx - yy)) / yy",
36939 "1 - ((xx * yy) + (yy / xx)) - 3",
36940 "sin(2 * xx) + cos(pi / yy)",
36941 "1 - sin(2 * xx) + cos(pi / yy)",
36942 "sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3)",
36943 "(xx^2 / sin(2 * pi / yy)) -xx / 2",
36944 "xx + (cos(yy - sin(2 / xx * pi)) - sin(xx - cos(2 * yy / pi))) - yy",
36945 "clamp(-1.0, sin(2 * pi * xx) + cos(yy / 2 * pi), +1.0)",
36946 "max(3.33, min(sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3), 1.11))",
36947 "if(avg(xx,yy) <= xx + yy, xx - yy, xx * yy) + 2 * pi / xx",
36948 "1.1xx^1 + 2.2yy^2 - 3.3xx^3 + 4.4yy^4 - 5.5xx^5 + 6.6yy^6 - 7.7xx^27 + 8.8yy^55",
36949 "(1.1*(2.2*(3.3*(4.4*(5.5*(6.6*(7.7*(8.8*(9.9+x)))))))))",
36950 "(((((((((x+9.9)*8.8)*7.7)*6.6)*5.5)*4.4)*3.3)*2.2)*1.1)",
36951 "(x + y) * z", "x + (y * z)", "(x + y) * 7", "x + (y * 7)",
36952 "(x + 7) * y", "x + (7 * y)", "(7 + x) * y", "7 + (x * y)",
36953 "(2 + x) * 3", "2 + (x * 3)", "(2 + 3) * x", "2 + (3 * x)",
36954 "(x + 2) * 3", "x + (2 * 3)",
36955 "(x + y) * (z / w)", "(x + y) * (z / 7)", "(x + y) * (7 / z)", "(x + 7) * (y / z)",
36956 "(7 + x) * (y / z)", "(2 + x) * (y / z)", "(x + 2) * (y / 3)", "(2 + x) * (y / 3)",
36957 "(x + 2) * (3 / y)", "x + (y * (z / w))", "x + (y * (z / 7))", "x + (y * (7 / z))",
36958 "x + (7 * (y / z))", "7 + (x * (y / z))", "2 + (x * (3 / y))", "x + (2 * (y / 4))",
36959 "2 + (x * (y / 3))", "x + (2 * (3 / y))",
36960 "x + ((y * z) / w)", "x + ((y * z) / 7)", "x + ((y * 7) / z)", "x + ((7 * y) / z)",
36961 "7 + ((y * z) / w)", "2 + ((x * 3) / y)", "x + ((2 * y) / 3)", "2 + ((x * y) / 3)",
36962 "x + ((2 * 3) / y)", "(((x + y) * z) / w)",
36963 "(((x + y) * z) / 7)", "(((x + y) * 7) / z)", "(((x + 7) * y) / z)", "(((7 + x) * y) / z)",
36964 "(((2 + x) * 3) / y)", "(((x + 2) * y) / 3)", "(((2 + x) * y) / 3)", "(((x + 2) * 3) / y)",
36965 "((x + (y * z)) / w)", "((x + (y * z)) / 7)", "((x + (y * 7)) / y)", "((x + (7 * y)) / z)",
36966 "((7 + (x * y)) / z)", "((2 + (x * 3)) / y)", "((x + (2 * y)) / 3)", "((2 + (x * y)) / 3)",
36967 "((x + (2 * 3)) / y)",
36968 "(xx + yy) * zz", "xx + (yy * zz)",
36969 "(xx + yy) * 7", "xx + (yy * 7)",
36970 "(xx + 7) * yy", "xx + (7 * yy)",
36971 "(7 + xx) * yy", "7 + (xx * yy)",
36972 "(2 + x) * 3", "2 + (x * 3)",
36973 "(2 + 3) * x", "2 + (3 * x)",
36974 "(x + 2) * 3", "x + (2 * 3)",
36975 "(xx + yy) * (zz / ww)", "(xx + yy) * (zz / 7)",
36976 "(xx + yy) * (7 / zz)", "(xx + 7) * (yy / zz)",
36977 "(7 + xx) * (yy / zz)", "(2 + xx) * (yy / zz)",
36978 "(xx + 2) * (yy / 3)", "(2 + xx) * (yy / 3)",
36979 "(xx + 2) * (3 / yy)", "xx + (yy * (zz / ww))",
36980 "xx + (yy * (zz / 7))", "xx + (yy * (7 / zz))",
36981 "xx + (7 * (yy / zz))", "7 + (xx * (yy / zz))",
36982 "2 + (xx * (3 / yy))", "xx + (2 * (yy / 4))",
36983 "2 + (xx * (yy / 3))", "xx + (2 * (3 / yy))",
36984 "xx + ((yy * zz) / ww)", "xx + ((yy * zz) / 7)",
36985 "xx + ((yy * 7) / zz)", "xx + ((7 * yy) / zz)",
36986 "7 + ((yy * zz) / ww)", "2 + ((xx * 3) / yy)",
36987 "xx + ((2 * yy) / 3)", "2 + ((xx * yy) / 3)",
36988 "xx + ((2 * 3) / yy)", "(((xx + yy) * zz) / ww)",
36989 "(((xx + yy) * zz) / 7)", "(((xx + yy) * 7) / zz)",
36990 "(((xx + 7) * yy) / zz)", "(((7 + xx) * yy) / zz)",
36991 "(((2 + xx) * 3) / yy)", "(((xx + 2) * yy) / 3)",
36992 "(((2 + xx) * yy) / 3)", "(((xx + 2) * 3) / yy)",
36993 "((xx + (yy * zz)) / ww)", "((xx + (yy * zz)) / 7)",
36994 "((xx + (yy * 7)) / yy)", "((xx + (7 * yy)) / zz)",
36995 "((7 + (xx * yy)) / zz)", "((2 + (xx * 3)) / yy)",
36996 "((xx + (2 * yy)) / 3)", "((2 + (xx * yy)) / 3)",
36997 "((xx + (2 * 3)) / yy)"
37000 static const std::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string);
37002 T x = T(0);
37003 T y = T(0);
37004 T z = T(0);
37005 T w = T(0);
37006 T xx = T(0);
37007 T yy = T(0);
37008 T zz = T(0);
37009 T ww = T(0);
37011 exprtk::symbol_table<T> symbol_table;
37012 symbol_table.add_constants();
37013 symbol_table.add_variable( "x", x);
37014 symbol_table.add_variable( "y", y);
37015 symbol_table.add_variable( "z", z);
37016 symbol_table.add_variable( "w", w);
37017 symbol_table.add_variable("xx",xx);
37018 symbol_table.add_variable("yy",yy);
37019 symbol_table.add_variable("zz",zz);
37020 symbol_table.add_variable("ww",ww);
37022 typedef typename std::deque<exprtk::expression<T> > expr_list_t;
37023 expr_list_t expr_list;
37025 const std::size_t rounds = 50;
37028 for (std::size_t r = 0; r < rounds; ++r)
37030 expr_list.clear();
37031 exprtk::parser<T> parser;
37033 for (std::size_t i = 0; i < expression_list_size; ++i)
37035 exprtk::expression<T> expression;
37036 expression.register_symbol_table(symbol_table);
37038 if (!parser.compile(expression_list[i],expression))
37040 return false;
37043 expr_list.push_back(expression);
37048 struct execute
37050 static inline T process(T& x, T& y, expression<T>& expression)
37052 static const T lower_bound = T(-20);
37053 static const T upper_bound = T(+20);
37054 static const T delta = T(0.1);
37056 T total = T(0);
37058 for (x = lower_bound; x <= upper_bound; x += delta)
37060 for (y = lower_bound; y <= upper_bound; y += delta)
37062 total += expression.value();
37066 return total;
37070 for (std::size_t i = 0; i < expr_list.size(); ++i)
37072 execute::process( x, y, expr_list[i]);
37073 execute::process(xx, yy, expr_list[i]);
37077 for (std::size_t i = 0; i < 10000; ++i)
37079 const T v = T(123.456 + i);
37081 if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 1>::result(v),details::numeric::pow(v,T( 1)))))
37082 return false;
37084 #define else_stmt(N) \
37085 else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,N>::result(v),details::numeric::pow(v,T(N))))) \
37086 return false; \
37088 else_stmt( 2) else_stmt( 3) else_stmt( 4) else_stmt( 5)
37089 else_stmt( 6) else_stmt( 7) else_stmt( 8) else_stmt( 9)
37090 else_stmt(10) else_stmt(11) else_stmt(12) else_stmt(13)
37091 else_stmt(14) else_stmt(15) else_stmt(16) else_stmt(17)
37092 else_stmt(18) else_stmt(19) else_stmt(20) else_stmt(21)
37093 else_stmt(22) else_stmt(23) else_stmt(24) else_stmt(25)
37094 else_stmt(26) else_stmt(27) else_stmt(28) else_stmt(29)
37095 else_stmt(30) else_stmt(31) else_stmt(32) else_stmt(33)
37096 else_stmt(34) else_stmt(35) else_stmt(36) else_stmt(37)
37097 else_stmt(38) else_stmt(39) else_stmt(40) else_stmt(41)
37098 else_stmt(42) else_stmt(43) else_stmt(44) else_stmt(45)
37099 else_stmt(46) else_stmt(47) else_stmt(48) else_stmt(49)
37100 else_stmt(50) else_stmt(51) else_stmt(52) else_stmt(53)
37101 else_stmt(54) else_stmt(55) else_stmt(56) else_stmt(57)
37102 else_stmt(58) else_stmt(59) else_stmt(60) else_stmt(61)
37106 return true;
37110 #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
37111 # ifndef NOMINMAX
37112 # define NOMINMAX
37113 # endif
37114 # ifndef WIN32_LEAN_AND_MEAN
37115 # define WIN32_LEAN_AND_MEAN
37116 # endif
37117 # define NOGDI
37118 # define NORESOURCE
37119 # include <windows.h>
37120 # include <ctime>
37121 #else
37122 # include <ctime>
37123 # include <sys/time.h>
37124 # include <sys/types.h>
37125 #endif
37127 namespace exprtk
37129 class timer
37131 public:
37133 #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
37134 timer()
37135 : in_use_(false)
37137 QueryPerformanceFrequency(&clock_frequency_);
37140 inline void start()
37142 in_use_ = true;
37143 QueryPerformanceCounter(&start_time_);
37146 inline void stop()
37148 QueryPerformanceCounter(&stop_time_);
37149 in_use_ = false;
37152 inline double time() const
37154 return (1.0 * (stop_time_.QuadPart - start_time_.QuadPart)) / (1.0 * clock_frequency_.QuadPart);
37157 #else
37159 timer()
37160 : in_use_(false)
37162 start_time_.tv_sec = 0;
37163 start_time_.tv_usec = 0;
37164 stop_time_.tv_sec = 0;
37165 stop_time_.tv_usec = 0;
37168 inline void start()
37170 in_use_ = true;
37171 gettimeofday(&start_time_,0);
37174 inline void stop()
37176 gettimeofday(&stop_time_, 0);
37177 in_use_ = false;
37180 inline unsigned long long int usec_time() const
37182 if (!in_use_)
37184 if (stop_time_.tv_sec >= start_time_.tv_sec)
37186 return 1000000LLU * static_cast<details::_uint64_t>(stop_time_.tv_sec - start_time_.tv_sec ) +
37187 static_cast<details::_uint64_t>(stop_time_.tv_usec - start_time_.tv_usec) ;
37189 else
37190 return std::numeric_limits<details::_uint64_t>::max();
37192 else
37193 return std::numeric_limits<details::_uint64_t>::max();
37196 inline double time() const
37198 return usec_time() * 0.000001;
37201 #endif
37203 inline bool in_use() const
37205 return in_use_;
37208 private:
37210 bool in_use_;
37212 #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
37213 LARGE_INTEGER start_time_;
37214 LARGE_INTEGER stop_time_;
37215 LARGE_INTEGER clock_frequency_;
37216 #else
37217 struct timeval start_time_;
37218 struct timeval stop_time_;
37219 #endif
37222 } // namespace exprtk
37224 #ifndef exprtk_disable_rtl_io
37225 namespace exprtk
37227 namespace rtl { namespace io { namespace details
37229 template <typename T>
37230 inline void print_type(const std::string& fmt,
37231 const T v,
37232 exprtk::details::numeric::details::real_type_tag)
37234 printf(fmt.c_str(),v);
37237 template <typename T>
37238 struct print_impl
37240 typedef typename igeneric_function<T>::generic_type generic_type;
37241 typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
37242 typedef typename generic_type::scalar_view scalar_t;
37243 typedef typename generic_type::vector_view vector_t;
37244 typedef typename generic_type::string_view string_t;
37245 typedef typename exprtk::details::numeric::details::number_type<T>::type num_type;
37247 static void process(const std::string& scalar_format, parameter_list_t parameters)
37249 for (std::size_t i = 0; i < parameters.size(); ++i)
37251 generic_type& gt = parameters[i];
37253 switch (gt.type)
37255 case generic_type::e_scalar : print(scalar_format,scalar_t(gt));
37256 break;
37258 case generic_type::e_vector : print(scalar_format,vector_t(gt));
37259 break;
37261 case generic_type::e_string : print(string_t(gt));
37262 break;
37264 default : continue;
37269 static inline void print(const std::string& scalar_format, const scalar_t& s)
37271 print_type(scalar_format,s(),num_type());
37274 static inline void print(const std::string& scalar_format, const vector_t& v)
37276 for (std::size_t i = 0; i < v.size(); ++i)
37278 print_type(scalar_format,v[i],num_type());
37280 if ((i + 1) < v.size())
37281 printf(" ");
37285 static inline void print(const string_t& s)
37287 printf("%s",to_str(s).c_str());
37291 } // namespace exprtk::rtl::io::details
37293 template <typename T>
37294 struct print : public exprtk::igeneric_function<T>
37296 typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
37298 using exprtk::igeneric_function<T>::operator();
37300 print(const std::string& scalar_format = "%10.5f")
37301 : scalar_format_(scalar_format)
37303 exprtk::enable_zero_parameters(*this);
37306 inline T operator() (parameter_list_t parameters)
37308 details::print_impl<T>::process(scalar_format_,parameters);
37309 return T(0);
37312 std::string scalar_format_;
37315 template <typename T>
37316 struct println : public exprtk::igeneric_function<T>
37318 typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
37320 using exprtk::igeneric_function<T>::operator();
37322 println(const std::string& scalar_format = "%10.5f")
37323 : scalar_format_(scalar_format)
37325 exprtk::enable_zero_parameters(*this);
37328 inline T operator() (parameter_list_t parameters)
37330 details::print_impl<T>::process(scalar_format_,parameters);
37331 printf("\n");
37332 return T(0);
37335 std::string scalar_format_;
37338 template <typename T>
37339 struct package
37341 print <T> p;
37342 println<T> pl;
37344 bool register_package(exprtk::symbol_table<T>& symtab)
37346 #define exprtk_register_function(FunctionName,FunctionType) \
37347 if (!symtab.add_function(FunctionName,FunctionType)) \
37349 exprtk_debug(( \
37350 "exprtk::rtl::io::register_package - Failed to add function: %s\n", \
37351 FunctionName)); \
37352 return false; \
37355 exprtk_register_function("print" , p)
37356 exprtk_register_function("println", pl)
37357 #undef exprtk_register_function
37359 return true;
37363 } // namespace exprtk::rtl::io
37364 } // namespace exprtk::rtl
37365 } // namespace exprtk
37366 #endif
37368 #ifndef exprtk_disable_rtl_io_file
37369 #include <fstream>
37370 namespace exprtk
37372 namespace rtl { namespace io { namespace file { namespace details
37374 enum file_mode
37376 e_error = 0,
37377 e_read = 1,
37378 e_write = 2,
37379 e_rdwrt = 4
37382 struct file_descriptor
37384 file_descriptor(const std::string& fname, const std::string& access)
37385 : stream_ptr(0),
37386 mode(get_file_mode(access)),
37387 file_name(fname)
37390 void* stream_ptr;
37391 file_mode mode;
37392 std::string file_name;
37394 bool open()
37396 if (e_read == mode)
37398 std::ifstream* stream = new std::ifstream(file_name.c_str(),std::ios::binary);
37400 if (!(*stream))
37402 file_name.clear();
37403 delete stream;
37405 return false;
37407 else
37408 stream_ptr = stream;
37410 return true;
37412 else if (e_write == mode)
37414 std::ofstream* stream = new std::ofstream(file_name.c_str(),std::ios::binary);
37416 if (!(*stream))
37418 file_name.clear();
37419 delete stream;
37421 return false;
37423 else
37424 stream_ptr = stream;
37426 return true;
37428 else if (e_rdwrt == mode)
37430 std::fstream* stream = new std::fstream(file_name.c_str(),std::ios::binary);
37432 if (!(*stream))
37434 file_name.clear();
37435 delete stream;
37437 return false;
37439 else
37440 stream_ptr = stream;
37442 return true;
37444 else
37445 return false;
37448 template <typename Stream, typename Ptr>
37449 void close(Ptr& p)
37451 Stream* stream = reinterpret_cast<Stream*>(p);
37452 stream->close();
37453 delete stream;
37454 p = reinterpret_cast<Ptr>(0);
37457 bool close()
37459 switch (mode)
37461 case e_read : close<std::ifstream>(stream_ptr);
37462 break;
37464 case e_write : close<std::ofstream>(stream_ptr);
37465 break;
37467 case e_rdwrt : close<std::fstream> (stream_ptr);
37468 break;
37470 default : return false;
37473 return true;
37476 template <typename View>
37477 bool write(const View& view, const std::size_t amount, const std::size_t offset = 0)
37479 switch (mode)
37481 case e_write : reinterpret_cast<std::ofstream*>(stream_ptr)->
37482 write(reinterpret_cast<const char*>(view.begin() + offset), amount * sizeof(typename View::value_t));
37483 break;
37485 case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)->
37486 write(reinterpret_cast<const char*>(view.begin() + offset) , amount * sizeof(typename View::value_t));
37487 break;
37489 default : return false;
37492 return true;
37495 template <typename View>
37496 bool read(View& view, const std::size_t amount, const std::size_t offset = 0)
37498 switch (mode)
37500 case e_read : reinterpret_cast<std::ifstream*>(stream_ptr)->
37501 read(reinterpret_cast<char*>(view.begin() + offset), amount * sizeof(typename View::value_t));
37502 break;
37504 case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)->
37505 read(reinterpret_cast<char*>(view.begin() + offset) , amount * sizeof(typename View::value_t));
37506 break;
37508 default : return false;
37511 return true;
37514 bool getline(std::string& s)
37516 switch (mode)
37518 case e_read : return (!!std::getline(*reinterpret_cast<std::ifstream*>(stream_ptr),s));
37519 case e_rdwrt : return (!!std::getline(*reinterpret_cast<std::fstream* >(stream_ptr),s));
37520 default : return false;
37524 bool eof() const
37526 switch (mode)
37528 case e_read : return reinterpret_cast<std::ifstream*>(stream_ptr)->eof();
37529 case e_write : return reinterpret_cast<std::ofstream*>(stream_ptr)->eof();
37530 case e_rdwrt : return reinterpret_cast<std::fstream* >(stream_ptr)->eof();
37531 default : return true;
37535 file_mode get_file_mode(const std::string& access) const
37537 if (access.empty() || access.size() > 2)
37538 return e_error;
37540 std::size_t w_cnt = 0;
37541 std::size_t r_cnt = 0;
37543 for (std::size_t i = 0; i < access.size(); ++i)
37545 switch (std::tolower(access[i]))
37547 case 'r' : r_cnt++; break;
37548 case 'w' : w_cnt++; break;
37549 default : return e_error;
37553 if ((0 == r_cnt) && (0 == w_cnt))
37554 return e_error;
37555 else if ((r_cnt > 1) || (w_cnt > 1))
37556 return e_error;
37557 else if ((1 == r_cnt) && (1 == w_cnt))
37558 return e_rdwrt;
37559 else if (1 == r_cnt)
37560 return e_read;
37561 else
37562 return e_write;
37566 template <typename T>
37567 file_descriptor* make_handle(T v)
37569 file_descriptor* fd = reinterpret_cast<file_descriptor*>(0);
37571 std::memcpy(reinterpret_cast<char*>(&fd),
37572 reinterpret_cast<const char*>(&v),
37573 sizeof(fd));
37574 return fd;
37577 template <typename T>
37578 void perform_check()
37580 #ifdef _MSC_VER
37581 #pragma warning(push)
37582 #pragma warning(disable: 4127)
37583 #endif
37584 if (sizeof(T) < sizeof(void*))
37586 throw std::runtime_error("exprtk::rtl::io::file - Error - pointer size larger than holder.");
37588 #ifdef _MSC_VER
37589 #pragma warning(pop)
37590 #endif
37593 } // namespace exprtk::rtl::io::file::details
37595 template <typename T>
37596 class open : public exprtk::igeneric_function<T>
37598 public:
37600 typedef typename exprtk::igeneric_function<T> igfun_t;
37601 typedef typename igfun_t::parameter_list_t parameter_list_t;
37602 typedef typename igfun_t::generic_type generic_type;
37603 typedef typename generic_type::string_view string_t;
37605 using exprtk::igeneric_function<T>::operator();
37607 open()
37608 : exprtk::igeneric_function<T>("S|SS")
37609 { details::perform_check<T>(); }
37611 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
37613 std::string file_name = to_str(string_t(parameters[0]));
37614 std::string access;
37616 if (file_name.empty())
37617 return T(0);
37619 if (0 == ps_index)
37620 access = "r";
37621 else if (0 == string_t(parameters[1]).size())
37622 return T(0);
37623 else
37624 access = to_str(string_t(parameters[1]));
37626 details::file_descriptor* fd = new details::file_descriptor(file_name,access);
37628 if (fd->open())
37630 T t = T(0);
37632 std::memcpy(reinterpret_cast<char*>(&t ),
37633 reinterpret_cast<char*>(&fd),
37634 sizeof(fd));
37635 return t;
37637 else
37639 delete fd;
37640 return T(0);
37645 template <typename T>
37646 struct close : public exprtk::ifunction<T>
37648 using exprtk::ifunction<T>::operator();
37650 close()
37651 : exprtk::ifunction<T>(1)
37652 { details::perform_check<T>(); }
37654 inline T operator() (const T& v)
37656 details::file_descriptor* fd = details::make_handle(v);
37658 if (!fd->close())
37659 return T(0);
37661 delete fd;
37663 return T(1);
37667 template <typename T>
37668 class write : public exprtk::igeneric_function<T>
37670 public:
37672 typedef typename exprtk::igeneric_function<T> igfun_t;
37673 typedef typename igfun_t::parameter_list_t parameter_list_t;
37674 typedef typename igfun_t::generic_type generic_type;
37675 typedef typename generic_type::string_view string_t;
37676 typedef typename generic_type::scalar_view scalar_t;
37677 typedef typename generic_type::vector_view vector_t;
37679 using exprtk::igeneric_function<T>::operator();
37681 write()
37682 : igfun_t("TS|TST|TV|TVT")
37683 { details::perform_check<T>(); }
37685 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
37687 details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])());
37689 std::size_t amount = 0;
37691 switch (ps_index)
37693 case 0 : {
37694 const string_t buffer(parameters[1]);
37695 amount = buffer.size();
37696 return T(fd->write(buffer, amount) ? 1 : 0);
37699 case 1 : {
37700 const string_t buffer(parameters[1]);
37701 amount = std::min(buffer.size(),
37702 static_cast<std::size_t>(scalar_t(parameters[2])()));
37703 return T(fd->write(buffer, amount) ? 1 : 0);
37706 case 2 : {
37707 const vector_t vec(parameters[1]);
37708 amount = vec.size();
37709 return T(fd->write(vec, amount) ? 1 : 0);
37712 case 3 : {
37713 const vector_t vec(parameters[1]);
37714 amount = std::min(vec.size(),
37715 static_cast<std::size_t>(scalar_t(parameters[2])()));
37716 return T(fd->write(vec, amount) ? 1 : 0);
37720 return T(0);
37724 template <typename T>
37725 class read : public exprtk::igeneric_function<T>
37727 public:
37729 typedef typename exprtk::igeneric_function<T> igfun_t;
37730 typedef typename igfun_t::parameter_list_t parameter_list_t;
37731 typedef typename igfun_t::generic_type generic_type;
37732 typedef typename generic_type::string_view string_t;
37733 typedef typename generic_type::scalar_view scalar_t;
37734 typedef typename generic_type::vector_view vector_t;
37736 using exprtk::igeneric_function<T>::operator();
37738 read()
37739 : igfun_t("TS|TST|TV|TVT")
37740 { details::perform_check<T>(); }
37742 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
37744 details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])());
37746 std::size_t amount = 0;
37748 switch (ps_index)
37750 case 0 : {
37751 string_t buffer(parameters[1]);
37752 amount = buffer.size();
37753 return T(fd->read(buffer,amount) ? 1 : 0);
37756 case 1 : {
37757 string_t buffer(parameters[1]);
37758 amount = std::min(buffer.size(),
37759 static_cast<std::size_t>(scalar_t(parameters[2])()));
37760 return T(fd->read(buffer,amount) ? 1 : 0);
37763 case 2 : {
37764 vector_t vec(parameters[1]);
37765 amount = vec.size();
37766 return T(fd->read(vec,amount) ? 1 : 0);
37769 case 3 : {
37770 vector_t vec(parameters[1]);
37771 amount = std::min(vec.size(),
37772 static_cast<std::size_t>(scalar_t(parameters[2])()));
37773 return T(fd->read(vec,amount) ? 1 : 0);
37777 return T(0);
37781 template <typename T>
37782 class getline : public exprtk::igeneric_function<T>
37784 public:
37786 typedef typename exprtk::igeneric_function<T> igfun_t;
37787 typedef typename igfun_t::parameter_list_t parameter_list_t;
37788 typedef typename igfun_t::generic_type generic_type;
37789 typedef typename generic_type::string_view string_t;
37790 typedef typename generic_type::scalar_view scalar_t;
37792 using exprtk::igeneric_function<T>::operator();
37794 getline()
37795 : igfun_t("T",igfun_t::e_rtrn_string)
37796 { details::perform_check<T>(); }
37798 inline T operator() (std::string& result,
37799 parameter_list_t parameters)
37801 details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])());
37802 return T(fd->getline(result) ? 1 : 0);
37806 template <typename T>
37807 struct eof : public exprtk::ifunction<T>
37809 using exprtk::ifunction<T>::operator();
37811 eof()
37812 : exprtk::ifunction<T>(1)
37813 { details::perform_check<T>(); }
37815 inline T operator() (const T& v)
37817 details::file_descriptor* fd = details::make_handle(v);
37819 return (fd->eof() ? T(1) : T(0));
37823 template <typename T>
37824 struct package
37826 open <T> o;
37827 close <T> c;
37828 write <T> w;
37829 read <T> r;
37830 getline<T> g;
37831 eof <T> e;
37833 bool register_package(exprtk::symbol_table<T>& symtab)
37835 #define exprtk_register_function(FunctionName,FunctionType) \
37836 if (!symtab.add_function(FunctionName,FunctionType)) \
37838 exprtk_debug(( \
37839 "exprtk::rtl::io::file::register_package - Failed to add function: %s\n", \
37840 FunctionName)); \
37841 return false; \
37844 exprtk_register_function("open" ,o)
37845 exprtk_register_function("close" ,c)
37846 exprtk_register_function("write" ,w)
37847 exprtk_register_function("read" ,r)
37848 exprtk_register_function("getline",g)
37849 exprtk_register_function("eof" ,e)
37850 #undef exprtk_register_function
37852 return true;
37856 } // namespace exprtk::rtl::io::file
37857 } // namespace exprtk::rtl::io
37858 } // namespace exprtk::rtl
37859 } // namespace exprtk
37860 #endif
37862 #ifndef exprtk_disable_rtl_vecops
37863 namespace exprtk
37865 namespace rtl { namespace vecops {
37867 namespace helper
37869 template <typename Vector>
37870 inline bool invalid_range(const Vector& v, const std::size_t r0, const std::size_t r1)
37872 if (r0 > (v.size() - 1))
37873 return true;
37874 else if (r1 > (v.size() - 1))
37875 return true;
37876 else if (r1 < r0)
37877 return true;
37878 else
37879 return false;
37882 template <typename T>
37883 struct load_vector_range
37885 typedef typename exprtk::igeneric_function<T> igfun_t;
37886 typedef typename igfun_t::parameter_list_t parameter_list_t;
37887 typedef typename igfun_t::generic_type generic_type;
37888 typedef typename generic_type::scalar_view scalar_t;
37889 typedef typename generic_type::vector_view vector_t;
37891 static inline bool process(parameter_list_t& parameters,
37892 std::size_t& r0, std::size_t& r1,
37893 const std::size_t& r0_prmidx,
37894 const std::size_t& r1_prmidx,
37895 const std::size_t vec_idx = 0)
37897 if (r0_prmidx >= parameters.size())
37898 return false;
37900 if (r1_prmidx >= parameters.size())
37901 return false;
37903 if (!scalar_t(parameters[r0_prmidx]).to_uint(r0))
37904 return false;
37906 if (!scalar_t(parameters[r1_prmidx]).to_uint(r1))
37907 return false;
37909 return !invalid_range(vector_t(parameters[vec_idx]), r0, r1);
37914 namespace details
37916 template <typename T>
37917 inline void kahan_sum(T& sum, T& error, const T v)
37919 const T x = v - error;
37920 const T y = sum + x;
37921 error = (y - sum) - x;
37922 sum = y;
37925 } // namespace exprtk::rtl::details
37927 template <typename T>
37928 class all_true : public exprtk::igeneric_function<T>
37930 public:
37932 typedef typename exprtk::igeneric_function<T> igfun_t;
37933 typedef typename igfun_t::parameter_list_t parameter_list_t;
37934 typedef typename igfun_t::generic_type generic_type;
37935 typedef typename generic_type::vector_view vector_t;
37937 using exprtk::igeneric_function<T>::operator();
37939 all_true()
37940 : exprtk::igeneric_function<T>("V|VTT")
37942 Overloads:
37943 0. V - vector
37944 1. VTT - vector, r0, r1
37948 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
37950 const vector_t vec(parameters[0]);
37952 std::size_t r0 = 0;
37953 std::size_t r1 = vec.size() - 1;
37955 if (
37956 (1 == ps_index) &&
37957 !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
37959 return std::numeric_limits<T>::quiet_NaN();
37961 for (std::size_t i = r0; i <= r1; ++i)
37963 if (vec[i] == T(0))
37965 return T(0);
37969 return T(1);
37973 template <typename T>
37974 class all_false : public exprtk::igeneric_function<T>
37976 public:
37978 typedef typename exprtk::igeneric_function<T> igfun_t;
37979 typedef typename igfun_t::parameter_list_t parameter_list_t;
37980 typedef typename igfun_t::generic_type generic_type;
37981 typedef typename generic_type::vector_view vector_t;
37983 using exprtk::igeneric_function<T>::operator();
37985 all_false()
37986 : exprtk::igeneric_function<T>("V|VTT")
37988 Overloads:
37989 0. V - vector
37990 1. VTT - vector, r0, r1
37994 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
37996 const vector_t vec(parameters[0]);
37998 std::size_t r0 = 0;
37999 std::size_t r1 = vec.size() - 1;
38001 if (
38002 (1 == ps_index) &&
38003 !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
38005 return std::numeric_limits<T>::quiet_NaN();
38007 for (std::size_t i = r0; i <= r1; ++i)
38009 if (vec[i] != T(0))
38011 return T(0);
38015 return T(1);
38019 template <typename T>
38020 class any_true : public exprtk::igeneric_function<T>
38022 public:
38024 typedef typename exprtk::igeneric_function<T> igfun_t;
38025 typedef typename igfun_t::parameter_list_t parameter_list_t;
38026 typedef typename igfun_t::generic_type generic_type;
38027 typedef typename generic_type::vector_view vector_t;
38029 using exprtk::igeneric_function<T>::operator();
38031 any_true()
38032 : exprtk::igeneric_function<T>("V|VTT")
38034 Overloads:
38035 0. V - vector
38036 1. VTT - vector, r0, r1
38040 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38042 const vector_t vec(parameters[0]);
38044 std::size_t r0 = 0;
38045 std::size_t r1 = vec.size() - 1;
38047 if (
38048 (1 == ps_index) &&
38049 !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
38051 return std::numeric_limits<T>::quiet_NaN();
38053 for (std::size_t i = r0; i <= r1; ++i)
38055 if (vec[i] != T(0))
38057 return T(1);
38061 return T(0);
38065 template <typename T>
38066 class any_false : public exprtk::igeneric_function<T>
38068 public:
38070 typedef typename exprtk::igeneric_function<T> igfun_t;
38071 typedef typename igfun_t::parameter_list_t parameter_list_t;
38072 typedef typename igfun_t::generic_type generic_type;
38073 typedef typename generic_type::vector_view vector_t;
38075 using exprtk::igeneric_function<T>::operator();
38077 any_false()
38078 : exprtk::igeneric_function<T>("V|VTT")
38080 Overloads:
38081 0. V - vector
38082 1. VTT - vector, r0, r1
38086 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38088 const vector_t vec(parameters[0]);
38090 std::size_t r0 = 0;
38091 std::size_t r1 = vec.size() - 1;
38093 if (
38094 (1 == ps_index) &&
38095 !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
38097 return std::numeric_limits<T>::quiet_NaN();
38099 for (std::size_t i = r0; i <= r1; ++i)
38101 if (vec[i] == T(0))
38103 return T(1);
38107 return T(0);
38111 template <typename T>
38112 class count : public exprtk::igeneric_function<T>
38114 public:
38116 typedef typename exprtk::igeneric_function<T> igfun_t;
38117 typedef typename igfun_t::parameter_list_t parameter_list_t;
38118 typedef typename igfun_t::generic_type generic_type;
38119 typedef typename generic_type::vector_view vector_t;
38121 using exprtk::igeneric_function<T>::operator();
38123 count()
38124 : exprtk::igeneric_function<T>("V|VTT")
38126 Overloads:
38127 0. V - vector
38128 1. VTT - vector, r0, r1
38132 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38134 const vector_t vec(parameters[0]);
38136 std::size_t r0 = 0;
38137 std::size_t r1 = vec.size() - 1;
38139 if (
38140 (1 == ps_index) &&
38141 !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
38143 return std::numeric_limits<T>::quiet_NaN();
38145 std::size_t cnt = 0;
38147 for (std::size_t i = r0; i <= r1; ++i)
38149 if (vec[i] != T(0)) ++cnt;
38152 return T(cnt);
38156 template <typename T>
38157 class copy : public exprtk::igeneric_function<T>
38159 public:
38161 typedef typename exprtk::igeneric_function<T> igfun_t;
38162 typedef typename igfun_t::parameter_list_t parameter_list_t;
38163 typedef typename igfun_t::generic_type generic_type;
38164 typedef typename generic_type::scalar_view scalar_t;
38165 typedef typename generic_type::vector_view vector_t;
38167 using exprtk::igeneric_function<T>::operator();
38169 copy()
38170 : exprtk::igeneric_function<T>("VV|VTTVTT")
38172 Overloads:
38173 0. VV - x(vector), y(vector)
38174 1. VTTVTT - x(vector), xr0, xr1, y(vector), yr0, yr1,
38178 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38180 const vector_t x(parameters[0]);
38181 vector_t y(parameters[(0 == ps_index) ? 1 : 3]);
38183 std::size_t xr0 = 0;
38184 std::size_t xr1 = x.size() - 1;
38186 std::size_t yr0 = 0;
38187 std::size_t yr1 = y.size() - 1;
38189 if (1 == ps_index)
38191 if (
38192 !helper::load_vector_range<T>::process(parameters, xr0, xr1, 1, 2, 0) ||
38193 !helper::load_vector_range<T>::process(parameters, yr0, yr1, 4, 5, 3)
38195 return T(0);
38198 const std::size_t n = std::min(xr1 - xr0 + 1, yr1 - yr0 + 1);
38200 std::copy(x.begin() + xr0, x.begin() + xr0 + n, y.begin() + yr0);
38202 return T(n);
38206 template <typename T>
38207 class rol : public exprtk::igeneric_function<T>
38209 public:
38211 typedef typename exprtk::igeneric_function<T> igfun_t;
38212 typedef typename igfun_t::parameter_list_t parameter_list_t;
38213 typedef typename igfun_t::generic_type generic_type;
38214 typedef typename generic_type::scalar_view scalar_t;
38215 typedef typename generic_type::vector_view vector_t;
38217 using exprtk::igeneric_function<T>::operator();
38219 rol()
38220 : exprtk::igeneric_function<T>("VT|VTTT")
38222 Overloads:
38223 0. VT - vector, N
38224 1. VTTT - vector, N, r0, r1
38228 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38230 vector_t vec(parameters[0]);
38232 std::size_t n = 0;
38233 std::size_t r0 = 0;
38234 std::size_t r1 = vec.size() - 1;
38236 if (!scalar_t(parameters[1]).to_uint(n))
38237 return T(0);
38239 if (
38240 (1 == ps_index) &&
38241 !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
38243 return T(0);
38245 std::size_t dist = r1 - r0 + 1;
38246 std::size_t shift = n % dist;
38248 std::rotate(vec.begin() + r0, vec.begin() + r0 + shift, vec.begin() + r1 + 1);
38250 return T(1);
38254 template <typename T>
38255 class ror : public exprtk::igeneric_function<T>
38257 public:
38259 typedef typename exprtk::igeneric_function<T> igfun_t;
38260 typedef typename igfun_t::parameter_list_t parameter_list_t;
38261 typedef typename igfun_t::generic_type generic_type;
38262 typedef typename generic_type::scalar_view scalar_t;
38263 typedef typename generic_type::vector_view vector_t;
38265 using exprtk::igeneric_function<T>::operator();
38267 ror()
38268 : exprtk::igeneric_function<T>("VT|VTTT")
38270 Overloads:
38271 0. VT - vector, N
38272 1. VTTT - vector, N, r0, r1
38276 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38278 vector_t vec(parameters[0]);
38280 std::size_t n = 0;
38281 std::size_t r0 = 0;
38282 std::size_t r1 = vec.size() - 1;
38284 if (!scalar_t(parameters[1]).to_uint(n))
38285 return T(0);
38287 if (
38288 (1 == ps_index) &&
38289 !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
38291 return T(0);
38293 std::size_t dist = r1 - r0 + 1;
38294 std::size_t shift = (dist - (n % dist)) % dist;
38296 std::rotate(vec.begin() + r0, vec.begin() + r0 + shift, vec.begin() + r1 + 1);
38298 return T(1);
38302 template <typename T>
38303 class shift_left : public exprtk::igeneric_function<T>
38305 public:
38307 typedef typename exprtk::igeneric_function<T> igfun_t;
38308 typedef typename igfun_t::parameter_list_t parameter_list_t;
38309 typedef typename igfun_t::generic_type generic_type;
38310 typedef typename generic_type::scalar_view scalar_t;
38311 typedef typename generic_type::vector_view vector_t;
38313 using exprtk::igeneric_function<T>::operator();
38315 shift_left()
38316 : exprtk::igeneric_function<T>("VT|VTTT")
38318 Overloads:
38319 0. VT - vector, N
38320 1. VTTT - vector, N, r0, r1
38324 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38326 vector_t vec(parameters[0]);
38328 std::size_t n = 0;
38329 std::size_t r0 = 0;
38330 std::size_t r1 = vec.size() - 1;
38332 if (!scalar_t(parameters[1]).to_uint(n))
38333 return T(0);
38335 if (
38336 (1 == ps_index) &&
38337 !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
38339 return T(0);
38341 std::size_t dist = r1 - r0 + 1;
38343 if (n > dist)
38344 return T(0);
38346 std::rotate(vec.begin() + r0, vec.begin() + r0 + n, vec.begin() + r1 + 1);
38348 for (std::size_t i = r1 - n + 1; i <= r1; ++i)
38350 vec[i] = T(0);
38353 return T(1);
38357 template <typename T>
38358 class shift_right : public exprtk::igeneric_function<T>
38360 public:
38362 typedef typename exprtk::igeneric_function<T> igfun_t;
38363 typedef typename igfun_t::parameter_list_t parameter_list_t;
38364 typedef typename igfun_t::generic_type generic_type;
38365 typedef typename generic_type::scalar_view scalar_t;
38366 typedef typename generic_type::vector_view vector_t;
38368 using exprtk::igeneric_function<T>::operator();
38370 shift_right()
38371 : exprtk::igeneric_function<T>("VT|VTTT")
38373 Overloads:
38374 0. VT - vector, N
38375 1. VTTT - vector, N, r0, r1
38379 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38381 vector_t vec(parameters[0]);
38383 std::size_t n = 0;
38384 std::size_t r0 = 0;
38385 std::size_t r1 = vec.size() - 1;
38387 if (!scalar_t(parameters[1]).to_uint(n))
38388 return T(0);
38390 if (
38391 (1 == ps_index) &&
38392 !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
38394 return T(0);
38396 std::size_t dist = r1 - r0 + 1;
38398 if (n > dist)
38399 return T(0);
38401 std::size_t shift = (dist - (n % dist)) % dist;
38403 std::rotate(vec.begin() + r0, vec.begin() + r0 + shift, vec.begin() + r1 + 1);
38405 for (std::size_t i = r0; i < r0 + n; ++i)
38407 vec[i] = T(0);
38410 return T(1);
38414 template <typename T>
38415 class sort : public exprtk::igeneric_function<T>
38417 public:
38419 typedef typename exprtk::igeneric_function<T> igfun_t;
38420 typedef typename igfun_t::parameter_list_t parameter_list_t;
38421 typedef typename igfun_t::generic_type generic_type;
38422 typedef typename generic_type::string_view string_t;
38423 typedef typename generic_type::vector_view vector_t;
38425 using exprtk::igeneric_function<T>::operator();
38427 sort()
38428 : exprtk::igeneric_function<T>("V|VTT|VS|VSTT")
38430 Overloads:
38431 0. V - vector
38432 1. VTT - vector, r0, r1
38433 2. VS - vector, string
38434 3. VSTT - vector, string, r0, r1
38438 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38440 vector_t vec(parameters[0]);
38442 std::size_t r0 = 0;
38443 std::size_t r1 = vec.size() - 1;
38445 if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0))
38446 return T(0);
38447 if ((3 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
38448 return T(0);
38450 bool ascending = true;
38452 if ((2 == ps_index) || (3 == ps_index))
38454 if (exprtk::details::imatch(to_str(string_t(parameters[1])),"ascending"))
38455 ascending = true;
38456 else if (exprtk::details::imatch(to_str(string_t(parameters[1])),"descending"))
38457 ascending = false;
38458 else
38459 return T(0);
38462 if (ascending)
38463 std::sort(vec.begin() + r0, vec.begin() + r1 + 1, std::less<T> ());
38464 else
38465 std::sort(vec.begin() + r0, vec.begin() + r1 + 1, std::greater<T>());
38467 return T(1);
38471 template <typename T>
38472 class nthelement : public exprtk::igeneric_function<T>
38474 public:
38476 typedef typename exprtk::igeneric_function<T> igfun_t;
38477 typedef typename igfun_t::parameter_list_t parameter_list_t;
38478 typedef typename igfun_t::generic_type generic_type;
38479 typedef typename generic_type::scalar_view scalar_t;
38480 typedef typename generic_type::vector_view vector_t;
38482 using exprtk::igeneric_function<T>::operator();
38484 nthelement()
38485 : exprtk::igeneric_function<T>("VT|VTTT")
38487 Overloads:
38488 0. VT - vector, nth-element
38489 1. VTTT - vector, nth-element, r0, r1
38493 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38495 vector_t vec(parameters[0]);
38497 std::size_t n = 0;
38498 std::size_t r0 = 0;
38499 std::size_t r1 = vec.size() - 1;
38501 if (!scalar_t(parameters[1]).to_uint(n))
38502 return T(0);
38504 if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
38505 return std::numeric_limits<T>::quiet_NaN();
38507 std::nth_element(vec.begin() + r0, vec.begin() + r0 + n , vec.begin() + r1 + 1);
38509 return T(1);
38513 template <typename T>
38514 class iota : public exprtk::igeneric_function<T>
38516 public:
38518 typedef typename exprtk::igeneric_function<T> igfun_t;
38519 typedef typename igfun_t::parameter_list_t parameter_list_t;
38520 typedef typename igfun_t::generic_type generic_type;
38521 typedef typename generic_type::scalar_view scalar_t;
38522 typedef typename generic_type::vector_view vector_t;
38524 using exprtk::igeneric_function<T>::operator();
38526 iota()
38527 : exprtk::igeneric_function<T>("VT|VTT|VTTT|VTTTT")
38529 Overloads:
38530 0. VT - vector, increment
38531 1. VTT - vector, increment, base
38532 2. VTTTT - vector, increment, r0, r1
38533 3. VTTTT - vector, increment, base, r0, r1
38537 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38539 vector_t vec(parameters[0]);
38541 T increment = scalar_t(parameters[1])();
38542 T base = ((1 == ps_index) || (3 == ps_index)) ? scalar_t(parameters[2])() : T(0);
38544 std::size_t r0 = 0;
38545 std::size_t r1 = vec.size() - 1;
38547 if ((2 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
38548 return std::numeric_limits<T>::quiet_NaN();
38549 else if ((3 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 3, 4, 0))
38550 return std::numeric_limits<T>::quiet_NaN();
38551 else
38553 long long j = 0;
38555 for (std::size_t i = r0; i <= r1; ++i, ++j)
38557 vec[i] = base + (increment * j);
38561 return T(1);
38565 template <typename T>
38566 class sumk : public exprtk::igeneric_function<T>
38568 public:
38570 typedef typename exprtk::igeneric_function<T> igfun_t;
38571 typedef typename igfun_t::parameter_list_t parameter_list_t;
38572 typedef typename igfun_t::generic_type generic_type;
38573 typedef typename generic_type::vector_view vector_t;
38575 using exprtk::igeneric_function<T>::operator();
38577 sumk()
38578 : exprtk::igeneric_function<T>("V|VTT")
38580 Overloads:
38581 0. V - vector
38582 1. VTT - vector, r0, r1
38586 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38588 const vector_t vec(parameters[0]);
38590 std::size_t r0 = 0;
38591 std::size_t r1 = vec.size() - 1;
38593 if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0))
38594 return std::numeric_limits<T>::quiet_NaN();
38596 T result = T(0);
38597 T error = T(0);
38599 for (std::size_t i = r0; i <= r1; ++i)
38601 details::kahan_sum(result, error, vec[i]);
38604 return result;
38608 template <typename T>
38609 class axpy : public exprtk::igeneric_function<T>
38611 public:
38613 typedef typename exprtk::igeneric_function<T> igfun_t;
38614 typedef typename igfun_t::parameter_list_t parameter_list_t;
38615 typedef typename igfun_t::generic_type generic_type;
38616 typedef typename generic_type::scalar_view scalar_t;
38617 typedef typename generic_type::vector_view vector_t;
38619 using exprtk::igeneric_function<T>::operator();
38621 axpy()
38622 : exprtk::igeneric_function<T>("TVV|TVVTT")
38624 y <- ax + y
38625 Overloads:
38626 0. TVV - a, x(vector), y(vector)
38627 1. TVVTT - a, x(vector), y(vector), r0, r1
38631 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38633 const vector_t x(parameters[1]);
38634 vector_t y(parameters[2]);
38636 std::size_t r0 = 0;
38637 std::size_t r1 = std::min(x.size(),y.size()) - 1;
38639 if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 3, 4, 1))
38640 return std::numeric_limits<T>::quiet_NaN();
38641 else if (helper::invalid_range(y, r0, r1))
38642 return std::numeric_limits<T>::quiet_NaN();
38644 const T a = scalar_t(parameters[0])();
38646 for (std::size_t i = r0; i <= r1; ++i)
38648 y[i] = (a * x[i]) + y[i];
38651 return T(1);
38655 template <typename T>
38656 class axpby : public exprtk::igeneric_function<T>
38658 public:
38660 typedef typename exprtk::igeneric_function<T> igfun_t;
38661 typedef typename igfun_t::parameter_list_t parameter_list_t;
38662 typedef typename igfun_t::generic_type generic_type;
38663 typedef typename generic_type::scalar_view scalar_t;
38664 typedef typename generic_type::vector_view vector_t;
38666 using exprtk::igeneric_function<T>::operator();
38668 axpby()
38669 : exprtk::igeneric_function<T>("TVTV|TVTVTT")
38671 y <- ax + by
38672 Overloads:
38673 0. TVTV - a, x(vector), b, y(vector)
38674 1. TVTVTT - a, x(vector), b, y(vector), r0, r1
38678 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38680 const vector_t x(parameters[1]);
38681 vector_t y(parameters[3]);
38683 std::size_t r0 = 0;
38684 std::size_t r1 = std::min(x.size(),y.size()) - 1;
38686 if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1))
38687 return std::numeric_limits<T>::quiet_NaN();
38688 else if (helper::invalid_range(y, r0, r1))
38689 return std::numeric_limits<T>::quiet_NaN();
38691 const T a = scalar_t(parameters[0])();
38692 const T b = scalar_t(parameters[2])();
38694 for (std::size_t i = r0; i <= r1; ++i)
38696 y[i] = (a * x[i]) + (b * y[i]);
38699 return T(1);
38703 template <typename T>
38704 class axpyz : public exprtk::igeneric_function<T>
38706 public:
38708 typedef typename exprtk::igeneric_function<T> igfun_t;
38709 typedef typename igfun_t::parameter_list_t parameter_list_t;
38710 typedef typename igfun_t::generic_type generic_type;
38711 typedef typename generic_type::scalar_view scalar_t;
38712 typedef typename generic_type::vector_view vector_t;
38714 using exprtk::igeneric_function<T>::operator();
38716 axpyz()
38717 : exprtk::igeneric_function<T>("TVVV|TVVVTT")
38719 z <- ax + y
38720 Overloads:
38721 0. TVVV - a, x(vector), y(vector), z(vector)
38722 1. TVVVTT - a, x(vector), y(vector), z(vector), r0, r1
38726 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38728 const vector_t x(parameters[1]);
38729 const vector_t y(parameters[2]);
38730 vector_t z(parameters[3]);
38732 std::size_t r0 = 0;
38733 std::size_t r1 = std::min(x.size(),y.size()) - 1;
38735 if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 3, 4, 1))
38736 return std::numeric_limits<T>::quiet_NaN();
38737 else if (helper::invalid_range(y, r0, r1))
38738 return std::numeric_limits<T>::quiet_NaN();
38739 else if (helper::invalid_range(z, r0, r1))
38740 return std::numeric_limits<T>::quiet_NaN();
38742 const T a = scalar_t(parameters[0])();
38744 for (std::size_t i = r0; i <= r1; ++i)
38746 z[i] = (a * x[i]) + y[i];
38749 return T(1);
38753 template <typename T>
38754 class axpbyz : public exprtk::igeneric_function<T>
38756 public:
38758 typedef typename exprtk::igeneric_function<T> igfun_t;
38759 typedef typename igfun_t::parameter_list_t parameter_list_t;
38760 typedef typename igfun_t::generic_type generic_type;
38761 typedef typename generic_type::scalar_view scalar_t;
38762 typedef typename generic_type::vector_view vector_t;
38764 using exprtk::igeneric_function<T>::operator();
38766 axpbyz()
38767 : exprtk::igeneric_function<T>("TVTVV|TVTVVTT")
38769 z <- ax + by
38770 Overloads:
38771 0. TVTVV - a, x(vector), b, y(vector), z(vector)
38772 1. TVTVVTT - a, x(vector), b, y(vector), z(vector), r0, r1
38776 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38778 const vector_t x(parameters[1]);
38779 const vector_t y(parameters[3]);
38780 vector_t z(parameters[4]);
38782 std::size_t r0 = 0;
38783 std::size_t r1 = std::min(x.size(),y.size()) - 1;
38785 if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1))
38786 return std::numeric_limits<T>::quiet_NaN();
38787 else if (helper::invalid_range(y, r0, r1))
38788 return std::numeric_limits<T>::quiet_NaN();
38789 else if (helper::invalid_range(z, r0, r1))
38790 return std::numeric_limits<T>::quiet_NaN();
38792 const T a = scalar_t(parameters[0])();
38793 const T b = scalar_t(parameters[2])();
38795 for (std::size_t i = r0; i <= r1; ++i)
38797 z[i] = (a * x[i]) + (b * y[i]);
38800 return T(1);
38804 template <typename T>
38805 class axpbz : public exprtk::igeneric_function<T>
38807 public:
38809 typedef typename exprtk::igeneric_function<T> igfun_t;
38810 typedef typename igfun_t::parameter_list_t parameter_list_t;
38811 typedef typename igfun_t::generic_type generic_type;
38812 typedef typename generic_type::scalar_view scalar_t;
38813 typedef typename generic_type::vector_view vector_t;
38815 using exprtk::igeneric_function<T>::operator();
38817 axpbz()
38818 : exprtk::igeneric_function<T>("TVTV|TVTVTT")
38820 z <- ax + b
38821 Overloads:
38822 0. TVTV - a, x(vector), b, z(vector)
38823 1. TVTVTT - a, x(vector), b, z(vector), r0, r1
38827 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38829 const vector_t x(parameters[1]);
38830 vector_t z(parameters[3]);
38832 std::size_t r0 = 0;
38833 std::size_t r1 = x.size() - 1;
38835 if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1))
38836 return std::numeric_limits<T>::quiet_NaN();
38837 else if (helper::invalid_range(z, r0, r1))
38838 return std::numeric_limits<T>::quiet_NaN();
38840 const T a = scalar_t(parameters[0])();
38841 const T b = scalar_t(parameters[2])();
38843 for (std::size_t i = r0; i <= r1; ++i)
38845 z[i] = (a * x[i]) + b;
38848 return T(1);
38852 template <typename T>
38853 class dot : public exprtk::igeneric_function<T>
38855 public:
38857 typedef typename exprtk::igeneric_function<T> igfun_t;
38858 typedef typename igfun_t::parameter_list_t parameter_list_t;
38859 typedef typename igfun_t::generic_type generic_type;
38860 typedef typename generic_type::scalar_view scalar_t;
38861 typedef typename generic_type::vector_view vector_t;
38863 using exprtk::igeneric_function<T>::operator();
38865 dot()
38866 : exprtk::igeneric_function<T>("VV|VVTT")
38868 Overloads:
38869 0. VV - x(vector), y(vector)
38870 1. VVTT - x(vector), y(vector), r0, r1
38874 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38876 const vector_t x(parameters[0]);
38877 const vector_t y(parameters[1]);
38879 std::size_t r0 = 0;
38880 std::size_t r1 = std::min(x.size(),y.size()) - 1;
38882 if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
38883 return std::numeric_limits<T>::quiet_NaN();
38884 else if (helper::invalid_range(y, r0, r1))
38885 return std::numeric_limits<T>::quiet_NaN();
38887 T result = T(0);
38889 for (std::size_t i = r0; i <= r1; ++i)
38891 result += (x[i] * y[i]);
38894 return result;
38898 template <typename T>
38899 class dotk : public exprtk::igeneric_function<T>
38901 public:
38903 typedef typename exprtk::igeneric_function<T> igfun_t;
38904 typedef typename igfun_t::parameter_list_t parameter_list_t;
38905 typedef typename igfun_t::generic_type generic_type;
38906 typedef typename generic_type::scalar_view scalar_t;
38907 typedef typename generic_type::vector_view vector_t;
38909 using exprtk::igeneric_function<T>::operator();
38911 dotk()
38912 : exprtk::igeneric_function<T>("VV|VVTT")
38914 Overloads:
38915 0. VV - x(vector), y(vector)
38916 1. VVTT - x(vector), y(vector), r0, r1
38920 inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38922 const vector_t x(parameters[0]);
38923 const vector_t y(parameters[1]);
38925 std::size_t r0 = 0;
38926 std::size_t r1 = std::min(x.size(),y.size()) - 1;
38928 if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
38929 return std::numeric_limits<T>::quiet_NaN();
38930 else if (helper::invalid_range(y, r0, r1))
38931 return std::numeric_limits<T>::quiet_NaN();
38933 T result = T(0);
38934 T error = T(0);
38936 for (std::size_t i = r0; i <= r1; ++i)
38938 details::kahan_sum(result, error, (x[i] * y[i]));
38941 return result;
38945 template <typename T>
38946 struct package
38948 all_true <T> at;
38949 all_false <T> af;
38950 any_true <T> nt;
38951 any_false <T> nf;
38952 count <T> c;
38953 copy <T> cp;
38954 rol <T> rl;
38955 ror <T> rr;
38956 shift_left <T> sl;
38957 shift_right<T> sr;
38958 sort <T> st;
38959 nthelement <T> ne;
38960 iota <T> ia;
38961 sumk <T> sk;
38962 axpy <T> b1_axpy;
38963 axpby <T> b1_axpby;
38964 axpyz <T> b1_axpyz;
38965 axpbyz <T> b1_axpbyz;
38966 axpbz <T> b1_axpbz;
38967 dot <T> dt;
38968 dotk <T> dtk;
38970 bool register_package(exprtk::symbol_table<T>& symtab)
38972 #define exprtk_register_function(FunctionName,FunctionType) \
38973 if (!symtab.add_function(FunctionName,FunctionType)) \
38975 exprtk_debug(( \
38976 "exprtk::rtl::vecops::register_package - Failed to add function: %s\n", \
38977 FunctionName)); \
38978 return false; \
38981 exprtk_register_function("all_true" ,at)
38982 exprtk_register_function("all_false" ,af)
38983 exprtk_register_function("any_true" ,nt)
38984 exprtk_register_function("any_false" ,nf)
38985 exprtk_register_function("count" , c)
38986 exprtk_register_function("copy" ,cp)
38987 exprtk_register_function("rotate_left" ,rl)
38988 exprtk_register_function("rol" ,rl)
38989 exprtk_register_function("rotate_right" ,rr)
38990 exprtk_register_function("ror" ,rr)
38991 exprtk_register_function("shftl" ,sl)
38992 exprtk_register_function("shftr" ,sr)
38993 exprtk_register_function("sort" ,st)
38994 exprtk_register_function("nth_element" ,ne)
38995 exprtk_register_function("iota" ,ia)
38996 exprtk_register_function("sumk" ,sk)
38997 exprtk_register_function("axpy" ,b1_axpy)
38998 exprtk_register_function("axpby" ,b1_axpby)
38999 exprtk_register_function("axpyz" ,b1_axpyz)
39000 exprtk_register_function("axpbyz",b1_axpbyz)
39001 exprtk_register_function("axpbz" ,b1_axpbz)
39002 exprtk_register_function("dot" ,dt)
39003 exprtk_register_function("dotk" ,dtk)
39004 #undef exprtk_register_function
39006 return true;
39010 } // namespace exprtk::rtl::vecops
39011 } // namespace exprtk::rtl
39012 } // namespace exprtk
39013 #endif
39015 namespace exprtk
39017 namespace information
39019 static const char* library = "Mathematical Expression Toolkit";
39020 static const char* version = "2.7182818284590452353602874713526624977572470936999595749"
39021 "669676277240766303535475945713821785251664274274663919320";
39022 static const char* date = "20200101";
39024 static inline std::string data()
39026 static const std::string info_str = std::string(library) +
39027 std::string(" v") + std::string(version) +
39028 std::string(" (") + date + std::string(")");
39029 return info_str;
39032 } // namespace information
39034 #ifdef exprtk_debug
39035 #undef exprtk_debug
39036 #endif
39038 #ifdef exprtk_error_location
39039 #undef exprtk_error_location
39040 #endif
39042 #ifdef exprtk_disable_fallthrough_begin
39043 #undef exprtk_disable_fallthrough_begin
39044 #endif
39046 #ifdef exprtk_disable_fallthrough_end
39047 #undef exprtk_disable_fallthrough_end
39048 #endif
39050 } // namespace exprtk
39052 #endif