1 /*
2  ******************************************************************
3  *           C++ Mathematical Expression Toolkit Library          *
4  *                                                                *
5  * Author: Arash Partow (1999-2021)                               *
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  ******************************************************************
30 */
31 
32 
33 #ifndef INCLUDE_EXPRTK_HPP
34 #define INCLUDE_EXPRTK_HPP
35 
36 
37 #include <algorithm>
38 #include <cassert>
39 #include <cctype>
40 #include <cmath>
41 #include <complex>
42 #include <cstdio>
43 #include <cstdlib>
44 #include <cstring>
45 #include <deque>
46 #include <exception>
47 #include <functional>
48 #include <iterator>
49 #include <limits>
50 #include <list>
51 #include <map>
52 #include <set>
53 #include <stack>
54 #include <stdexcept>
55 #include <string>
56 #include <utility>
57 #include <vector>
58 
59 
60 namespace exprtk
61 {
62    #ifdef exprtk_enable_debugging
63      #define exprtk_debug(params) printf params
64    #else
65      #define exprtk_debug(params) (void)0
66    #endif
67 
68    #define exprtk_error_location             \
69    "exprtk.hpp:" + details::to_str(__LINE__) \
70 
71    #if defined(__GNUC__) && (__GNUC__  >= 7)
72 
73       #define exprtk_disable_fallthrough_begin                      \
74       _Pragma ("GCC diagnostic push")                               \
75       _Pragma ("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") \
76 
77       #define exprtk_disable_fallthrough_end                        \
78       _Pragma ("GCC diagnostic pop")                                \
79 
80    #else
81       #define exprtk_disable_fallthrough_begin (void)0;
82       #define exprtk_disable_fallthrough_end   (void)0;
83    #endif
84 
85    namespace details
86    {
87       typedef unsigned char            uchar_t;
88       typedef char                      char_t;
89       typedef uchar_t*               uchar_ptr;
90       typedef char_t*                 char_ptr;
91       typedef uchar_t const*        uchar_cptr;
92       typedef char_t const*          char_cptr;
93       typedef unsigned long long int _uint64_t;
94       typedef long long int           _int64_t;
95 
is_whitespace(const char_t c)96       inline bool is_whitespace(const char_t c)
97       {
98          return (' '  == c) || ('\n' == c) ||
99                 ('\r' == c) || ('\t' == c) ||
100                 ('\b' == c) || ('\v' == c) ||
101                 ('\f' == c) ;
102       }
103 
is_operator_char(const char_t c)104       inline bool is_operator_char(const char_t c)
105       {
106          return ('+' == 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) ||
116                 ('|' == c) || (';' == c) ;
117       }
118 
is_letter(const char_t c)119       inline bool is_letter(const char_t c)
120       {
121          return (('a' <= c) && (c <= 'z')) ||
122                 (('A' <= c) && (c <= 'Z')) ;
123       }
124 
is_digit(const char_t c)125       inline bool is_digit(const char_t c)
126       {
127          return ('0' <= c) && (c <= '9');
128       }
129 
is_letter_or_digit(const char_t c)130       inline bool is_letter_or_digit(const char_t c)
131       {
132          return is_letter(c) || is_digit(c);
133       }
134 
is_left_bracket(const char_t c)135       inline bool is_left_bracket(const char_t c)
136       {
137          return ('(' == c) || ('[' == c) || ('{' == c);
138       }
139 
is_right_bracket(const char_t c)140       inline bool is_right_bracket(const char_t c)
141       {
142          return (')' == c) || (']' == c) || ('}' == c);
143       }
144 
is_bracket(const char_t c)145       inline bool is_bracket(const char_t c)
146       {
147          return is_left_bracket(c) || is_right_bracket(c);
148       }
149 
is_sign(const char_t c)150       inline bool is_sign(const char_t c)
151       {
152          return ('+' == c) || ('-' == c);
153       }
154 
is_invalid(const char_t c)155       inline bool is_invalid(const char_t c)
156       {
157          return !is_whitespace   (c) &&
158                 !is_operator_char(c) &&
159                 !is_letter       (c) &&
160                 !is_digit        (c) &&
161                 ('.'  != c)          &&
162                 ('_'  != c)          &&
163                 ('$'  != c)          &&
164                 ('~'  != c)          &&
165                 ('\'' != c);
166       }
167 
is_valid_string_char(const char_t c)168       inline bool is_valid_string_char(const char_t c)
169       {
170          return std::isprint(static_cast<unsigned char>(c)) ||
171                 is_whitespace(c);
172       }
173 
174       #ifndef exprtk_disable_caseinsensitivity
case_normalise(std::string & s)175       inline void case_normalise(std::string& s)
176       {
177          for (std::size_t i = 0; i < s.size(); ++i)
178          {
179             s[i] = static_cast<std::string::value_type>(std::tolower(s[i]));
180          }
181       }
182 
imatch(const char_t c1,const char_t c2)183       inline bool imatch(const char_t c1, const char_t c2)
184       {
185          return std::tolower(c1) == std::tolower(c2);
186       }
187 
imatch(const std::string & s1,const std::string & s2)188       inline bool imatch(const std::string& s1, const std::string& s2)
189       {
190          if (s1.size() == s2.size())
191          {
192             for (std::size_t i = 0; i < s1.size(); ++i)
193             {
194                if (std::tolower(s1[i]) != std::tolower(s2[i]))
195                {
196                   return false;
197                }
198             }
199 
200             return true;
201          }
202 
203          return false;
204       }
205 
206       struct ilesscompare
207       {
operator ()exprtk::details::ilesscompare208          inline bool operator() (const std::string& s1, const std::string& s2) const
209          {
210             const std::size_t length = std::min(s1.size(),s2.size());
211 
212             for (std::size_t i = 0; i < length;  ++i)
213             {
214                const char_t c1 = static_cast<char>(std::tolower(s1[i]));
215                const char_t c2 = static_cast<char>(std::tolower(s2[i]));
216 
217                if (c1 > c2)
218                   return false;
219                else if (c1 < c2)
220                   return true;
221             }
222 
223             return s1.size() < s2.size();
224          }
225       };
226 
227       #else
case_normalise(std::string &)228       inline void case_normalise(std::string&)
229       {}
230 
imatch(const char_t c1,const char_t c2)231       inline bool imatch(const char_t c1, const char_t c2)
232       {
233          return c1 == c2;
234       }
235 
imatch(const std::string & s1,const std::string & s2)236       inline bool imatch(const std::string& s1, const std::string& s2)
237       {
238          return s1 == s2;
239       }
240 
241       struct ilesscompare
242       {
operator ()exprtk::details::ilesscompare243          inline bool operator() (const std::string& s1, const std::string& s2) const
244          {
245             return s1 < s2;
246          }
247       };
248       #endif
249 
is_valid_sf_symbol(const std::string & symbol)250       inline bool is_valid_sf_symbol(const std::string& symbol)
251       {
252          // Special function: $f12 or $F34
253          return (4 == symbol.size())  &&
254                 ('$' == symbol[0])    &&
255                 imatch('f',symbol[1]) &&
256                 is_digit(symbol[2])   &&
257                 is_digit(symbol[3]);
258       }
259 
front(const std::string & s)260       inline const char_t& front(const std::string& s)
261       {
262          return s[0];
263       }
264 
back(const std::string & s)265       inline const char_t& back(const std::string& s)
266       {
267          return s[s.size() - 1];
268       }
269 
to_str(int i)270       inline std::string to_str(int i)
271       {
272          if (0 == i)
273             return std::string("0");
274 
275          std::string result;
276 
277          if (i < 0)
278          {
279             for ( ; i; i /= 10)
280             {
281                result += '0' + char(-(i % 10));
282             }
283 
284             result += '-';
285          }
286          else
287          {
288             for ( ; i; i /= 10)
289             {
290                result += '0' + char(i % 10);
291             }
292          }
293 
294          std::reverse(result.begin(), result.end());
295 
296          return result;
297       }
298 
to_str(std::size_t i)299       inline std::string to_str(std::size_t i)
300       {
301          return to_str(static_cast<int>(i));
302       }
303 
is_hex_digit(const std::string::value_type digit)304       inline bool is_hex_digit(const std::string::value_type digit)
305       {
306          return (('0' <= digit) && (digit <= '9')) ||
307                 (('A' <= digit) && (digit <= 'F')) ||
308                 (('a' <= digit) && (digit <= 'f')) ;
309       }
310 
hex_to_bin(uchar_t h)311       inline uchar_t hex_to_bin(uchar_t h)
312       {
313          if (('0' <= h) && (h <= '9'))
314             return (h - '0');
315          else
316             return static_cast<unsigned char>(std::toupper(h) - 'A');
317       }
318 
319       template <typename Iterator>
parse_hex(Iterator & itr,Iterator end,std::string::value_type & result)320       inline bool parse_hex(Iterator& itr, Iterator end,
321                             std::string::value_type& result)
322       {
323          if (
324               (end ==  (itr    ))               ||
325               (end ==  (itr + 1))               ||
326               (end ==  (itr + 2))               ||
327               (end ==  (itr + 3))               ||
328               ('0' != *(itr    ))               ||
329               ('X' != std::toupper(*(itr + 1))) ||
330               (!is_hex_digit(*(itr + 2)))       ||
331               (!is_hex_digit(*(itr + 3)))
332             )
333          {
334             return false;
335          }
336 
337          result = hex_to_bin(static_cast<uchar_t>(*(itr + 2))) << 4 |
338                   hex_to_bin(static_cast<uchar_t>(*(itr + 3))) ;
339 
340          return true;
341       }
342 
cleanup_escapes(std::string & s)343       inline bool cleanup_escapes(std::string& s)
344       {
345          typedef std::string::iterator str_itr_t;
346 
347          str_itr_t itr1 = s.begin();
348          str_itr_t itr2 = s.begin();
349          str_itr_t end  = s.end  ();
350 
351          std::size_t removal_count  = 0;
352 
353          while (end != itr1)
354          {
355             if ('\\' == (*itr1))
356             {
357                if (end == ++itr1)
358                {
359                   return false;
360                }
361                else if (parse_hex(itr1, end, *itr2))
362                {
363                   itr1+= 4;
364                   itr2+= 1;
365                   removal_count +=4;
366                }
367                else if ('a' == (*itr1)) { (*itr2++) = '\a'; ++itr1; ++removal_count; }
368                else if ('b' == (*itr1)) { (*itr2++) = '\b'; ++itr1; ++removal_count; }
369                else if ('f' == (*itr1)) { (*itr2++) = '\f'; ++itr1; ++removal_count; }
370                else if ('n' == (*itr1)) { (*itr2++) = '\n'; ++itr1; ++removal_count; }
371                else if ('r' == (*itr1)) { (*itr2++) = '\r'; ++itr1; ++removal_count; }
372                else if ('t' == (*itr1)) { (*itr2++) = '\t'; ++itr1; ++removal_count; }
373                else if ('v' == (*itr1)) { (*itr2++) = '\v'; ++itr1; ++removal_count; }
374                else if ('0' == (*itr1)) { (*itr2++) = '\0'; ++itr1; ++removal_count; }
375                else
376                {
377                   (*itr2++) = (*itr1++);
378                   ++removal_count;
379                }
380                continue;
381             }
382             else
383                (*itr2++) = (*itr1++);
384          }
385 
386          if ((removal_count > s.size()) || (0 == removal_count))
387             return false;
388 
389          s.resize(s.size() - removal_count);
390 
391          return true;
392       }
393 
394       class build_string
395       {
396       public:
397 
build_string(const std::size_t & initial_size=64)398          build_string(const std::size_t& initial_size = 64)
399          {
400             data_.reserve(initial_size);
401          }
402 
operator <<(const std::string & s)403          inline build_string& operator << (const std::string& s)
404          {
405             data_ += s;
406             return (*this);
407          }
408 
operator <<(char_cptr s)409          inline build_string& operator << (char_cptr s)
410          {
411             data_ += std::string(s);
412             return (*this);
413          }
414 
operator std::string() const415          inline operator std::string () const
416          {
417             return data_;
418          }
419 
as_string() const420          inline std::string as_string() const
421          {
422             return data_;
423          }
424 
425       private:
426 
427          std::string data_;
428       };
429 
430       static const std::string reserved_words[] =
431                                   {
432                                     "break",  "case",  "continue",  "default",  "false",  "for",
433                                     "if", "else", "ilike",  "in", "like", "and",  "nand", "nor",
434                                     "not",  "null",  "or",   "repeat", "return",  "shl",  "shr",
435                                     "swap", "switch", "true",  "until", "var",  "while", "xnor",
436                                     "xor", "&", "|"
437                                   };
438 
439       static const std::size_t reserved_words_size = sizeof(reserved_words) / sizeof(std::string);
440 
441       static const std::string reserved_symbols[] =
442                                   {
443                                     "abs",  "acos",  "acosh",  "and",  "asin",  "asinh", "atan",
444                                     "atanh", "atan2", "avg",  "break", "case", "ceil",  "clamp",
445                                     "continue",   "cos",   "cosh",   "cot",   "csc",  "default",
446                                     "deg2grad",  "deg2rad",   "equal",  "erf",   "erfc",  "exp",
447                                     "expm1",  "false",   "floor",  "for",   "frac",  "grad2deg",
448                                     "hypot", "iclamp", "if",  "else", "ilike", "in",  "inrange",
449                                     "like",  "log",  "log10", "log2",  "logn",  "log1p", "mand",
450                                     "max", "min",  "mod", "mor",  "mul", "ncdf",  "nand", "nor",
451                                     "not",   "not_equal",   "null",   "or",   "pow",  "rad2deg",
452                                     "repeat", "return", "root", "round", "roundn", "sec", "sgn",
453                                     "shl", "shr", "sin", "sinc", "sinh", "sqrt",  "sum", "swap",
454                                     "switch", "tan",  "tanh", "true",  "trunc", "until",  "var",
455                                     "while", "xnor", "xor", "&", "|"
456                                   };
457 
458       static const std::size_t reserved_symbols_size = sizeof(reserved_symbols) / sizeof(std::string);
459 
460       static const std::string base_function_list[] =
461                                   {
462                                     "abs", "acos",  "acosh", "asin",  "asinh", "atan",  "atanh",
463                                     "atan2",  "avg",  "ceil",  "clamp",  "cos",  "cosh",  "cot",
464                                     "csc",  "equal",  "erf",  "erfc",  "exp",  "expm1", "floor",
465                                     "frac", "hypot", "iclamp",  "like", "log", "log10",  "log2",
466                                     "logn", "log1p", "mand", "max", "min", "mod", "mor",  "mul",
467                                     "ncdf",  "pow",  "root",  "round",  "roundn",  "sec", "sgn",
468                                     "sin", "sinc", "sinh", "sqrt", "sum", "swap", "tan", "tanh",
469                                     "trunc",  "not_equal",  "inrange",  "deg2grad",   "deg2rad",
470                                     "rad2deg", "grad2deg"
471                                   };
472 
473       static const std::size_t base_function_list_size = sizeof(base_function_list) / sizeof(std::string);
474 
475       static const std::string logic_ops_list[] =
476                                   {
477                                     "and", "nand", "nor", "not", "or",  "xnor", "xor", "&", "|"
478                                   };
479 
480       static const std::size_t logic_ops_list_size = sizeof(logic_ops_list) / sizeof(std::string);
481 
482       static const std::string cntrl_struct_list[] =
483                                   {
484                                      "if", "switch", "for", "while", "repeat", "return"
485                                   };
486 
487       static const std::size_t cntrl_struct_list_size = sizeof(cntrl_struct_list) / sizeof(std::string);
488 
489       static const std::string arithmetic_ops_list[] =
490                                   {
491                                     "+", "-", "*", "/", "%", "^"
492                                   };
493 
494       static const std::size_t arithmetic_ops_list_size = sizeof(arithmetic_ops_list) / sizeof(std::string);
495 
496       static const std::string assignment_ops_list[] =
497                                   {
498                                     ":=", "+=", "-=",
499                                     "*=", "/=", "%="
500                                   };
501 
502       static const std::size_t assignment_ops_list_size = sizeof(assignment_ops_list) / sizeof(std::string);
503 
504       static const std::string inequality_ops_list[] =
505                                   {
506                                      "<",  "<=", "==",
507                                      "=",  "!=", "<>",
508                                     ">=",  ">"
509                                   };
510 
511       static const std::size_t inequality_ops_list_size = sizeof(inequality_ops_list) / sizeof(std::string);
512 
is_reserved_word(const std::string & symbol)513       inline bool is_reserved_word(const std::string& symbol)
514       {
515          for (std::size_t i = 0; i < reserved_words_size; ++i)
516          {
517             if (imatch(symbol, reserved_words[i]))
518             {
519                return true;
520             }
521          }
522 
523          return false;
524       }
525 
is_reserved_symbol(const std::string & symbol)526       inline bool is_reserved_symbol(const std::string& symbol)
527       {
528          for (std::size_t i = 0; i < reserved_symbols_size; ++i)
529          {
530             if (imatch(symbol, reserved_symbols[i]))
531             {
532                return true;
533             }
534          }
535 
536          return false;
537       }
538 
is_base_function(const std::string & function_name)539       inline bool is_base_function(const std::string& function_name)
540       {
541          for (std::size_t i = 0; i < base_function_list_size; ++i)
542          {
543             if (imatch(function_name, base_function_list[i]))
544             {
545                return true;
546             }
547          }
548 
549          return false;
550       }
551 
is_control_struct(const std::string & cntrl_strct)552       inline bool is_control_struct(const std::string& cntrl_strct)
553       {
554          for (std::size_t i = 0; i < cntrl_struct_list_size; ++i)
555          {
556             if (imatch(cntrl_strct, cntrl_struct_list[i]))
557             {
558                return true;
559             }
560          }
561 
562          return false;
563       }
564 
is_logic_opr(const std::string & lgc_opr)565       inline bool is_logic_opr(const std::string& lgc_opr)
566       {
567          for (std::size_t i = 0; i < logic_ops_list_size; ++i)
568          {
569             if (imatch(lgc_opr, logic_ops_list[i]))
570             {
571                return true;
572             }
573          }
574 
575          return false;
576       }
577 
578       struct cs_match
579       {
cmpexprtk::details::cs_match580          static inline bool cmp(const char_t c0, const char_t c1)
581          {
582             return (c0 == c1);
583          }
584       };
585 
586       struct cis_match
587       {
cmpexprtk::details::cis_match588          static inline bool cmp(const char_t c0, const char_t c1)
589          {
590             return (std::tolower(c0) == std::tolower(c1));
591          }
592       };
593 
594       template <typename Iterator, typename Compare>
match_impl(const Iterator pattern_begin,const Iterator pattern_end,const Iterator data_begin,const Iterator data_end,const typename std::iterator_traits<Iterator>::value_type & zero_or_more,const typename std::iterator_traits<Iterator>::value_type & zero_or_one)595       inline bool match_impl(const Iterator pattern_begin,
596                              const Iterator pattern_end  ,
597                              const Iterator data_begin   ,
598                              const Iterator data_end     ,
599                              const typename std::iterator_traits<Iterator>::value_type& zero_or_more,
600                              const typename std::iterator_traits<Iterator>::value_type& zero_or_one )
601       {
602          const Iterator null_itr(0);
603 
604          Iterator d_itr    = data_begin;
605          Iterator p_itr    = pattern_begin;
606          Iterator tb_p_itr = null_itr;
607          Iterator tb_d_itr = null_itr;
608 
609          while (d_itr != data_end)
610          {
611             if (zero_or_more == *p_itr)
612             {
613                while ((pattern_end != p_itr) && ((zero_or_more == *p_itr) || (zero_or_one == *p_itr)))
614                {
615                   ++p_itr;
616                }
617 
618                if (pattern_end == p_itr)
619                   return true;
620 
621                const typename std::iterator_traits<Iterator>::value_type c = *(p_itr);
622 
623                while ((data_end != d_itr) && !Compare::cmp(c,*d_itr))
624                {
625                   ++d_itr;
626                }
627 
628                tb_p_itr = p_itr;
629                tb_d_itr = d_itr;
630 
631                continue;
632             }
633             else if (!Compare::cmp(*p_itr, *d_itr) && (zero_or_one != *p_itr))
634             {
635                if (null_itr == tb_d_itr)
636                   return false;
637 
638                d_itr = tb_d_itr++;
639                p_itr = tb_p_itr;
640 
641                continue;
642             }
643 
644             ++p_itr;
645             ++d_itr;
646          }
647 
648          while ((pattern_end != p_itr) && ((zero_or_more == *p_itr) || (zero_or_one == *p_itr)))
649          {
650             ++p_itr;
651          }
652 
653          return (pattern_end == p_itr);
654       }
655 
wc_match(const std::string & wild_card,const std::string & str)656       inline bool wc_match(const std::string& wild_card,
657                            const std::string& str)
658       {
659          return match_impl<char_cptr,cs_match>(
660                    wild_card.data(), wild_card.data() + wild_card.size(),
661                    str.data(), str.data() + str.size(),
662                    '*', '?');
663       }
664 
wc_imatch(const std::string & wild_card,const std::string & str)665       inline bool wc_imatch(const std::string& wild_card,
666                             const std::string& str)
667       {
668          return match_impl<char_cptr,cis_match>(
669                    wild_card.data(), wild_card.data() + wild_card.size(),
670                    str.data(), str.data() + str.size(),
671                    '*', '?');
672       }
673 
sequence_match(const std::string & pattern,const std::string & str,std::size_t & diff_index,char_t & diff_value)674       inline bool sequence_match(const std::string& pattern,
675                                  const std::string& str,
676                                  std::size_t&       diff_index,
677                                  char_t&            diff_value)
678       {
679          if (str.empty())
680          {
681             return ("Z" == pattern);
682          }
683          else if ('*' == pattern[0])
684             return false;
685 
686          typedef std::string::const_iterator itr_t;
687 
688          itr_t p_itr = pattern.begin();
689          itr_t s_itr = str    .begin();
690 
691          itr_t p_end = pattern.end();
692          itr_t s_end = str    .end();
693 
694          while ((s_end != s_itr) && (p_end != p_itr))
695          {
696             if ('*' == (*p_itr))
697             {
698                const char_t target = static_cast<char>(std::toupper(*(p_itr - 1)));
699 
700                if ('*' == target)
701                {
702                   diff_index = static_cast<std::size_t>(std::distance(str.begin(),s_itr));
703                   diff_value = static_cast<char>(std::toupper(*p_itr));
704 
705                   return false;
706                }
707                else
708                   ++p_itr;
709 
710                while (s_itr != s_end)
711                {
712                   if (target != std::toupper(*s_itr))
713                      break;
714                   else
715                      ++s_itr;
716                }
717 
718                continue;
719             }
720             else if (
721                       ('?' != *p_itr) &&
722                       std::toupper(*p_itr) != std::toupper(*s_itr)
723                     )
724             {
725                diff_index = static_cast<std::size_t>(std::distance(str.begin(),s_itr));
726                diff_value = static_cast<char>(std::toupper(*p_itr));
727 
728                return false;
729             }
730 
731             ++p_itr;
732             ++s_itr;
733          }
734 
735          return (
736                   (s_end == s_itr) &&
737                   (
738                     (p_end ==  p_itr) ||
739                     ('*'   == *p_itr)
740                   )
741                 );
742       }
743 
744       static const double pow10[] = {
745                                       1.0,
746                                       1.0E+001, 1.0E+002, 1.0E+003, 1.0E+004,
747                                       1.0E+005, 1.0E+006, 1.0E+007, 1.0E+008,
748                                       1.0E+009, 1.0E+010, 1.0E+011, 1.0E+012,
749                                       1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016
750                                     };
751 
752       static const std::size_t pow10_size = sizeof(pow10) / sizeof(double);
753 
754       namespace numeric
755       {
756          namespace constant
757          {
758             static const double e       =  2.71828182845904523536028747135266249775724709369996;
759             static const double pi      =  3.14159265358979323846264338327950288419716939937510;
760             static const double pi_2    =  1.57079632679489661923132169163975144209858469968755;
761             static const double pi_4    =  0.78539816339744830961566084581987572104929234984378;
762             static const double pi_180  =  0.01745329251994329576923690768488612713442871888542;
763             static const double _1_pi   =  0.31830988618379067153776752674502872406891929148091;
764             static const double _2_pi   =  0.63661977236758134307553505349005744813783858296183;
765             static const double _180_pi = 57.29577951308232087679815481410517033240547246656443;
766             static const double log2    =  0.69314718055994530941723212145817656807550013436026;
767             static const double sqrt2   =  1.41421356237309504880168872420969807856967187537695;
768          }
769 
770          namespace details
771          {
unknown_type_tagexprtk::details::numeric::details::unknown_type_tag772             struct unknown_type_tag { unknown_type_tag() {} };
real_type_tagexprtk::details::numeric::details::real_type_tag773             struct real_type_tag    { real_type_tag   () {} };
complex_type_tagexprtk::details::numeric::details::complex_type_tag774             struct complex_type_tag { complex_type_tag() {} };
int_type_tagexprtk::details::numeric::details::int_type_tag775             struct int_type_tag     { int_type_tag    () {} };
776 
777             template <typename T>
778             struct number_type
779             {
780                typedef unknown_type_tag type;
number_typeexprtk::details::numeric::details::number_type781                number_type() {}
782             };
783 
784             #define exprtk_register_real_type_tag(T)             \
785             template <> struct number_type<T>                    \
786             { typedef real_type_tag type; number_type() {} };    \
787 
788             #define exprtk_register_complex_type_tag(T)          \
789             template <> struct number_type<std::complex<T> >     \
790             { typedef complex_type_tag type; number_type() {} }; \
791 
792             #define exprtk_register_int_type_tag(T)              \
793             template <> struct number_type<T>                    \
794             { typedef int_type_tag type; number_type() {} };     \
795 
796             exprtk_register_real_type_tag(double     )
797             exprtk_register_real_type_tag(long double)
798             exprtk_register_real_type_tag(float      )
799 
800             exprtk_register_complex_type_tag(double     )
801             exprtk_register_complex_type_tag(long double)
802             exprtk_register_complex_type_tag(float      )
803 
804             exprtk_register_int_type_tag(short         )
805             exprtk_register_int_type_tag(int           )
806             exprtk_register_int_type_tag(_int64_t      )
807             exprtk_register_int_type_tag(unsigned short)
808             exprtk_register_int_type_tag(unsigned int  )
809             exprtk_register_int_type_tag(_uint64_t     )
810 
811             #undef exprtk_register_real_type_tag
812             #undef exprtk_register_int_type_tag
813 
814             template <typename T>
815             struct epsilon_type {};
816 
817             #define exprtk_define_epsilon_type(Type, Epsilon) \
818             template <> struct epsilon_type<Type>             \
819             {                                                 \
820                static inline Type value()                     \
821                {                                              \
822                   const Type epsilon = static_cast<Type>(Epsilon);         \
823                   return epsilon;                             \
824                }                                              \
825             };                                                \
826 
827             exprtk_define_epsilon_type(float      ,      0.000001f)
828             exprtk_define_epsilon_type(double     ,   0.0000000001)
829             exprtk_define_epsilon_type(long double, 0.000000000001)
830 
831             #undef exprtk_define_epsilon_type
832 
833             template <typename T>
is_nan_impl(const T v,real_type_tag)834             inline bool is_nan_impl(const T v, real_type_tag)
835             {
836                return std::not_equal_to<T>()(v,v);
837             }
838 
839             template <typename T>
to_int32_impl(const T v,real_type_tag)840             inline int to_int32_impl(const T v, real_type_tag)
841             {
842                return static_cast<int>(v);
843             }
844 
845             template <typename T>
to_int64_impl(const T v,real_type_tag)846             inline _int64_t to_int64_impl(const T v, real_type_tag)
847             {
848                return static_cast<_int64_t>(v);
849             }
850 
851             template <typename T>
is_true_impl(const T v)852             inline bool is_true_impl(const T v)
853             {
854                return std::not_equal_to<T>()(T(0),v);
855             }
856 
857             template <typename T>
is_false_impl(const T v)858             inline bool is_false_impl(const T v)
859             {
860                return std::equal_to<T>()(T(0),v);
861             }
862 
863             template <typename T>
abs_impl(const T v,real_type_tag)864             inline T abs_impl(const T v, real_type_tag)
865             {
866                return ((v < T(0)) ? -v : v);
867             }
868 
869             template <typename T>
min_impl(const T v0,const T v1,real_type_tag)870             inline T min_impl(const T v0, const T v1, real_type_tag)
871             {
872                return std::min<T>(v0,v1);
873             }
874 
875             template <typename T>
max_impl(const T v0,const T v1,real_type_tag)876             inline T max_impl(const T v0, const T v1, real_type_tag)
877             {
878                return std::max<T>(v0,v1);
879             }
880 
881             template <typename T>
equal_impl(const T v0,const T v1,real_type_tag)882             inline T equal_impl(const T v0, const T v1, real_type_tag)
883             {
884                const T epsilon = epsilon_type<T>::value();
885                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);
886             }
887 
equal_impl(const float v0,const float v1,real_type_tag)888             inline float equal_impl(const float v0, const float v1, real_type_tag)
889             {
890                const float epsilon = epsilon_type<float>::value();
891                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;
892             }
893 
894             template <typename T>
equal_impl(const T v0,const T v1,int_type_tag)895             inline T equal_impl(const T v0, const T v1, int_type_tag)
896             {
897                return (v0 == v1) ? 1 : 0;
898             }
899 
900             template <typename T>
expm1_impl(const T v,real_type_tag)901             inline T expm1_impl(const T v, real_type_tag)
902             {
903                // return std::expm1<T>(v);
904                if (abs_impl(v,real_type_tag()) < T(0.00001))
905                   return v + (T(0.5) * v * v);
906                else
907                   return std::exp(v) - T(1);
908             }
909 
910             template <typename T>
expm1_impl(const T v,int_type_tag)911             inline T expm1_impl(const T v, int_type_tag)
912             {
913                return T(std::exp<double>(v)) - T(1);
914             }
915 
916             template <typename T>
nequal_impl(const T v0,const T v1,real_type_tag)917             inline T nequal_impl(const T v0, const T v1, real_type_tag)
918             {
919                typedef real_type_tag rtg;
920                const T epsilon = epsilon_type<T>::value();
921                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);
922             }
923 
nequal_impl(const float v0,const float v1,real_type_tag)924             inline float nequal_impl(const float v0, const float v1, real_type_tag)
925             {
926                typedef real_type_tag rtg;
927                const float epsilon = epsilon_type<float>::value();
928                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;
929             }
930 
931             template <typename T>
nequal_impl(const T v0,const T v1,int_type_tag)932             inline T nequal_impl(const T v0, const T v1, int_type_tag)
933             {
934                return (v0 != v1) ? 1 : 0;
935             }
936 
937             template <typename T>
modulus_impl(const T v0,const T v1,real_type_tag)938             inline T modulus_impl(const T v0, const T v1, real_type_tag)
939             {
940                return std::fmod(v0,v1);
941             }
942 
943             template <typename T>
modulus_impl(const T v0,const T v1,int_type_tag)944             inline T modulus_impl(const T v0, const T v1, int_type_tag)
945             {
946                return v0 % v1;
947             }
948 
949             template <typename T>
pow_impl(const T v0,const T v1,real_type_tag)950             inline T pow_impl(const T v0, const T v1, real_type_tag)
951             {
952                return std::pow(v0,v1);
953             }
954 
955             template <typename T>
pow_impl(const T v0,const T v1,int_type_tag)956             inline T pow_impl(const T v0, const T v1, int_type_tag)
957             {
958                return std::pow(static_cast<double>(v0),static_cast<double>(v1));
959             }
960 
961             template <typename T>
logn_impl(const T v0,const T v1,real_type_tag)962             inline T logn_impl(const T v0, const T v1, real_type_tag)
963             {
964                return std::log(v0) / std::log(v1);
965             }
966 
967             template <typename T>
logn_impl(const T v0,const T v1,int_type_tag)968             inline T logn_impl(const T v0, const T v1, int_type_tag)
969             {
970                return static_cast<T>(logn_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag()));
971             }
972 
973             template <typename T>
log1p_impl(const T v,real_type_tag)974             inline T log1p_impl(const T v, real_type_tag)
975             {
976                if (v > T(-1))
977                {
978                   if (abs_impl(v,real_type_tag()) > T(0.0001))
979                   {
980                      return std::log(T(1) + v);
981                   }
982                   else
983                      return (T(-0.5) * v + T(1)) * v;
984                }
985                else
986                   return std::numeric_limits<T>::quiet_NaN();
987             }
988 
989             template <typename T>
log1p_impl(const T v,int_type_tag)990             inline T log1p_impl(const T v, int_type_tag)
991             {
992                if (v > T(-1))
993                {
994                   return std::log(T(1) + v);
995                }
996                else
997                   return std::numeric_limits<T>::quiet_NaN();
998             }
999 
1000             template <typename T>
root_impl(const T v0,const T v1,real_type_tag)1001             inline T root_impl(const T v0, const T v1, real_type_tag)
1002             {
1003                if (v1 < T(0))
1004                   return std::numeric_limits<T>::quiet_NaN();
1005 
1006                const std::size_t n = static_cast<std::size_t>(v1);
1007 
1008                if ((v0 < T(0)) && (0 == (n % 2)))
1009                   return std::numeric_limits<T>::quiet_NaN();
1010 
1011                return std::pow(v0, T(1) / n);
1012             }
1013 
1014             template <typename T>
root_impl(const T v0,const T v1,int_type_tag)1015             inline T root_impl(const T v0, const T v1, int_type_tag)
1016             {
1017                return root_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag());
1018             }
1019 
1020             template <typename T>
round_impl(const T v,real_type_tag)1021             inline T round_impl(const T v, real_type_tag)
1022             {
1023                return ((v < T(0)) ? std::ceil(v - T(0.5)) : std::floor(v + T(0.5)));
1024             }
1025 
1026             template <typename T>
roundn_impl(const T v0,const T v1,real_type_tag)1027             inline T roundn_impl(const T v0, const T v1, real_type_tag)
1028             {
1029                const int index = std::max<int>(0, std::min<int>(pow10_size - 1, static_cast<int>(std::floor(v1))));
1030                const T p10 = T(pow10[index]);
1031 
1032                if (v0 < T(0))
1033                   return T(std::ceil ((v0 * p10) - T(0.5)) / p10);
1034                else
1035                   return T(std::floor((v0 * p10) + T(0.5)) / p10);
1036             }
1037 
1038             template <typename T>
roundn_impl(const T v0,const T,int_type_tag)1039             inline T roundn_impl(const T v0, const T, int_type_tag)
1040             {
1041                return v0;
1042             }
1043 
1044             template <typename T>
hypot_impl(const T v0,const T v1,real_type_tag)1045             inline T hypot_impl(const T v0, const T v1, real_type_tag)
1046             {
1047                return std::sqrt((v0 * v0) + (v1 * v1));
1048             }
1049 
1050             template <typename T>
hypot_impl(const T v0,const T v1,int_type_tag)1051             inline T hypot_impl(const T v0, const T v1, int_type_tag)
1052             {
1053                return static_cast<T>(std::sqrt(static_cast<double>((v0 * v0) + (v1 * v1))));
1054             }
1055 
1056             template <typename T>
atan2_impl(const T v0,const T v1,real_type_tag)1057             inline T atan2_impl(const T v0, const T v1, real_type_tag)
1058             {
1059                return std::atan2(v0,v1);
1060             }
1061 
1062             template <typename T>
atan2_impl(const T,const T,int_type_tag)1063             inline T atan2_impl(const T, const T, int_type_tag)
1064             {
1065                return 0;
1066             }
1067 
1068             template <typename T>
shr_impl(const T v0,const T v1,real_type_tag)1069             inline T shr_impl(const T v0, const T v1, real_type_tag)
1070             {
1071                return v0 * (T(1) / std::pow(T(2),static_cast<T>(static_cast<int>(v1))));
1072             }
1073 
1074             template <typename T>
shr_impl(const T v0,const T v1,int_type_tag)1075             inline T shr_impl(const T v0, const T v1, int_type_tag)
1076             {
1077                return v0 >> v1;
1078             }
1079 
1080             template <typename T>
shl_impl(const T v0,const T v1,real_type_tag)1081             inline T shl_impl(const T v0, const T v1, real_type_tag)
1082             {
1083                return v0 * std::pow(T(2),static_cast<T>(static_cast<int>(v1)));
1084             }
1085 
1086             template <typename T>
shl_impl(const T v0,const T v1,int_type_tag)1087             inline T shl_impl(const T v0, const T v1, int_type_tag)
1088             {
1089                return v0 << v1;
1090             }
1091 
1092             template <typename T>
sgn_impl(const T v,real_type_tag)1093             inline T sgn_impl(const T v, real_type_tag)
1094             {
1095                     if (v > T(0)) return T(+1);
1096                else if (v < T(0)) return T(-1);
1097                else               return T( 0);
1098             }
1099 
1100             template <typename T>
sgn_impl(const T v,int_type_tag)1101             inline T sgn_impl(const T v, int_type_tag)
1102             {
1103                     if (v > T(0)) return T(+1);
1104                else if (v < T(0)) return T(-1);
1105                else               return T( 0);
1106             }
1107 
1108             template <typename T>
and_impl(const T v0,const T v1,real_type_tag)1109             inline T and_impl(const T v0, const T v1, real_type_tag)
1110             {
1111                return (is_true_impl(v0) && is_true_impl(v1)) ? T(1) : T(0);
1112             }
1113 
1114             template <typename T>
and_impl(const T v0,const T v1,int_type_tag)1115             inline T and_impl(const T v0, const T v1, int_type_tag)
1116             {
1117                return v0 && v1;
1118             }
1119 
1120             template <typename T>
nand_impl(const T v0,const T v1,real_type_tag)1121             inline T nand_impl(const T v0, const T v1, real_type_tag)
1122             {
1123                return (is_false_impl(v0) || is_false_impl(v1)) ? T(1) : T(0);
1124             }
1125 
1126             template <typename T>
nand_impl(const T v0,const T v1,int_type_tag)1127             inline T nand_impl(const T v0, const T v1, int_type_tag)
1128             {
1129                return !(v0 && v1);
1130             }
1131 
1132             template <typename T>
or_impl(const T v0,const T v1,real_type_tag)1133             inline T or_impl(const T v0, const T v1, real_type_tag)
1134             {
1135                return (is_true_impl(v0) || is_true_impl(v1)) ? T(1) : T(0);
1136             }
1137 
1138             template <typename T>
or_impl(const T v0,const T v1,int_type_tag)1139             inline T or_impl(const T v0, const T v1, int_type_tag)
1140             {
1141                return (v0 || v1);
1142             }
1143 
1144             template <typename T>
nor_impl(const T v0,const T v1,real_type_tag)1145             inline T nor_impl(const T v0, const T v1, real_type_tag)
1146             {
1147                return (is_false_impl(v0) && is_false_impl(v1)) ? T(1) : T(0);
1148             }
1149 
1150             template <typename T>
nor_impl(const T v0,const T v1,int_type_tag)1151             inline T nor_impl(const T v0, const T v1, int_type_tag)
1152             {
1153                return !(v0 || v1);
1154             }
1155 
1156             template <typename T>
xor_impl(const T v0,const T v1,real_type_tag)1157             inline T xor_impl(const T v0, const T v1, real_type_tag)
1158             {
1159                return (is_false_impl(v0) != is_false_impl(v1)) ? T(1) : T(0);
1160             }
1161 
1162             template <typename T>
xor_impl(const T v0,const T v1,int_type_tag)1163             inline T xor_impl(const T v0, const T v1, int_type_tag)
1164             {
1165                return v0 ^ v1;
1166             }
1167 
1168             template <typename T>
xnor_impl(const T v0,const T v1,real_type_tag)1169             inline T xnor_impl(const T v0, const T v1, real_type_tag)
1170             {
1171                const bool v0_true = is_true_impl(v0);
1172                const bool v1_true = is_true_impl(v1);
1173 
1174                if ((v0_true &&  v1_true) || (!v0_true && !v1_true))
1175                   return T(1);
1176                else
1177                   return T(0);
1178             }
1179 
1180             template <typename T>
xnor_impl(const T v0,const T v1,int_type_tag)1181             inline T xnor_impl(const T v0, const T v1, int_type_tag)
1182             {
1183                const bool v0_true = is_true_impl(v0);
1184                const bool v1_true = is_true_impl(v1);
1185 
1186                if ((v0_true &&  v1_true) || (!v0_true && !v1_true))
1187                   return T(1);
1188                else
1189                   return T(0);
1190             }
1191 
1192             #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER)
1193             #define exprtk_define_erf(TT,impl)           \
1194             inline TT erf_impl(TT v) { return impl(v); } \
1195 
exprtk_define_erf(float,::erff)1196             exprtk_define_erf(      float,::erff)
1197             exprtk_define_erf(     double,::erf )
1198             exprtk_define_erf(long double,::erfl)
1199             #undef exprtk_define_erf
1200             #endif
1201 
1202             template <typename T>
1203             inline T erf_impl(T v, real_type_tag)
1204             {
1205                #if defined(_MSC_VER) && (_MSC_VER < 1900)
1206                // Credits: Abramowitz & Stegun Equations 7.1.25-28
1207                static const T c[] = {
1208                                       T( 1.26551223), T(1.00002368),
1209                                       T( 0.37409196), T(0.09678418),
1210                                       T(-0.18628806), T(0.27886807),
1211                                       T(-1.13520398), T(1.48851587),
1212                                       T(-0.82215223), T(0.17087277)
1213                                     };
1214 
1215                const T t = T(1) / (T(1) + T(0.5) * abs_impl(v,real_type_tag()));
1216 
1217                T result = T(1) - t * std::exp((-v * v) -
1218                                       c[0] + t * (c[1] + t *
1219                                      (c[2] + t * (c[3] + t *
1220                                      (c[4] + t * (c[5] + t *
1221                                      (c[6] + t * (c[7] + t *
1222                                      (c[8] + t * (c[9]))))))))));
1223 
1224                return (v >= T(0)) ? result : -result;
1225                #else
1226                return erf_impl(v);
1227                #endif
1228             }
1229 
1230             template <typename T>
erf_impl(T v,int_type_tag)1231             inline T erf_impl(T v, int_type_tag)
1232             {
1233                return erf_impl(static_cast<double>(v),real_type_tag());
1234             }
1235 
1236             #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER)
1237             #define exprtk_define_erfc(TT,impl)           \
1238             inline TT erfc_impl(TT v) { return impl(v); } \
1239 
exprtk_define_erfc(float,::erfcf)1240             exprtk_define_erfc(      float,::erfcf)
1241             exprtk_define_erfc(     double,::erfc )
1242             exprtk_define_erfc(long double,::erfcl)
1243             #undef exprtk_define_erfc
1244             #endif
1245 
1246             template <typename T>
1247             inline T erfc_impl(T v, real_type_tag)
1248             {
1249                #if defined(_MSC_VER) && (_MSC_VER < 1900)
1250                return T(1) - erf_impl(v,real_type_tag());
1251                #else
1252                return erfc_impl(v);
1253                #endif
1254             }
1255 
1256             template <typename T>
erfc_impl(T v,int_type_tag)1257             inline T erfc_impl(T v, int_type_tag)
1258             {
1259                return erfc_impl(static_cast<double>(v),real_type_tag());
1260             }
1261 
1262             template <typename T>
ncdf_impl(T v,real_type_tag)1263             inline T ncdf_impl(T v, real_type_tag)
1264             {
1265                T cnd = T(0.5) * (T(1) + erf_impl(
1266                                            abs_impl(v,real_type_tag()) /
1267                                            T(numeric::constant::sqrt2),real_type_tag()));
1268                return  (v < T(0)) ? (T(1) - cnd) : cnd;
1269             }
1270 
1271             template <typename T>
ncdf_impl(T v,int_type_tag)1272             inline T ncdf_impl(T v, int_type_tag)
1273             {
1274                return ncdf_impl(static_cast<double>(v),real_type_tag());
1275             }
1276 
1277             template <typename T>
sinc_impl(T v,real_type_tag)1278             inline T sinc_impl(T v, real_type_tag)
1279             {
1280                if (std::abs(v) >= std::numeric_limits<T>::epsilon())
1281                    return(std::sin(v) / v);
1282                else
1283                   return T(1);
1284             }
1285 
1286             template <typename T>
sinc_impl(T v,int_type_tag)1287             inline T sinc_impl(T v, int_type_tag)
1288             {
1289                return sinc_impl(static_cast<double>(v),real_type_tag());
1290             }
1291 
acos_impl(const T v,real_type_tag)1292             template <typename T> inline T  acos_impl(const T v, real_type_tag) { return std::acos (v); }
acosh_impl(const T v,real_type_tag)1293             template <typename T> inline T acosh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) - T(1))); }
asin_impl(const T v,real_type_tag)1294             template <typename T> inline T  asin_impl(const T v, real_type_tag) { return std::asin (v); }
asinh_impl(const T v,real_type_tag)1295             template <typename T> inline T asinh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) + T(1))); }
atan_impl(const T v,real_type_tag)1296             template <typename T> inline T  atan_impl(const T v, real_type_tag) { return std::atan (v); }
atanh_impl(const T v,real_type_tag)1297             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); }
ceil_impl(const T v,real_type_tag)1298             template <typename T> inline T  ceil_impl(const T v, real_type_tag) { return std::ceil (v); }
cos_impl(const T v,real_type_tag)1299             template <typename T> inline T   cos_impl(const T v, real_type_tag) { return std::cos  (v); }
cosh_impl(const T v,real_type_tag)1300             template <typename T> inline T  cosh_impl(const T v, real_type_tag) { return std::cosh (v); }
exp_impl(const T v,real_type_tag)1301             template <typename T> inline T   exp_impl(const T v, real_type_tag) { return std::exp  (v); }
floor_impl(const T v,real_type_tag)1302             template <typename T> inline T floor_impl(const T v, real_type_tag) { return std::floor(v); }
log_impl(const T v,real_type_tag)1303             template <typename T> inline T   log_impl(const T v, real_type_tag) { return std::log  (v); }
log10_impl(const T v,real_type_tag)1304             template <typename T> inline T log10_impl(const T v, real_type_tag) { return std::log10(v); }
log2_impl(const T v,real_type_tag)1305             template <typename T> inline T  log2_impl(const T v, real_type_tag) { return std::log(v)/T(numeric::constant::log2); }
neg_impl(const T v,real_type_tag)1306             template <typename T> inline T   neg_impl(const T v, real_type_tag) { return -v;            }
pos_impl(const T v,real_type_tag)1307             template <typename T> inline T   pos_impl(const T v, real_type_tag) { return +v;            }
sin_impl(const T v,real_type_tag)1308             template <typename T> inline T   sin_impl(const T v, real_type_tag) { return std::sin  (v); }
sinh_impl(const T v,real_type_tag)1309             template <typename T> inline T  sinh_impl(const T v, real_type_tag) { return std::sinh (v); }
sqrt_impl(const T v,real_type_tag)1310             template <typename T> inline T  sqrt_impl(const T v, real_type_tag) { return std::sqrt (v); }
tan_impl(const T v,real_type_tag)1311             template <typename T> inline T   tan_impl(const T v, real_type_tag) { return std::tan  (v); }
tanh_impl(const T v,real_type_tag)1312             template <typename T> inline T  tanh_impl(const T v, real_type_tag) { return std::tanh (v); }
cot_impl(const T v,real_type_tag)1313             template <typename T> inline T   cot_impl(const T v, real_type_tag) { return T(1) / std::tan(v); }
sec_impl(const T v,real_type_tag)1314             template <typename T> inline T   sec_impl(const T v, real_type_tag) { return T(1) / std::cos(v); }
csc_impl(const T v,real_type_tag)1315             template <typename T> inline T   csc_impl(const T v, real_type_tag) { return T(1) / std::sin(v); }
r2d_impl(const T v,real_type_tag)1316             template <typename T> inline T   r2d_impl(const T v, real_type_tag) { return (v * T(numeric::constant::_180_pi)); }
d2r_impl(const T v,real_type_tag)1317             template <typename T> inline T   d2r_impl(const T v, real_type_tag) { return (v * T(numeric::constant::pi_180));  }
d2g_impl(const T v,real_type_tag)1318             template <typename T> inline T   d2g_impl(const T v, real_type_tag) { return (v * T(20.0/9.0)); }
g2d_impl(const T v,real_type_tag)1319             template <typename T> inline T   g2d_impl(const T v, real_type_tag) { return (v * T(9.0/20.0)); }
notl_impl(const T v,real_type_tag)1320             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)); }
frac_impl(const T v,real_type_tag)1321             template <typename T> inline T  frac_impl(const T v, real_type_tag) { return (v - static_cast<long long>(v)); }
trunc_impl(const T v,real_type_tag)1322             template <typename T> inline T trunc_impl(const T v, real_type_tag) { return T(static_cast<long long>(v));    }
1323 
const_pi_impl(real_type_tag)1324             template <typename T> inline T const_pi_impl(real_type_tag) { return T(numeric::constant::pi); }
const_e_impl(real_type_tag)1325             template <typename T> inline T const_e_impl (real_type_tag) { return T(numeric::constant::e);  }
1326 
abs_impl(const T v,int_type_tag)1327             template <typename T> inline T   abs_impl(const T v, int_type_tag) { return ((v >= T(0)) ? v : -v); }
exp_impl(const T v,int_type_tag)1328             template <typename T> inline T   exp_impl(const T v, int_type_tag) { return std::exp  (v); }
log_impl(const T v,int_type_tag)1329             template <typename T> inline T   log_impl(const T v, int_type_tag) { return std::log  (v); }
log10_impl(const T v,int_type_tag)1330             template <typename T> inline T log10_impl(const T v, int_type_tag) { return std::log10(v); }
log2_impl(const T v,int_type_tag)1331             template <typename T> inline T  log2_impl(const T v, int_type_tag) { return std::log(v)/T(numeric::constant::log2); }
neg_impl(const T v,int_type_tag)1332             template <typename T> inline T   neg_impl(const T v, int_type_tag) { return -v;            }
pos_impl(const T v,int_type_tag)1333             template <typename T> inline T   pos_impl(const T v, int_type_tag) { return +v;            }
ceil_impl(const T v,int_type_tag)1334             template <typename T> inline T  ceil_impl(const T v, int_type_tag) { return v;             }
floor_impl(const T v,int_type_tag)1335             template <typename T> inline T floor_impl(const T v, int_type_tag) { return v;             }
round_impl(const T v,int_type_tag)1336             template <typename T> inline T round_impl(const T v, int_type_tag) { return v;             }
notl_impl(const T v,int_type_tag)1337             template <typename T> inline T  notl_impl(const T v, int_type_tag) { return !v;            }
sqrt_impl(const T v,int_type_tag)1338             template <typename T> inline T  sqrt_impl(const T v, int_type_tag) { return std::sqrt (v); }
frac_impl(const T,int_type_tag)1339             template <typename T> inline T  frac_impl(const T  , int_type_tag) { return T(0);          }
trunc_impl(const T v,int_type_tag)1340             template <typename T> inline T trunc_impl(const T v, int_type_tag) { return v;             }
acos_impl(const T,int_type_tag)1341             template <typename T> inline T  acos_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
acosh_impl(const T,int_type_tag)1342             template <typename T> inline T acosh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
asin_impl(const T,int_type_tag)1343             template <typename T> inline T  asin_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
asinh_impl(const T,int_type_tag)1344             template <typename T> inline T asinh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
atan_impl(const T,int_type_tag)1345             template <typename T> inline T  atan_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
atanh_impl(const T,int_type_tag)1346             template <typename T> inline T atanh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
cos_impl(const T,int_type_tag)1347             template <typename T> inline T   cos_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
cosh_impl(const T,int_type_tag)1348             template <typename T> inline T  cosh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
sin_impl(const T,int_type_tag)1349             template <typename T> inline T   sin_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
sinh_impl(const T,int_type_tag)1350             template <typename T> inline T  sinh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
tan_impl(const T,int_type_tag)1351             template <typename T> inline T   tan_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
tanh_impl(const T,int_type_tag)1352             template <typename T> inline T  tanh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
cot_impl(const T,int_type_tag)1353             template <typename T> inline T   cot_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
sec_impl(const T,int_type_tag)1354             template <typename T> inline T   sec_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
csc_impl(const T,int_type_tag)1355             template <typename T> inline T   csc_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1356 
1357             template <typename T>
is_integer_impl(const T & v,real_type_tag)1358             inline bool is_integer_impl(const T& v, real_type_tag)
1359             {
1360                return std::equal_to<T>()(T(0),std::fmod(v,T(1)));
1361             }
1362 
1363             template <typename T>
is_integer_impl(const T &,int_type_tag)1364             inline bool is_integer_impl(const T&, int_type_tag)
1365             {
1366                return true;
1367             }
1368          }
1369 
1370          template <typename Type>
1371          struct numeric_info { enum { length = 0, size = 32, bound_length = 0, min_exp = 0, max_exp = 0 }; };
1372 
1373          template <> struct numeric_info<int>         { enum { length = 10, size = 16, bound_length = 9}; };
1374          template <> struct numeric_info<float>       { enum { min_exp =  -38, max_exp =  +38}; };
1375          template <> struct numeric_info<double>      { enum { min_exp = -308, max_exp = +308}; };
1376          template <> struct numeric_info<long double> { enum { min_exp = -308, max_exp = +308}; };
1377 
1378          template <typename T>
to_int32(const T v)1379          inline int to_int32(const T v)
1380          {
1381             const typename details::number_type<T>::type num_type;
1382             return to_int32_impl(v, num_type);
1383          }
1384 
1385          template <typename T>
to_int64(const T v)1386          inline _int64_t to_int64(const T v)
1387          {
1388             const typename details::number_type<T>::type num_type;
1389             return to_int64_impl(v, num_type);
1390          }
1391 
1392          template <typename T>
is_nan(const T v)1393          inline bool is_nan(const T v)
1394          {
1395             const typename details::number_type<T>::type num_type;
1396             return is_nan_impl(v, num_type);
1397          }
1398 
1399          template <typename T>
min(const T v0,const T v1)1400          inline T min(const T v0, const T v1)
1401          {
1402             const typename details::number_type<T>::type num_type;
1403             return min_impl(v0, v1, num_type);
1404          }
1405 
1406          template <typename T>
max(const T v0,const T v1)1407          inline T max(const T v0, const T v1)
1408          {
1409             const typename details::number_type<T>::type num_type;
1410             return max_impl(v0, v1, num_type);
1411          }
1412 
1413          template <typename T>
equal(const T v0,const T v1)1414          inline T equal(const T v0, const T v1)
1415          {
1416             const typename details::number_type<T>::type num_type;
1417             return equal_impl(v0, v1, num_type);
1418          }
1419 
1420          template <typename T>
nequal(const T v0,const T v1)1421          inline T nequal(const T v0, const T v1)
1422          {
1423             const typename details::number_type<T>::type num_type;
1424             return nequal_impl(v0, v1, num_type);
1425          }
1426 
1427          template <typename T>
modulus(const T v0,const T v1)1428          inline T modulus(const T v0, const T v1)
1429          {
1430             const typename details::number_type<T>::type num_type;
1431             return modulus_impl(v0, v1, num_type);
1432          }
1433 
1434          template <typename T>
pow(const T v0,const T v1)1435          inline T pow(const T v0, const T v1)
1436          {
1437             const typename details::number_type<T>::type num_type;
1438             return pow_impl(v0, v1, num_type);
1439          }
1440 
1441          template <typename T>
logn(const T v0,const T v1)1442          inline T logn(const T v0, const T v1)
1443          {
1444             const typename details::number_type<T>::type num_type;
1445             return logn_impl(v0, v1, num_type);
1446          }
1447 
1448          template <typename T>
root(const T v0,const T v1)1449          inline T root(const T v0, const T v1)
1450          {
1451             const typename details::number_type<T>::type num_type;
1452             return root_impl(v0, v1, num_type);
1453          }
1454 
1455          template <typename T>
roundn(const T v0,const T v1)1456          inline T roundn(const T v0, const T v1)
1457          {
1458             const typename details::number_type<T>::type num_type;
1459             return roundn_impl(v0, v1, num_type);
1460          }
1461 
1462          template <typename T>
hypot(const T v0,const T v1)1463          inline T hypot(const T v0, const T v1)
1464          {
1465             const typename details::number_type<T>::type num_type;
1466             return hypot_impl(v0, v1, num_type);
1467          }
1468 
1469          template <typename T>
atan2(const T v0,const T v1)1470          inline T atan2(const T v0, const T v1)
1471          {
1472             const typename details::number_type<T>::type num_type;
1473             return atan2_impl(v0, v1, num_type);
1474          }
1475 
1476          template <typename T>
shr(const T v0,const T v1)1477          inline T shr(const T v0, const T v1)
1478          {
1479             const typename details::number_type<T>::type num_type;
1480             return shr_impl(v0, v1, num_type);
1481          }
1482 
1483          template <typename T>
shl(const T v0,const T v1)1484          inline T shl(const T v0, const T v1)
1485          {
1486             const typename details::number_type<T>::type num_type;
1487             return shl_impl(v0, v1, num_type);
1488          }
1489 
1490          template <typename T>
and_opr(const T v0,const T v1)1491          inline T and_opr(const T v0, const T v1)
1492          {
1493             const typename details::number_type<T>::type num_type;
1494             return and_impl(v0, v1, num_type);
1495          }
1496 
1497          template <typename T>
nand_opr(const T v0,const T v1)1498          inline T nand_opr(const T v0, const T v1)
1499          {
1500             const typename details::number_type<T>::type num_type;
1501             return nand_impl(v0, v1, num_type);
1502          }
1503 
1504          template <typename T>
or_opr(const T v0,const T v1)1505          inline T or_opr(const T v0, const T v1)
1506          {
1507             const typename details::number_type<T>::type num_type;
1508             return or_impl(v0, v1, num_type);
1509          }
1510 
1511          template <typename T>
nor_opr(const T v0,const T v1)1512          inline T nor_opr(const T v0, const T v1)
1513          {
1514             const typename details::number_type<T>::type num_type;
1515             return nor_impl(v0, v1, num_type);
1516          }
1517 
1518          template <typename T>
xor_opr(const T v0,const T v1)1519          inline T xor_opr(const T v0, const T v1)
1520          {
1521             const typename details::number_type<T>::type num_type;
1522             return xor_impl(v0, v1, num_type);
1523          }
1524 
1525          template <typename T>
xnor_opr(const T v0,const T v1)1526          inline T xnor_opr(const T v0, const T v1)
1527          {
1528             const typename details::number_type<T>::type num_type;
1529             return xnor_impl(v0, v1, num_type);
1530          }
1531 
1532          template <typename T>
is_integer(const T v)1533          inline bool is_integer(const T v)
1534          {
1535             const typename details::number_type<T>::type num_type;
1536             return is_integer_impl(v, num_type);
1537          }
1538 
1539          template <typename T, unsigned int N>
1540          struct fast_exp
1541          {
resultexprtk::details::numeric::fast_exp1542             static inline T result(T v)
1543             {
1544                unsigned int k = N;
1545                T l = T(1);
1546 
1547                while (k)
1548                {
1549                   if (k & 1)
1550                   {
1551                      l *= v;
1552                      --k;
1553                   }
1554 
1555                   v *= v;
1556                   k >>= 1;
1557                }
1558 
1559                return l;
1560             }
1561          };
1562 
resultexprtk::details::numeric::fast_exp1563          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; } };
resultexprtk::details::numeric::fast_exp1564          template <typename T> struct fast_exp<T, 9> { static inline T result(T v) { return fast_exp<T,8>::result(v) * v; } };
resultexprtk::details::numeric::fast_exp1565          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; } };
resultexprtk::details::numeric::fast_exp1566          template <typename T> struct fast_exp<T, 7> { static inline T result(T v) { return fast_exp<T,6>::result(v) * v; } };
resultexprtk::details::numeric::fast_exp1567          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; } };
resultexprtk::details::numeric::fast_exp1568          template <typename T> struct fast_exp<T, 5> { static inline T result(T v) { return fast_exp<T,4>::result(v) * v; } };
resultexprtk::details::numeric::fast_exp1569          template <typename T> struct fast_exp<T, 4> { static inline T result(T v) { T v_2 = v * v; return v_2 * v_2; } };
resultexprtk::details::numeric::fast_exp1570          template <typename T> struct fast_exp<T, 3> { static inline T result(T v) { return v * v * v; } };
resultexprtk::details::numeric::fast_exp1571          template <typename T> struct fast_exp<T, 2> { static inline T result(T v) { return v * v;     } };
resultexprtk::details::numeric::fast_exp1572          template <typename T> struct fast_exp<T, 1> { static inline T result(T v) { return v;         } };
resultexprtk::details::numeric::fast_exp1573          template <typename T> struct fast_exp<T, 0> { static inline T result(T  ) { return T(1);      } };
1574 
1575          #define exprtk_define_unary_function(FunctionName)        \
1576          template <typename T>                                     \
1577          inline T FunctionName (const T v)                         \
1578          {                                                         \
1579             const typename details::number_type<T>::type num_type; \
1580             return  FunctionName##_impl(v,num_type);               \
1581          }                                                         \
1582 
1583          exprtk_define_unary_function(abs  )
1584          exprtk_define_unary_function(acos )
1585          exprtk_define_unary_function(acosh)
1586          exprtk_define_unary_function(asin )
1587          exprtk_define_unary_function(asinh)
1588          exprtk_define_unary_function(atan )
1589          exprtk_define_unary_function(atanh)
1590          exprtk_define_unary_function(ceil )
1591          exprtk_define_unary_function(cos  )
1592          exprtk_define_unary_function(cosh )
1593          exprtk_define_unary_function(exp  )
1594          exprtk_define_unary_function(expm1)
1595          exprtk_define_unary_function(floor)
1596          exprtk_define_unary_function(log  )
1597          exprtk_define_unary_function(log10)
1598          exprtk_define_unary_function(log2 )
1599          exprtk_define_unary_function(log1p)
1600          exprtk_define_unary_function(neg  )
1601          exprtk_define_unary_function(pos  )
1602          exprtk_define_unary_function(round)
1603          exprtk_define_unary_function(sin  )
1604          exprtk_define_unary_function(sinc )
1605          exprtk_define_unary_function(sinh )
1606          exprtk_define_unary_function(sqrt )
1607          exprtk_define_unary_function(tan  )
1608          exprtk_define_unary_function(tanh )
1609          exprtk_define_unary_function(cot  )
1610          exprtk_define_unary_function(sec  )
1611          exprtk_define_unary_function(csc  )
1612          exprtk_define_unary_function(r2d  )
1613          exprtk_define_unary_function(d2r  )
1614          exprtk_define_unary_function(d2g  )
1615          exprtk_define_unary_function(g2d  )
1616          exprtk_define_unary_function(notl )
1617          exprtk_define_unary_function(sgn  )
1618          exprtk_define_unary_function(erf  )
1619          exprtk_define_unary_function(erfc )
1620          exprtk_define_unary_function(ncdf )
1621          exprtk_define_unary_function(frac )
1622          exprtk_define_unary_function(trunc)
1623          #undef exprtk_define_unary_function
1624       }
1625 
1626       template <typename T>
compute_pow10(T d,const int exponent)1627       inline T compute_pow10(T d, const int exponent)
1628       {
1629          static const double fract10[] =
1630          {
1631            0.0,
1632            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,
1633            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,
1634            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,
1635            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,
1636            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,
1637            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,
1638            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,
1639            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,
1640            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,
1641            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,
1642            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,
1643            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,
1644            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,
1645            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,
1646            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,
1647            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,
1648            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,
1649            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,
1650            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,
1651            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,
1652            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,
1653            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,
1654            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,
1655            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,
1656            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,
1657            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,
1658            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,
1659            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,
1660            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,
1661            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,
1662            1.0E+301, 1.0E+302, 1.0E+303, 1.0E+304, 1.0E+305, 1.0E+306, 1.0E+307, 1.0E+308
1663          };
1664 
1665          static const int fract10_size = static_cast<int>(sizeof(fract10) / sizeof(double));
1666 
1667          const int e = std::abs(exponent);
1668 
1669          if (exponent >= std::numeric_limits<T>::min_exponent10)
1670          {
1671             if (e < fract10_size)
1672             {
1673                if (exponent > 0)
1674                   return T(d * fract10[e]);
1675                else
1676                   return T(d / fract10[e]);
1677             }
1678             else
1679                return T(d * std::pow(10.0, 10.0 * exponent));
1680          }
1681          else
1682          {
1683                      d /= T(fract10[           -std::numeric_limits<T>::min_exponent10]);
1684             return T(d /    fract10[-exponent + std::numeric_limits<T>::min_exponent10]);
1685          }
1686       }
1687 
1688       template <typename Iterator, typename T>
string_to_type_converter_impl_ref(Iterator & itr,const Iterator end,T & result)1689       inline bool string_to_type_converter_impl_ref(Iterator& itr, const Iterator end, T& result)
1690       {
1691          if (itr == end)
1692             return false;
1693 
1694          const bool negative = ('-' == (*itr));
1695 
1696          if (negative || ('+' == (*itr)))
1697          {
1698             if (end == ++itr)
1699                return false;
1700          }
1701 
1702          static const uchar_t zero = static_cast<uchar_t>('0');
1703 
1704          while ((end != itr) && (zero == (*itr))) ++itr;
1705 
1706          bool return_result = true;
1707          unsigned int digit = 0;
1708          const std::size_t length  = static_cast<std::size_t>(std::distance(itr,end));
1709 
1710          if (length <= 4)
1711          {
1712             exprtk_disable_fallthrough_begin
1713             switch (length)
1714             {
1715                #ifdef exprtk_use_lut
1716 
1717                #define exprtk_process_digit                          \
1718                if ((digit = details::digit_table[(int)*itr++]) < 10) \
1719                   result = result * 10 + (digit);                    \
1720                else                                                  \
1721                {                                                     \
1722                   return_result = false;                             \
1723                   break;                                             \
1724                }                                                     \
1725 
1726                #else
1727 
1728                #define exprtk_process_digit         \
1729                if ((digit = (*itr++ - zero)) < 10)  \
1730                   result = result * T(10) + digit;  \
1731                else                                 \
1732                {                                    \
1733                   return_result = false;            \
1734                   break;                            \
1735                }                                    \
1736 
1737                #endif
1738 
1739                case  4 : exprtk_process_digit
1740                case  3 : exprtk_process_digit
1741                case  2 : exprtk_process_digit
1742                case  1 : if ((digit = (*itr - zero))>= 10) { digit = 0; return_result = false; }
1743 
1744                #undef exprtk_process_digit
1745             }
1746             exprtk_disable_fallthrough_end
1747          }
1748          else
1749             return_result = false;
1750 
1751          if (length && return_result)
1752          {
1753             result = result * 10 + static_cast<T>(digit);
1754             ++itr;
1755          }
1756 
1757          result = negative ? -result : result;
1758          return return_result;
1759       }
1760 
1761       template <typename Iterator, typename T>
parse_nan(Iterator & itr,const Iterator end,T & t)1762       static inline bool parse_nan(Iterator& itr, const Iterator end, T& t)
1763       {
1764          typedef typename std::iterator_traits<Iterator>::value_type type;
1765 
1766          static const std::size_t nan_length = 3;
1767 
1768          if (std::distance(itr,end) != static_cast<int>(nan_length))
1769             return false;
1770 
1771          if (static_cast<type>('n') == (*itr))
1772          {
1773             if (
1774                  (static_cast<type>('a') != *(itr + 1)) ||
1775                  (static_cast<type>('n') != *(itr + 2))
1776                )
1777             {
1778                return false;
1779             }
1780          }
1781          else if (
1782                    (static_cast<type>('A') != *(itr + 1)) ||
1783                    (static_cast<type>('N') != *(itr + 2))
1784                  )
1785          {
1786             return false;
1787          }
1788 
1789          t = std::numeric_limits<T>::quiet_NaN();
1790 
1791          return true;
1792       }
1793 
1794       template <typename Iterator, typename T>
parse_inf(Iterator & itr,const Iterator end,T & t,bool negative)1795       static inline bool parse_inf(Iterator& itr, const Iterator end, T& t, bool negative)
1796       {
1797          static const char_t inf_uc[] = "INFINITY";
1798          static const char_t inf_lc[] = "infinity";
1799          static const std::size_t inf_length = 8;
1800 
1801          const std::size_t length = static_cast<std::size_t>(std::distance(itr,end));
1802 
1803          if ((3 != length) && (inf_length != length))
1804             return false;
1805 
1806          char_cptr inf_itr = ('i' == (*itr)) ? inf_lc : inf_uc;
1807 
1808          while (end != itr)
1809          {
1810             if (*inf_itr == static_cast<char>(*itr))
1811             {
1812                ++itr;
1813                ++inf_itr;
1814                continue;
1815             }
1816             else
1817                return false;
1818          }
1819 
1820          if (negative)
1821             t = -std::numeric_limits<T>::infinity();
1822          else
1823             t =  std::numeric_limits<T>::infinity();
1824 
1825          return true;
1826       }
1827 
1828       template <typename T>
valid_exponent(const int exponent,numeric::details::real_type_tag)1829       inline bool valid_exponent(const int exponent, numeric::details::real_type_tag)
1830       {
1831          using namespace details::numeric;
1832          return (numeric_info<T>::min_exp <= exponent) && (exponent <= numeric_info<T>::max_exp);
1833       }
1834 
1835       template <typename Iterator, typename T>
string_to_real(Iterator & itr_external,const Iterator end,T & t,numeric::details::real_type_tag)1836       inline bool string_to_real(Iterator& itr_external, const Iterator end, T& t, numeric::details::real_type_tag)
1837       {
1838          if (end == itr_external) return false;
1839 
1840          Iterator itr = itr_external;
1841 
1842          T d = T(0);
1843 
1844          const bool negative = ('-' == (*itr));
1845 
1846          if (negative || '+' == (*itr))
1847          {
1848             if (end == ++itr)
1849                return false;
1850          }
1851 
1852          bool instate = false;
1853 
1854          static const char_t zero = static_cast<uchar_t>('0');
1855 
1856          #define parse_digit_1(d)          \
1857          if ((digit = (*itr - zero)) < 10) \
1858             { d = d * T(10) + digit; }     \
1859          else                              \
1860             { break; }                     \
1861          if (end == ++itr) break;          \
1862 
1863          #define parse_digit_2(d)          \
1864          if ((digit = (*itr - zero)) < 10) \
1865             { d = d * T(10) + digit; }     \
1866          else { break; }                   \
1867             ++itr;                         \
1868 
1869          if ('.' != (*itr))
1870          {
1871             const Iterator curr = itr;
1872 
1873             while ((end != itr) && (zero == (*itr))) ++itr;
1874 
1875             while (end != itr)
1876             {
1877                unsigned int digit;
1878                parse_digit_1(d)
1879                parse_digit_1(d)
1880                parse_digit_2(d)
1881             }
1882 
1883             if (curr != itr) instate = true;
1884          }
1885 
1886          int exponent = 0;
1887 
1888          if (end != itr)
1889          {
1890             if ('.' == (*itr))
1891             {
1892                const Iterator curr = ++itr;
1893                T tmp_d = T(0);
1894 
1895                while (end != itr)
1896                {
1897                   unsigned int digit;
1898                   parse_digit_1(tmp_d)
1899                   parse_digit_1(tmp_d)
1900                   parse_digit_2(tmp_d)
1901                }
1902 
1903                if (curr != itr)
1904                {
1905                   instate = true;
1906 
1907                   const int frac_exponent = static_cast<int>(-std::distance(curr, itr));
1908 
1909                   if (!valid_exponent<T>(frac_exponent, numeric::details::real_type_tag()))
1910                      return false;
1911 
1912                   d += compute_pow10(tmp_d, frac_exponent);
1913                }
1914 
1915                #undef parse_digit_1
1916                #undef parse_digit_2
1917             }
1918 
1919             if (end != itr)
1920             {
1921                typename std::iterator_traits<Iterator>::value_type c = (*itr);
1922 
1923                if (('e' == c) || ('E' == c))
1924                {
1925                   int exp = 0;
1926 
1927                   if (!details::string_to_type_converter_impl_ref(++itr, end, exp))
1928                   {
1929                      if (end == itr)
1930                         return false;
1931                      else
1932                         c = (*itr);
1933                   }
1934 
1935                   exponent += exp;
1936                }
1937 
1938                if (end != itr)
1939                {
1940                   if (('f' == c) || ('F' == c) || ('l' == c) || ('L' == c))
1941                      ++itr;
1942                   else if ('#' == c)
1943                   {
1944                      if (end == ++itr)
1945                         return false;
1946                      else if (('I' <= (*itr)) && ((*itr) <= 'n'))
1947                      {
1948                         if (('i' == (*itr)) || ('I' == (*itr)))
1949                         {
1950                            return parse_inf(itr, end, t, negative);
1951                         }
1952                         else if (('n' == (*itr)) || ('N' == (*itr)))
1953                         {
1954                            return parse_nan(itr, end, t);
1955                         }
1956                         else
1957                            return false;
1958                      }
1959                      else
1960                         return false;
1961                   }
1962                   else if (('I' <= (*itr)) && ((*itr) <= 'n'))
1963                   {
1964                      if (('i' == (*itr)) || ('I' == (*itr)))
1965                      {
1966                         return parse_inf(itr, end, t, negative);
1967                      }
1968                      else if (('n' == (*itr)) || ('N' == (*itr)))
1969                      {
1970                         return parse_nan(itr, end, t);
1971                      }
1972                      else
1973                         return false;
1974                   }
1975                   else
1976                      return false;
1977                }
1978             }
1979          }
1980 
1981          if ((end != itr) || (!instate))
1982             return false;
1983          else if (!valid_exponent<T>(exponent, numeric::details::real_type_tag()))
1984             return false;
1985          else if (exponent)
1986             d = compute_pow10(d,exponent);
1987 
1988          t = static_cast<T>((negative) ? -d : d);
1989          return true;
1990       }
1991 
1992       template <typename T>
string_to_real(const std::string & s,T & t)1993       inline bool string_to_real(const std::string& s, T& t)
1994       {
1995          const typename numeric::details::number_type<T>::type num_type;
1996 
1997          char_cptr begin = s.data();
1998          char_cptr end   = s.data() + s.size();
1999 
2000          return string_to_real(begin, end, t, num_type);
2001       }
2002 
2003       template <typename T>
2004       struct functor_t
2005       {
2006          /*
2007             Note: The following definitions for Type, may require tweaking
2008                   based on the compiler and target architecture. The benchmark
2009                   should provide enough information to make the right choice.
2010          */
2011          //typedef T Type;
2012          //typedef const T Type;
2013          typedef const T& Type;
2014          typedef       T& RefType;
2015          typedef T (*qfunc_t)(Type t0, Type t1, Type t2, Type t3);
2016          typedef T (*tfunc_t)(Type t0, Type t1, Type t2);
2017          typedef T (*bfunc_t)(Type t0, Type t1);
2018          typedef T (*ufunc_t)(Type t0);
2019       };
2020 
2021    } // namespace details
2022 
2023    struct loop_runtime_check
2024    {
2025       enum loop_types
2026       {
2027          e_invalid           = 0,
2028          e_for_loop          = 1,
2029          e_while_loop        = 2,
2030          e_repeat_until_loop = 4,
2031          e_all_loops         = 7
2032       };
2033 
2034       enum violation_type
2035       {
2036           e_unknown         = 0,
2037           e_iteration_count = 1,
2038           e_timeout         = 2
2039       };
2040 
2041       loop_types loop_set;
2042 
loop_runtime_checkexprtk::loop_runtime_check2043       loop_runtime_check()
2044       : loop_set(e_invalid),
2045         max_loop_iterations(0)
2046       {}
2047 
2048       details::_uint64_t max_loop_iterations;
2049 
2050       struct violation_context
2051       {
2052          loop_types loop;
2053          violation_type violation;
2054          details::_uint64_t iteration_count;
2055       };
2056 
handle_runtime_violationexprtk::loop_runtime_check2057       virtual void handle_runtime_violation(const violation_context&)
2058       {
2059          throw std::runtime_error("ExprTk Loop run-time violation.");
2060       }
2061 
~loop_runtime_checkexprtk::loop_runtime_check2062       virtual ~loop_runtime_check() {}
2063    };
2064 
2065    typedef loop_runtime_check* loop_runtime_check_ptr;
2066 
2067    namespace lexer
2068    {
2069       struct token
2070       {
2071          enum token_type
2072          {
2073             e_none        =   0, e_error       =   1, e_err_symbol  =   2,
2074             e_err_number  =   3, e_err_string  =   4, e_err_sfunc   =   5,
2075             e_eof         =   6, e_number      =   7, e_symbol      =   8,
2076             e_string      =   9, e_assign      =  10, e_addass      =  11,
2077             e_subass      =  12, e_mulass      =  13, e_divass      =  14,
2078             e_modass      =  15, e_shr         =  16, e_shl         =  17,
2079             e_lte         =  18, e_ne          =  19, e_gte         =  20,
2080             e_swap        =  21, e_lt          = '<', e_gt          = '>',
2081             e_eq          = '=', e_rbracket    = ')', e_lbracket    = '(',
2082             e_rsqrbracket = ']', e_lsqrbracket = '[', e_rcrlbracket = '}',
2083             e_lcrlbracket = '{', e_comma       = ',', e_add         = '+',
2084             e_sub         = '-', e_div         = '/', e_mul         = '*',
2085             e_mod         = '%', e_pow         = '^', e_colon       = ':',
2086             e_ternary     = '?'
2087          };
2088 
tokenexprtk::lexer::token2089          token()
2090          : type(e_none),
2091            value(""),
2092            position(std::numeric_limits<std::size_t>::max())
2093          {}
2094 
clearexprtk::lexer::token2095          void clear()
2096          {
2097             type     = e_none;
2098             value    = "";
2099             position = std::numeric_limits<std::size_t>::max();
2100          }
2101 
2102          template <typename Iterator>
set_operatorexprtk::lexer::token2103          inline token& set_operator(const token_type tt,
2104                                     const Iterator begin, const Iterator end,
2105                                     const Iterator base_begin = Iterator(0))
2106          {
2107             type = tt;
2108             value.assign(begin,end);
2109             if (base_begin)
2110                position = static_cast<std::size_t>(std::distance(base_begin,begin));
2111             return (*this);
2112          }
2113 
2114          template <typename Iterator>
set_symbolexprtk::lexer::token2115          inline token& set_symbol(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
2116          {
2117             type = e_symbol;
2118             value.assign(begin,end);
2119             if (base_begin)
2120                position = static_cast<std::size_t>(std::distance(base_begin,begin));
2121             return (*this);
2122          }
2123 
2124          template <typename Iterator>
set_numericexprtk::lexer::token2125          inline token& set_numeric(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
2126          {
2127             type = e_number;
2128             value.assign(begin,end);
2129             if (base_begin)
2130                position = static_cast<std::size_t>(std::distance(base_begin,begin));
2131             return (*this);
2132          }
2133 
2134          template <typename Iterator>
set_stringexprtk::lexer::token2135          inline token& set_string(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
2136          {
2137             type = e_string;
2138             value.assign(begin,end);
2139             if (base_begin)
2140                position = static_cast<std::size_t>(std::distance(base_begin,begin));
2141             return (*this);
2142          }
2143 
set_stringexprtk::lexer::token2144          inline token& set_string(const std::string& s, const std::size_t p)
2145          {
2146             type     = e_string;
2147             value    = s;
2148             position = p;
2149             return (*this);
2150          }
2151 
2152          template <typename Iterator>
set_errorexprtk::lexer::token2153          inline token& set_error(const token_type et,
2154                                  const Iterator begin, const Iterator end,
2155                                  const Iterator base_begin = Iterator(0))
2156          {
2157             if (
2158                  (e_error      == et) ||
2159                  (e_err_symbol == et) ||
2160                  (e_err_number == et) ||
2161                  (e_err_string == et) ||
2162                  (e_err_sfunc  == et)
2163                )
2164             {
2165                type = et;
2166             }
2167             else
2168                type = e_error;
2169 
2170             value.assign(begin,end);
2171 
2172             if (base_begin)
2173                position = static_cast<std::size_t>(std::distance(base_begin,begin));
2174 
2175             return (*this);
2176          }
2177 
to_strexprtk::lexer::token2178          static inline std::string to_str(token_type t)
2179          {
2180             switch (t)
2181             {
2182                case e_none        : return "NONE";
2183                case e_error       : return "ERROR";
2184                case e_err_symbol  : return "ERROR_SYMBOL";
2185                case e_err_number  : return "ERROR_NUMBER";
2186                case e_err_string  : return "ERROR_STRING";
2187                case e_eof         : return "EOF";
2188                case e_number      : return "NUMBER";
2189                case e_symbol      : return "SYMBOL";
2190                case e_string      : return "STRING";
2191                case e_assign      : return ":=";
2192                case e_addass      : return "+=";
2193                case e_subass      : return "-=";
2194                case e_mulass      : return "*=";
2195                case e_divass      : return "/=";
2196                case e_modass      : return "%=";
2197                case e_shr         : return ">>";
2198                case e_shl         : return "<<";
2199                case e_lte         : return "<=";
2200                case e_ne          : return "!=";
2201                case e_gte         : return ">=";
2202                case e_lt          : return "<";
2203                case e_gt          : return ">";
2204                case e_eq          : return "=";
2205                case e_rbracket    : return ")";
2206                case e_lbracket    : return "(";
2207                case e_rsqrbracket : return "]";
2208                case e_lsqrbracket : return "[";
2209                case e_rcrlbracket : return "}";
2210                case e_lcrlbracket : return "{";
2211                case e_comma       : return ",";
2212                case e_add         : return "+";
2213                case e_sub         : return "-";
2214                case e_div         : return "/";
2215                case e_mul         : return "*";
2216                case e_mod         : return "%";
2217                case e_pow         : return "^";
2218                case e_colon       : return ":";
2219                case e_ternary     : return "?";
2220                case e_swap        : return "<=>";
2221                default            : return "UNKNOWN";
2222             }
2223          }
2224 
is_errorexprtk::lexer::token2225          inline bool is_error() const
2226          {
2227             return (
2228                      (e_error      == type) ||
2229                      (e_err_symbol == type) ||
2230                      (e_err_number == type) ||
2231                      (e_err_string == type) ||
2232                      (e_err_sfunc  == type)
2233                    );
2234          }
2235 
2236          token_type type;
2237          std::string value;
2238          std::size_t position;
2239       };
2240 
2241       class generator
2242       {
2243       public:
2244 
2245          typedef token token_t;
2246          typedef std::vector<token_t> token_list_t;
2247          typedef token_list_t::iterator token_list_itr_t;
2248          typedef details::char_t char_t;
2249 
generator()2250          generator()
2251          : base_itr_(0),
2252            s_itr_   (0),
2253            s_end_   (0)
2254          {
2255             clear();
2256          }
2257 
clear()2258          inline void clear()
2259          {
2260             base_itr_ = 0;
2261             s_itr_    = 0;
2262             s_end_    = 0;
2263             token_list_.clear();
2264             token_itr_ = token_list_.end();
2265             store_token_itr_ = token_list_.end();
2266          }
2267 
process(const std::string & str)2268          inline bool process(const std::string& str)
2269          {
2270             base_itr_ = str.data();
2271             s_itr_    = str.data();
2272             s_end_    = str.data() + str.size();
2273 
2274             eof_token_.set_operator(token_t::e_eof,s_end_,s_end_,base_itr_);
2275             token_list_.clear();
2276 
2277             while (!is_end(s_itr_))
2278             {
2279                scan_token();
2280 
2281                if (!token_list_.empty() && token_list_.back().is_error())
2282                   return false;
2283             }
2284 
2285             return true;
2286          }
2287 
empty() const2288          inline bool empty() const
2289          {
2290             return token_list_.empty();
2291          }
2292 
size() const2293          inline std::size_t size() const
2294          {
2295             return token_list_.size();
2296          }
2297 
begin()2298          inline void begin()
2299          {
2300             token_itr_ = token_list_.begin();
2301             store_token_itr_ = token_list_.begin();
2302          }
2303 
store()2304          inline void store()
2305          {
2306             store_token_itr_ = token_itr_;
2307          }
2308 
restore()2309          inline void restore()
2310          {
2311             token_itr_ = store_token_itr_;
2312          }
2313 
next_token()2314          inline token_t& next_token()
2315          {
2316             if (token_list_.end() != token_itr_)
2317             {
2318                return *token_itr_++;
2319             }
2320             else
2321                return eof_token_;
2322          }
2323 
peek_next_token()2324          inline token_t& peek_next_token()
2325          {
2326             if (token_list_.end() != token_itr_)
2327             {
2328                return *token_itr_;
2329             }
2330             else
2331                return eof_token_;
2332          }
2333 
operator [](const std::size_t & index)2334          inline token_t& operator[](const std::size_t& index)
2335          {
2336             if (index < token_list_.size())
2337                return token_list_[index];
2338             else
2339                return eof_token_;
2340          }
2341 
operator [](const std::size_t & index) const2342          inline token_t operator[](const std::size_t& index) const
2343          {
2344             if (index < token_list_.size())
2345                return token_list_[index];
2346             else
2347                return eof_token_;
2348          }
2349 
finished() const2350          inline bool finished() const
2351          {
2352             return (token_list_.end() == token_itr_);
2353          }
2354 
insert_front(token_t::token_type tk_type)2355          inline void insert_front(token_t::token_type tk_type)
2356          {
2357             if (
2358                  !token_list_.empty() &&
2359                  (token_list_.end() != token_itr_)
2360                )
2361             {
2362                token_t t = *token_itr_;
2363 
2364                t.type     = tk_type;
2365                token_itr_ = token_list_.insert(token_itr_,t);
2366             }
2367          }
2368 
substr(const std::size_t & begin,const std::size_t & end)2369          inline std::string substr(const std::size_t& begin, const std::size_t& end)
2370          {
2371             const details::char_cptr begin_itr = ((base_itr_ + begin) < s_end_) ? (base_itr_ + begin) : s_end_;
2372             const details::char_cptr end_itr   = ((base_itr_ +   end) < s_end_) ? (base_itr_ +   end) : s_end_;
2373 
2374             return std::string(begin_itr,end_itr);
2375          }
2376 
remaining() const2377          inline std::string remaining() const
2378          {
2379             if (finished())
2380                return "";
2381             else if (token_list_.begin() != token_itr_)
2382                return std::string(base_itr_ + (token_itr_ - 1)->position, s_end_);
2383             else
2384                return std::string(base_itr_ + token_itr_->position, s_end_);
2385          }
2386 
2387       private:
2388 
is_end(details::char_cptr itr)2389          inline bool is_end(details::char_cptr itr)
2390          {
2391             return (s_end_ == itr);
2392          }
2393 
2394          #ifndef exprtk_disable_comments
is_comment_start(details::char_cptr itr)2395          inline bool is_comment_start(details::char_cptr itr)
2396          {
2397             const char_t c0 = *(itr + 0);
2398             const char_t c1 = *(itr + 1);
2399 
2400             if ('#' == c0)
2401                return true;
2402             else if (!is_end(itr + 1))
2403             {
2404                if (('/' == c0) && ('/' == c1)) return true;
2405                if (('/' == c0) && ('*' == c1)) return true;
2406             }
2407             return false;
2408          }
2409          #else
is_comment_start(details::char_cptr)2410          inline bool is_comment_start(details::char_cptr)
2411          {
2412             return false;
2413          }
2414          #endif
2415 
skip_whitespace()2416          inline void skip_whitespace()
2417          {
2418             while (!is_end(s_itr_) && details::is_whitespace(*s_itr_))
2419             {
2420                ++s_itr_;
2421             }
2422          }
2423 
skip_comments()2424          inline void skip_comments()
2425          {
2426             #ifndef exprtk_disable_comments
2427             // The following comment styles are supported:
2428             // 1. // .... \n
2429             // 2. #  .... \n
2430             // 3. /* .... */
2431             struct test
2432             {
2433                static inline bool comment_start(const char_t c0, const char_t c1, int& mode, int& incr)
2434                {
2435                   mode = 0;
2436                        if ('#' == c0)    { mode = 1; incr = 1; }
2437                   else if ('/' == c0)
2438                   {
2439                           if ('/' == c1) { mode = 1; incr = 2; }
2440                      else if ('*' == c1) { mode = 2; incr = 2; }
2441                   }
2442                   return (0 != mode);
2443                }
2444 
2445                static inline bool comment_end(const char_t c0, const char_t c1, int& mode)
2446                {
2447                   if (
2448                        ((1 == mode) && ('\n' == c0)) ||
2449                        ((2 == mode) && ( '*' == c0) && ('/' == c1))
2450                      )
2451                   {
2452                      mode = 0;
2453                      return true;
2454                   }
2455                   else
2456                      return false;
2457                }
2458             };
2459 
2460             int mode      = 0;
2461             int increment = 0;
2462 
2463             if (is_end(s_itr_))
2464                return;
2465             else if (!test::comment_start(*s_itr_, *(s_itr_ + 1), mode, increment))
2466                return;
2467 
2468             details::char_cptr cmt_start = s_itr_;
2469 
2470             s_itr_ += increment;
2471 
2472             while (!is_end(s_itr_))
2473             {
2474                if ((1 == mode) && test::comment_end(*s_itr_, 0, mode))
2475                {
2476                   ++s_itr_;
2477                   return;
2478                }
2479 
2480                if ((2 == mode))
2481                {
2482                   if (!is_end((s_itr_ + 1)) && test::comment_end(*s_itr_, *(s_itr_ + 1), mode))
2483                   {
2484                      s_itr_ += 2;
2485                      return;
2486                   }
2487                }
2488 
2489                 ++s_itr_;
2490             }
2491 
2492             if (2 == mode)
2493             {
2494                token_t t;
2495                t.set_error(token::e_error, cmt_start, cmt_start + mode, base_itr_);
2496                token_list_.push_back(t);
2497             }
2498             #endif
2499          }
2500 
scan_token()2501          inline void scan_token()
2502          {
2503             if (details::is_whitespace(*s_itr_))
2504             {
2505                skip_whitespace();
2506                return;
2507             }
2508             else if (is_comment_start(s_itr_))
2509             {
2510                skip_comments();
2511                return;
2512             }
2513             else if (details::is_operator_char(*s_itr_))
2514             {
2515                scan_operator();
2516                return;
2517             }
2518             else if (details::is_letter(*s_itr_))
2519             {
2520                scan_symbol();
2521                return;
2522             }
2523             else if (details::is_digit((*s_itr_)) || ('.' == (*s_itr_)))
2524             {
2525                scan_number();
2526                return;
2527             }
2528             else if ('$' == (*s_itr_))
2529             {
2530                scan_special_function();
2531                return;
2532             }
2533             #ifndef exprtk_disable_string_capabilities
2534             else if ('\'' == (*s_itr_))
2535             {
2536                scan_string();
2537                return;
2538             }
2539             #endif
2540             else if ('~' == (*s_itr_))
2541             {
2542                token_t t;
2543                t.set_symbol(s_itr_, s_itr_ + 1, base_itr_);
2544                token_list_.push_back(t);
2545                ++s_itr_;
2546                return;
2547             }
2548             else
2549             {
2550                token_t t;
2551                t.set_error(token::e_error, s_itr_, s_itr_ + 2, base_itr_);
2552                token_list_.push_back(t);
2553                ++s_itr_;
2554             }
2555          }
2556 
scan_operator()2557          inline void scan_operator()
2558          {
2559             token_t t;
2560 
2561             const char_t c0 = s_itr_[0];
2562 
2563             if (!is_end(s_itr_ + 1))
2564             {
2565                const char_t c1 = s_itr_[1];
2566 
2567                if (!is_end(s_itr_ + 2))
2568                {
2569                   const char_t c2 = s_itr_[2];
2570 
2571                   if ((c0 == '<') && (c1 == '=') && (c2 == '>'))
2572                   {
2573                      t.set_operator(token_t::e_swap, s_itr_, s_itr_ + 3, base_itr_);
2574                      token_list_.push_back(t);
2575                      s_itr_ += 3;
2576                      return;
2577                   }
2578                }
2579 
2580                token_t::token_type ttype = token_t::e_none;
2581 
2582                     if ((c0 == '<') && (c1 == '=')) ttype = token_t::e_lte;
2583                else if ((c0 == '>') && (c1 == '=')) ttype = token_t::e_gte;
2584                else if ((c0 == '<') && (c1 == '>')) ttype = token_t::e_ne;
2585                else if ((c0 == '!') && (c1 == '=')) ttype = token_t::e_ne;
2586                else if ((c0 == '=') && (c1 == '=')) ttype = token_t::e_eq;
2587                else if ((c0 == ':') && (c1 == '=')) ttype = token_t::e_assign;
2588                else if ((c0 == '<') && (c1 == '<')) ttype = token_t::e_shl;
2589                else if ((c0 == '>') && (c1 == '>')) ttype = token_t::e_shr;
2590                else if ((c0 == '+') && (c1 == '=')) ttype = token_t::e_addass;
2591                else if ((c0 == '-') && (c1 == '=')) ttype = token_t::e_subass;
2592                else if ((c0 == '*') && (c1 == '=')) ttype = token_t::e_mulass;
2593                else if ((c0 == '/') && (c1 == '=')) ttype = token_t::e_divass;
2594                else if ((c0 == '%') && (c1 == '=')) ttype = token_t::e_modass;
2595 
2596                if (token_t::e_none != ttype)
2597                {
2598                   t.set_operator(ttype, s_itr_, s_itr_ + 2, base_itr_);
2599                   token_list_.push_back(t);
2600                   s_itr_ += 2;
2601                   return;
2602                }
2603             }
2604 
2605             if ('<' == c0)
2606                t.set_operator(token_t::e_lt , s_itr_, s_itr_ + 1, base_itr_);
2607             else if ('>' == c0)
2608                t.set_operator(token_t::e_gt , s_itr_, s_itr_ + 1, base_itr_);
2609             else if (';' == c0)
2610                t.set_operator(token_t::e_eof, s_itr_, s_itr_ + 1, base_itr_);
2611             else if ('&' == c0)
2612                t.set_symbol(s_itr_, s_itr_ + 1, base_itr_);
2613             else if ('|' == c0)
2614                t.set_symbol(s_itr_, s_itr_ + 1, base_itr_);
2615             else
2616                t.set_operator(token_t::token_type(c0), s_itr_, s_itr_ + 1, base_itr_);
2617 
2618             token_list_.push_back(t);
2619             ++s_itr_;
2620          }
2621 
scan_symbol()2622          inline void scan_symbol()
2623          {
2624             details::char_cptr initial_itr = s_itr_;
2625 
2626             while (!is_end(s_itr_))
2627             {
2628                if (!details::is_letter_or_digit(*s_itr_) && ('_' != (*s_itr_)))
2629                {
2630                   if ('.' != (*s_itr_))
2631                      break;
2632                   /*
2633                      Permit symbols that contain a 'dot'
2634                      Allowed   : abc.xyz, a123.xyz, abc.123, abc_.xyz a123_.xyz abc._123
2635                      Disallowed: .abc, abc.<white-space>, abc.<eof>, abc.<operator +,-,*,/...>
2636                   */
2637                   if (
2638                        (s_itr_ != initial_itr)                     &&
2639                        !is_end(s_itr_ + 1)                         &&
2640                        !details::is_letter_or_digit(*(s_itr_ + 1)) &&
2641                        ('_' != (*(s_itr_ + 1)))
2642                      )
2643                      break;
2644                }
2645 
2646                ++s_itr_;
2647             }
2648 
2649             token_t t;
2650             t.set_symbol(initial_itr,s_itr_,base_itr_);
2651             token_list_.push_back(t);
2652          }
2653 
scan_number()2654          inline void scan_number()
2655          {
2656             /*
2657                Attempt to match a valid numeric value in one of the following formats:
2658                (01) 123456
2659                (02) 123456.
2660                (03) 123.456
2661                (04) 123.456e3
2662                (05) 123.456E3
2663                (06) 123.456e+3
2664                (07) 123.456E+3
2665                (08) 123.456e-3
2666                (09) 123.456E-3
2667                (00) .1234
2668                (11) .1234e3
2669                (12) .1234E+3
2670                (13) .1234e+3
2671                (14) .1234E-3
2672                (15) .1234e-3
2673             */
2674 
2675             details::char_cptr initial_itr = s_itr_;
2676             bool dot_found                 = false;
2677             bool e_found                   = false;
2678             bool post_e_sign_found         = false;
2679             bool post_e_digit_found        = false;
2680             token_t t;
2681 
2682             while (!is_end(s_itr_))
2683             {
2684                if ('.' == (*s_itr_))
2685                {
2686                   if (dot_found)
2687                   {
2688                      t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
2689                      token_list_.push_back(t);
2690 
2691                      return;
2692                   }
2693 
2694                   dot_found = true;
2695                   ++s_itr_;
2696 
2697                   continue;
2698                }
2699                else if ('e' == std::tolower(*s_itr_))
2700                {
2701                   const char_t& c = *(s_itr_ + 1);
2702 
2703                   if (is_end(s_itr_ + 1))
2704                   {
2705                      t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
2706                      token_list_.push_back(t);
2707 
2708                      return;
2709                   }
2710                   else if (
2711                             ('+' != c) &&
2712                             ('-' != c) &&
2713                             !details::is_digit(c)
2714                           )
2715                   {
2716                      t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
2717                      token_list_.push_back(t);
2718 
2719                      return;
2720                   }
2721 
2722                   e_found = true;
2723                   ++s_itr_;
2724 
2725                   continue;
2726                }
2727                else if (e_found && details::is_sign(*s_itr_) && !post_e_digit_found)
2728                {
2729                   if (post_e_sign_found)
2730                   {
2731                      t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
2732                      token_list_.push_back(t);
2733 
2734                      return;
2735                   }
2736 
2737                   post_e_sign_found = true;
2738                   ++s_itr_;
2739 
2740                   continue;
2741                }
2742                else if (e_found && details::is_digit(*s_itr_))
2743                {
2744                   post_e_digit_found = true;
2745                   ++s_itr_;
2746 
2747                   continue;
2748                }
2749                else if (('.' != (*s_itr_)) && !details::is_digit(*s_itr_))
2750                   break;
2751                else
2752                   ++s_itr_;
2753             }
2754 
2755             t.set_numeric(initial_itr, s_itr_, base_itr_);
2756             token_list_.push_back(t);
2757 
2758             return;
2759          }
2760 
scan_special_function()2761          inline void scan_special_function()
2762          {
2763             details::char_cptr initial_itr = s_itr_;
2764             token_t t;
2765 
2766             // $fdd(x,x,x) = at least 11 chars
2767             if (std::distance(s_itr_,s_end_) < 11)
2768             {
2769                t.set_error(
2770                   token::e_err_sfunc,
2771                   initial_itr, std::min(initial_itr + 11, s_end_),
2772                   base_itr_);
2773                token_list_.push_back(t);
2774 
2775                return;
2776             }
2777 
2778             if (
2779                  !(('$' == *s_itr_)                       &&
2780                    (details::imatch  ('f',*(s_itr_ + 1))) &&
2781                    (details::is_digit(*(s_itr_ + 2)))     &&
2782                    (details::is_digit(*(s_itr_ + 3))))
2783                )
2784             {
2785                t.set_error(
2786                   token::e_err_sfunc,
2787                   initial_itr, std::min(initial_itr + 4, s_end_),
2788                   base_itr_);
2789                token_list_.push_back(t);
2790 
2791                return;
2792             }
2793 
2794             s_itr_ += 4; // $fdd = 4chars
2795 
2796             t.set_symbol(initial_itr, s_itr_, base_itr_);
2797             token_list_.push_back(t);
2798 
2799             return;
2800          }
2801 
2802          #ifndef exprtk_disable_string_capabilities
scan_string()2803          inline void scan_string()
2804          {
2805             details::char_cptr initial_itr = s_itr_ + 1;
2806             token_t t;
2807 
2808             if (std::distance(s_itr_,s_end_) < 2)
2809             {
2810                t.set_error(token::e_err_string, s_itr_, s_end_, base_itr_);
2811                token_list_.push_back(t);
2812 
2813                return;
2814             }
2815 
2816             ++s_itr_;
2817 
2818             bool escaped_found = false;
2819             bool escaped = false;
2820 
2821             while (!is_end(s_itr_))
2822             {
2823                if (!details::is_valid_string_char(*s_itr_))
2824                {
2825                   t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_);
2826                   token_list_.push_back(t);
2827 
2828                   return;
2829                }
2830                else if (!escaped && ('\\' == *s_itr_))
2831                {
2832                   escaped_found = true;
2833                   escaped = true;
2834                   ++s_itr_;
2835 
2836                   continue;
2837                }
2838                else if (!escaped)
2839                {
2840                   if ('\'' == *s_itr_)
2841                      break;
2842                }
2843                else if (escaped)
2844                {
2845                   if (
2846                        !is_end(s_itr_) && ('0' == *(s_itr_)) &&
2847                        ((s_itr_ + 4) <= s_end_)
2848                      )
2849                   {
2850                      const bool x_seperator = ('X' == std::toupper(*(s_itr_ + 1)));
2851 
2852                      const bool both_digits = details::is_hex_digit(*(s_itr_ + 2)) &&
2853                                               details::is_hex_digit(*(s_itr_ + 3)) ;
2854 
2855                      if (!(x_seperator && both_digits))
2856                      {
2857                         t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_);
2858                         token_list_.push_back(t);
2859 
2860                         return;
2861                      }
2862                      else
2863                         s_itr_ += 3;
2864                   }
2865 
2866                   escaped = false;
2867                }
2868 
2869                ++s_itr_;
2870             }
2871 
2872             if (is_end(s_itr_))
2873             {
2874                t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_);
2875                token_list_.push_back(t);
2876 
2877                return;
2878             }
2879 
2880             if (!escaped_found)
2881                t.set_string(initial_itr, s_itr_, base_itr_);
2882             else
2883             {
2884                std::string parsed_string(initial_itr,s_itr_);
2885 
2886                if (!details::cleanup_escapes(parsed_string))
2887                {
2888                   t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_);
2889                   token_list_.push_back(t);
2890 
2891                   return;
2892                }
2893 
2894                t.set_string(
2895                     parsed_string,
2896                     static_cast<std::size_t>(std::distance(base_itr_,initial_itr)));
2897             }
2898 
2899             token_list_.push_back(t);
2900             ++s_itr_;
2901 
2902             return;
2903          }
2904          #endif
2905 
2906       private:
2907 
2908          token_list_t       token_list_;
2909          token_list_itr_t   token_itr_;
2910          token_list_itr_t   store_token_itr_;
2911          token_t            eof_token_;
2912          details::char_cptr base_itr_;
2913          details::char_cptr s_itr_;
2914          details::char_cptr s_end_;
2915 
2916          friend class token_scanner;
2917          friend class token_modifier;
2918          friend class token_inserter;
2919          friend class token_joiner;
2920       };
2921 
2922       class helper_interface
2923       {
2924       public:
2925 
init()2926          virtual void init()                     {              }
reset()2927          virtual void reset()                    {              }
result()2928          virtual bool result()                   { return true; }
process(generator &)2929          virtual std::size_t process(generator&) { return 0;    }
~helper_interface()2930          virtual ~helper_interface()             {              }
2931       };
2932 
2933       class token_scanner : public helper_interface
2934       {
2935       public:
2936 
~token_scanner()2937          virtual ~token_scanner()
2938          {}
2939 
token_scanner(const std::size_t & stride)2940          explicit token_scanner(const std::size_t& stride)
2941          : stride_(stride)
2942          {
2943             if (stride > 4)
2944             {
2945                throw std::invalid_argument("token_scanner() - Invalid stride value");
2946             }
2947          }
2948 
process(generator & g)2949          inline std::size_t process(generator& g)
2950          {
2951             if (g.token_list_.size() >= stride_)
2952             {
2953                for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i)
2954                {
2955                   token t;
2956 
2957                   switch (stride_)
2958                   {
2959                      case 1 :
2960                               {
2961                                  const token& t0 = g.token_list_[i];
2962 
2963                                  if (!operator()(t0))
2964                                  {
2965                                     return i;
2966                                  }
2967                               }
2968                               break;
2969 
2970                      case 2 :
2971                               {
2972                                  const token& t0 = g.token_list_[i    ];
2973                                  const token& t1 = g.token_list_[i + 1];
2974 
2975                                  if (!operator()(t0, t1))
2976                                  {
2977                                     return i;
2978                                  }
2979                               }
2980                               break;
2981 
2982                      case 3 :
2983                               {
2984                                  const token& t0 = g.token_list_[i    ];
2985                                  const token& t1 = g.token_list_[i + 1];
2986                                  const token& t2 = g.token_list_[i + 2];
2987 
2988                                  if (!operator()(t0, t1, t2))
2989                                  {
2990                                     return i;
2991                                  }
2992                               }
2993                               break;
2994 
2995                      case 4 :
2996                               {
2997                                  const token& t0 = g.token_list_[i    ];
2998                                  const token& t1 = g.token_list_[i + 1];
2999                                  const token& t2 = g.token_list_[i + 2];
3000                                  const token& t3 = g.token_list_[i + 3];
3001 
3002                                  if (!operator()(t0, t1, t2, t3))
3003                                  {
3004                                     return i;
3005                                  }
3006                               }
3007                               break;
3008                   }
3009                }
3010             }
3011 
3012             return (g.token_list_.size() - stride_ + 1);
3013          }
3014 
operator ()(const token &)3015          virtual bool operator() (const token&)
3016          {
3017             return false;
3018          }
3019 
operator ()(const token &,const token &)3020          virtual bool operator() (const token&, const token&)
3021          {
3022             return false;
3023          }
3024 
operator ()(const token &,const token &,const token &)3025          virtual bool operator() (const token&, const token&, const token&)
3026          {
3027             return false;
3028          }
3029 
operator ()(const token &,const token &,const token &,const token &)3030          virtual bool operator() (const token&, const token&, const token&, const token&)
3031          {
3032             return false;
3033          }
3034 
3035       private:
3036 
3037          const std::size_t stride_;
3038       };
3039 
3040       class token_modifier : public helper_interface
3041       {
3042       public:
3043 
process(generator & g)3044          inline std::size_t process(generator& g)
3045          {
3046             std::size_t changes = 0;
3047 
3048             for (std::size_t i = 0; i < g.token_list_.size(); ++i)
3049             {
3050                if (modify(g.token_list_[i])) changes++;
3051             }
3052 
3053             return changes;
3054          }
3055 
3056          virtual bool modify(token& t) = 0;
3057       };
3058 
3059       class token_inserter : public helper_interface
3060       {
3061       public:
3062 
token_inserter(const std::size_t & stride)3063          explicit token_inserter(const std::size_t& stride)
3064          : stride_(stride)
3065          {
3066             if (stride > 5)
3067             {
3068                throw std::invalid_argument("token_inserter() - Invalid stride value");
3069             }
3070          }
3071 
process(generator & g)3072          inline std::size_t process(generator& g)
3073          {
3074             if (g.token_list_.empty())
3075                return 0;
3076             else if (g.token_list_.size() < stride_)
3077                return 0;
3078 
3079             std::size_t changes = 0;
3080 
3081             typedef std::pair<std::size_t, token> insert_t;
3082             std::vector<insert_t> insert_list;
3083             insert_list.reserve(10000);
3084 
3085             for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i)
3086             {
3087                int insert_index = -1;
3088                token t;
3089 
3090                switch (stride_)
3091                {
3092                   case 1 : insert_index = insert(g.token_list_[i],t);
3093                            break;
3094 
3095                   case 2 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], t);
3096                            break;
3097 
3098                   case 3 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], g.token_list_[i + 2], t);
3099                            break;
3100 
3101                   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);
3102                            break;
3103 
3104                   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);
3105                            break;
3106                }
3107 
3108                if ((insert_index >= 0) && (insert_index <= (static_cast<int>(stride_) + 1)))
3109                {
3110                   insert_list.push_back(insert_t(i, t));
3111                   changes++;
3112                }
3113             }
3114 
3115             if (!insert_list.empty())
3116             {
3117                generator::token_list_t token_list;
3118 
3119                std::size_t insert_index = 0;
3120 
3121                for (std::size_t i = 0; i < g.token_list_.size(); ++i)
3122                {
3123                   token_list.push_back(g.token_list_[i]);
3124 
3125                   if (
3126                        (insert_index < insert_list.size()) &&
3127                        (insert_list[insert_index].first == i)
3128                      )
3129                   {
3130                      token_list.push_back(insert_list[insert_index].second);
3131                      insert_index++;
3132                   }
3133                }
3134 
3135                std::swap(g.token_list_,token_list);
3136             }
3137 
3138             return changes;
3139          }
3140 
3141          #define token_inserter_empty_body \
3142          {                                 \
3143             return -1;                     \
3144          }                                 \
3145 
3146          inline virtual int insert(const token&, token&)
3147          token_inserter_empty_body
3148 
3149          inline virtual int insert(const token&, const token&, token&)
3150          token_inserter_empty_body
3151 
3152          inline virtual int insert(const token&, const token&, const token&, token&)
3153          token_inserter_empty_body
3154 
3155          inline virtual int insert(const token&, const token&, const token&, const token&, token&)
3156          token_inserter_empty_body
3157 
3158          inline virtual int insert(const token&, const token&, const token&, const token&, const token&, token&)
3159          token_inserter_empty_body
3160 
3161          #undef token_inserter_empty_body
3162 
3163       private:
3164 
3165          const std::size_t stride_;
3166       };
3167 
3168       class token_joiner : public helper_interface
3169       {
3170       public:
3171 
token_joiner(const std::size_t & stride)3172          explicit token_joiner(const std::size_t& stride)
3173          : stride_(stride)
3174          {}
3175 
process(generator & g)3176          inline std::size_t process(generator& g)
3177          {
3178             if (g.token_list_.empty())
3179                return 0;
3180 
3181             switch (stride_)
3182             {
3183                case 2  : return process_stride_2(g);
3184                case 3  : return process_stride_3(g);
3185                default : return 0;
3186             }
3187          }
3188 
join(const token &,const token &,token &)3189          virtual bool join(const token&, const token&, token&)               { return false; }
join(const token &,const token &,const token &,token &)3190          virtual bool join(const token&, const token&, const token&, token&) { return false; }
3191 
3192       private:
3193 
process_stride_2(generator & g)3194          inline std::size_t process_stride_2(generator& g)
3195          {
3196             if (g.token_list_.size() < 2)
3197                return 0;
3198 
3199             std::size_t changes = 0;
3200 
3201             generator::token_list_t token_list;
3202             token_list.reserve(10000);
3203 
3204             for (int i = 0;  i < static_cast<int>(g.token_list_.size() - 1); ++i)
3205             {
3206                token t;
3207 
3208                for ( ; ; )
3209                {
3210                   if (!join(g[i], g[i + 1], t))
3211                   {
3212                      token_list.push_back(g[i]);
3213                      break;
3214                   }
3215 
3216                   token_list.push_back(t);
3217 
3218                   ++changes;
3219 
3220                   i+=2;
3221 
3222                   if (static_cast<std::size_t>(i) >= g.token_list_.size())
3223                      break;
3224                }
3225             }
3226 
3227             token_list.push_back(g.token_list_.back());
3228 
3229             std::swap(token_list, g.token_list_);
3230 
3231             return changes;
3232          }
3233 
process_stride_3(generator & g)3234          inline std::size_t process_stride_3(generator& g)
3235          {
3236             if (g.token_list_.size() < 3)
3237                return 0;
3238 
3239             std::size_t changes = 0;
3240 
3241             generator::token_list_t token_list;
3242             token_list.reserve(10000);
3243 
3244             for (int i = 0;  i < static_cast<int>(g.token_list_.size() - 2); ++i)
3245             {
3246                token t;
3247 
3248                for ( ; ; )
3249                {
3250                   if (!join(g[i], g[i + 1], g[i + 2], t))
3251                   {
3252                      token_list.push_back(g[i]);
3253                      break;
3254                   }
3255 
3256                   token_list.push_back(t);
3257 
3258                   ++changes;
3259 
3260                   i+=3;
3261 
3262                   if (static_cast<std::size_t>(i) >= g.token_list_.size())
3263                      break;
3264                }
3265             }
3266 
3267             token_list.push_back(*(g.token_list_.begin() + g.token_list_.size() - 2));
3268             token_list.push_back(*(g.token_list_.begin() + g.token_list_.size() - 1));
3269 
3270             std::swap(token_list, g.token_list_);
3271 
3272             return changes;
3273          }
3274 
3275          const std::size_t stride_;
3276       };
3277 
3278       namespace helper
3279       {
3280 
dump(const lexer::generator & generator)3281          inline void dump(const lexer::generator& generator)
3282          {
3283             for (std::size_t i = 0; i < generator.size(); ++i)
3284             {
3285                const lexer::token& t = generator[i];
3286                printf("Token[%02d] @ %03d  %6s  -->  '%s'\n",
3287                       static_cast<int>(i),
3288                       static_cast<int>(t.position),
3289                       t.to_str(t.type).c_str(),
3290                       t.value.c_str());
3291             }
3292          }
3293 
3294          class commutative_inserter : public lexer::token_inserter
3295          {
3296          public:
3297 
3298             using lexer::token_inserter::insert;
3299 
commutative_inserter()3300             commutative_inserter()
3301             : lexer::token_inserter(2)
3302             {}
3303 
ignore_symbol(const std::string & symbol)3304             inline void ignore_symbol(const std::string& symbol)
3305             {
3306                ignore_set_.insert(symbol);
3307             }
3308 
insert(const lexer::token & t0,const lexer::token & t1,lexer::token & new_token)3309             inline int insert(const lexer::token& t0, const lexer::token& t1, lexer::token& new_token)
3310             {
3311                bool match         = false;
3312                new_token.type     = lexer::token::e_mul;
3313                new_token.value    = "*";
3314                new_token.position = t1.position;
3315 
3316                if (t0.type == lexer::token::e_symbol)
3317                {
3318                   if (ignore_set_.end() != ignore_set_.find(t0.value))
3319                   {
3320                      return -1;
3321                   }
3322                   else if (!t0.value.empty() && ('$' == t0.value[0]))
3323                   {
3324                      return -1;
3325                   }
3326                }
3327 
3328                if (t1.type == lexer::token::e_symbol)
3329                {
3330                   if (ignore_set_.end() != ignore_set_.find(t1.value))
3331                   {
3332                      return -1;
3333                   }
3334                }
3335                     if ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_symbol     )) match = true;
3336                else if ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_lbracket   )) match = true;
3337                else if ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_lcrlbracket)) match = true;
3338                else if ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_lsqrbracket)) match = true;
3339                else if ((t0.type == lexer::token::e_symbol     ) && (t1.type == lexer::token::e_number     )) match = true;
3340                else if ((t0.type == lexer::token::e_rbracket   ) && (t1.type == lexer::token::e_number     )) match = true;
3341                else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_number     )) match = true;
3342                else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_number     )) match = true;
3343                else if ((t0.type == lexer::token::e_rbracket   ) && (t1.type == lexer::token::e_symbol     )) match = true;
3344                else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_symbol     )) match = true;
3345                else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_symbol     )) match = true;
3346                else if ((t0.type == lexer::token::e_symbol     ) && (t1.type == lexer::token::e_symbol     )) match = true;
3347 
3348                return (match) ? 1 : -1;
3349             }
3350 
3351          private:
3352 
3353             std::set<std::string,details::ilesscompare> ignore_set_;
3354          };
3355 
3356          class operator_joiner : public token_joiner
3357          {
3358          public:
3359 
operator_joiner(const std::size_t & stride)3360             explicit operator_joiner(const std::size_t& stride)
3361             : token_joiner(stride)
3362             {}
3363 
join(const lexer::token & t0,const lexer::token & t1,lexer::token & t)3364             inline bool join(const lexer::token& t0, const lexer::token& t1, lexer::token& t)
3365             {
3366                // ': =' --> ':='
3367                if ((t0.type == lexer::token::e_colon) && (t1.type == lexer::token::e_eq))
3368                {
3369                   t.type     = lexer::token::e_assign;
3370                   t.value    = ":=";
3371                   t.position = t0.position;
3372 
3373                   return true;
3374                }
3375                // '+ =' --> '+='
3376                else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_eq))
3377                {
3378                   t.type     = lexer::token::e_addass;
3379                   t.value    = "+=";
3380                   t.position = t0.position;
3381 
3382                   return true;
3383                }
3384                // '- =' --> '-='
3385                else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_eq))
3386                {
3387                   t.type     = lexer::token::e_subass;
3388                   t.value    = "-=";
3389                   t.position = t0.position;
3390 
3391                   return true;
3392                }
3393                // '* =' --> '*='
3394                else if ((t0.type == lexer::token::e_mul) && (t1.type == lexer::token::e_eq))
3395                {
3396                   t.type     = lexer::token::e_mulass;
3397                   t.value    = "*=";
3398                   t.position = t0.position;
3399 
3400                   return true;
3401                }
3402                // '/ =' --> '/='
3403                else if ((t0.type == lexer::token::e_div) && (t1.type == lexer::token::e_eq))
3404                {
3405                   t.type     = lexer::token::e_divass;
3406                   t.value    = "/=";
3407                   t.position = t0.position;
3408 
3409                   return true;
3410                }
3411                // '% =' --> '%='
3412                else if ((t0.type == lexer::token::e_mod) && (t1.type == lexer::token::e_eq))
3413                {
3414                   t.type     = lexer::token::e_modass;
3415                   t.value    = "%=";
3416                   t.position = t0.position;
3417 
3418                   return true;
3419                }
3420                // '> =' --> '>='
3421                else if ((t0.type == lexer::token::e_gt) && (t1.type == lexer::token::e_eq))
3422                {
3423                   t.type     = lexer::token::e_gte;
3424                   t.value    = ">=";
3425                   t.position = t0.position;
3426 
3427                   return true;
3428                }
3429                // '< =' --> '<='
3430                else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_eq))
3431                {
3432                   t.type     = lexer::token::e_lte;
3433                   t.value    = "<=";
3434                   t.position = t0.position;
3435 
3436                   return true;
3437                }
3438                // '= =' --> '=='
3439                else if ((t0.type == lexer::token::e_eq) && (t1.type == lexer::token::e_eq))
3440                {
3441                   t.type     = lexer::token::e_eq;
3442                   t.value    = "==";
3443                   t.position = t0.position;
3444 
3445                   return true;
3446                }
3447                // '! =' --> '!='
3448                else if ((static_cast<char>(t0.type) == '!') && (t1.type == lexer::token::e_eq))
3449                {
3450                   t.type     = lexer::token::e_ne;
3451                   t.value    = "!=";
3452                   t.position = t0.position;
3453 
3454                   return true;
3455                }
3456                // '< >' --> '<>'
3457                else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_gt))
3458                {
3459                   t.type     = lexer::token::e_ne;
3460                   t.value    = "<>";
3461                   t.position = t0.position;
3462 
3463                   return true;
3464                }
3465                // '<= >' --> '<=>'
3466                else if ((t0.type == lexer::token::e_lte) && (t1.type == lexer::token::e_gt))
3467                {
3468                   t.type     = lexer::token::e_swap;
3469                   t.value    = "<=>";
3470                   t.position = t0.position;
3471 
3472                   return true;
3473                }
3474                // '+ -' --> '-'
3475                else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_sub))
3476                {
3477                   t.type     = lexer::token::e_sub;
3478                   t.value    = "-";
3479                   t.position = t0.position;
3480 
3481                   return true;
3482                }
3483                // '- +' --> '-'
3484                else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_add))
3485                {
3486                   t.type     = lexer::token::e_sub;
3487                   t.value    = "-";
3488                   t.position = t0.position;
3489 
3490                   return true;
3491                }
3492                // '- -' --> '+'
3493                else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_sub))
3494                {
3495                   /*
3496                      Note: May need to reconsider this when wanting to implement
3497                      pre/postfix decrement operator
3498                   */
3499                   t.type     = lexer::token::e_add;
3500                   t.value    = "+";
3501                   t.position = t0.position;
3502 
3503                   return true;
3504                }
3505                else
3506                   return false;
3507             }
3508 
join(const lexer::token & t0,const lexer::token & t1,const lexer::token & t2,lexer::token & t)3509             inline bool join(const lexer::token& t0, const lexer::token& t1, const lexer::token& t2, lexer::token& t)
3510             {
3511                // '[ * ]' --> '[*]'
3512                if (
3513                     (t0.type == lexer::token::e_lsqrbracket) &&
3514                     (t1.type == lexer::token::e_mul        ) &&
3515                     (t2.type == lexer::token::e_rsqrbracket)
3516                   )
3517                {
3518                   t.type     = lexer::token::e_symbol;
3519                   t.value    = "[*]";
3520                   t.position = t0.position;
3521 
3522                   return true;
3523                }
3524                else
3525                   return false;
3526             }
3527          };
3528 
3529          class bracket_checker : public lexer::token_scanner
3530          {
3531          public:
3532 
3533             using lexer::token_scanner::operator();
3534 
bracket_checker()3535             bracket_checker()
3536             : token_scanner(1),
3537               state_(true)
3538             {}
3539 
result()3540             bool result()
3541             {
3542                if (!stack_.empty())
3543                {
3544                   lexer::token t;
3545                   t.value      = stack_.top().first;
3546                   t.position   = stack_.top().second;
3547                   error_token_ = t;
3548                   state_       = false;
3549 
3550                   return false;
3551                }
3552                else
3553                   return state_;
3554             }
3555 
error_token()3556             lexer::token error_token()
3557             {
3558                return error_token_;
3559             }
3560 
reset()3561             void reset()
3562             {
3563                // Why? because msvc doesn't support swap properly.
3564                stack_ = std::stack<std::pair<char,std::size_t> >();
3565                state_ = true;
3566                error_token_.clear();
3567             }
3568 
operator ()(const lexer::token & t)3569             bool operator() (const lexer::token& t)
3570             {
3571                if (
3572                     !t.value.empty()                       &&
3573                     (lexer::token::e_string != t.type)     &&
3574                     (lexer::token::e_symbol != t.type)     &&
3575                     exprtk::details::is_bracket(t.value[0])
3576                   )
3577                {
3578                   details::char_t c = t.value[0];
3579 
3580                        if (t.type == lexer::token::e_lbracket   ) stack_.push(std::make_pair(')',t.position));
3581                   else if (t.type == lexer::token::e_lcrlbracket) stack_.push(std::make_pair('}',t.position));
3582                   else if (t.type == lexer::token::e_lsqrbracket) stack_.push(std::make_pair(']',t.position));
3583                   else if (exprtk::details::is_right_bracket(c))
3584                   {
3585                      if (stack_.empty())
3586                      {
3587                         state_       = false;
3588                         error_token_ = t;
3589 
3590                         return false;
3591                      }
3592                      else if (c != stack_.top().first)
3593                      {
3594                         state_       = false;
3595                         error_token_ = t;
3596 
3597                         return false;
3598                      }
3599                      else
3600                         stack_.pop();
3601                   }
3602                }
3603 
3604                return true;
3605             }
3606 
3607          private:
3608 
3609             bool state_;
3610             std::stack<std::pair<char,std::size_t> > stack_;
3611             lexer::token error_token_;
3612          };
3613 
3614          class numeric_checker : public lexer::token_scanner
3615          {
3616          public:
3617 
3618             using lexer::token_scanner::operator();
3619 
numeric_checker()3620             numeric_checker()
3621             : token_scanner (1),
3622               current_index_(0)
3623             {}
3624 
result()3625             bool result()
3626             {
3627                return error_list_.empty();
3628             }
3629 
reset()3630             void reset()
3631             {
3632                error_list_.clear();
3633                current_index_ = 0;
3634             }
3635 
operator ()(const lexer::token & t)3636             bool operator() (const lexer::token& t)
3637             {
3638                if (token::e_number == t.type)
3639                {
3640                   double v;
3641 
3642                   if (!exprtk::details::string_to_real(t.value,v))
3643                   {
3644                      error_list_.push_back(current_index_);
3645                   }
3646                }
3647 
3648                ++current_index_;
3649 
3650                return true;
3651             }
3652 
error_count() const3653             std::size_t error_count() const
3654             {
3655                return error_list_.size();
3656             }
3657 
error_index(const std::size_t & i)3658             std::size_t error_index(const std::size_t& i)
3659             {
3660                if (i < error_list_.size())
3661                   return error_list_[i];
3662                else
3663                   return std::numeric_limits<std::size_t>::max();
3664             }
3665 
clear_errors()3666             void clear_errors()
3667             {
3668                error_list_.clear();
3669             }
3670 
3671          private:
3672 
3673             std::size_t current_index_;
3674             std::vector<std::size_t> error_list_;
3675          };
3676 
3677          class symbol_replacer : public lexer::token_modifier
3678          {
3679          private:
3680 
3681             typedef std::map<std::string,std::pair<std::string,token::token_type>,details::ilesscompare> replace_map_t;
3682 
3683          public:
3684 
remove(const std::string & target_symbol)3685             bool remove(const std::string& target_symbol)
3686             {
3687                const replace_map_t::iterator itr = replace_map_.find(target_symbol);
3688 
3689                if (replace_map_.end() == itr)
3690                   return false;
3691 
3692                replace_map_.erase(itr);
3693 
3694                return true;
3695             }
3696 
add_replace(const std::string & target_symbol,const std::string & replace_symbol,const lexer::token::token_type token_type=lexer::token::e_symbol)3697             bool add_replace(const std::string& target_symbol,
3698                              const std::string& replace_symbol,
3699                              const lexer::token::token_type token_type = lexer::token::e_symbol)
3700             {
3701                const replace_map_t::iterator itr = replace_map_.find(target_symbol);
3702 
3703                if (replace_map_.end() != itr)
3704                {
3705                   return false;
3706                }
3707 
3708                replace_map_[target_symbol] = std::make_pair(replace_symbol,token_type);
3709 
3710                return true;
3711             }
3712 
clear()3713             void clear()
3714             {
3715                replace_map_.clear();
3716             }
3717 
3718          private:
3719 
modify(lexer::token & t)3720             bool modify(lexer::token& t)
3721             {
3722                if (lexer::token::e_symbol == t.type)
3723                {
3724                   if (replace_map_.empty())
3725                      return false;
3726 
3727                   const replace_map_t::iterator itr = replace_map_.find(t.value);
3728 
3729                   if (replace_map_.end() != itr)
3730                   {
3731                      t.value = itr->second.first;
3732                      t.type  = itr->second.second;
3733 
3734                      return true;
3735                   }
3736                }
3737 
3738                return false;
3739             }
3740 
3741             replace_map_t replace_map_;
3742          };
3743 
3744          class sequence_validator : public lexer::token_scanner
3745          {
3746          private:
3747 
3748             typedef std::pair<lexer::token::token_type,lexer::token::token_type> token_pair_t;
3749             typedef std::set<token_pair_t> set_t;
3750 
3751          public:
3752 
3753             using lexer::token_scanner::operator();
3754 
sequence_validator()3755             sequence_validator()
3756             : lexer::token_scanner(2)
3757             {
3758                add_invalid(lexer::token::e_number, lexer::token::e_number);
3759                add_invalid(lexer::token::e_string, lexer::token::e_string);
3760                add_invalid(lexer::token::e_number, lexer::token::e_string);
3761                add_invalid(lexer::token::e_string, lexer::token::e_number);
3762 
3763                add_invalid_set1(lexer::token::e_assign );
3764                add_invalid_set1(lexer::token::e_shr    );
3765                add_invalid_set1(lexer::token::e_shl    );
3766                add_invalid_set1(lexer::token::e_lte    );
3767                add_invalid_set1(lexer::token::e_ne     );
3768                add_invalid_set1(lexer::token::e_gte    );
3769                add_invalid_set1(lexer::token::e_lt     );
3770                add_invalid_set1(lexer::token::e_gt     );
3771                add_invalid_set1(lexer::token::e_eq     );
3772                add_invalid_set1(lexer::token::e_comma  );
3773                add_invalid_set1(lexer::token::e_add    );
3774                add_invalid_set1(lexer::token::e_sub    );
3775                add_invalid_set1(lexer::token::e_div    );
3776                add_invalid_set1(lexer::token::e_mul    );
3777                add_invalid_set1(lexer::token::e_mod    );
3778                add_invalid_set1(lexer::token::e_pow    );
3779                add_invalid_set1(lexer::token::e_colon  );
3780                add_invalid_set1(lexer::token::e_ternary);
3781             }
3782 
result()3783             bool result()
3784             {
3785                return error_list_.empty();
3786             }
3787 
operator ()(const lexer::token & t0,const lexer::token & t1)3788             bool operator() (const lexer::token& t0, const lexer::token& t1)
3789             {
3790                const set_t::value_type p = std::make_pair(t0.type,t1.type);
3791 
3792                if (invalid_bracket_check(t0.type,t1.type))
3793                {
3794                   error_list_.push_back(std::make_pair(t0,t1));
3795                }
3796                else if (invalid_comb_.find(p) != invalid_comb_.end())
3797                {
3798                   error_list_.push_back(std::make_pair(t0,t1));
3799                }
3800 
3801                return true;
3802             }
3803 
error_count() const3804             std::size_t error_count() const
3805             {
3806                return error_list_.size();
3807             }
3808 
error(const std::size_t index)3809             std::pair<lexer::token,lexer::token> error(const std::size_t index)
3810             {
3811                if (index < error_list_.size())
3812                {
3813                   return error_list_[index];
3814                }
3815                else
3816                {
3817                   static const lexer::token error_token;
3818                   return std::make_pair(error_token,error_token);
3819                }
3820             }
3821 
clear_errors()3822             void clear_errors()
3823             {
3824                error_list_.clear();
3825             }
3826 
3827          private:
3828 
add_invalid(lexer::token::token_type base,lexer::token::token_type t)3829             void add_invalid(lexer::token::token_type base, lexer::token::token_type t)
3830             {
3831                invalid_comb_.insert(std::make_pair(base,t));
3832             }
3833 
add_invalid_set1(lexer::token::token_type t)3834             void add_invalid_set1(lexer::token::token_type t)
3835             {
3836                add_invalid(t, lexer::token::e_assign);
3837                add_invalid(t, lexer::token::e_shr   );
3838                add_invalid(t, lexer::token::e_shl   );
3839                add_invalid(t, lexer::token::e_lte   );
3840                add_invalid(t, lexer::token::e_ne    );
3841                add_invalid(t, lexer::token::e_gte   );
3842                add_invalid(t, lexer::token::e_lt    );
3843                add_invalid(t, lexer::token::e_gt    );
3844                add_invalid(t, lexer::token::e_eq    );
3845                add_invalid(t, lexer::token::e_comma );
3846                add_invalid(t, lexer::token::e_div   );
3847                add_invalid(t, lexer::token::e_mul   );
3848                add_invalid(t, lexer::token::e_mod   );
3849                add_invalid(t, lexer::token::e_pow   );
3850                add_invalid(t, lexer::token::e_colon );
3851             }
3852 
invalid_bracket_check(lexer::token::token_type base,lexer::token::token_type t)3853             bool invalid_bracket_check(lexer::token::token_type base, lexer::token::token_type t)
3854             {
3855                if (details::is_right_bracket(static_cast<char>(base)))
3856                {
3857                   switch (t)
3858                   {
3859                      case lexer::token::e_assign : return (']' != base);
3860                      case lexer::token::e_string : return (')' != base);
3861                      default                     : return false;
3862                   }
3863                }
3864                else if (details::is_left_bracket(static_cast<char>(base)))
3865                {
3866                   if (details::is_right_bracket(static_cast<char>(t)))
3867                      return false;
3868                   else if (details::is_left_bracket(static_cast<char>(t)))
3869                      return false;
3870                   else
3871                   {
3872                      switch (t)
3873                      {
3874                         case lexer::token::e_number  : return false;
3875                         case lexer::token::e_symbol  : return false;
3876                         case lexer::token::e_string  : return false;
3877                         case lexer::token::e_add     : return false;
3878                         case lexer::token::e_sub     : return false;
3879                         case lexer::token::e_colon   : return false;
3880                         case lexer::token::e_ternary : return false;
3881                         default                      : return true ;
3882                      }
3883                   }
3884                }
3885                else if (details::is_right_bracket(static_cast<char>(t)))
3886                {
3887                   switch (base)
3888                   {
3889                      case lexer::token::e_number  : return false;
3890                      case lexer::token::e_symbol  : return false;
3891                      case lexer::token::e_string  : return false;
3892                      case lexer::token::e_eof     : return false;
3893                      case lexer::token::e_colon   : return false;
3894                      case lexer::token::e_ternary : return false;
3895                      default                      : return true ;
3896                   }
3897                }
3898                else if (details::is_left_bracket(static_cast<char>(t)))
3899                {
3900                   switch (base)
3901                   {
3902                      case lexer::token::e_rbracket    : return true;
3903                      case lexer::token::e_rsqrbracket : return true;
3904                      case lexer::token::e_rcrlbracket : return true;
3905                      default                          : return false;
3906                   }
3907                }
3908 
3909                return false;
3910             }
3911 
3912             set_t invalid_comb_;
3913             std::vector<std::pair<lexer::token,lexer::token> > error_list_;
3914          };
3915 
3916          class sequence_validator_3tokens : public lexer::token_scanner
3917          {
3918          private:
3919 
3920             typedef lexer::token::token_type token_t;
3921             typedef std::pair<token_t,std::pair<token_t,token_t> > token_triplet_t;
3922             typedef std::set<token_triplet_t> set_t;
3923 
3924          public:
3925 
3926             using lexer::token_scanner::operator();
3927 
sequence_validator_3tokens()3928             sequence_validator_3tokens()
3929             : lexer::token_scanner(3)
3930             {
3931                add_invalid(lexer::token::e_number, lexer::token::e_number, lexer::token::e_number);
3932                add_invalid(lexer::token::e_string, lexer::token::e_string, lexer::token::e_string);
3933                add_invalid(lexer::token::e_comma , lexer::token::e_comma , lexer::token::e_comma );
3934 
3935                add_invalid(lexer::token::e_add   , lexer::token::e_add   , lexer::token::e_add   );
3936                add_invalid(lexer::token::e_sub   , lexer::token::e_sub   , lexer::token::e_sub   );
3937                add_invalid(lexer::token::e_div   , lexer::token::e_div   , lexer::token::e_div   );
3938                add_invalid(lexer::token::e_mul   , lexer::token::e_mul   , lexer::token::e_mul   );
3939                add_invalid(lexer::token::e_mod   , lexer::token::e_mod   , lexer::token::e_mod   );
3940                add_invalid(lexer::token::e_pow   , lexer::token::e_pow   , lexer::token::e_pow   );
3941 
3942                add_invalid(lexer::token::e_add   , lexer::token::e_sub   , lexer::token::e_add   );
3943                add_invalid(lexer::token::e_sub   , lexer::token::e_add   , lexer::token::e_sub   );
3944                add_invalid(lexer::token::e_div   , lexer::token::e_mul   , lexer::token::e_div   );
3945                add_invalid(lexer::token::e_mul   , lexer::token::e_div   , lexer::token::e_mul   );
3946                add_invalid(lexer::token::e_mod   , lexer::token::e_pow   , lexer::token::e_mod   );
3947                add_invalid(lexer::token::e_pow   , lexer::token::e_mod   , lexer::token::e_pow   );
3948             }
3949 
result()3950             bool result()
3951             {
3952                return error_list_.empty();
3953             }
3954 
operator ()(const lexer::token & t0,const lexer::token & t1,const lexer::token & t2)3955             bool operator() (const lexer::token& t0, const lexer::token& t1, const lexer::token& t2)
3956             {
3957                const set_t::value_type p = std::make_pair(t0.type,std::make_pair(t1.type,t2.type));
3958 
3959                if (invalid_comb_.find(p) != invalid_comb_.end())
3960                {
3961                   error_list_.push_back(std::make_pair(t0,t1));
3962                }
3963 
3964                return true;
3965             }
3966 
error_count() const3967             std::size_t error_count() const
3968             {
3969                return error_list_.size();
3970             }
3971 
error(const std::size_t index)3972             std::pair<lexer::token,lexer::token> error(const std::size_t index)
3973             {
3974                if (index < error_list_.size())
3975                {
3976                   return error_list_[index];
3977                }
3978                else
3979                {
3980                   static const lexer::token error_token;
3981                   return std::make_pair(error_token,error_token);
3982                }
3983             }
3984 
clear_errors()3985             void clear_errors()
3986             {
3987                error_list_.clear();
3988             }
3989 
3990          private:
3991 
add_invalid(token_t t0,token_t t1,token_t t2)3992             void add_invalid(token_t t0, token_t t1, token_t t2)
3993             {
3994                invalid_comb_.insert(std::make_pair(t0,std::make_pair(t1,t2)));
3995             }
3996 
3997             set_t invalid_comb_;
3998             std::vector<std::pair<lexer::token,lexer::token> > error_list_;
3999          };
4000 
4001          struct helper_assembly
4002          {
register_scannerexprtk::lexer::helper::helper_assembly4003             inline bool register_scanner(lexer::token_scanner* scanner)
4004             {
4005                if (token_scanner_list.end() != std::find(token_scanner_list.begin(),
4006                                                          token_scanner_list.end  (),
4007                                                          scanner))
4008                {
4009                   return false;
4010                }
4011 
4012                token_scanner_list.push_back(scanner);
4013 
4014                return true;
4015             }
4016 
register_modifierexprtk::lexer::helper::helper_assembly4017             inline bool register_modifier(lexer::token_modifier* modifier)
4018             {
4019                if (token_modifier_list.end() != std::find(token_modifier_list.begin(),
4020                                                           token_modifier_list.end  (),
4021                                                           modifier))
4022                {
4023                   return false;
4024                }
4025 
4026                token_modifier_list.push_back(modifier);
4027 
4028                return true;
4029             }
4030 
register_joinerexprtk::lexer::helper::helper_assembly4031             inline bool register_joiner(lexer::token_joiner* joiner)
4032             {
4033                if (token_joiner_list.end() != std::find(token_joiner_list.begin(),
4034                                                         token_joiner_list.end  (),
4035                                                         joiner))
4036                {
4037                   return false;
4038                }
4039 
4040                token_joiner_list.push_back(joiner);
4041 
4042                return true;
4043             }
4044 
register_inserterexprtk::lexer::helper::helper_assembly4045             inline bool register_inserter(lexer::token_inserter* inserter)
4046             {
4047                if (token_inserter_list.end() != std::find(token_inserter_list.begin(),
4048                                                           token_inserter_list.end  (),
4049                                                           inserter))
4050                {
4051                   return false;
4052                }
4053 
4054                token_inserter_list.push_back(inserter);
4055 
4056                return true;
4057             }
4058 
run_modifiersexprtk::lexer::helper::helper_assembly4059             inline bool run_modifiers(lexer::generator& g)
4060             {
4061                error_token_modifier = reinterpret_cast<lexer::token_modifier*>(0);
4062 
4063                for (std::size_t i = 0; i < token_modifier_list.size(); ++i)
4064                {
4065                   lexer::token_modifier& modifier = (*token_modifier_list[i]);
4066 
4067                   modifier.reset();
4068                   modifier.process(g);
4069 
4070                   if (!modifier.result())
4071                   {
4072                      error_token_modifier = token_modifier_list[i];
4073 
4074                      return false;
4075                   }
4076                }
4077 
4078                return true;
4079             }
4080 
run_joinersexprtk::lexer::helper::helper_assembly4081             inline bool run_joiners(lexer::generator& g)
4082             {
4083                error_token_joiner = reinterpret_cast<lexer::token_joiner*>(0);
4084 
4085                for (std::size_t i = 0; i < token_joiner_list.size(); ++i)
4086                {
4087                   lexer::token_joiner& joiner = (*token_joiner_list[i]);
4088 
4089                   joiner.reset();
4090                   joiner.process(g);
4091 
4092                   if (!joiner.result())
4093                   {
4094                      error_token_joiner = token_joiner_list[i];
4095 
4096                      return false;
4097                   }
4098                }
4099 
4100                return true;
4101             }
4102 
run_insertersexprtk::lexer::helper::helper_assembly4103             inline bool run_inserters(lexer::generator& g)
4104             {
4105                error_token_inserter = reinterpret_cast<lexer::token_inserter*>(0);
4106 
4107                for (std::size_t i = 0; i < token_inserter_list.size(); ++i)
4108                {
4109                   lexer::token_inserter& inserter = (*token_inserter_list[i]);
4110 
4111                   inserter.reset();
4112                   inserter.process(g);
4113 
4114                   if (!inserter.result())
4115                   {
4116                      error_token_inserter = token_inserter_list[i];
4117 
4118                      return false;
4119                   }
4120                }
4121 
4122                return true;
4123             }
4124 
run_scannersexprtk::lexer::helper::helper_assembly4125             inline bool run_scanners(lexer::generator& g)
4126             {
4127                error_token_scanner = reinterpret_cast<lexer::token_scanner*>(0);
4128 
4129                for (std::size_t i = 0; i < token_scanner_list.size(); ++i)
4130                {
4131                   lexer::token_scanner& scanner = (*token_scanner_list[i]);
4132 
4133                   scanner.reset();
4134                   scanner.process(g);
4135 
4136                   if (!scanner.result())
4137                   {
4138                      error_token_scanner = token_scanner_list[i];
4139 
4140                      return false;
4141                   }
4142                }
4143 
4144                return true;
4145             }
4146 
4147             std::vector<lexer::token_scanner*>  token_scanner_list;
4148             std::vector<lexer::token_modifier*> token_modifier_list;
4149             std::vector<lexer::token_joiner*>   token_joiner_list;
4150             std::vector<lexer::token_inserter*> token_inserter_list;
4151 
4152             lexer::token_scanner*  error_token_scanner;
4153             lexer::token_modifier* error_token_modifier;
4154             lexer::token_joiner*   error_token_joiner;
4155             lexer::token_inserter* error_token_inserter;
4156          };
4157       }
4158 
4159       class parser_helper
4160       {
4161       public:
4162 
4163          typedef token         token_t;
4164          typedef generator generator_t;
4165 
init(const std::string & str)4166          inline bool init(const std::string& str)
4167          {
4168             if (!lexer_.process(str))
4169             {
4170                return false;
4171             }
4172 
4173             lexer_.begin();
4174 
4175             next_token();
4176 
4177             return true;
4178          }
4179 
lexer()4180          inline generator_t& lexer()
4181          {
4182             return lexer_;
4183          }
4184 
lexer() const4185          inline const generator_t& lexer() const
4186          {
4187             return lexer_;
4188          }
4189 
store_token()4190          inline void store_token()
4191          {
4192             lexer_.store();
4193             store_current_token_ = current_token_;
4194          }
4195 
restore_token()4196          inline void restore_token()
4197          {
4198             lexer_.restore();
4199             current_token_ = store_current_token_;
4200          }
4201 
next_token()4202          inline void next_token()
4203          {
4204             current_token_ = lexer_.next_token();
4205          }
4206 
current_token() const4207          inline const token_t& current_token() const
4208          {
4209             return current_token_;
4210          }
4211 
4212          enum token_advance_mode
4213          {
4214             e_hold    = 0,
4215             e_advance = 1
4216          };
4217 
advance_token(const token_advance_mode mode)4218          inline void advance_token(const token_advance_mode mode)
4219          {
4220             if (e_advance == mode)
4221             {
4222                next_token();
4223             }
4224          }
4225 
token_is(const token_t::token_type & ttype,const token_advance_mode mode=e_advance)4226          inline bool token_is(const token_t::token_type& ttype, const token_advance_mode mode = e_advance)
4227          {
4228             if (current_token().type != ttype)
4229             {
4230                return false;
4231             }
4232 
4233             advance_token(mode);
4234 
4235             return true;
4236          }
4237 
token_is(const token_t::token_type & ttype,const std::string & value,const token_advance_mode mode=e_advance)4238          inline bool token_is(const token_t::token_type& ttype,
4239                               const std::string& value,
4240                               const token_advance_mode mode = e_advance)
4241          {
4242             if (
4243                  (current_token().type != ttype) ||
4244                  !exprtk::details::imatch(value,current_token().value)
4245                )
4246             {
4247                return false;
4248             }
4249 
4250             advance_token(mode);
4251 
4252             return true;
4253          }
4254 
peek_token_is(const token_t::token_type & ttype)4255          inline bool peek_token_is(const token_t::token_type& ttype)
4256          {
4257             return (lexer_.peek_next_token().type == ttype);
4258          }
4259 
peek_token_is(const std::string & s)4260          inline bool peek_token_is(const std::string& s)
4261          {
4262             return (exprtk::details::imatch(lexer_.peek_next_token().value,s));
4263          }
4264 
4265       private:
4266 
4267          generator_t lexer_;
4268          token_t     current_token_;
4269          token_t     store_current_token_;
4270       };
4271    }
4272 
4273    template <typename T>
4274    class vector_view
4275    {
4276    public:
4277 
4278       typedef T* data_ptr_t;
4279 
vector_view(data_ptr_t data,const std::size_t & size)4280       vector_view(data_ptr_t data, const std::size_t& size)
4281       : size_(size),
4282         data_(data),
4283         data_ref_(0)
4284       {}
4285 
vector_view(const vector_view<T> & vv)4286       vector_view(const vector_view<T>& vv)
4287       : size_(vv.size_),
4288         data_(vv.data_),
4289         data_ref_(0)
4290       {}
4291 
rebase(data_ptr_t data)4292       inline void rebase(data_ptr_t data)
4293       {
4294          data_ = data;
4295 
4296          if (!data_ref_.empty())
4297          {
4298             for (std::size_t i = 0; i < data_ref_.size(); ++i)
4299             {
4300                (*data_ref_[i]) = data;
4301             }
4302          }
4303       }
4304 
data() const4305       inline data_ptr_t data() const
4306       {
4307          return data_;
4308       }
4309 
size() const4310       inline std::size_t size() const
4311       {
4312          return size_;
4313       }
4314 
operator [](const std::size_t index) const4315       inline const T& operator[](const std::size_t index) const
4316       {
4317          return data_[index];
4318       }
4319 
operator [](const std::size_t index)4320       inline T& operator[](const std::size_t index)
4321       {
4322          return data_[index];
4323       }
4324 
set_ref(data_ptr_t * data_ref)4325       void set_ref(data_ptr_t* data_ref)
4326       {
4327          data_ref_.push_back(data_ref);
4328       }
4329 
4330    private:
4331 
4332       const std::size_t size_;
4333       data_ptr_t  data_;
4334       std::vector<data_ptr_t*> data_ref_;
4335    };
4336 
4337    template <typename T>
make_vector_view(T * data,const std::size_t size,const std::size_t offset=0)4338    inline vector_view<T> make_vector_view(T* data,
4339                                           const std::size_t size, const std::size_t offset = 0)
4340    {
4341       return vector_view<T>(data + offset, size);
4342    }
4343 
4344    template <typename T>
make_vector_view(std::vector<T> & v,const std::size_t size,const std::size_t offset=0)4345    inline vector_view<T> make_vector_view(std::vector<T>& v,
4346                                           const std::size_t size, const std::size_t offset = 0)
4347    {
4348       return vector_view<T>(v.data() + offset, size);
4349    }
4350 
4351    template <typename T> class results_context;
4352 
4353    template <typename T>
4354    struct type_store
4355    {
4356       enum store_type
4357       {
4358          e_unknown,
4359          e_scalar ,
4360          e_vector ,
4361          e_string
4362       };
4363 
type_storeexprtk::type_store4364       type_store()
4365       : data(0),
4366         size(0),
4367         type(e_unknown)
4368       {}
4369 
4370       union
4371       {
4372           void*  data;
4373           T*     vec_data;
4374       };
4375 
4376       std::size_t size;
4377       store_type  type;
4378 
4379       class parameter_list
4380       {
4381       public:
4382 
parameter_list(std::vector<type_store> & pl)4383          explicit parameter_list(std::vector<type_store>& pl)
4384          : parameter_list_(pl)
4385          {}
4386 
empty() const4387          inline bool empty() const
4388          {
4389             return parameter_list_.empty();
4390          }
4391 
size() const4392          inline std::size_t size() const
4393          {
4394             return parameter_list_.size();
4395          }
4396 
operator [](const std::size_t & index)4397          inline type_store& operator[](const std::size_t& index)
4398          {
4399             return parameter_list_[index];
4400          }
4401 
operator [](const std::size_t & index) const4402          inline const type_store& operator[](const std::size_t& index) const
4403          {
4404             return parameter_list_[index];
4405          }
4406 
front()4407          inline type_store& front()
4408          {
4409             return parameter_list_[0];
4410          }
4411 
front() const4412          inline const type_store& front() const
4413          {
4414             return parameter_list_[0];
4415          }
4416 
back()4417          inline type_store& back()
4418          {
4419             return parameter_list_.back();
4420          }
4421 
back() const4422          inline const type_store& back() const
4423          {
4424             return parameter_list_.back();
4425          }
4426 
4427       private:
4428 
4429          std::vector<type_store>& parameter_list_;
4430 
4431          friend class results_context<T>;
4432       };
4433 
4434       template <typename ViewType>
4435       struct type_view
4436       {
4437          typedef type_store<T> type_store_t;
4438          typedef ViewType      value_t;
4439 
type_viewexprtk::type_store::type_view4440          explicit type_view(type_store_t& ts)
4441          : ts_(ts),
4442            data_(reinterpret_cast<value_t*>(ts_.data))
4443          {}
4444 
type_viewexprtk::type_store::type_view4445          explicit type_view(const type_store_t& ts)
4446          : ts_(const_cast<type_store_t&>(ts)),
4447            data_(reinterpret_cast<value_t*>(ts_.data))
4448          {}
4449 
sizeexprtk::type_store::type_view4450          inline std::size_t size() const
4451          {
4452             return ts_.size;
4453          }
4454 
operator []exprtk::type_store::type_view4455          inline value_t& operator[](const std::size_t& i)
4456          {
4457             return data_[i];
4458          }
4459 
operator []exprtk::type_store::type_view4460          inline const value_t& operator[](const std::size_t& i) const
4461          {
4462             return data_[i];
4463          }
4464 
beginexprtk::type_store::type_view4465          inline const value_t* begin() const { return data_; }
beginexprtk::type_store::type_view4466          inline       value_t* begin()       { return data_; }
4467 
endexprtk::type_store::type_view4468          inline const value_t* end() const
4469          {
4470             return static_cast<value_t*>(data_ + ts_.size);
4471          }
4472 
endexprtk::type_store::type_view4473          inline value_t* end()
4474          {
4475             return static_cast<value_t*>(data_ + ts_.size);
4476          }
4477 
4478          type_store_t& ts_;
4479          value_t* data_;
4480       };
4481 
4482       typedef type_view<T>    vector_view;
4483       typedef type_view<char> string_view;
4484 
4485       struct scalar_view
4486       {
4487          typedef type_store<T> type_store_t;
4488          typedef T value_t;
4489 
scalar_viewexprtk::type_store::scalar_view4490          explicit scalar_view(type_store_t& ts)
4491          : v_(*reinterpret_cast<value_t*>(ts.data))
4492          {}
4493 
scalar_viewexprtk::type_store::scalar_view4494          explicit scalar_view(const type_store_t& ts)
4495          : v_(*reinterpret_cast<value_t*>(const_cast<type_store_t&>(ts).data))
4496          {}
4497 
operator ()exprtk::type_store::scalar_view4498          inline value_t& operator() ()
4499          {
4500             return v_;
4501          }
4502 
operator ()exprtk::type_store::scalar_view4503          inline const value_t& operator() () const
4504          {
4505             return v_;
4506          }
4507 
4508          template <typename IntType>
to_intexprtk::type_store::scalar_view4509          inline bool to_int(IntType& i) const
4510          {
4511             if (!exprtk::details::numeric::is_integer(v_))
4512                return false;
4513 
4514             i = static_cast<IntType>(v_);
4515 
4516             return true;
4517          }
4518 
4519          template <typename UIntType>
to_uintexprtk::type_store::scalar_view4520          inline bool to_uint(UIntType& u) const
4521          {
4522             if (v_ < T(0))
4523                return false;
4524             else if (!exprtk::details::numeric::is_integer(v_))
4525                return false;
4526 
4527             u = static_cast<UIntType>(v_);
4528 
4529             return true;
4530          }
4531 
4532          T& v_;
4533       };
4534    };
4535 
4536    template <typename StringView>
to_str(const StringView & view)4537    inline std::string to_str(const StringView& view)
4538    {
4539       return std::string(view.begin(),view.size());
4540    }
4541 
4542    #ifndef exprtk_disable_return_statement
4543    namespace details
4544    {
4545       template <typename T> class return_node;
4546       template <typename T> class return_envelope_node;
4547    }
4548    #endif
4549 
4550    template <typename T>
4551    class results_context
4552    {
4553    public:
4554 
4555       typedef type_store<T> type_store_t;
4556 
results_context()4557       results_context()
4558       : results_available_(false)
4559       {}
4560 
count() const4561       inline std::size_t count() const
4562       {
4563          if (results_available_)
4564             return parameter_list_.size();
4565          else
4566             return 0;
4567       }
4568 
operator [](const std::size_t & index)4569       inline type_store_t& operator[](const std::size_t& index)
4570       {
4571          return parameter_list_[index];
4572       }
4573 
operator [](const std::size_t & index) const4574       inline const type_store_t& operator[](const std::size_t& index) const
4575       {
4576          return parameter_list_[index];
4577       }
4578 
4579    private:
4580 
clear()4581       inline void clear()
4582       {
4583          results_available_ = false;
4584       }
4585 
4586       typedef std::vector<type_store_t> ts_list_t;
4587       typedef typename type_store_t::parameter_list parameter_list_t;
4588 
assign(const parameter_list_t & pl)4589       inline void assign(const parameter_list_t& pl)
4590       {
4591          parameter_list_    = pl.parameter_list_;
4592          results_available_ = true;
4593       }
4594 
4595       bool results_available_;
4596       ts_list_t parameter_list_;
4597 
4598       #ifndef exprtk_disable_return_statement
4599       friend class details::return_node<T>;
4600       friend class details::return_envelope_node<T>;
4601       #endif
4602    };
4603 
4604    namespace details
4605    {
4606       enum operator_type
4607       {
4608          e_default , e_null    , e_add     , e_sub     ,
4609          e_mul     , e_div     , e_mod     , e_pow     ,
4610          e_atan2   , e_min     , e_max     , e_avg     ,
4611          e_sum     , e_prod    , e_lt      , e_lte     ,
4612          e_eq      , e_equal   , e_ne      , e_nequal  ,
4613          e_gte     , e_gt      , e_and     , e_nand    ,
4614          e_or      , e_nor     , e_xor     , e_xnor    ,
4615          e_mand    , e_mor     , e_scand   , e_scor    ,
4616          e_shr     , e_shl     , e_abs     , e_acos    ,
4617          e_acosh   , e_asin    , e_asinh   , e_atan    ,
4618          e_atanh   , e_ceil    , e_cos     , e_cosh    ,
4619          e_exp     , e_expm1   , e_floor   , e_log     ,
4620          e_log10   , e_log2    , e_log1p   , e_logn    ,
4621          e_neg     , e_pos     , e_round   , e_roundn  ,
4622          e_root    , e_sqrt    , e_sin     , e_sinc    ,
4623          e_sinh    , e_sec     , e_csc     , e_tan     ,
4624          e_tanh    , e_cot     , e_clamp   , e_iclamp  ,
4625          e_inrange , e_sgn     , e_r2d     , e_d2r     ,
4626          e_d2g     , e_g2d     , e_hypot   , e_notl    ,
4627          e_erf     , e_erfc    , e_ncdf    , e_frac    ,
4628          e_trunc   , e_assign  , e_addass  , e_subass  ,
4629          e_mulass  , e_divass  , e_modass  , e_in      ,
4630          e_like    , e_ilike   , e_multi   , e_smulti  ,
4631          e_swap    ,
4632 
4633          // Do not add new functions/operators after this point.
4634          e_sf00 = 1000, e_sf01 = 1001, e_sf02 = 1002, e_sf03 = 1003,
4635          e_sf04 = 1004, e_sf05 = 1005, e_sf06 = 1006, e_sf07 = 1007,
4636          e_sf08 = 1008, e_sf09 = 1009, e_sf10 = 1010, e_sf11 = 1011,
4637          e_sf12 = 1012, e_sf13 = 1013, e_sf14 = 1014, e_sf15 = 1015,
4638          e_sf16 = 1016, e_sf17 = 1017, e_sf18 = 1018, e_sf19 = 1019,
4639          e_sf20 = 1020, e_sf21 = 1021, e_sf22 = 1022, e_sf23 = 1023,
4640          e_sf24 = 1024, e_sf25 = 1025, e_sf26 = 1026, e_sf27 = 1027,
4641          e_sf28 = 1028, e_sf29 = 1029, e_sf30 = 1030, e_sf31 = 1031,
4642          e_sf32 = 1032, e_sf33 = 1033, e_sf34 = 1034, e_sf35 = 1035,
4643          e_sf36 = 1036, e_sf37 = 1037, e_sf38 = 1038, e_sf39 = 1039,
4644          e_sf40 = 1040, e_sf41 = 1041, e_sf42 = 1042, e_sf43 = 1043,
4645          e_sf44 = 1044, e_sf45 = 1045, e_sf46 = 1046, e_sf47 = 1047,
4646          e_sf48 = 1048, e_sf49 = 1049, e_sf50 = 1050, e_sf51 = 1051,
4647          e_sf52 = 1052, e_sf53 = 1053, e_sf54 = 1054, e_sf55 = 1055,
4648          e_sf56 = 1056, e_sf57 = 1057, e_sf58 = 1058, e_sf59 = 1059,
4649          e_sf60 = 1060, e_sf61 = 1061, e_sf62 = 1062, e_sf63 = 1063,
4650          e_sf64 = 1064, e_sf65 = 1065, e_sf66 = 1066, e_sf67 = 1067,
4651          e_sf68 = 1068, e_sf69 = 1069, e_sf70 = 1070, e_sf71 = 1071,
4652          e_sf72 = 1072, e_sf73 = 1073, e_sf74 = 1074, e_sf75 = 1075,
4653          e_sf76 = 1076, e_sf77 = 1077, e_sf78 = 1078, e_sf79 = 1079,
4654          e_sf80 = 1080, e_sf81 = 1081, e_sf82 = 1082, e_sf83 = 1083,
4655          e_sf84 = 1084, e_sf85 = 1085, e_sf86 = 1086, e_sf87 = 1087,
4656          e_sf88 = 1088, e_sf89 = 1089, e_sf90 = 1090, e_sf91 = 1091,
4657          e_sf92 = 1092, e_sf93 = 1093, e_sf94 = 1094, e_sf95 = 1095,
4658          e_sf96 = 1096, e_sf97 = 1097, e_sf98 = 1098, e_sf99 = 1099,
4659          e_sffinal  = 1100,
4660          e_sf4ext00 = 2000, e_sf4ext01 = 2001, e_sf4ext02 = 2002, e_sf4ext03 = 2003,
4661          e_sf4ext04 = 2004, e_sf4ext05 = 2005, e_sf4ext06 = 2006, e_sf4ext07 = 2007,
4662          e_sf4ext08 = 2008, e_sf4ext09 = 2009, e_sf4ext10 = 2010, e_sf4ext11 = 2011,
4663          e_sf4ext12 = 2012, e_sf4ext13 = 2013, e_sf4ext14 = 2014, e_sf4ext15 = 2015,
4664          e_sf4ext16 = 2016, e_sf4ext17 = 2017, e_sf4ext18 = 2018, e_sf4ext19 = 2019,
4665          e_sf4ext20 = 2020, e_sf4ext21 = 2021, e_sf4ext22 = 2022, e_sf4ext23 = 2023,
4666          e_sf4ext24 = 2024, e_sf4ext25 = 2025, e_sf4ext26 = 2026, e_sf4ext27 = 2027,
4667          e_sf4ext28 = 2028, e_sf4ext29 = 2029, e_sf4ext30 = 2030, e_sf4ext31 = 2031,
4668          e_sf4ext32 = 2032, e_sf4ext33 = 2033, e_sf4ext34 = 2034, e_sf4ext35 = 2035,
4669          e_sf4ext36 = 2036, e_sf4ext37 = 2037, e_sf4ext38 = 2038, e_sf4ext39 = 2039,
4670          e_sf4ext40 = 2040, e_sf4ext41 = 2041, e_sf4ext42 = 2042, e_sf4ext43 = 2043,
4671          e_sf4ext44 = 2044, e_sf4ext45 = 2045, e_sf4ext46 = 2046, e_sf4ext47 = 2047,
4672          e_sf4ext48 = 2048, e_sf4ext49 = 2049, e_sf4ext50 = 2050, e_sf4ext51 = 2051,
4673          e_sf4ext52 = 2052, e_sf4ext53 = 2053, e_sf4ext54 = 2054, e_sf4ext55 = 2055,
4674          e_sf4ext56 = 2056, e_sf4ext57 = 2057, e_sf4ext58 = 2058, e_sf4ext59 = 2059,
4675          e_sf4ext60 = 2060, e_sf4ext61 = 2061
4676       };
4677 
to_str(const operator_type opr)4678       inline std::string to_str(const operator_type opr)
4679       {
4680          switch (opr)
4681          {
4682             case e_add    : return  "+"  ;
4683             case e_sub    : return  "-"  ;
4684             case e_mul    : return  "*"  ;
4685             case e_div    : return  "/"  ;
4686             case e_mod    : return  "%"  ;
4687             case e_pow    : return  "^"  ;
4688             case e_assign : return ":="  ;
4689             case e_addass : return "+="  ;
4690             case e_subass : return "-="  ;
4691             case e_mulass : return "*="  ;
4692             case e_divass : return "/="  ;
4693             case e_modass : return "%="  ;
4694             case e_lt     : return  "<"  ;
4695             case e_lte    : return "<="  ;
4696             case e_eq     : return "=="  ;
4697             case e_equal  : return  "="  ;
4698             case e_ne     : return "!="  ;
4699             case e_nequal : return "<>"  ;
4700             case e_gte    : return ">="  ;
4701             case e_gt     : return  ">"  ;
4702             case e_and    : return "and" ;
4703             case e_or     : return "or"  ;
4704             case e_xor    : return "xor" ;
4705             case e_nand   : return "nand";
4706             case e_nor    : return "nor" ;
4707             case e_xnor   : return "xnor";
4708             default       : return "N/A" ;
4709          }
4710       }
4711 
4712       struct base_operation_t
4713       {
base_operation_texprtk::details::base_operation_t4714          base_operation_t(const operator_type t, const unsigned int& np)
4715          : type(t),
4716            num_params(np)
4717          {}
4718 
4719          operator_type type;
4720          unsigned int num_params;
4721       };
4722 
4723       namespace loop_unroll
4724       {
4725          #ifndef exprtk_disable_superscalar_unroll
4726          const unsigned int global_loop_batch_size = 16;
4727          #else
4728          const unsigned int global_loop_batch_size = 4;
4729          #endif
4730 
4731          struct details
4732          {
detailsexprtk::details::loop_unroll::details4733             explicit details(const std::size_t& vsize,
4734                              const unsigned int loop_batch_size = global_loop_batch_size)
4735             : batch_size(loop_batch_size   ),
4736               remainder (vsize % batch_size),
4737               upper_bound(static_cast<int>(vsize - (remainder ? loop_batch_size : 0)))
4738             {}
4739 
4740             unsigned int batch_size;
4741             int   remainder;
4742             int upper_bound;
4743          };
4744       }
4745 
4746       #ifdef exprtk_enable_debugging
dump_ptr(const std::string & s,const void * ptr,const std::size_t size=0)4747       inline void dump_ptr(const std::string& s, const void* ptr, const std::size_t size = 0)
4748       {
4749          if (size)
4750             exprtk_debug(("%s - addr: %p\n",s.c_str(),ptr));
4751          else
4752             exprtk_debug(("%s - addr: %p size: %d\n",
4753                           s.c_str(),
4754                           ptr,
4755                           static_cast<unsigned int>(size)));
4756       }
4757       #else
dump_ptr(const std::string &,const void *)4758       inline void dump_ptr(const std::string&, const void*) {}
dump_ptr(const std::string &,const void *,const std::size_t)4759       inline void dump_ptr(const std::string&, const void*, const std::size_t) {}
4760       #endif
4761 
4762       template <typename T>
4763       class vec_data_store
4764       {
4765       public:
4766 
4767          typedef vec_data_store<T> type;
4768          typedef T* data_t;
4769 
4770       private:
4771 
4772          struct control_block
4773          {
control_blockexprtk::details::vec_data_store::control_block4774             control_block()
4775             : ref_count(1),
4776               size     (0),
4777               data     (0),
4778               destruct (true)
4779             {}
4780 
control_blockexprtk::details::vec_data_store::control_block4781             explicit control_block(const std::size_t& dsize)
4782             : ref_count(1    ),
4783               size     (dsize),
4784               data     (0    ),
4785               destruct (true )
4786             { create_data(); }
4787 
control_blockexprtk::details::vec_data_store::control_block4788             control_block(const std::size_t& dsize, data_t dptr, bool dstrct = false)
4789             : ref_count(1     ),
4790               size     (dsize ),
4791               data     (dptr  ),
4792               destruct (dstrct)
4793             {}
4794 
~control_blockexprtk::details::vec_data_store::control_block4795            ~control_block()
4796             {
4797                if (data && destruct && (0 == ref_count))
4798                {
4799                   dump_ptr("~control_block() data",data);
4800                   delete[] data;
4801                   data = reinterpret_cast<data_t>(0);
4802                }
4803             }
4804 
createexprtk::details::vec_data_store::control_block4805             static inline control_block* create(const std::size_t& dsize, data_t data_ptr = data_t(0), bool dstrct = false)
4806             {
4807                if (dsize)
4808                {
4809                   if (0 == data_ptr)
4810                      return (new control_block(dsize));
4811                   else
4812                      return (new control_block(dsize, data_ptr, dstrct));
4813                }
4814                else
4815                   return (new control_block);
4816             }
4817 
destroyexprtk::details::vec_data_store::control_block4818             static inline void destroy(control_block*& cntrl_blck)
4819             {
4820                if (cntrl_blck)
4821                {
4822                   if (
4823                        (0 !=   cntrl_blck->ref_count) &&
4824                        (0 == --cntrl_blck->ref_count)
4825                      )
4826                   {
4827                      delete cntrl_blck;
4828                   }
4829 
4830                   cntrl_blck = 0;
4831                }
4832             }
4833 
4834             std::size_t ref_count;
4835             std::size_t size;
4836             data_t      data;
4837             bool        destruct;
4838 
4839          private:
4840 
4841             control_block(const control_block&);
4842             control_block& operator=(const control_block&);
4843 
create_dataexprtk::details::vec_data_store::control_block4844             inline void create_data()
4845             {
4846                destruct = true;
4847                data     = new T[size];
4848                std::fill_n(data, size, T(0));
4849                dump_ptr("control_block::create_data() - data",data,size);
4850             }
4851          };
4852 
4853       public:
4854 
vec_data_store()4855          vec_data_store()
4856          : control_block_(control_block::create(0))
4857          {}
4858 
vec_data_store(const std::size_t & size)4859          explicit vec_data_store(const std::size_t& size)
4860          : control_block_(control_block::create(size,reinterpret_cast<data_t>(0),true))
4861          {}
4862 
vec_data_store(const std::size_t & size,data_t data,bool dstrct=false)4863          vec_data_store(const std::size_t& size, data_t data, bool dstrct = false)
4864          : control_block_(control_block::create(size, data, dstrct))
4865          {}
4866 
vec_data_store(const type & vds)4867          vec_data_store(const type& vds)
4868          {
4869             control_block_ = vds.control_block_;
4870             control_block_->ref_count++;
4871          }
4872 
~vec_data_store()4873         ~vec_data_store()
4874          {
4875             control_block::destroy(control_block_);
4876          }
4877 
operator =(const type & vds)4878          type& operator=(const type& vds)
4879          {
4880             if (this != &vds)
4881             {
4882                std::size_t final_size = min_size(control_block_, vds.control_block_);
4883 
4884                vds.control_block_->size = final_size;
4885                    control_block_->size = final_size;
4886 
4887                if (control_block_->destruct || (0 == control_block_->data))
4888                {
4889                   control_block::destroy(control_block_);
4890 
4891                   control_block_ = vds.control_block_;
4892                   control_block_->ref_count++;
4893                }
4894             }
4895 
4896             return (*this);
4897          }
4898 
data()4899          inline data_t data()
4900          {
4901             return control_block_->data;
4902          }
4903 
data() const4904          inline data_t data() const
4905          {
4906             return control_block_->data;
4907          }
4908 
size()4909          inline std::size_t size()
4910          {
4911             return control_block_->size;
4912          }
4913 
size() const4914          inline std::size_t size() const
4915          {
4916             return control_block_->size;
4917          }
4918 
ref()4919          inline data_t& ref()
4920          {
4921             return control_block_->data;
4922          }
4923 
dump() const4924          inline void dump() const
4925          {
4926             #ifdef exprtk_enable_debugging
4927             exprtk_debug(("size: %d\taddress:%p\tdestruct:%c\n",
4928                           size(),
4929                           data(),
4930                           (control_block_->destruct ? 'T' : 'F')));
4931 
4932             for (std::size_t i = 0; i < size(); ++i)
4933             {
4934                if (5 == i)
4935                   exprtk_debug(("\n"));
4936 
4937                exprtk_debug(("%15.10f ",data()[i]));
4938             }
4939             exprtk_debug(("\n"));
4940             #endif
4941          }
4942 
match_sizes(type & vds0,type & vds1)4943          static inline void match_sizes(type& vds0, type& vds1)
4944          {
4945             const std::size_t size = min_size(vds0.control_block_,vds1.control_block_);
4946             vds0.control_block_->size = size;
4947             vds1.control_block_->size = size;
4948          }
4949 
4950       private:
4951 
min_size(control_block * cb0,control_block * cb1)4952          static inline std::size_t min_size(control_block* cb0, control_block* cb1)
4953          {
4954             const std::size_t size0 = cb0->size;
4955             const std::size_t size1 = cb1->size;
4956 
4957             if (size0 && size1)
4958                return std::min(size0,size1);
4959             else
4960                return (size0) ? size0 : size1;
4961          }
4962 
4963          control_block* control_block_;
4964       };
4965 
4966       namespace numeric
4967       {
4968          namespace details
4969          {
4970             template <typename T>
process_impl(const operator_type operation,const T arg)4971             inline T process_impl(const operator_type operation, const T arg)
4972             {
4973                switch (operation)
4974                {
4975                   case e_abs   : return numeric::abs  (arg);
4976                   case e_acos  : return numeric::acos (arg);
4977                   case e_acosh : return numeric::acosh(arg);
4978                   case e_asin  : return numeric::asin (arg);
4979                   case e_asinh : return numeric::asinh(arg);
4980                   case e_atan  : return numeric::atan (arg);
4981                   case e_atanh : return numeric::atanh(arg);
4982                   case e_ceil  : return numeric::ceil (arg);
4983                   case e_cos   : return numeric::cos  (arg);
4984                   case e_cosh  : return numeric::cosh (arg);
4985                   case e_exp   : return numeric::exp  (arg);
4986                   case e_expm1 : return numeric::expm1(arg);
4987                   case e_floor : return numeric::floor(arg);
4988                   case e_log   : return numeric::log  (arg);
4989                   case e_log10 : return numeric::log10(arg);
4990                   case e_log2  : return numeric::log2 (arg);
4991                   case e_log1p : return numeric::log1p(arg);
4992                   case e_neg   : return numeric::neg  (arg);
4993                   case e_pos   : return numeric::pos  (arg);
4994                   case e_round : return numeric::round(arg);
4995                   case e_sin   : return numeric::sin  (arg);
4996                   case e_sinc  : return numeric::sinc (arg);
4997                   case e_sinh  : return numeric::sinh (arg);
4998                   case e_sqrt  : return numeric::sqrt (arg);
4999                   case e_tan   : return numeric::tan  (arg);
5000                   case e_tanh  : return numeric::tanh (arg);
5001                   case e_cot   : return numeric::cot  (arg);
5002                   case e_sec   : return numeric::sec  (arg);
5003                   case e_csc   : return numeric::csc  (arg);
5004                   case e_r2d   : return numeric::r2d  (arg);
5005                   case e_d2r   : return numeric::d2r  (arg);
5006                   case e_d2g   : return numeric::d2g  (arg);
5007                   case e_g2d   : return numeric::g2d  (arg);
5008                   case e_notl  : return numeric::notl (arg);
5009                   case e_sgn   : return numeric::sgn  (arg);
5010                   case e_erf   : return numeric::erf  (arg);
5011                   case e_erfc  : return numeric::erfc (arg);
5012                   case e_ncdf  : return numeric::ncdf (arg);
5013                   case e_frac  : return numeric::frac (arg);
5014                   case e_trunc : return numeric::trunc(arg);
5015 
5016                   default      : exprtk_debug(("numeric::details::process_impl<T> - Invalid unary operation.\n"));
5017                                  return std::numeric_limits<T>::quiet_NaN();
5018                }
5019             }
5020 
5021             template <typename T>
process_impl(const operator_type operation,const T arg0,const T arg1)5022             inline T process_impl(const operator_type operation, const T arg0, const T arg1)
5023             {
5024                switch (operation)
5025                {
5026                   case e_add    : return (arg0 + arg1);
5027                   case e_sub    : return (arg0 - arg1);
5028                   case e_mul    : return (arg0 * arg1);
5029                   case e_div    : return (arg0 / arg1);
5030                   case e_mod    : return modulus<T>(arg0,arg1);
5031                   case e_pow    : return pow<T>(arg0,arg1);
5032                   case e_atan2  : return atan2<T>(arg0,arg1);
5033                   case e_min    : return std::min<T>(arg0,arg1);
5034                   case e_max    : return std::max<T>(arg0,arg1);
5035                   case e_logn   : return logn<T>(arg0,arg1);
5036                   case e_lt     : return (arg0 <  arg1) ? T(1) : T(0);
5037                   case e_lte    : return (arg0 <= arg1) ? T(1) : T(0);
5038                   case e_eq     : return std::equal_to<T>()(arg0,arg1) ? T(1) : T(0);
5039                   case e_ne     : return std::not_equal_to<T>()(arg0,arg1) ? T(1) : T(0);
5040                   case e_gte    : return (arg0 >= arg1) ? T(1) : T(0);
5041                   case e_gt     : return (arg0 >  arg1) ? T(1) : T(0);
5042                   case e_and    : return and_opr <T>(arg0,arg1);
5043                   case e_nand   : return nand_opr<T>(arg0,arg1);
5044                   case e_or     : return or_opr  <T>(arg0,arg1);
5045                   case e_nor    : return nor_opr <T>(arg0,arg1);
5046                   case e_xor    : return xor_opr <T>(arg0,arg1);
5047                   case e_xnor   : return xnor_opr<T>(arg0,arg1);
5048                   case e_root   : return root    <T>(arg0,arg1);
5049                   case e_roundn : return roundn  <T>(arg0,arg1);
5050                   case e_equal  : return equal      (arg0,arg1);
5051                   case e_nequal : return nequal     (arg0,arg1);
5052                   case e_hypot  : return hypot   <T>(arg0,arg1);
5053                   case e_shr    : return shr     <T>(arg0,arg1);
5054                   case e_shl    : return shl     <T>(arg0,arg1);
5055 
5056                   default       : exprtk_debug(("numeric::details::process_impl<T> - Invalid binary operation.\n"));
5057                                   return std::numeric_limits<T>::quiet_NaN();
5058                }
5059             }
5060 
5061             template <typename T>
process_impl(const operator_type operation,const T arg0,const T arg1,int_type_tag)5062             inline T process_impl(const operator_type operation, const T arg0, const T arg1, int_type_tag)
5063             {
5064                switch (operation)
5065                {
5066                   case e_add    : return (arg0 + arg1);
5067                   case e_sub    : return (arg0 - arg1);
5068                   case e_mul    : return (arg0 * arg1);
5069                   case e_div    : return (arg0 / arg1);
5070                   case e_mod    : return arg0 % arg1;
5071                   case e_pow    : return pow<T>(arg0,arg1);
5072                   case e_min    : return std::min<T>(arg0,arg1);
5073                   case e_max    : return std::max<T>(arg0,arg1);
5074                   case e_logn   : return logn<T>(arg0,arg1);
5075                   case e_lt     : return (arg0 <  arg1) ? T(1) : T(0);
5076                   case e_lte    : return (arg0 <= arg1) ? T(1) : T(0);
5077                   case e_eq     : return (arg0 == arg1) ? T(1) : T(0);
5078                   case e_ne     : return (arg0 != arg1) ? T(1) : T(0);
5079                   case e_gte    : return (arg0 >= arg1) ? T(1) : T(0);
5080                   case e_gt     : return (arg0 >  arg1) ? T(1) : T(0);
5081                   case e_and    : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(1) : T(0);
5082                   case e_nand   : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(0) : T(1);
5083                   case e_or     : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(1) : T(0);
5084                   case e_nor    : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(0) : T(1);
5085                   case e_xor    : return arg0 ^ arg1;
5086                   case e_xnor   : return !(arg0 ^ arg1);
5087                   case e_root   : return root<T>(arg0,arg1);
5088                   case e_equal  : return arg0 == arg1;
5089                   case e_nequal : return arg0 != arg1;
5090                   case e_hypot  : return hypot<T>(arg0,arg1);
5091                   case e_shr    : return arg0 >> arg1;
5092                   case e_shl    : return arg0 << arg1;
5093 
5094                   default       : exprtk_debug(("numeric::details::process_impl<IntType> - Invalid binary operation.\n"));
5095                                   return std::numeric_limits<T>::quiet_NaN();
5096                }
5097             }
5098          }
5099 
5100          template <typename T>
process(const operator_type operation,const T arg)5101          inline T process(const operator_type operation, const T arg)
5102          {
5103             return exprtk::details::numeric::details::process_impl(operation,arg);
5104          }
5105 
5106          template <typename T>
process(const operator_type operation,const T arg0,const T arg1)5107          inline T process(const operator_type operation, const T arg0, const T arg1)
5108          {
5109             return exprtk::details::numeric::details::process_impl(operation, arg0, arg1);
5110          }
5111       }
5112 
5113       template <typename Node>
5114       struct node_collector_interface
5115       {
5116          typedef Node* node_ptr_t;
5117          typedef Node** node_pp_t;
5118          typedef std::vector<node_pp_t> noderef_list_t;
5119 
~node_collector_interfaceexprtk::details::node_collector_interface5120          virtual ~node_collector_interface() {}
5121 
collect_nodesexprtk::details::node_collector_interface5122          virtual void collect_nodes(noderef_list_t&) {}
5123       };
5124 
5125       template <typename Node>
5126       struct node_depth_base;
5127 
5128       template <typename T>
5129       class expression_node : public node_collector_interface<expression_node<T> >,
5130                               public node_depth_base<expression_node<T> >
5131       {
5132       public:
5133 
5134          enum node_type
5135          {
5136             e_none          , e_null          , e_constant    , e_unary        ,
5137             e_binary        , e_binary_ext    , e_trinary     , e_quaternary   ,
5138             e_vararg        , e_conditional   , e_while       , e_repeat       ,
5139             e_for           , e_switch        , e_mswitch     , e_return       ,
5140             e_retenv        , e_variable      , e_stringvar   , e_stringconst  ,
5141             e_stringvarrng  , e_cstringvarrng , e_strgenrange , e_strconcat    ,
5142             e_stringvarsize , e_strswap       , e_stringsize  , e_stringvararg ,
5143             e_function      , e_vafunction    , e_genfunction , e_strfunction  ,
5144             e_strcondition  , e_strccondition , e_add         , e_sub          ,
5145             e_mul           , e_div           , e_mod         , e_pow          ,
5146             e_lt            , e_lte           , e_gt          , e_gte          ,
5147             e_eq            , e_ne            , e_and         , e_nand         ,
5148             e_or            , e_nor           , e_xor         , e_xnor         ,
5149             e_in            , e_like          , e_ilike       , e_inranges     ,
5150             e_ipow          , e_ipowinv       , e_abs         , e_acos         ,
5151             e_acosh         , e_asin          , e_asinh       , e_atan         ,
5152             e_atanh         , e_ceil          , e_cos         , e_cosh         ,
5153             e_exp           , e_expm1         , e_floor       , e_log          ,
5154             e_log10         , e_log2          , e_log1p       , e_neg          ,
5155             e_pos           , e_round         , e_sin         , e_sinc         ,
5156             e_sinh          , e_sqrt          , e_tan         , e_tanh         ,
5157             e_cot           , e_sec           , e_csc         , e_r2d          ,
5158             e_d2r           , e_d2g           , e_g2d         , e_notl         ,
5159             e_sgn           , e_erf           , e_erfc        , e_ncdf         ,
5160             e_frac          , e_trunc         , e_uvouv       , e_vov          ,
5161             e_cov           , e_voc           , e_vob         , e_bov          ,
5162             e_cob           , e_boc           , e_vovov       , e_vovoc        ,
5163             e_vocov         , e_covov         , e_covoc       , e_vovovov      ,
5164             e_vovovoc       , e_vovocov       , e_vocovov     , e_covovov      ,
5165             e_covocov       , e_vocovoc       , e_covovoc     , e_vococov      ,
5166             e_sf3ext        , e_sf4ext        , e_nulleq      , e_strass       ,
5167             e_vector        , e_vecelem       , e_rbvecelem   , e_rbveccelem   ,
5168             e_vecdefass     , e_vecvalass     , e_vecvecass   , e_vecopvalass  ,
5169             e_vecopvecass   , e_vecfunc       , e_vecvecswap  , e_vecvecineq   ,
5170             e_vecvalineq    , e_valvecineq    , e_vecvecarith , e_vecvalarith  ,
5171             e_valvecarith   , e_vecunaryop    , e_break       , e_continue     ,
5172             e_swap
5173          };
5174 
5175          typedef T value_type;
5176          typedef expression_node<T>* expression_ptr;
5177          typedef node_collector_interface<expression_node<T> > nci_t;
5178          typedef typename nci_t::noderef_list_t noderef_list_t;
5179          typedef node_depth_base<expression_node<T> > ndb_t;
5180 
~expression_node()5181          virtual ~expression_node()
5182          {}
5183 
value() const5184          inline virtual T value() const
5185          {
5186             return std::numeric_limits<T>::quiet_NaN();
5187          }
5188 
branch(const std::size_t & index=0) const5189          inline virtual expression_node<T>* branch(const std::size_t& index = 0) const
5190          {
5191             return reinterpret_cast<expression_ptr>(index * 0);
5192          }
5193 
type() const5194          inline virtual node_type type() const
5195          {
5196             return e_none;
5197          }
5198       };
5199 
5200       template <typename T>
5201       inline bool is_generally_string_node(const expression_node<T>* node);
5202 
is_true(const double v)5203       inline bool is_true(const double v)
5204       {
5205          return std::not_equal_to<double>()(0.0,v);
5206       }
5207 
is_true(const long double v)5208       inline bool is_true(const long double v)
5209       {
5210          return std::not_equal_to<long double>()(0.0L,v);
5211       }
5212 
is_true(const float v)5213       inline bool is_true(const float v)
5214       {
5215          return std::not_equal_to<float>()(0.0f,v);
5216       }
5217 
5218       template <typename T>
is_true(const std::complex<T> & v)5219       inline bool is_true(const std::complex<T>& v)
5220       {
5221          return std::not_equal_to<std::complex<T> >()(std::complex<T>(0),v);
5222       }
5223 
5224       template <typename T>
is_true(const expression_node<T> * node)5225       inline bool is_true(const expression_node<T>* node)
5226       {
5227          return std::not_equal_to<T>()(T(0),node->value());
5228       }
5229 
5230       template <typename T>
is_true(const std::pair<expression_node<T> *,bool> & node)5231       inline bool is_true(const std::pair<expression_node<T>*,bool>& node)
5232       {
5233          return std::not_equal_to<T>()(T(0),node.first->value());
5234       }
5235 
5236       template <typename T>
is_false(const expression_node<T> * node)5237       inline bool is_false(const expression_node<T>* node)
5238       {
5239          return std::equal_to<T>()(T(0),node->value());
5240       }
5241 
5242       template <typename T>
is_false(const std::pair<expression_node<T> *,bool> & node)5243       inline bool is_false(const std::pair<expression_node<T>*,bool>& node)
5244       {
5245          return std::equal_to<T>()(T(0),node.first->value());
5246       }
5247 
5248       template <typename T>
is_unary_node(const expression_node<T> * node)5249       inline bool is_unary_node(const expression_node<T>* node)
5250       {
5251          return node && (details::expression_node<T>::e_unary == node->type());
5252       }
5253 
5254       template <typename T>
is_neg_unary_node(const expression_node<T> * node)5255       inline bool is_neg_unary_node(const expression_node<T>* node)
5256       {
5257          return node && (details::expression_node<T>::e_neg == node->type());
5258       }
5259 
5260       template <typename T>
is_binary_node(const expression_node<T> * node)5261       inline bool is_binary_node(const expression_node<T>* node)
5262       {
5263          return node && (details::expression_node<T>::e_binary == node->type());
5264       }
5265 
5266       template <typename T>
is_variable_node(const expression_node<T> * node)5267       inline bool is_variable_node(const expression_node<T>* node)
5268       {
5269          return node && (details::expression_node<T>::e_variable == node->type());
5270       }
5271 
5272       template <typename T>
is_ivariable_node(const expression_node<T> * node)5273       inline bool is_ivariable_node(const expression_node<T>* node)
5274       {
5275          return node &&
5276                 (
5277                   details::expression_node<T>::e_variable   == node->type() ||
5278                   details::expression_node<T>::e_vecelem    == node->type() ||
5279                   details::expression_node<T>::e_rbvecelem  == node->type() ||
5280                   details::expression_node<T>::e_rbveccelem == node->type()
5281                 );
5282       }
5283 
5284       template <typename T>
is_vector_elem_node(const expression_node<T> * node)5285       inline bool is_vector_elem_node(const expression_node<T>* node)
5286       {
5287          return node && (details::expression_node<T>::e_vecelem == node->type());
5288       }
5289 
5290       template <typename T>
is_rebasevector_elem_node(const expression_node<T> * node)5291       inline bool is_rebasevector_elem_node(const expression_node<T>* node)
5292       {
5293          return node && (details::expression_node<T>::e_rbvecelem == node->type());
5294       }
5295 
5296       template <typename T>
is_rebasevector_celem_node(const expression_node<T> * node)5297       inline bool is_rebasevector_celem_node(const expression_node<T>* node)
5298       {
5299          return node && (details::expression_node<T>::e_rbveccelem == node->type());
5300       }
5301 
5302       template <typename T>
is_vector_node(const expression_node<T> * node)5303       inline bool is_vector_node(const expression_node<T>* node)
5304       {
5305          return node && (details::expression_node<T>::e_vector == node->type());
5306       }
5307 
5308       template <typename T>
is_ivector_node(const expression_node<T> * node)5309       inline bool is_ivector_node(const expression_node<T>* node)
5310       {
5311          if (node)
5312          {
5313             switch (node->type())
5314             {
5315                case details::expression_node<T>::e_vector      :
5316                case details::expression_node<T>::e_vecvalass   :
5317                case details::expression_node<T>::e_vecvecass   :
5318                case details::expression_node<T>::e_vecopvalass :
5319                case details::expression_node<T>::e_vecopvecass :
5320                case details::expression_node<T>::e_vecvecswap  :
5321                case details::expression_node<T>::e_vecvecarith :
5322                case details::expression_node<T>::e_vecvalarith :
5323                case details::expression_node<T>::e_valvecarith :
5324                case details::expression_node<T>::e_vecunaryop  : return true;
5325                default                                         : return false;
5326             }
5327          }
5328          else
5329             return false;
5330       }
5331 
5332       template <typename T>
is_constant_node(const expression_node<T> * node)5333       inline bool is_constant_node(const expression_node<T>* node)
5334       {
5335          return node && (details::expression_node<T>::e_constant == node->type());
5336       }
5337 
5338       template <typename T>
is_null_node(const expression_node<T> * node)5339       inline bool is_null_node(const expression_node<T>* node)
5340       {
5341          return node && (details::expression_node<T>::e_null == node->type());
5342       }
5343 
5344       template <typename T>
is_break_node(const expression_node<T> * node)5345       inline bool is_break_node(const expression_node<T>* node)
5346       {
5347          return node && (details::expression_node<T>::e_break == node->type());
5348       }
5349 
5350       template <typename T>
is_continue_node(const expression_node<T> * node)5351       inline bool is_continue_node(const expression_node<T>* node)
5352       {
5353          return node && (details::expression_node<T>::e_continue == node->type());
5354       }
5355 
5356       template <typename T>
is_swap_node(const expression_node<T> * node)5357       inline bool is_swap_node(const expression_node<T>* node)
5358       {
5359          return node && (details::expression_node<T>::e_swap == node->type());
5360       }
5361 
5362       template <typename T>
is_function(const expression_node<T> * node)5363       inline bool is_function(const expression_node<T>* node)
5364       {
5365          return node && (details::expression_node<T>::e_function == node->type());
5366       }
5367 
5368       template <typename T>
is_return_node(const expression_node<T> * node)5369       inline bool is_return_node(const expression_node<T>* node)
5370       {
5371          return node && (details::expression_node<T>::e_return == node->type());
5372       }
5373 
5374       template <typename T> class unary_node;
5375 
5376       template <typename T>
is_negate_node(const expression_node<T> * node)5377       inline bool is_negate_node(const expression_node<T>* node)
5378       {
5379          if (node && is_unary_node(node))
5380          {
5381             return (details::e_neg == static_cast<const unary_node<T>*>(node)->operation());
5382          }
5383          else
5384             return false;
5385       }
5386 
5387       template <typename T>
branch_deletable(expression_node<T> * node)5388       inline bool branch_deletable(expression_node<T>* node)
5389       {
5390          return (0 != node)             &&
5391                 !is_variable_node(node) &&
5392                 !is_string_node  (node) ;
5393       }
5394 
5395       template <std::size_t N, typename T>
all_nodes_valid(expression_node<T> * (& b)[N])5396       inline bool all_nodes_valid(expression_node<T>* (&b)[N])
5397       {
5398          for (std::size_t i = 0; i < N; ++i)
5399          {
5400             if (0 == b[i]) return false;
5401          }
5402 
5403          return true;
5404       }
5405 
5406       template <typename T,
5407                 typename Allocator,
5408                 template <typename, typename> class Sequence>
all_nodes_valid(const Sequence<expression_node<T> *,Allocator> & b)5409       inline bool all_nodes_valid(const Sequence<expression_node<T>*,Allocator>& b)
5410       {
5411          for (std::size_t i = 0; i < b.size(); ++i)
5412          {
5413             if (0 == b[i]) return false;
5414          }
5415 
5416          return true;
5417       }
5418 
5419       template <std::size_t N, typename T>
all_nodes_variables(expression_node<T> * (& b)[N])5420       inline bool all_nodes_variables(expression_node<T>* (&b)[N])
5421       {
5422          for (std::size_t i = 0; i < N; ++i)
5423          {
5424             if (0 == b[i])
5425                return false;
5426             else if (!is_variable_node(b[i]))
5427                return false;
5428          }
5429 
5430          return true;
5431       }
5432 
5433       template <typename T,
5434                 typename Allocator,
5435                 template <typename, typename> class Sequence>
all_nodes_variables(Sequence<expression_node<T> *,Allocator> & b)5436       inline bool all_nodes_variables(Sequence<expression_node<T>*,Allocator>& b)
5437       {
5438          for (std::size_t i = 0; i < b.size(); ++i)
5439          {
5440             if (0 == b[i])
5441                return false;
5442             else if (!is_variable_node(b[i]))
5443                return false;
5444          }
5445 
5446          return true;
5447       }
5448 
5449       template <typename Node>
5450       class node_collection_destructor
5451       {
5452       public:
5453 
5454          typedef node_collector_interface<Node> nci_t;
5455 
5456          typedef typename nci_t::node_ptr_t     node_ptr_t;
5457          typedef typename nci_t::node_pp_t      node_pp_t;
5458          typedef typename nci_t::noderef_list_t noderef_list_t;
5459 
delete_nodes(node_ptr_t & root)5460          static void delete_nodes(node_ptr_t& root)
5461          {
5462             std::vector<node_pp_t> node_delete_list;
5463             node_delete_list.reserve(1000);
5464 
5465             collect_nodes(root, node_delete_list);
5466 
5467             for (std::size_t i = 0; i < node_delete_list.size(); ++i)
5468             {
5469                node_ptr_t& node = *node_delete_list[i];
5470                exprtk_debug(("ncd::delete_nodes() - deleting: %p\n", static_cast<void*>(node)));
5471                delete node;
5472                node = reinterpret_cast<node_ptr_t>(0);
5473             }
5474          }
5475 
5476       private:
5477 
collect_nodes(node_ptr_t & root,noderef_list_t & node_delete_list)5478          static void collect_nodes(node_ptr_t& root, noderef_list_t& node_delete_list)
5479          {
5480             std::deque<node_ptr_t> node_list;
5481             node_list.push_back(root);
5482             node_delete_list.push_back(&root);
5483 
5484             noderef_list_t child_node_delete_list;
5485             child_node_delete_list.reserve(1000);
5486 
5487             while (!node_list.empty())
5488             {
5489                node_list.front()->collect_nodes(child_node_delete_list);
5490 
5491                if (!child_node_delete_list.empty())
5492                {
5493                   for (std::size_t i = 0; i < child_node_delete_list.size(); ++i)
5494                   {
5495                      node_pp_t& node = child_node_delete_list[i];
5496 
5497                      if (0 == (*node))
5498                      {
5499                         exprtk_debug(("ncd::collect_nodes() - null node encountered.\n"));
5500                      }
5501 
5502                      node_list.push_back(*node);
5503                   }
5504 
5505                   node_delete_list.insert(
5506                      node_delete_list.end(),
5507                      child_node_delete_list.begin(), child_node_delete_list.end());
5508 
5509                   child_node_delete_list.clear();
5510                }
5511 
5512                node_list.pop_front();
5513             }
5514 
5515             std::reverse(node_delete_list.begin(), node_delete_list.end());
5516          }
5517       };
5518 
5519       template <typename NodeAllocator, typename T, std::size_t N>
free_all_nodes(NodeAllocator & node_allocator,expression_node<T> * (& b)[N])5520       inline void free_all_nodes(NodeAllocator& node_allocator, expression_node<T>* (&b)[N])
5521       {
5522          for (std::size_t i = 0; i < N; ++i)
5523          {
5524             free_node(node_allocator,b[i]);
5525          }
5526       }
5527 
5528       template <typename NodeAllocator,
5529                 typename T,
5530                 typename Allocator,
5531                 template <typename, typename> class Sequence>
free_all_nodes(NodeAllocator & node_allocator,Sequence<expression_node<T> *,Allocator> & b)5532       inline void free_all_nodes(NodeAllocator& node_allocator, Sequence<expression_node<T>*,Allocator>& b)
5533       {
5534          for (std::size_t i = 0; i < b.size(); ++i)
5535          {
5536             free_node(node_allocator,b[i]);
5537          }
5538 
5539          b.clear();
5540       }
5541 
5542       template <typename NodeAllocator, typename T>
free_node(NodeAllocator &,expression_node<T> * & node)5543       inline void free_node(NodeAllocator&, expression_node<T>*& node)
5544       {
5545          if ((0 == node) || is_variable_node(node) || is_string_node(node))
5546          {
5547             return;
5548          }
5549 
5550          node_collection_destructor<expression_node<T> >
5551             ::delete_nodes(node);
5552       }
5553 
5554       template <typename T>
destroy_node(expression_node<T> * & node)5555       inline void destroy_node(expression_node<T>*& node)
5556       {
5557          if (0 != node)
5558          {
5559             node_collection_destructor<expression_node<T> >
5560                ::delete_nodes(node);
5561          }
5562       }
5563 
5564       template <typename Node>
5565       struct node_depth_base
5566       {
node_depth_baseexprtk::details::node_depth_base5567          node_depth_base()
5568          : depth_set(false),
5569            depth(0)
5570          {}
5571 
~node_depth_baseexprtk::details::node_depth_base5572          virtual ~node_depth_base() {}
5573 
node_depthexprtk::details::node_depth_base5574          virtual std::size_t node_depth() const { return 1; }
5575 
compute_node_depthexprtk::details::node_depth_base5576          std::size_t compute_node_depth(const Node* const& node) const
5577          {
5578             if (!depth_set)
5579             {
5580                depth = 1 + (node ? node->node_depth() : 0);
5581                depth_set = true;
5582             }
5583 
5584             return depth;
5585          }
5586 
compute_node_depthexprtk::details::node_depth_base5587          std::size_t compute_node_depth(const std::pair<Node*,bool>& branch) const
5588          {
5589             if (!depth_set)
5590             {
5591                depth = 1 + (branch.first ? branch.first->node_depth() : 0);
5592                depth_set = true;
5593             }
5594 
5595             return depth;
5596          }
5597 
5598          template <std::size_t N>
compute_node_depthexprtk::details::node_depth_base5599          std::size_t compute_node_depth(const std::pair<Node*,bool> (&branch)[N]) const
5600          {
5601             if (!depth_set)
5602             {
5603                depth = 0;
5604                for (std::size_t i = 0; i < N; ++i)
5605                {
5606                   if (branch[i].first)
5607                   {
5608                      depth = std::max(depth,branch[i].first->node_depth());
5609                   }
5610                }
5611                depth += 1;
5612                depth_set = true;
5613             }
5614 
5615             return depth;
5616          }
5617 
5618          template <typename BranchType>
compute_node_depthexprtk::details::node_depth_base5619          std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1) const
5620          {
5621             if (!depth_set)
5622             {
5623                depth = 1 + std::max(compute_node_depth(n0), compute_node_depth(n1));
5624                depth_set = true;
5625             }
5626 
5627             return depth;
5628          }
5629 
5630          template <typename BranchType>
compute_node_depthexprtk::details::node_depth_base5631          std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1,
5632                                         const BranchType& n2) const
5633          {
5634             if (!depth_set)
5635             {
5636                depth = 1 + std::max(
5637                               std::max(compute_node_depth(n0), compute_node_depth(n1)),
5638                               compute_node_depth(n2));
5639                depth_set = true;
5640             }
5641 
5642             return depth;
5643          }
5644 
5645          template <typename BranchType>
compute_node_depthexprtk::details::node_depth_base5646          std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1,
5647                                         const BranchType& n2, const BranchType& n3) const
5648          {
5649             if (!depth_set)
5650             {
5651                depth = 1 + std::max(
5652                            std::max(compute_node_depth(n0), compute_node_depth(n1)),
5653                            std::max(compute_node_depth(n2), compute_node_depth(n3)));
5654                depth_set = true;
5655             }
5656 
5657             return depth;
5658          }
5659 
5660          template <typename Allocator,
5661                    template <typename, typename> class Sequence>
compute_node_depthexprtk::details::node_depth_base5662          std::size_t compute_node_depth(const Sequence<Node*, Allocator>& branch_list) const
5663          {
5664             if (!depth_set)
5665             {
5666                for (std::size_t i = 0; i < branch_list.size(); ++i)
5667                {
5668                   if (branch_list[i])
5669                   {
5670                      depth = std::max(depth, compute_node_depth(branch_list[i]));
5671                   }
5672                }
5673                depth_set = true;
5674             }
5675 
5676             return depth;
5677          }
5678 
5679          template <typename Allocator,
5680                    template <typename, typename> class Sequence>
compute_node_depthexprtk::details::node_depth_base5681          std::size_t compute_node_depth(const Sequence<std::pair<Node*,bool>,Allocator>& branch_list) const
5682          {
5683             if (!depth_set)
5684             {
5685                for (std::size_t i = 0; i < branch_list.size(); ++i)
5686                {
5687                   if (branch_list[i].first)
5688                   {
5689                      depth = std::max(depth, compute_node_depth(branch_list[i].first));
5690                   }
5691                }
5692                depth_set = true;
5693             }
5694 
5695             return depth;
5696          }
5697 
5698          mutable bool depth_set;
5699          mutable std::size_t depth;
5700 
5701          template <typename NodeSequence>
collectexprtk::details::node_depth_base5702          void collect(Node*const& node,
5703                       const bool deletable,
5704                       NodeSequence& delete_node_list) const
5705          {
5706             if ((0 != node) && deletable)
5707             {
5708                delete_node_list.push_back(const_cast<Node**>(&node));
5709             }
5710          }
5711 
5712          template <typename NodeSequence>
collectexprtk::details::node_depth_base5713          void collect(const std::pair<Node*, bool>& branch,
5714                       NodeSequence& delete_node_list) const
5715          {
5716             collect(branch.first, branch.second, delete_node_list);
5717          }
5718 
5719          template <typename NodeSequence>
collectexprtk::details::node_depth_base5720          void collect(Node*& node,
5721                       NodeSequence& delete_node_list) const
5722          {
5723             collect(node, branch_deletable(node), delete_node_list);
5724          }
5725 
5726          template <std::size_t N, typename NodeSequence>
collectexprtk::details::node_depth_base5727          void collect(const std::pair<Node*, bool>(&branch)[N],
5728                       NodeSequence& delete_node_list) const
5729          {
5730             for (std::size_t i = 0; i < N; ++i)
5731             {
5732                collect(branch[i].first, branch[i].second, delete_node_list);
5733             }
5734          }
5735 
5736          template <typename Allocator,
5737                    template <typename, typename> class Sequence,
5738                    typename NodeSequence>
collectexprtk::details::node_depth_base5739          void collect(const Sequence<std::pair<Node*, bool>, Allocator>& branch,
5740                       NodeSequence& delete_node_list) const
5741          {
5742             for (std::size_t i = 0; i < branch.size(); ++i)
5743             {
5744                collect(branch[i].first, branch[i].second, delete_node_list);
5745             }
5746          }
5747 
5748          template <typename Allocator,
5749                    template <typename, typename> class Sequence,
5750                    typename NodeSequence>
collectexprtk::details::node_depth_base5751          void collect(const Sequence<Node*, Allocator>& branch_list,
5752                       NodeSequence& delete_node_list) const
5753          {
5754             for (std::size_t i = 0; i < branch_list.size(); ++i)
5755             {
5756                collect(branch_list[i], branch_deletable(branch_list[i]), delete_node_list);
5757             }
5758          }
5759 
5760          template <typename Boolean,
5761                    typename AllocatorT,
5762                    typename AllocatorB,
5763                    template <typename, typename> class Sequence,
5764                    typename NodeSequence>
collectexprtk::details::node_depth_base5765          void collect(const Sequence<Node*, AllocatorT>& branch_list,
5766                       const Sequence<Boolean, AllocatorB>& branch_deletable_list,
5767                       NodeSequence& delete_node_list) const
5768          {
5769             for (std::size_t i = 0; i < branch_list.size(); ++i)
5770             {
5771                collect(branch_list[i], branch_deletable_list[i], delete_node_list);
5772             }
5773          }
5774       };
5775 
5776       template <typename Type>
5777       class vector_holder
5778       {
5779       private:
5780 
5781          typedef Type value_type;
5782          typedef value_type* value_ptr;
5783          typedef const value_ptr const_value_ptr;
5784 
5785          class vector_holder_base
5786          {
5787          public:
5788 
~vector_holder_base()5789             virtual ~vector_holder_base() {}
5790 
operator [](const std::size_t & index) const5791             inline value_ptr operator[](const std::size_t& index) const
5792             {
5793                return value_at(index);
5794             }
5795 
size() const5796             inline std::size_t size() const
5797             {
5798                return vector_size();
5799             }
5800 
data() const5801             inline value_ptr data() const
5802             {
5803                return value_at(0);
5804             }
5805 
rebaseable() const5806             virtual inline bool rebaseable() const
5807             {
5808                return false;
5809             }
5810 
set_ref(value_ptr *)5811             virtual void set_ref(value_ptr*) {}
5812 
5813          protected:
5814 
5815             virtual value_ptr value_at(const std::size_t&) const = 0;
5816             virtual std::size_t vector_size()              const = 0;
5817          };
5818 
5819          class array_vector_impl : public vector_holder_base
5820          {
5821          public:
5822 
array_vector_impl(const Type * vec,const std::size_t & vec_size)5823             array_vector_impl(const Type* vec, const std::size_t& vec_size)
5824             : vec_(vec),
5825               size_(vec_size)
5826             {}
5827 
5828          protected:
5829 
value_at(const std::size_t & index) const5830             value_ptr value_at(const std::size_t& index) const
5831             {
5832                if (index < size_)
5833                   return const_cast<const_value_ptr>(vec_ + index);
5834                else
5835                   return const_value_ptr(0);
5836             }
5837 
vector_size() const5838             std::size_t vector_size() const
5839             {
5840                return size_;
5841             }
5842 
5843          private:
5844 
5845             array_vector_impl operator=(const array_vector_impl&);
5846 
5847             const Type* vec_;
5848             const std::size_t size_;
5849          };
5850 
5851          template <typename Allocator,
5852                    template <typename, typename> class Sequence>
5853          class sequence_vector_impl : public vector_holder_base
5854          {
5855          public:
5856 
5857             typedef Sequence<Type,Allocator> sequence_t;
5858 
sequence_vector_impl(sequence_t & seq)5859             sequence_vector_impl(sequence_t& seq)
5860             : sequence_(seq)
5861             {}
5862 
5863          protected:
5864 
value_at(const std::size_t & index) const5865             value_ptr value_at(const std::size_t& index) const
5866             {
5867                return (index < sequence_.size()) ? (&sequence_[index]) : const_value_ptr(0);
5868             }
5869 
vector_size() const5870             std::size_t vector_size() const
5871             {
5872                return sequence_.size();
5873             }
5874 
5875          private:
5876 
5877             sequence_vector_impl operator=(const sequence_vector_impl&);
5878 
5879             sequence_t& sequence_;
5880          };
5881 
5882          class vector_view_impl : public vector_holder_base
5883          {
5884          public:
5885 
5886             typedef exprtk::vector_view<Type> vector_view_t;
5887 
vector_view_impl(vector_view_t & vec_view)5888             vector_view_impl(vector_view_t& vec_view)
5889             : vec_view_(vec_view)
5890             {}
5891 
set_ref(value_ptr * ref)5892             void set_ref(value_ptr* ref)
5893             {
5894                vec_view_.set_ref(ref);
5895             }
5896 
rebaseable() const5897             virtual inline bool rebaseable() const
5898             {
5899                return true;
5900             }
5901 
5902          protected:
5903 
value_at(const std::size_t & index) const5904             value_ptr value_at(const std::size_t& index) const
5905             {
5906                return (index < vec_view_.size()) ? (&vec_view_[index]) : const_value_ptr(0);
5907             }
5908 
vector_size() const5909             std::size_t vector_size() const
5910             {
5911                return vec_view_.size();
5912             }
5913 
5914          private:
5915 
5916             vector_view_impl operator=(const vector_view_impl&);
5917 
5918             vector_view_t& vec_view_;
5919          };
5920 
5921       public:
5922 
5923          typedef typename details::vec_data_store<Type> vds_t;
5924 
vector_holder(Type * vec,const std::size_t & vec_size)5925          vector_holder(Type* vec, const std::size_t& vec_size)
5926          : vector_holder_base_(new(buffer)array_vector_impl(vec,vec_size))
5927          {}
5928 
vector_holder(const vds_t & vds)5929          vector_holder(const vds_t& vds)
5930          : vector_holder_base_(new(buffer)array_vector_impl(vds.data(),vds.size()))
5931          {}
5932 
5933          template <typename Allocator>
vector_holder(std::vector<Type,Allocator> & vec)5934          vector_holder(std::vector<Type,Allocator>& vec)
5935          : vector_holder_base_(new(buffer)sequence_vector_impl<Allocator,std::vector>(vec))
5936          {}
5937 
vector_holder(exprtk::vector_view<Type> & vec)5938          vector_holder(exprtk::vector_view<Type>& vec)
5939          : vector_holder_base_(new(buffer)vector_view_impl(vec))
5940          {}
5941 
operator [](const std::size_t & index) const5942          inline value_ptr operator[](const std::size_t& index) const
5943          {
5944             return (*vector_holder_base_)[index];
5945          }
5946 
size() const5947          inline std::size_t size() const
5948          {
5949             return vector_holder_base_->size();
5950          }
5951 
data() const5952          inline value_ptr data() const
5953          {
5954             return vector_holder_base_->data();
5955          }
5956 
set_ref(value_ptr * ref)5957          void set_ref(value_ptr* ref)
5958          {
5959             vector_holder_base_->set_ref(ref);
5960          }
5961 
rebaseable() const5962          bool rebaseable() const
5963          {
5964             return vector_holder_base_->rebaseable();
5965          }
5966 
5967       private:
5968 
5969          mutable vector_holder_base* vector_holder_base_;
5970          uchar_t buffer[64];
5971       };
5972 
5973       template <typename T>
5974       class null_node : public expression_node<T>
5975       {
5976       public:
5977 
value() const5978          inline T value() const
5979          {
5980             return std::numeric_limits<T>::quiet_NaN();
5981          }
5982 
type() const5983          inline typename expression_node<T>::node_type type() const
5984          {
5985             return expression_node<T>::e_null;
5986          }
5987       };
5988 
5989       template <typename T, std::size_t N>
construct_branch_pair(std::pair<expression_node<T> *,bool> (& branch)[N],expression_node<T> * b,const std::size_t & index)5990       inline void construct_branch_pair(std::pair<expression_node<T>*,bool> (&branch)[N],
5991                                         expression_node<T>* b,
5992                                         const std::size_t& index)
5993       {
5994          if (b && (index < N))
5995          {
5996             branch[index] = std::make_pair(b,branch_deletable(b));
5997          }
5998       }
5999 
6000       template <typename T>
construct_branch_pair(std::pair<expression_node<T> *,bool> & branch,expression_node<T> * b)6001       inline void construct_branch_pair(std::pair<expression_node<T>*,bool>& branch, expression_node<T>* b)
6002       {
6003          if (b)
6004          {
6005             branch = std::make_pair(b,branch_deletable(b));
6006          }
6007       }
6008 
6009       template <std::size_t N, typename T>
init_branches(std::pair<expression_node<T> *,bool> (& branch)[N],expression_node<T> * b0,expression_node<T> * b1=reinterpret_cast<expression_node<T> * > (0),expression_node<T> * b2=reinterpret_cast<expression_node<T> * > (0),expression_node<T> * b3=reinterpret_cast<expression_node<T> * > (0),expression_node<T> * b4=reinterpret_cast<expression_node<T> * > (0),expression_node<T> * b5=reinterpret_cast<expression_node<T> * > (0),expression_node<T> * b6=reinterpret_cast<expression_node<T> * > (0),expression_node<T> * b7=reinterpret_cast<expression_node<T> * > (0),expression_node<T> * b8=reinterpret_cast<expression_node<T> * > (0),expression_node<T> * b9=reinterpret_cast<expression_node<T> * > (0))6010       inline void init_branches(std::pair<expression_node<T>*,bool> (&branch)[N],
6011                                 expression_node<T>* b0,
6012                                 expression_node<T>* b1 = reinterpret_cast<expression_node<T>*>(0),
6013                                 expression_node<T>* b2 = reinterpret_cast<expression_node<T>*>(0),
6014                                 expression_node<T>* b3 = reinterpret_cast<expression_node<T>*>(0),
6015                                 expression_node<T>* b4 = reinterpret_cast<expression_node<T>*>(0),
6016                                 expression_node<T>* b5 = reinterpret_cast<expression_node<T>*>(0),
6017                                 expression_node<T>* b6 = reinterpret_cast<expression_node<T>*>(0),
6018                                 expression_node<T>* b7 = reinterpret_cast<expression_node<T>*>(0),
6019                                 expression_node<T>* b8 = reinterpret_cast<expression_node<T>*>(0),
6020                                 expression_node<T>* b9 = reinterpret_cast<expression_node<T>*>(0))
6021       {
6022          construct_branch_pair(branch, b0, 0);
6023          construct_branch_pair(branch, b1, 1);
6024          construct_branch_pair(branch, b2, 2);
6025          construct_branch_pair(branch, b3, 3);
6026          construct_branch_pair(branch, b4, 4);
6027          construct_branch_pair(branch, b5, 5);
6028          construct_branch_pair(branch, b6, 6);
6029          construct_branch_pair(branch, b7, 7);
6030          construct_branch_pair(branch, b8, 8);
6031          construct_branch_pair(branch, b9, 9);
6032       }
6033 
6034       template <typename T>
6035       class null_eq_node : public expression_node<T>
6036       {
6037       public:
6038 
6039          typedef expression_node<T>* expression_ptr;
6040          typedef std::pair<expression_ptr,bool> branch_t;
6041 
null_eq_node(expression_ptr branch,const bool equality=true)6042          explicit null_eq_node(expression_ptr branch, const bool equality = true)
6043          : equality_(equality)
6044          {
6045             construct_branch_pair(branch_, branch);
6046          }
6047 
value() const6048          inline T value() const
6049          {
6050             assert(branch_.first);
6051 
6052             const T v = branch_.first->value();
6053             const bool result = details::numeric::is_nan(v);
6054 
6055             if (result)
6056                return (equality_) ? T(1) : T(0);
6057             else
6058                return (equality_) ? T(0) : T(1);
6059          }
6060 
type() const6061          inline typename expression_node<T>::node_type type() const
6062          {
6063             return expression_node<T>::e_nulleq;
6064          }
6065 
operation() const6066          inline operator_type operation() const
6067          {
6068             return details::e_eq;
6069          }
6070 
branch(const std::size_t &) const6071          inline expression_node<T>* branch(const std::size_t&) const
6072          {
6073             return branch_.first;
6074          }
6075 
collect_nodes(typename expression_node<T>::noderef_list_t & node_delete_list)6076          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
6077          {
6078             expression_node<T>::ndb_t::collect(branch_,node_delete_list);
6079          }
6080 
node_depth() const6081          std::size_t node_depth() const
6082          {
6083             return expression_node<T>::ndb_t::compute_node_depth(branch_);
6084          }
6085 
6086       private:
6087 
6088          bool equality_;
6089          branch_t branch_;
6090       };
6091 
6092       template <typename T>
6093       class literal_node : public expression_node<T>
6094       {
6095       public:
6096 
literal_node(const T & v)6097          explicit literal_node(const T& v)
6098          : value_(v)
6099          {}
6100 
value() const6101          inline T value() const
6102          {
6103             return value_;
6104          }
6105 
type() const6106          inline typename expression_node<T>::node_type type() const
6107          {
6108             return expression_node<T>::e_constant;
6109          }
6110 
branch(const std::size_t &) const6111          inline expression_node<T>* branch(const std::size_t&) const
6112          {
6113             return reinterpret_cast<expression_node<T>*>(0);
6114          }
6115 
6116       private:
6117 
literal_node(literal_node<T> &)6118          literal_node(literal_node<T>&) {}
operator =(literal_node<T> &)6119          literal_node<T>& operator=(literal_node<T>&) { return (*this); }
6120 
6121          const T value_;
6122       };
6123 
6124       template <typename T>
6125       struct range_pack;
6126 
6127       template <typename T>
6128       struct range_data_type;
6129 
6130       template <typename T>
6131       class range_interface
6132       {
6133       public:
6134 
6135          typedef range_pack<T> range_t;
6136 
~range_interface()6137          virtual ~range_interface()
6138          {}
6139 
6140          virtual range_t& range_ref() = 0;
6141 
6142          virtual const range_t& range_ref() const = 0;
6143       };
6144 
6145       #ifndef exprtk_disable_string_capabilities
6146       template <typename T>
6147       class string_base_node
6148       {
6149       public:
6150 
6151          typedef range_data_type<T> range_data_type_t;
6152 
~string_base_node()6153          virtual ~string_base_node()
6154          {}
6155 
6156          virtual std::string str () const = 0;
6157 
6158          virtual char_cptr   base() const = 0;
6159 
6160          virtual std::size_t size() const = 0;
6161       };
6162 
6163       template <typename T>
6164       class string_literal_node : public expression_node <T>,
6165                                   public string_base_node<T>,
6166                                   public range_interface <T>
6167       {
6168       public:
6169 
6170          typedef range_pack<T> range_t;
6171 
string_literal_node(const std::string & v)6172          explicit string_literal_node(const std::string& v)
6173          : value_(v)
6174          {
6175             rp_.n0_c = std::make_pair<bool,std::size_t>(true,0);
6176             rp_.n1_c = std::make_pair<bool,std::size_t>(true,v.size() - 1);
6177             rp_.cache.first  = rp_.n0_c.second;
6178             rp_.cache.second = rp_.n1_c.second;
6179          }
6180 
value() const6181          inline T value() const
6182          {
6183             return std::numeric_limits<T>::quiet_NaN();
6184          }
6185 
type() const6186          inline typename expression_node<T>::node_type type() const
6187          {
6188             return expression_node<T>::e_stringconst;
6189          }
6190 
branch(const std::size_t &) const6191          inline expression_node<T>* branch(const std::size_t&) const
6192          {
6193             return reinterpret_cast<expression_node<T>*>(0);
6194          }
6195 
str() const6196          std::string str() const
6197          {
6198             return value_;
6199          }
6200 
base() const6201          char_cptr base() const
6202          {
6203             return value_.data();
6204          }
6205 
size() const6206          std::size_t size() const
6207          {
6208             return value_.size();
6209          }
6210 
range_ref()6211          range_t& range_ref()
6212          {
6213             return rp_;
6214          }
6215 
range_ref() const6216          const range_t& range_ref() const
6217          {
6218             return rp_;
6219          }
6220 
6221       private:
6222 
6223          string_literal_node(const string_literal_node<T>&);
6224          string_literal_node<T>& operator=(const string_literal_node<T>&);
6225 
6226          const std::string value_;
6227          range_t rp_;
6228       };
6229       #endif
6230 
6231       template <typename T>
6232       class unary_node : public expression_node<T>
6233       {
6234       public:
6235 
6236          typedef expression_node<T>* expression_ptr;
6237          typedef std::pair<expression_ptr,bool> branch_t;
6238 
unary_node(const operator_type & opr,expression_ptr branch)6239          unary_node(const operator_type& opr, expression_ptr branch)
6240          : operation_(opr)
6241          {
6242             construct_branch_pair(branch_,branch);
6243          }
6244 
value() const6245          inline T value() const
6246          {
6247             assert(branch_.first);
6248 
6249             const T arg = branch_.first->value();
6250 
6251             return numeric::process<T>(operation_,arg);
6252          }
6253 
type() const6254          inline typename expression_node<T>::node_type type() const
6255          {
6256             return expression_node<T>::e_unary;
6257          }
6258 
operation() const6259          inline operator_type operation() const
6260          {
6261             return operation_;
6262          }
6263 
branch(const std::size_t &) const6264          inline expression_node<T>* branch(const std::size_t&) const
6265          {
6266             return branch_.first;
6267          }
6268 
release()6269          inline void release()
6270          {
6271             branch_.second = false;
6272          }
6273 
collect_nodes(typename expression_node<T>::noderef_list_t & node_delete_list)6274          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
6275          {
6276             expression_node<T>::ndb_t::collect(branch_, node_delete_list);
6277          }
6278 
node_depth() const6279          std::size_t node_depth() const
6280          {
6281             return expression_node<T>::ndb_t::compute_node_depth(branch_);
6282          }
6283 
6284       protected:
6285 
6286          operator_type operation_;
6287          branch_t branch_;
6288       };
6289 
6290       template <typename T>
6291       class binary_node : public expression_node<T>
6292       {
6293       public:
6294 
6295          typedef expression_node<T>* expression_ptr;
6296          typedef std::pair<expression_ptr,bool> branch_t;
6297 
binary_node(const operator_type & opr,expression_ptr branch0,expression_ptr branch1)6298          binary_node(const operator_type& opr,
6299                      expression_ptr branch0,
6300                      expression_ptr branch1)
6301          : operation_(opr)
6302          {
6303             init_branches<2>(branch_, branch0, branch1);
6304          }
6305 
value() const6306          inline T value() const
6307          {
6308             assert(branch_[0].first);
6309             assert(branch_[1].first);
6310 
6311             const T arg0 = branch_[0].first->value();
6312             const T arg1 = branch_[1].first->value();
6313 
6314             return numeric::process<T>(operation_,arg0,arg1);
6315          }
6316 
type() const6317          inline typename expression_node<T>::node_type type() const
6318          {
6319             return expression_node<T>::e_binary;
6320          }
6321 
operation()6322          inline operator_type operation()
6323          {
6324             return operation_;
6325          }
6326 
branch(const std::size_t & index=0) const6327          inline expression_node<T>* branch(const std::size_t& index = 0) const
6328          {
6329             if (0 == index)
6330                return branch_[0].first;
6331             else if (1 == index)
6332                return branch_[1].first;
6333             else
6334                return reinterpret_cast<expression_ptr>(0);
6335          }
6336 
collect_nodes(typename expression_node<T>::noderef_list_t & node_delete_list)6337          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
6338          {
6339             expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
6340          }
6341 
node_depth() const6342          std::size_t node_depth() const
6343          {
6344             return expression_node<T>::ndb_t::template compute_node_depth<2>(branch_);
6345          }
6346 
6347       protected:
6348 
6349          operator_type operation_;
6350          branch_t branch_[2];
6351       };
6352 
6353       template <typename T, typename Operation>
6354       class binary_ext_node : public expression_node<T>
6355       {
6356       public:
6357 
6358          typedef expression_node<T>* expression_ptr;
6359          typedef std::pair<expression_ptr,bool> branch_t;
6360 
binary_ext_node(expression_ptr branch0,expression_ptr branch1)6361          binary_ext_node(expression_ptr branch0, expression_ptr branch1)
6362          {
6363             init_branches<2>(branch_, branch0, branch1);
6364          }
6365 
value() const6366          inline T value() const
6367          {
6368             assert(branch_[0].first);
6369             assert(branch_[1].first);
6370 
6371             const T arg0 = branch_[0].first->value();
6372             const T arg1 = branch_[1].first->value();
6373 
6374             return Operation::process(arg0,arg1);
6375          }
6376 
type() const6377          inline typename expression_node<T>::node_type type() const
6378          {
6379             return expression_node<T>::e_binary_ext;
6380          }
6381 
operation()6382          inline operator_type operation()
6383          {
6384             return Operation::operation();
6385          }
6386 
branch(const std::size_t & index=0) const6387          inline expression_node<T>* branch(const std::size_t& index = 0) const
6388          {
6389             if (0 == index)
6390                return branch_[0].first;
6391             else if (1 == index)
6392                return branch_[1].first;
6393             else
6394                return reinterpret_cast<expression_ptr>(0);
6395          }
6396 
collect_nodes(typename expression_node<T>::noderef_list_t & node_delete_list)6397          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
6398          {
6399             expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
6400          }
6401 
node_depth() const6402          std::size_t node_depth() const
6403          {
6404             return expression_node<T>::ndb_t::template compute_node_depth<2>(branch_);
6405          }
6406 
6407       protected:
6408 
6409          branch_t branch_[2];
6410       };
6411 
6412       template <typename T>
6413       class trinary_node : public expression_node<T>
6414       {
6415       public:
6416 
6417          typedef expression_node<T>* expression_ptr;
6418          typedef std::pair<expression_ptr,bool> branch_t;
6419 
trinary_node(const operator_type & opr,expression_ptr branch0,expression_ptr branch1,expression_ptr branch2)6420          trinary_node(const operator_type& opr,
6421                       expression_ptr branch0,
6422                       expression_ptr branch1,
6423                       expression_ptr branch2)
6424          : operation_(opr)
6425          {
6426             init_branches<3>(branch_, branch0, branch1, branch2);
6427          }
6428 
value() const6429          inline T value() const
6430          {
6431             assert(branch_[0].first);
6432             assert(branch_[1].first);
6433             assert(branch_[2].first);
6434 
6435             const T arg0 = branch_[0].first->value();
6436             const T arg1 = branch_[1].first->value();
6437             const T arg2 = branch_[2].first->value();
6438 
6439             switch (operation_)
6440             {
6441                case e_inrange : return (arg1 < arg0) ? T(0) : ((arg1 > arg2) ? T(0) : T(1));
6442 
6443                case e_clamp   : return (arg1 < arg0) ? arg0 : (arg1 > arg2 ? arg2 : arg1);
6444 
6445                case e_iclamp  : if ((arg1 <= arg0) || (arg1 >= arg2))
6446                                    return arg1;
6447                                 else
6448                                    return ((T(2) * arg1  <= (arg2 + arg0)) ? arg0 : arg2);
6449 
6450                default        : exprtk_debug(("trinary_node::value() - Error: Invalid operation\n"));
6451                                 return std::numeric_limits<T>::quiet_NaN();
6452             }
6453          }
6454 
type() const6455          inline typename expression_node<T>::node_type type() const
6456          {
6457             return expression_node<T>::e_trinary;
6458          }
6459 
collect_nodes(typename expression_node<T>::noderef_list_t & node_delete_list)6460          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
6461          {
6462             expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
6463          }
6464 
node_depth() const6465          std::size_t node_depth() const
6466          {
6467             return expression_node<T>::ndb_t::template compute_node_depth<3>(branch_);
6468          }
6469 
6470       protected:
6471 
6472          operator_type operation_;
6473          branch_t branch_[3];
6474       };
6475 
6476       template <typename T>
6477       class quaternary_node : public expression_node<T>
6478       {
6479       public:
6480 
6481          typedef expression_node<T>* expression_ptr;
6482          typedef std::pair<expression_ptr,bool> branch_t;
6483 
quaternary_node(const operator_type & opr,expression_ptr branch0,expression_ptr branch1,expression_ptr branch2,expression_ptr branch3)6484          quaternary_node(const operator_type& opr,
6485                          expression_ptr branch0,
6486                          expression_ptr branch1,
6487                          expression_ptr branch2,
6488                          expression_ptr branch3)
6489          : operation_(opr)
6490          {
6491             init_branches<4>(branch_, branch0, branch1, branch2, branch3);
6492          }
6493 
value() const6494          inline T value() const
6495          {
6496             return std::numeric_limits<T>::quiet_NaN();
6497          }
6498 
type() const6499          inline typename expression_node<T>::node_type type() const
6500          {
6501             return expression_node<T>::e_quaternary;
6502          }
6503 
collect_nodes(typename expression_node<T>::noderef_list_t & node_delete_list)6504          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
6505          {
6506             expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
6507          }
6508 
node_depth() const6509          std::size_t node_depth() const
6510          {
6511             return expression_node<T>::ndb_t::template compute_node_depth<4>(branch_);
6512          }
6513 
6514       protected:
6515 
6516          operator_type operation_;
6517          branch_t branch_[4];
6518       };
6519 
6520       template <typename T>
6521       class conditional_node : public expression_node<T>
6522       {
6523       public:
6524 
6525          typedef expression_node<T>* expression_ptr;
6526          typedef std::pair<expression_ptr,bool> branch_t;
6527 
conditional_node(expression_ptr condition,expression_ptr consequent,expression_ptr alternative)6528          conditional_node(expression_ptr condition,
6529                           expression_ptr consequent,
6530                           expression_ptr alternative)
6531          {
6532             construct_branch_pair(condition_  , condition  );
6533             construct_branch_pair(consequent_ , consequent );
6534             construct_branch_pair(alternative_, alternative);
6535          }
6536 
value() const6537          inline T value() const
6538          {
6539             assert(condition_  .first);
6540             assert(consequent_ .first);
6541             assert(alternative_.first);
6542 
6543             if (is_true(condition_))
6544                return consequent_.first->value();
6545             else
6546                return alternative_.first->value();
6547          }
6548 
type() const6549          inline typename expression_node<T>::node_type type() const
6550          {
6551             return expression_node<T>::e_conditional;
6552          }
6553 
collect_nodes(typename expression_node<T>::noderef_list_t & node_delete_list)6554          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
6555          {
6556             expression_node<T>::ndb_t::collect(condition_  , node_delete_list);
6557             expression_node<T>::ndb_t::collect(consequent_ , node_delete_list);
6558             expression_node<T>::ndb_t::collect(alternative_, node_delete_list);
6559          }
6560 
node_depth() const6561          std::size_t node_depth() const
6562          {
6563             return expression_node<T>::ndb_t::compute_node_depth
6564                (condition_, consequent_, alternative_);
6565          }
6566 
6567       private:
6568 
6569          branch_t condition_;
6570          branch_t consequent_;
6571          branch_t alternative_;
6572       };
6573 
6574       template <typename T>
6575       class cons_conditional_node : public expression_node<T>
6576       {
6577       public:
6578 
6579          // Consequent only conditional statement node
6580          typedef expression_node<T>* expression_ptr;
6581          typedef std::pair<expression_ptr,bool> branch_t;
6582 
cons_conditional_node(expression_ptr condition,expression_ptr consequent)6583          cons_conditional_node(expression_ptr condition,
6584                                expression_ptr consequent)
6585          {
6586             construct_branch_pair(condition_ , condition );
6587             construct_branch_pair(consequent_, consequent);
6588          }
6589 
value() const6590          inline T value() const
6591          {
6592             assert(condition_ .first);
6593             assert(consequent_.first);
6594 
6595             if (is_true(condition_))
6596                return consequent_.first->value();
6597             else
6598                return std::numeric_limits<T>::quiet_NaN();
6599          }
6600 
type() const6601          inline typename expression_node<T>::node_type type() const
6602          {
6603             return expression_node<T>::e_conditional;
6604          }
6605 
collect_nodes(typename expression_node<T>::noderef_list_t & node_delete_list)6606          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
6607          {
6608             expression_node<T>::ndb_t::collect(condition_ , node_delete_list);
6609             expression_node<T>::ndb_t::collect(consequent_, node_delete_list);
6610          }
6611 
node_depth() const6612          std::size_t node_depth() const
6613          {
6614             return expression_node<T>::ndb_t::
6615                compute_node_depth(condition_, consequent_);
6616          }
6617 
6618       private:
6619 
6620          branch_t condition_;
6621          branch_t consequent_;
6622       };
6623 
6624       #ifndef exprtk_disable_break_continue
6625       template <typename T>
6626       class break_exception
6627       {
6628       public:
6629 
break_exception(const T & v)6630          explicit break_exception(const T& v)
6631          : value(v)
6632          {}
6633 
6634          T value;
6635       };
6636 
6637       class continue_exception
6638       {};
6639 
6640       template <typename T>
6641       class break_node : public expression_node<T>
6642       {
6643       public:
6644 
6645          typedef expression_node<T>* expression_ptr;
6646          typedef std::pair<expression_ptr,bool> branch_t;
6647 
break_node(expression_ptr ret=expression_ptr (0))6648          break_node(expression_ptr ret = expression_ptr(0))
6649          {
6650             construct_branch_pair(return_, ret);
6651          }
6652 
value() const6653          inline T value() const
6654          {
6655             throw break_exception<T>(return_.first ? return_.first->value() : std::numeric_limits<T>::quiet_NaN());
6656             #ifndef _MSC_VER
6657             return std::numeric_limits<T>::quiet_NaN();
6658             #endif
6659          }
6660 
type() const6661          inline typename expression_node<T>::node_type type() const
6662          {
6663             return expression_node<T>::e_break;
6664          }
6665 
collect_nodes(typename expression_node<T>::noderef_list_t & node_delete_list)6666          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
6667          {
6668             expression_node<T>::ndb_t::collect(return_, node_delete_list);
6669          }
6670 
node_depth() const6671          std::size_t node_depth() const
6672          {
6673             return expression_node<T>::ndb_t::compute_node_depth(return_);
6674          }
6675 
6676       private:
6677 
6678          branch_t return_;
6679       };
6680 
6681       template <typename T>
6682       class continue_node : public expression_node<T>
6683       {
6684       public:
6685 
value() const6686          inline T value() const
6687          {
6688             throw continue_exception();
6689             #ifndef _MSC_VER
6690             return std::numeric_limits<T>::quiet_NaN();
6691             #endif
6692          }
6693 
type() const6694          inline typename expression_node<T>::node_type type() const
6695          {
6696             return expression_node<T>::e_break;
6697          }
6698       };
6699       #endif
6700 
6701       #ifdef exprtk_enable_runtime_checks
6702       struct loop_runtime_checker
6703       {
loop_runtime_checkerexprtk::details::loop_runtime_checker6704          loop_runtime_checker(loop_runtime_check_ptr loop_rt_chk = loop_runtime_check_ptr(0),
6705                               loop_runtime_check::loop_types lp_typ = loop_runtime_check::e_invalid)
6706          : iteration_count_(0),
6707            loop_runtime_check_(loop_rt_chk),
6708            loop_type(lp_typ)
6709          {}
6710 
resetexprtk::details::loop_runtime_checker6711          inline void reset(const _uint64_t initial_value = 0) const
6712          {
6713             iteration_count_ = initial_value;
6714          }
6715 
checkexprtk::details::loop_runtime_checker6716          inline bool check() const
6717          {
6718             if (
6719                  (0 == loop_runtime_check_) ||
6720                  (++iteration_count_ <= loop_runtime_check_->max_loop_iterations)
6721                )
6722             {
6723                return true;
6724             }
6725 
6726             loop_runtime_check::violation_context ctxt;
6727             ctxt.loop      = loop_type;
6728             ctxt.violation = loop_runtime_check::e_iteration_count;
6729 
6730             loop_runtime_check_->handle_runtime_violation(ctxt);
6731 
6732             return false;
6733          }
6734 
6735          mutable _uint64_t iteration_count_;
6736          mutable loop_runtime_check_ptr loop_runtime_check_;
6737          loop_runtime_check::loop_types loop_type;
6738       };
6739       #else
6740       struct loop_runtime_checker
6741       {
loop_runtime_checkerexprtk::details::loop_runtime_checker6742          loop_runtime_checker(loop_runtime_check_ptr, loop_runtime_check::loop_types)
6743          {}
6744 
resetexprtk::details::loop_runtime_checker6745          inline void reset(const _uint64_t = 0) const
6746          {}
6747 
checkexprtk::details::loop_runtime_checker6748          inline bool check() const
6749          {
6750             return true;
6751          }
6752       };
6753       #endif
6754 
6755       template <typename T>
6756       class while_loop_node : public expression_node<T>,
6757                               public loop_runtime_checker
6758       {
6759       public:
6760 
6761          typedef expression_node<T>* expression_ptr;
6762          typedef std::pair<expression_ptr,bool> branch_t;
6763 
while_loop_node(expression_ptr condition,expression_ptr loop_body,loop_runtime_check_ptr loop_rt_chk=loop_runtime_check_ptr (0))6764          while_loop_node(expression_ptr condition,
6765                          expression_ptr loop_body,
6766                          loop_runtime_check_ptr loop_rt_chk = loop_runtime_check_ptr(0))
6767          : loop_runtime_checker(loop_rt_chk,loop_runtime_check::e_while_loop)
6768          {
6769             construct_branch_pair(condition_, condition);
6770             construct_branch_pair(loop_body_, loop_body);
6771          }
6772 
value() const6773          inline T value() const
6774          {
6775             assert(condition_.first);
6776             assert(loop_body_.first);
6777 
6778             T result = T(0);
6779 
6780             loop_runtime_checker::reset();
6781 
6782             while (is_true(condition_) && loop_runtime_checker::check())
6783             {
6784                result = loop_body_.first->value();
6785             }
6786 
6787             return result;
6788          }
6789 
type() const6790          inline typename expression_node<T>::node_type type() const
6791          {
6792             return expression_node<T>::e_while;
6793          }
6794 
collect_nodes(typename expression_node<T>::noderef_list_t & node_delete_list)6795          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
6796          {
6797             expression_node<T>::ndb_t::collect(condition_, node_delete_list);
6798             expression_node<T>::ndb_t::collect(loop_body_, node_delete_list);
6799          }
6800 
node_depth() const6801          std::size_t node_depth() const
6802          {
6803             return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_);
6804          }
6805 
6806       private:
6807 
6808          branch_t condition_;
6809          branch_t loop_body_;
6810       };
6811 
6812       template <typename T>
6813       class repeat_until_loop_node : public expression_node<T>,
6814                                      public loop_runtime_checker
6815       {
6816       public:
6817 
6818          typedef expression_node<T>* expression_ptr;
6819          typedef std::pair<expression_ptr,bool> branch_t;
6820 
repeat_until_loop_node(expression_ptr condition,expression_ptr loop_body,loop_runtime_check_ptr loop_rt_chk=loop_runtime_check_ptr (0))6821          repeat_until_loop_node(expression_ptr condition,
6822                                 expression_ptr loop_body,
6823                                 loop_runtime_check_ptr loop_rt_chk = loop_runtime_check_ptr(0))
6824          : loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_repeat_until_loop)
6825          {
6826             construct_branch_pair(condition_, condition);
6827             construct_branch_pair(loop_body_, loop_body);
6828          }
6829 
value() const6830          inline T value() const
6831          {
6832             assert(condition_.first);
6833             assert(loop_body_.first);
6834 
6835             T result = T(0);
6836 
6837             loop_runtime_checker::reset(1);
6838 
6839             do
6840             {
6841                result = loop_body_.first->value();
6842             }
6843             while (is_false(condition_.first) && loop_runtime_checker::check());
6844 
6845             return result;
6846          }
6847 
type() const6848          inline typename expression_node<T>::node_type type() const
6849          {
6850             return expression_node<T>::e_repeat;
6851          }
6852 
collect_nodes(typename expression_node<T>::noderef_list_t & node_delete_list)6853          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
6854          {
6855             expression_node<T>::ndb_t::collect(condition_, node_delete_list);
6856             expression_node<T>::ndb_t::collect(loop_body_, node_delete_list);
6857          }
6858 
node_depth() const6859          std::size_t node_depth() const
6860          {
6861             return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_);
6862          }
6863 
6864       private:
6865 
6866          branch_t condition_;
6867          branch_t loop_body_;
6868       };
6869 
6870       template <typename T>
6871       class for_loop_node : public expression_node<T>,
6872                             public loop_runtime_checker
6873       {
6874       public:
6875 
6876          typedef expression_node<T>* expression_ptr;
6877          typedef std::pair<expression_ptr,bool> branch_t;
6878 
for_loop_node(expression_ptr initialiser,expression_ptr condition,expression_ptr incrementor,expression_ptr loop_body,loop_runtime_check_ptr loop_rt_chk=loop_runtime_check_ptr (0))6879          for_loop_node(expression_ptr initialiser,
6880                        expression_ptr condition,
6881                        expression_ptr incrementor,
6882                        expression_ptr loop_body,
6883                        loop_runtime_check_ptr loop_rt_chk = loop_runtime_check_ptr(0))
6884          : loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_for_loop)
6885          {
6886             construct_branch_pair(initialiser_, initialiser);
6887             construct_branch_pair(condition_  , condition  );
6888             construct_branch_pair(incrementor_, incrementor);
6889             construct_branch_pair(loop_body_  , loop_body  );
6890          }
6891 
value() const6892          inline T value() const
6893          {
6894             assert(condition_.first);
6895             assert(loop_body_.first);
6896 
6897             T result = T(0);
6898 
6899             loop_runtime_checker::reset();
6900 
6901             if (initialiser_.first)
6902                initialiser_.first->value();
6903 
6904             if (incrementor_.first)
6905             {
6906                while (is_true(condition_) && loop_runtime_checker::check())
6907                {
6908                   result = loop_body_.first->value();
6909                   incrementor_.first->value();
6910                }
6911             }
6912             else
6913             {
6914                while (is_true(condition_) && loop_runtime_checker::check())
6915                {
6916                   result = loop_body_.first->value();
6917                }
6918             }
6919 
6920             return result;
6921          }
6922 
type() const6923          inline typename expression_node<T>::node_type type() const
6924          {
6925             return expression_node<T>::e_for;
6926          }
6927 
collect_nodes(typename expression_node<T>::noderef_list_t & node_delete_list)6928          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
6929          {
6930             expression_node<T>::ndb_t::collect(initialiser_, node_delete_list);
6931             expression_node<T>::ndb_t::collect(condition_  , node_delete_list);
6932             expression_node<T>::ndb_t::collect(incrementor_, node_delete_list);
6933             expression_node<T>::ndb_t::collect(loop_body_  , node_delete_list);
6934          }
6935 
node_depth() const6936          std::size_t node_depth() const
6937          {
6938             return expression_node<T>::ndb_t::compute_node_depth
6939                (initialiser_, condition_, incrementor_, loop_body_);
6940          }
6941 
6942       private:
6943 
6944          branch_t initialiser_;
6945          branch_t condition_  ;
6946          branch_t incrementor_;
6947          branch_t loop_body_  ;
6948       };
6949 
6950       #ifndef exprtk_disable_break_continue
6951       template <typename T>
6952       class while_loop_bc_node : public expression_node<T>,
6953                                  public loop_runtime_checker
6954       {
6955       public:
6956 
6957          typedef expression_node<T>* expression_ptr;
6958          typedef std::pair<expression_ptr,bool> branch_t;
6959 
while_loop_bc_node(expression_ptr condition,expression_ptr loop_body,loop_runtime_check_ptr loop_rt_chk=loop_runtime_check_ptr (0))6960          while_loop_bc_node(expression_ptr condition,
6961                             expression_ptr loop_body,
6962                             loop_runtime_check_ptr loop_rt_chk = loop_runtime_check_ptr(0))
6963          : loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_while_loop)
6964          {
6965             construct_branch_pair(condition_, condition);
6966             construct_branch_pair(loop_body_, loop_body);
6967          }
6968 
value() const6969          inline T value() const
6970          {
6971             assert(condition_.first);
6972             assert(loop_body_.first);
6973 
6974             T result = T(0);
6975 
6976             loop_runtime_checker::reset();
6977 
6978             while (is_true(condition_) && loop_runtime_checker::check())
6979             {
6980                try
6981                {
6982                   result = loop_body_.first->value();
6983                }
6984                catch(const break_exception<T>& e)
6985                {
6986                   return e.value;
6987                }
6988                catch(const continue_exception&)
6989                {}
6990             }
6991 
6992             return result;
6993          }
6994 
type() const6995          inline typename expression_node<T>::node_type type() const
6996          {
6997             return expression_node<T>::e_while;
6998          }
6999 
collect_nodes(typename expression_node<T>::noderef_list_t & node_delete_list)7000          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
7001          {
7002             expression_node<T>::ndb_t::collect(condition_, node_delete_list);
7003             expression_node<T>::ndb_t::collect(loop_body_, node_delete_list);
7004          }
7005 
node_depth() const7006          std::size_t node_depth() const
7007          {
7008             return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_);
7009          }
7010 
7011       private:
7012 
7013          branch_t condition_;
7014          branch_t loop_body_;
7015       };
7016 
7017       template <typename T>
7018       class repeat_until_loop_bc_node : public expression_node<T>,
7019                                         public loop_runtime_checker
7020       {
7021       public:
7022 
7023          typedef expression_node<T>* expression_ptr;
7024          typedef std::pair<expression_ptr,bool> branch_t;
7025 
repeat_until_loop_bc_node(expression_ptr condition,expression_ptr loop_body,loop_runtime_check_ptr loop_rt_chk=loop_runtime_check_ptr (0))7026          repeat_until_loop_bc_node(expression_ptr condition,
7027                                    expression_ptr loop_body,
7028                                    loop_runtime_check_ptr loop_rt_chk = loop_runtime_check_ptr(0))
7029          : loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_repeat_until_loop)
7030          {
7031             construct_branch_pair(condition_, condition);
7032             construct_branch_pair(loop_body_, loop_body);
7033          }
7034 
value() const7035          inline T value() const
7036          {
7037             assert(condition_.first);
7038             assert(loop_body_.first);
7039 
7040             T result = T(0);
7041 
7042             loop_runtime_checker::reset();
7043 
7044             do
7045             {
7046                try
7047                {
7048                   result = loop_body_.first->value();
7049                }
7050                catch(const break_exception<T>& e)
7051                {
7052                   return e.value;
7053                }
7054                catch(const continue_exception&)
7055                {}
7056             }
7057             while (is_false(condition_.first) && loop_runtime_checker::check());
7058 
7059             return result;
7060          }
7061 
type() const7062          inline typename expression_node<T>::node_type type() const
7063          {
7064             return expression_node<T>::e_repeat;
7065          }
7066 
collect_nodes(typename expression_node<T>::noderef_list_t & node_delete_list)7067          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
7068          {
7069             expression_node<T>::ndb_t::collect(condition_, node_delete_list);
7070             expression_node<T>::ndb_t::collect(loop_body_, node_delete_list);
7071          }
7072 
node_depth() const7073          std::size_t node_depth() const
7074          {
7075             return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_);
7076          }
7077 
7078       private:
7079 
7080          branch_t condition_;
7081          branch_t loop_body_;
7082       };
7083 
7084       template <typename T>
7085       class for_loop_bc_node : public expression_node<T>,
7086                                public loop_runtime_checker
7087       {
7088       public:
7089 
7090          typedef expression_node<T>* expression_ptr;
7091          typedef std::pair<expression_ptr,bool> branch_t;
7092 
for_loop_bc_node(expression_ptr initialiser,expression_ptr condition,expression_ptr incrementor,expression_ptr loop_body,loop_runtime_check_ptr loop_rt_chk=loop_runtime_check_ptr (0))7093          for_loop_bc_node(expression_ptr initialiser,
7094                           expression_ptr condition,
7095                           expression_ptr incrementor,
7096                           expression_ptr loop_body,
7097                           loop_runtime_check_ptr loop_rt_chk = loop_runtime_check_ptr(0))
7098          : loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_for_loop)
7099          {
7100             construct_branch_pair(initialiser_, initialiser);
7101             construct_branch_pair(condition_  , condition  );
7102             construct_branch_pair(incrementor_, incrementor);
7103             construct_branch_pair(loop_body_  , loop_body  );
7104          }
7105 
value() const7106          inline T value() const
7107          {
7108             assert(condition_.first);
7109             assert(loop_body_.first);
7110 
7111             T result = T(0);
7112 
7113             loop_runtime_checker::reset();
7114 
7115             if (initialiser_.first)
7116                initialiser_.first->value();
7117 
7118             if (incrementor_.first)
7119             {
7120                while (is_true(condition_) && loop_runtime_checker::check())
7121                {
7122                   try
7123                   {
7124                      result = loop_body_.first->value();
7125                   }
7126                   catch(const break_exception<T>& e)
7127                   {
7128                      return e.value;
7129                   }
7130                   catch(const continue_exception&)
7131                   {}
7132 
7133                   incrementor_.first->value();
7134                }
7135             }
7136             else
7137             {
7138                while (is_true(condition_) && loop_runtime_checker::check())
7139                {
7140                   try
7141                   {
7142                      result = loop_body_.first->value();
7143                   }
7144                   catch(const break_exception<T>& e)
7145                   {
7146                      return e.value;
7147                   }
7148                   catch(const continue_exception&)
7149                   {}
7150                }
7151             }
7152 
7153             return result;
7154          }
7155 
type() const7156          inline typename expression_node<T>::node_type type() const
7157          {
7158             return expression_node<T>::e_for;
7159          }
7160 
collect_nodes(typename expression_node<T>::noderef_list_t & node_delete_list)7161          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
7162          {
7163             expression_node<T>::ndb_t::collect(initialiser_, node_delete_list);
7164             expression_node<T>::ndb_t::collect(condition_  , node_delete_list);
7165             expression_node<T>::ndb_t::collect(incrementor_, node_delete_list);
7166             expression_node<T>::ndb_t::collect(loop_body_  , node_delete_list);
7167          }
7168 
node_depth() const7169          std::size_t node_depth() const
7170          {
7171             return expression_node<T>::ndb_t::compute_node_depth
7172                (initialiser_, condition_, incrementor_, loop_body_);
7173          }
7174 
7175       private:
7176 
7177          branch_t initialiser_;
7178          branch_t condition_  ;
7179          branch_t incrementor_;
7180          branch_t loop_body_  ;
7181       };
7182       #endif
7183 
7184       template <typename T>
7185       class switch_node : public expression_node<T>
7186       {
7187       public:
7188 
7189          typedef expression_node<T>* expression_ptr;
7190          typedef std::pair<expression_ptr,bool> branch_t;
7191 
7192          template <typename Allocator,
7193                    template <typename, typename> class Sequence>
switch_node(const Sequence<expression_ptr,Allocator> & arg_list)7194          explicit switch_node(const Sequence<expression_ptr,Allocator>& arg_list)
7195          {
7196             if (1 != (arg_list.size() & 1))
7197                return;
7198 
7199             arg_list_.resize(arg_list.size());
7200 
7201             for (std::size_t i = 0; i < arg_list.size(); ++i)
7202             {
7203                if (arg_list[i])
7204                {
7205                   construct_branch_pair(arg_list_[i], arg_list[i]);
7206                }
7207                else
7208                {
7209                   arg_list_.clear();
7210                   return;
7211                }
7212             }
7213          }
7214 
value() const7215          inline T value() const
7216          {
7217             if (!arg_list_.empty())
7218             {
7219                const std::size_t upper_bound = (arg_list_.size() - 1);
7220 
7221                for (std::size_t i = 0; i < upper_bound; i += 2)
7222                {
7223                   expression_ptr condition  = arg_list_[i    ].first;
7224                   expression_ptr consequent = arg_list_[i + 1].first;
7225 
7226                   if (is_true(condition))
7227                   {
7228                      return consequent->value();
7229                   }
7230                }
7231 
7232                return arg_list_[upper_bound].first->value();
7233             }
7234             else
7235                return std::numeric_limits<T>::quiet_NaN();
7236          }
7237 
type() const7238          inline typename expression_node<T>::node_type type() const
7239          {
7240             return expression_node<T>::e_switch;
7241          }
7242 
collect_nodes(typename expression_node<T>::noderef_list_t & node_delete_list)7243          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
7244          {
7245             expression_node<T>::ndb_t::collect(arg_list_, node_delete_list);
7246          }
7247 
node_depth() const7248          std::size_t node_depth() const
7249          {
7250             return expression_node<T>::ndb_t::compute_node_depth(arg_list_);
7251          }
7252 
7253       protected:
7254 
7255          std::vector<branch_t> arg_list_;
7256       };
7257 
7258       template <typename T, typename Switch_N>
7259       class switch_n_node : public switch_node<T>
7260       {
7261       public:
7262 
7263          typedef expression_node<T>* expression_ptr;
7264 
7265          template <typename Allocator,
7266                    template <typename, typename> class Sequence>
switch_n_node(const Sequence<expression_ptr,Allocator> & arg_list)7267          explicit switch_n_node(const Sequence<expression_ptr,Allocator>& arg_list)
7268          : switch_node<T>(arg_list)
7269          {}
7270 
value() const7271          inline T value() const
7272          {
7273             return Switch_N::process(switch_node<T>::arg_list_);
7274          }
7275       };
7276 
7277       template <typename T>
7278       class multi_switch_node : public expression_node<T>
7279       {
7280       public:
7281 
7282          typedef expression_node<T>* expression_ptr;
7283          typedef std::pair<expression_ptr,bool> branch_t;
7284 
7285          template <typename Allocator,
7286                    template <typename, typename> class Sequence>
multi_switch_node(const Sequence<expression_ptr,Allocator> & arg_list)7287          explicit multi_switch_node(const Sequence<expression_ptr,Allocator>& arg_list)
7288          {
7289             if (0 != (arg_list.size() & 1))
7290                return;
7291 
7292             arg_list_.resize(arg_list.size());
7293 
7294             for (std::size_t i = 0; i < arg_list.size(); ++i)
7295             {
7296                if (arg_list[i])
7297                {
7298                   construct_branch_pair(arg_list_[i], arg_list[i]);
7299                }
7300                else
7301                {
7302                   arg_list_.clear();
7303                   return;
7304                }
7305             }
7306          }
7307 
value() const7308          inline T value() const
7309          {
7310             T result = T(0);
7311 
7312             if (arg_list_.empty())
7313             {
7314                return std::numeric_limits<T>::quiet_NaN();
7315             }
7316 
7317             const std::size_t upper_bound = (arg_list_.size() - 1);
7318 
7319             for (std::size_t i = 0; i < upper_bound; i += 2)
7320             {
7321                expression_ptr condition  = arg_list_[i    ].first;
7322                expression_ptr consequent = arg_list_[i + 1].first;
7323 
7324                if (is_true(condition))
7325                {
7326                   result = consequent->value();
7327                }
7328             }
7329 
7330             return result;
7331          }
7332 
type() const7333          inline typename expression_node<T>::node_type type() const
7334          {
7335             return expression_node<T>::e_mswitch;
7336          }
7337 
collect_nodes(typename expression_node<T>::noderef_list_t & node_delete_list)7338          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
7339          {
7340             expression_node<T>::ndb_t::collect(arg_list_, node_delete_list);
7341          }
7342 
node_depth() const7343          std::size_t node_depth() const
7344          {
7345             return expression_node<T>::ndb_t::compute_node_depth(arg_list_);
7346          }
7347 
7348       private:
7349 
7350          std::vector<branch_t> arg_list_;
7351       };
7352 
7353       template <typename T>
7354       class ivariable
7355       {
7356       public:
7357 
~ivariable()7358          virtual ~ivariable()
7359          {}
7360 
7361          virtual T& ref() = 0;
7362          virtual const T& ref() const = 0;
7363       };
7364 
7365       template <typename T>
7366       class variable_node : public expression_node<T>,
7367                             public ivariable      <T>
7368       {
7369       public:
7370 
7371          static T null_value;
7372 
variable_node()7373          explicit variable_node()
7374          : value_(&null_value)
7375          {}
7376 
variable_node(T & v)7377          explicit variable_node(T& v)
7378          : value_(&v)
7379          {}
7380 
operator <(const variable_node<T> & v) const7381          inline bool operator <(const variable_node<T>& v) const
7382          {
7383             return this < (&v);
7384          }
7385 
value() const7386          inline T value() const
7387          {
7388             return (*value_);
7389          }
7390 
ref()7391          inline T& ref()
7392          {
7393             return (*value_);
7394          }
7395 
ref() const7396          inline const T& ref() const
7397          {
7398             return (*value_);
7399          }
7400 
type() const7401          inline typename expression_node<T>::node_type type() const
7402          {
7403             return expression_node<T>::e_variable;
7404          }
7405 
7406       private:
7407 
7408          T* value_;
7409       };
7410 
7411       template <typename T>
7412       T variable_node<T>::null_value = T(std::numeric_limits<T>::quiet_NaN());
7413 
7414       template <typename T>
7415       struct range_pack
7416       {
7417          typedef expression_node<T>*           expression_node_ptr;
7418          typedef std::pair<std::size_t,std::size_t> cached_range_t;
7419 
range_packexprtk::details::range_pack7420          range_pack()
7421          : n0_e (std::make_pair(false,expression_node_ptr(0))),
7422            n1_e (std::make_pair(false,expression_node_ptr(0))),
7423            n0_c (std::make_pair(false,0)),
7424            n1_c (std::make_pair(false,0)),
7425            cache(std::make_pair(0,0))
7426          {}
7427 
clearexprtk::details::range_pack7428          void clear()
7429          {
7430             n0_e  = std::make_pair(false,expression_node_ptr(0));
7431             n1_e  = std::make_pair(false,expression_node_ptr(0));
7432             n0_c  = std::make_pair(false,0);
7433             n1_c  = std::make_pair(false,0);
7434             cache = std::make_pair(0,0);
7435          }
7436 
freeexprtk::details::range_pack7437          void free()
7438          {
7439             if (n0_e.first && n0_e.second)
7440             {
7441                n0_e.first = false;
7442 
7443                if (
7444                     !is_variable_node(n0_e.second) &&
7445                     !is_string_node  (n0_e.second)
7446                   )
7447                {
7448                   destroy_node(n0_e.second);
7449                }
7450             }
7451 
7452             if (n1_e.first && n1_e.second)
7453             {
7454                n1_e.first = false;
7455 
7456                if (
7457                     !is_variable_node(n1_e.second) &&
7458                     !is_string_node  (n1_e.second)
7459                   )
7460                {
7461                   destroy_node(n1_e.second);
7462                }
7463             }
7464          }
7465 
const_rangeexprtk::details::range_pack7466          bool const_range() const
7467          {
7468            return ( n0_c.first &&  n1_c.first) &&
7469                   (!n0_e.first && !n1_e.first);
7470          }
7471 
var_rangeexprtk::details::range_pack7472          bool var_range() const
7473          {
7474            return ( n0_e.first &&  n1_e.first) &&
7475                   (!n0_c.first && !n1_c.first);
7476          }
7477 
operator ()exprtk::details::range_pack7478          bool operator() (std::size_t& r0, std::size_t& r1,
7479                           const std::size_t& size = std::numeric_limits<std::size_t>::max()) const
7480          {
7481             if (n0_c.first)
7482                r0 = n0_c.second;
7483             else if (n0_e.first)
7484             {
7485                r0 = static_cast<std::size_t>(details::numeric::to_int64(n0_e.second->value()));
7486             }
7487             else
7488                return false;
7489 
7490             if (n1_c.first)
7491                r1 = n1_c.second;
7492             else if (n1_e.first)
7493             {
7494                r1 = static_cast<std::size_t>(details::numeric::to_int64(n1_e.second->value()));
7495             }
7496             else
7497                return false;
7498 
7499             if (
7500                  (std::numeric_limits<std::size_t>::max() != size) &&
7501                  (std::numeric_limits<std::size_t>::max() == r1  )
7502                )
7503             {
7504                r1 = size - 1;
7505             }
7506 
7507             cache.first  = r0;
7508             cache.second = r1;
7509 
7510             #ifndef exprtk_enable_runtime_checks
7511             return (r0 <= r1);
7512             #else
7513             return range_runtime_check(r0, r1, size);
7514             #endif
7515          }
7516 
const_sizeexprtk::details::range_pack7517          inline std::size_t const_size() const
7518          {
7519             return (n1_c.second - n0_c.second + 1);
7520          }
7521 
cache_sizeexprtk::details::range_pack7522          inline std::size_t cache_size() const
7523          {
7524             return (cache.second - cache.first + 1);
7525          }
7526 
7527          std::pair<bool,expression_node_ptr> n0_e;
7528          std::pair<bool,expression_node_ptr> n1_e;
7529          std::pair<bool,std::size_t        > n0_c;
7530          std::pair<bool,std::size_t        > n1_c;
7531          mutable cached_range_t             cache;
7532 
7533          #ifdef exprtk_enable_runtime_checks
range_runtime_checkexprtk::details::range_pack7534          bool range_runtime_check(const std::size_t r0,
7535                                   const std::size_t r1,
7536                                   const std::size_t size) const
7537          {
7538             if (r0 >= size)
7539             {
7540                throw std::runtime_error("range error: (r0 < 0) || (r0 >= size)");
7541                return false;
7542             }
7543 
7544             if (r1 >= size)
7545             {
7546                throw std::runtime_error("range error: (r1 < 0) || (r1 >= size)");
7547                return false;
7548             }
7549 
7550             return (r0 <= r1);
7551          }
7552          #endif
7553       };
7554 
7555       template <typename T>
7556       class string_base_node;
7557 
7558       template <typename T>
7559       struct range_data_type
7560       {
7561          typedef range_pack<T> range_t;
7562          typedef string_base_node<T>* strbase_ptr_t;
7563 
range_data_typeexprtk::details::range_data_type7564          range_data_type()
7565          : range(0),
7566            data (0),
7567            size (0),
7568            type_size(0),
7569            str_node (0)
7570          {}
7571 
7572          range_t*      range;
7573          void*         data;
7574          std::size_t   size;
7575          std::size_t   type_size;
7576          strbase_ptr_t str_node;
7577       };
7578 
7579       template <typename T> class vector_node;
7580 
7581       template <typename T>
7582       class vector_interface
7583       {
7584       public:
7585 
7586          typedef vector_node<T>*   vector_node_ptr;
7587          typedef vec_data_store<T>           vds_t;
7588 
~vector_interface()7589          virtual ~vector_interface()
7590          {}
7591 
7592          virtual std::size_t size   () const = 0;
7593 
7594          virtual vector_node_ptr vec() const = 0;
7595 
7596          virtual vector_node_ptr vec()       = 0;
7597 
7598          virtual       vds_t& vds   ()       = 0;
7599 
7600          virtual const vds_t& vds   () const = 0;
7601 
side_effect() const7602          virtual bool side_effect   () const { return false; }
7603       };
7604 
7605       template <typename T>
7606       class vector_node : public expression_node <T>,
7607                           public vector_interface<T>
7608       {
7609       public:
7610 
7611          typedef expression_node<T>*  expression_ptr;
7612          typedef vector_holder<T>    vector_holder_t;
7613          typedef vector_node<T>*     vector_node_ptr;
7614          typedef vec_data_store<T>             vds_t;
7615 
vector_node(vector_holder_t * vh)7616          explicit vector_node(vector_holder_t* vh)
7617          : vector_holder_(vh),
7618            vds_((*vector_holder_).size(),(*vector_holder_)[0])
7619          {
7620             vector_holder_->set_ref(&vds_.ref());
7621          }
7622 
vector_node(const vds_t & vds,vector_holder_t * vh)7623          vector_node(const vds_t& vds, vector_holder_t* vh)
7624          : vector_holder_(vh),
7625            vds_(vds)
7626          {}
7627 
value() const7628          inline T value() const
7629          {
7630             return vds().data()[0];
7631          }
7632 
vec() const7633          vector_node_ptr vec() const
7634          {
7635             return const_cast<vector_node_ptr>(this);
7636          }
7637 
vec()7638          vector_node_ptr vec()
7639          {
7640             return this;
7641          }
7642 
type() const7643          inline typename expression_node<T>::node_type type() const
7644          {
7645             return expression_node<T>::e_vector;
7646          }
7647 
size() const7648          std::size_t size() const
7649          {
7650             return vds().size();
7651          }
7652 
vds()7653          vds_t& vds()
7654          {
7655             return vds_;
7656          }
7657 
vds() const7658          const vds_t& vds() const
7659          {
7660             return vds_;
7661          }
7662 
vec_holder()7663          inline vector_holder_t& vec_holder()
7664          {
7665             return (*vector_holder_);
7666          }
7667 
7668       private:
7669 
7670          vector_holder_t* vector_holder_;
7671          vds_t                      vds_;
7672       };
7673 
7674       template <typename T>
7675       class vector_elem_node : public expression_node<T>,
7676                                public ivariable      <T>
7677       {
7678       public:
7679 
7680          typedef expression_node<T>*            expression_ptr;
7681          typedef vector_holder<T>               vector_holder_t;
7682          typedef vector_holder_t*               vector_holder_ptr;
7683          typedef std::pair<expression_ptr,bool> branch_t;
7684 
vector_elem_node(expression_ptr index,vector_holder_ptr vec_holder)7685          vector_elem_node(expression_ptr index, vector_holder_ptr vec_holder)
7686          : vec_holder_(vec_holder),
7687            vector_base_((*vec_holder)[0])
7688          {
7689             construct_branch_pair(index_, index);
7690          }
7691 
value() const7692          inline T value() const
7693          {
7694             return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_.first->value())));
7695          }
7696 
ref()7697          inline T& ref()
7698          {
7699             return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_.first->value())));
7700          }
7701 
ref() const7702          inline const T& ref() const
7703          {
7704             return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_.first->value())));
7705          }
7706 
type() const7707          inline typename expression_node<T>::node_type type() const
7708          {
7709             return expression_node<T>::e_vecelem;
7710          }
7711 
vec_holder()7712          inline vector_holder_t& vec_holder()
7713          {
7714             return (*vec_holder_);
7715          }
7716 
collect_nodes(typename expression_node<T>::noderef_list_t & node_delete_list)7717          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
7718          {
7719             expression_node<T>::ndb_t::collect(index_, node_delete_list);
7720          }
7721 
node_depth() const7722          std::size_t node_depth() const
7723          {
7724             return expression_node<T>::ndb_t::compute_node_depth(index_);
7725          }
7726 
7727       private:
7728 
7729          vector_holder_ptr vec_holder_;
7730          T* vector_base_;
7731          branch_t index_;
7732       };
7733 
7734       template <typename T>
7735       class rebasevector_elem_node : public expression_node<T>,
7736                                      public ivariable      <T>
7737       {
7738       public:
7739 
7740          typedef expression_node<T>*            expression_ptr;
7741          typedef vector_holder<T>               vector_holder_t;
7742          typedef vector_holder_t*               vector_holder_ptr;
7743          typedef vec_data_store<T>              vds_t;
7744          typedef std::pair<expression_ptr,bool> branch_t;
7745 
rebasevector_elem_node(expression_ptr index,vector_holder_ptr vec_holder)7746          rebasevector_elem_node(expression_ptr index, vector_holder_ptr vec_holder)
7747          : vector_holder_(vec_holder),
7748            vds_((*vector_holder_).size(),(*vector_holder_)[0])
7749          {
7750             vector_holder_->set_ref(&vds_.ref());
7751             construct_branch_pair(index_, index);
7752          }
7753 
value() const7754          inline T value() const
7755          {
7756             return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_.first->value())));
7757          }
7758 
ref()7759          inline T& ref()
7760          {
7761             return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_.first->value())));
7762          }
7763 
ref() const7764          inline const T& ref() const
7765          {
7766             return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_.first->value())));
7767          }
7768 
type() const7769          inline typename expression_node<T>::node_type type() const
7770          {
7771             return expression_node<T>::e_rbvecelem;
7772          }
7773 
vec_holder()7774          inline vector_holder_t& vec_holder()
7775          {
7776             return (*vector_holder_);
7777          }
7778 
collect_nodes(typename expression_node<T>::noderef_list_t & node_delete_list)7779          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
7780          {
7781             expression_node<T>::ndb_t::template collect(index_, node_delete_list);
7782          }
7783 
node_depth() const7784          std::size_t node_depth() const
7785          {
7786             return expression_node<T>::ndb_t::compute_node_depth(index_);
7787          }
7788 
7789       private:
7790 
7791          vector_holder_ptr vector_holder_;
7792          vds_t             vds_;
7793          branch_t          index_;
7794       };
7795 
7796       template <typename T>
7797       class rebasevector_celem_node : public expression_node<T>,
7798                                       public ivariable      <T>
7799       {
7800       public:
7801 
7802          typedef expression_node<T>* expression_ptr;
7803          typedef vector_holder<T>    vector_holder_t;
7804          typedef vector_holder_t*    vector_holder_ptr;
7805          typedef vec_data_store<T>   vds_t;
7806 
rebasevector_celem_node(const std::size_t index,vector_holder_ptr vec_holder)7807          rebasevector_celem_node(const std::size_t index, vector_holder_ptr vec_holder)
7808          : index_(index),
7809            vector_holder_(vec_holder),
7810            vds_((*vector_holder_).size(),(*vector_holder_)[0])
7811          {
7812             vector_holder_->set_ref(&vds_.ref());
7813          }
7814 
value() const7815          inline T value() const
7816          {
7817             return *(vds_.data() + index_);
7818          }
7819 
ref()7820          inline T& ref()
7821          {
7822             return *(vds_.data() + index_);
7823          }
7824 
ref() const7825          inline const T& ref() const
7826          {
7827             return *(vds_.data() + index_);
7828          }
7829 
type() const7830          inline typename expression_node<T>::node_type type() const
7831          {
7832             return expression_node<T>::e_rbveccelem;
7833          }
7834 
vec_holder()7835          inline vector_holder_t& vec_holder()
7836          {
7837             return (*vector_holder_);
7838          }
7839 
7840       private:
7841 
7842          const std::size_t index_;
7843          vector_holder_ptr vector_holder_;
7844          vds_t vds_;
7845       };
7846 
7847       template <typename T>
7848       class vector_assignment_node : public expression_node<T>
7849       {
7850       public:
7851 
7852          typedef expression_node<T>* expression_ptr;
7853 
vector_assignment_node(T * vector_base,const std::size_t & size,const std::vector<expression_ptr> & initialiser_list,const bool single_value_initialse)7854          vector_assignment_node(T* vector_base,
7855                                 const std::size_t& size,
7856                                 const std::vector<expression_ptr>& initialiser_list,
7857                                 const bool single_value_initialse)
7858          : vector_base_(vector_base),
7859            initialiser_list_(initialiser_list),
7860            size_(size),
7861            single_value_initialse_(single_value_initialse)
7862          {}
7863 
value() const7864          inline T value() const
7865          {
7866             if (single_value_initialse_)
7867             {
7868                for (std::size_t i = 0; i < size_; ++i)
7869                {
7870                   *(vector_base_ + i) = initialiser_list_[0]->value();
7871                }
7872             }
7873             else
7874             {
7875                std::size_t il_size = initialiser_list_.size();
7876 
7877                for (std::size_t i = 0; i < il_size; ++i)
7878                {
7879                   *(vector_base_ + i) = initialiser_list_[i]->value();
7880                }
7881 
7882                if (il_size < size_)
7883                {
7884                   for (std::size_t i = il_size; i < size_; ++i)
7885                   {
7886                      *(vector_base_ + i) = T(0);
7887                   }
7888                }
7889             }
7890 
7891             return *(vector_base_);
7892          }
7893 
type() const7894          inline typename expression_node<T>::node_type type() const
7895          {
7896             return expression_node<T>::e_vecdefass;
7897          }
7898 
collect_nodes(typename expression_node<T>::noderef_list_t & node_delete_list)7899          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
7900          {
7901             expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list);
7902          }
7903 
node_depth() const7904          std::size_t node_depth() const
7905          {
7906             return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_);
7907          }
7908 
7909       private:
7910 
7911          vector_assignment_node<T>& operator=(const vector_assignment_node<T>&);
7912 
7913          mutable T* vector_base_;
7914          std::vector<expression_ptr> initialiser_list_;
7915          const std::size_t size_;
7916          const bool single_value_initialse_;
7917       };
7918 
7919       template <typename T>
7920       class swap_node : public expression_node<T>
7921       {
7922       public:
7923 
7924          typedef expression_node<T>* expression_ptr;
7925          typedef variable_node<T>*   variable_node_ptr;
7926 
swap_node(variable_node_ptr var0,variable_node_ptr var1)7927          swap_node(variable_node_ptr var0, variable_node_ptr var1)
7928          : var0_(var0),
7929            var1_(var1)
7930          {}
7931 
value() const7932          inline T value() const
7933          {
7934             std::swap(var0_->ref(),var1_->ref());
7935             return var1_->ref();
7936          }
7937 
type() const7938          inline typename expression_node<T>::node_type type() const
7939          {
7940             return expression_node<T>::e_swap;
7941          }
7942 
7943       private:
7944 
7945          variable_node_ptr var0_;
7946          variable_node_ptr var1_;
7947       };
7948 
7949       template <typename T>
7950       class swap_generic_node : public binary_node<T>
7951       {
7952       public:
7953 
7954          typedef expression_node<T>* expression_ptr;
7955          typedef ivariable<T>* ivariable_ptr;
7956 
swap_generic_node(expression_ptr var0,expression_ptr var1)7957          swap_generic_node(expression_ptr var0, expression_ptr var1)
7958          : binary_node<T>(details::e_swap, var0, var1),
7959            var0_(dynamic_cast<ivariable_ptr>(var0)),
7960            var1_(dynamic_cast<ivariable_ptr>(var1))
7961          {}
7962 
value() const7963          inline T value() const
7964          {
7965             std::swap(var0_->ref(),var1_->ref());
7966             return var1_->ref();
7967          }
7968 
type() const7969          inline typename expression_node<T>::node_type type() const
7970          {
7971             return expression_node<T>::e_swap;
7972          }
7973 
7974       private:
7975 
7976          ivariable_ptr var0_;
7977          ivariable_ptr var1_;
7978       };
7979 
7980       template <typename T>
7981       class swap_vecvec_node : public binary_node     <T>,
7982                                public vector_interface<T>
7983       {
7984       public:
7985 
7986          typedef expression_node<T>*  expression_ptr;
7987          typedef vector_node<T>*     vector_node_ptr;
7988          typedef vec_data_store<T>             vds_t;
7989 
swap_vecvec_node(expression_ptr branch0,expression_ptr branch1)7990          swap_vecvec_node(expression_ptr branch0,
7991                           expression_ptr branch1)
7992          : binary_node<T>(details::e_swap, branch0, branch1),
7993            vec0_node_ptr_(0),
7994            vec1_node_ptr_(0),
7995            vec_size_     (0),
7996            initialised_  (false)
7997          {
7998             if (is_ivector_node(binary_node<T>::branch_[0].first))
7999             {
8000                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
8001 
8002                if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
8003                {
8004                   vec0_node_ptr_ = vi->vec();
8005                   vds()          = vi->vds();
8006                }
8007             }
8008 
8009             if (is_ivector_node(binary_node<T>::branch_[1].first))
8010             {
8011                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
8012 
8013                if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
8014                {
8015                   vec1_node_ptr_ = vi->vec();
8016                }
8017             }
8018 
8019             if (vec0_node_ptr_ && vec1_node_ptr_)
8020             {
8021                vec_size_ = std::min(vec0_node_ptr_->vds().size(),
8022                                     vec1_node_ptr_->vds().size());
8023 
8024                initialised_ = true;
8025             }
8026          }
8027 
value() const8028          inline T value() const
8029          {
8030             assert(binary_node<T>::branch_[0].first);
8031             assert(binary_node<T>::branch_[1].first);
8032 
8033             if (initialised_)
8034             {
8035                binary_node<T>::branch_[0].first->value();
8036                binary_node<T>::branch_[1].first->value();
8037 
8038                T* vec0 = vec0_node_ptr_->vds().data();
8039                T* vec1 = vec1_node_ptr_->vds().data();
8040 
8041                for (std::size_t i = 0; i < vec_size_; ++i)
8042                {
8043                   std::swap(vec0[i],vec1[i]);
8044                }
8045 
8046                return vec1_node_ptr_->value();
8047             }
8048             else
8049                return std::numeric_limits<T>::quiet_NaN();
8050          }
8051 
vec() const8052          vector_node_ptr vec() const
8053          {
8054             return vec0_node_ptr_;
8055          }
8056 
vec()8057          vector_node_ptr vec()
8058          {
8059             return vec0_node_ptr_;
8060          }
8061 
type() const8062          inline typename expression_node<T>::node_type type() const
8063          {
8064             return expression_node<T>::e_vecvecswap;
8065          }
8066 
size() const8067          std::size_t size() const
8068          {
8069             return vec_size_;
8070          }
8071 
vds()8072          vds_t& vds()
8073          {
8074             return vds_;
8075          }
8076 
vds() const8077          const vds_t& vds() const
8078          {
8079             return vds_;
8080          }
8081 
8082       private:
8083 
8084          vector_node<T>* vec0_node_ptr_;
8085          vector_node<T>* vec1_node_ptr_;
8086          std::size_t     vec_size_;
8087          bool            initialised_;
8088          vds_t           vds_;
8089       };
8090 
8091       #ifndef exprtk_disable_string_capabilities
8092       template <typename T>
8093       class stringvar_node : public expression_node <T>,
8094                              public string_base_node<T>,
8095                              public range_interface <T>
8096       {
8097       public:
8098 
8099          typedef range_pack<T> range_t;
8100 
8101          static std::string null_value;
8102 
stringvar_node()8103          explicit stringvar_node()
8104          : value_(&null_value)
8105          {}
8106 
stringvar_node(std::string & v)8107          explicit stringvar_node(std::string& v)
8108          : value_(&v)
8109          {
8110             rp_.n0_c = std::make_pair<bool,std::size_t>(true,0);
8111             rp_.n1_c = std::make_pair<bool,std::size_t>(true,v.size() - 1);
8112             rp_.cache.first  = rp_.n0_c.second;
8113             rp_.cache.second = rp_.n1_c.second;
8114          }
8115 
operator <(const stringvar_node<T> & v) const8116          inline bool operator <(const stringvar_node<T>& v) const
8117          {
8118             return this < (&v);
8119          }
8120 
value() const8121          inline T value() const
8122          {
8123             rp_.n1_c.second  = (*value_).size() - 1;
8124             rp_.cache.second = rp_.n1_c.second;
8125 
8126             return std::numeric_limits<T>::quiet_NaN();
8127          }
8128 
str() const8129          std::string str() const
8130          {
8131             return ref();
8132          }
8133 
base() const8134          char_cptr base() const
8135          {
8136             return &(*value_)[0];
8137          }
8138 
size() const8139          std::size_t size() const
8140          {
8141             return ref().size();
8142          }
8143 
ref()8144          std::string& ref()
8145          {
8146             return (*value_);
8147          }
8148 
ref() const8149          const std::string& ref() const
8150          {
8151             return (*value_);
8152          }
8153 
range_ref()8154          range_t& range_ref()
8155          {
8156             return rp_;
8157          }
8158 
range_ref() const8159          const range_t& range_ref() const
8160          {
8161             return rp_;
8162          }
8163 
type() const8164          inline typename expression_node<T>::node_type type() const
8165          {
8166             return expression_node<T>::e_stringvar;
8167          }
8168 
8169       private:
8170 
8171          std::string* value_;
8172          mutable range_t rp_;
8173       };
8174 
8175       template <typename T>
8176       std::string stringvar_node<T>::null_value = std::string("");
8177 
8178       template <typename T>
8179       class string_range_node : public expression_node <T>,
8180                                 public string_base_node<T>,
8181                                 public range_interface <T>
8182       {
8183       public:
8184 
8185          typedef range_pack<T> range_t;
8186 
8187          static std::string null_value;
8188 
string_range_node(std::string & v,const range_t & rp)8189          explicit string_range_node(std::string& v, const range_t& rp)
8190          : value_(&v),
8191            rp_(rp)
8192          {}
8193 
~string_range_node()8194          virtual ~string_range_node()
8195          {
8196             rp_.free();
8197          }
8198 
operator <(const string_range_node<T> & v) const8199          inline bool operator <(const string_range_node<T>& v) const
8200          {
8201             return this < (&v);
8202          }
8203 
value() const8204          inline T value() const
8205          {
8206             return std::numeric_limits<T>::quiet_NaN();
8207          }
8208 
str() const8209          inline std::string str() const
8210          {
8211             return (*value_);
8212          }
8213 
base() const8214          char_cptr base() const
8215          {
8216             return &(*value_)[0];
8217          }
8218 
size() const8219          std::size_t size() const
8220          {
8221             return ref().size();
8222          }
8223 
range() const8224          inline range_t range() const
8225          {
8226             return rp_;
8227          }
8228 
ref()8229          inline virtual std::string& ref()
8230          {
8231             return (*value_);
8232          }
8233 
ref() const8234          inline virtual const std::string& ref() const
8235          {
8236             return (*value_);
8237          }
8238 
range_ref()8239          inline range_t& range_ref()
8240          {
8241             return rp_;
8242          }
8243 
range_ref() const8244          inline const range_t& range_ref() const
8245          {
8246             return rp_;
8247          }
8248 
type() const8249          inline typename expression_node<T>::node_type type() const
8250          {
8251             return expression_node<T>::e_stringvarrng;
8252          }
8253 
8254       private:
8255 
8256          std::string* value_;
8257          range_t      rp_;
8258       };
8259 
8260       template <typename T>
8261       std::string string_range_node<T>::null_value = std::string("");
8262 
8263       template <typename T>
8264       class const_string_range_node : public expression_node <T>,
8265                                       public string_base_node<T>,
8266                                       public range_interface <T>
8267       {
8268       public:
8269 
8270          typedef range_pack<T> range_t;
8271 
const_string_range_node(const std::string & v,const range_t & rp)8272          explicit const_string_range_node(const std::string& v, const range_t& rp)
8273          : value_(v),
8274            rp_(rp)
8275          {}
8276 
~const_string_range_node()8277         ~const_string_range_node()
8278          {
8279             rp_.free();
8280          }
8281 
value() const8282          inline T value() const
8283          {
8284             return std::numeric_limits<T>::quiet_NaN();
8285          }
8286 
str() const8287          std::string str() const
8288          {
8289             return value_;
8290          }
8291 
base() const8292          char_cptr base() const
8293          {
8294             return value_.data();
8295          }
8296 
size() const8297          std::size_t size() const
8298          {
8299             return value_.size();
8300          }
8301 
range() const8302          range_t range() const
8303          {
8304             return rp_;
8305          }
8306 
range_ref()8307          range_t& range_ref()
8308          {
8309             return rp_;
8310          }
8311 
range_ref() const8312          const range_t& range_ref() const
8313          {
8314             return rp_;
8315          }
8316 
type() const8317          inline typename expression_node<T>::node_type type() const
8318          {
8319             return expression_node<T>::e_cstringvarrng;
8320          }
8321 
8322       private:
8323 
8324          const_string_range_node<T>& operator=(const const_string_range_node<T>&);
8325 
8326          const std::string value_;
8327          range_t rp_;
8328       };
8329 
8330       template <typename T>
8331       class generic_string_range_node : public expression_node <T>,
8332                                         public string_base_node<T>,
8333                                         public range_interface <T>
8334       {
8335       public:
8336 
8337          typedef expression_node <T>*      expression_ptr;
8338          typedef stringvar_node  <T>*     strvar_node_ptr;
8339          typedef string_base_node<T>*        str_base_ptr;
8340          typedef range_pack      <T>              range_t;
8341          typedef range_t*                       range_ptr;
8342          typedef range_interface<T>              irange_t;
8343          typedef irange_t*                     irange_ptr;
8344          typedef std::pair<expression_ptr,bool>  branch_t;
8345 
8346 
generic_string_range_node(expression_ptr str_branch,const range_t & brange)8347          generic_string_range_node(expression_ptr str_branch, const range_t& brange)
8348          : initialised_(false),
8349            str_base_ptr_ (0),
8350            str_range_ptr_(0),
8351            base_range_(brange)
8352          {
8353             range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
8354             range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
8355             range_.cache.first  = range_.n0_c.second;
8356             range_.cache.second = range_.n1_c.second;
8357 
8358             construct_branch_pair(branch_, str_branch);
8359 
8360             if (is_generally_string_node(branch_.first))
8361             {
8362                str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_.first);
8363 
8364                if (0 == str_base_ptr_)
8365                   return;
8366 
8367                str_range_ptr_ = dynamic_cast<irange_ptr>(branch_.first);
8368 
8369                if (0 == str_range_ptr_)
8370                   return;
8371             }
8372 
8373             initialised_ = (str_base_ptr_ && str_range_ptr_);
8374          }
8375 
~generic_string_range_node()8376         ~generic_string_range_node()
8377          {
8378             base_range_.free();
8379          }
8380 
value() const8381          inline T value() const
8382          {
8383             if (initialised_)
8384             {
8385                assert(branch_.first);
8386 
8387                branch_.first->value();
8388 
8389                std::size_t str_r0 = 0;
8390                std::size_t str_r1 = 0;
8391 
8392                std::size_t r0 = 0;
8393                std::size_t r1 = 0;
8394 
8395                const range_t& range = str_range_ptr_->range_ref();
8396 
8397                const std::size_t base_str_size = str_base_ptr_->size();
8398 
8399                if (
8400                     range      (str_r0, str_r1, base_str_size) &&
8401                     base_range_(    r0,     r1, base_str_size)
8402                   )
8403                {
8404                   const std::size_t size = (r1 - r0) + 1;
8405 
8406                   range_.n1_c.second  = size - 1;
8407                   range_.cache.second = range_.n1_c.second;
8408 
8409                   value_.assign(str_base_ptr_->base() + str_r0 + r0, size);
8410                }
8411             }
8412 
8413             return std::numeric_limits<T>::quiet_NaN();
8414          }
8415 
str() const8416          std::string str() const
8417          {
8418             return value_;
8419          }
8420 
base() const8421          char_cptr base() const
8422          {
8423             return &value_[0];
8424          }
8425 
size() const8426          std::size_t size() const
8427          {
8428             return value_.size();
8429          }
8430 
range_ref()8431          range_t& range_ref()
8432          {
8433             return range_;
8434          }
8435 
range_ref() const8436          const range_t& range_ref() const
8437          {
8438             return range_;
8439          }
8440 
type() const8441          inline typename expression_node<T>::node_type type() const
8442          {
8443             return expression_node<T>::e_strgenrange;
8444          }
8445 
collect_nodes(typename expression_node<T>::noderef_list_t & node_delete_list)8446          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
8447          {
8448             expression_node<T>::ndb_t::collect(branch_, node_delete_list);
8449          }
8450 
node_depth() const8451          std::size_t node_depth() const
8452          {
8453             return expression_node<T>::ndb_t::compute_node_depth(branch_);
8454          }
8455 
8456       private:
8457 
8458          bool                initialised_;
8459          branch_t                 branch_;
8460          str_base_ptr       str_base_ptr_;
8461          irange_ptr        str_range_ptr_;
8462          mutable range_t      base_range_;
8463          mutable range_t           range_;
8464          mutable std::string       value_;
8465       };
8466 
8467       template <typename T>
8468       class string_concat_node : public binary_node     <T>,
8469                                  public string_base_node<T>,
8470                                  public range_interface <T>
8471       {
8472       public:
8473 
8474          typedef expression_node <T>*  expression_ptr;
8475          typedef string_base_node<T>*    str_base_ptr;
8476          typedef range_pack      <T>          range_t;
8477          typedef range_t*                   range_ptr;
8478          typedef range_interface<T>          irange_t;
8479          typedef irange_t*                 irange_ptr;
8480 
string_concat_node(const operator_type & opr,expression_ptr branch0,expression_ptr branch1)8481          string_concat_node(const operator_type& opr,
8482                             expression_ptr branch0,
8483                             expression_ptr branch1)
8484          : binary_node<T>(opr, branch0, branch1),
8485            initialised_(false),
8486            str0_base_ptr_ (0),
8487            str1_base_ptr_ (0),
8488            str0_range_ptr_(0),
8489            str1_range_ptr_(0)
8490          {
8491             range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
8492             range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
8493 
8494             range_.cache.first  = range_.n0_c.second;
8495             range_.cache.second = range_.n1_c.second;
8496 
8497             if (is_generally_string_node(binary_node<T>::branch_[0].first))
8498             {
8499                str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
8500 
8501                if (0 == str0_base_ptr_)
8502                   return;
8503 
8504                str0_range_ptr_ = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
8505 
8506                if (0 == str0_range_ptr_)
8507                   return;
8508             }
8509 
8510             if (is_generally_string_node(binary_node<T>::branch_[1].first))
8511             {
8512                str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
8513 
8514                if (0 == str1_base_ptr_)
8515                   return;
8516 
8517                str1_range_ptr_ = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
8518 
8519                if (0 == str1_range_ptr_)
8520                   return;
8521             }
8522 
8523             initialised_ = str0_base_ptr_  &&
8524                            str1_base_ptr_  &&
8525                            str0_range_ptr_ &&
8526                            str1_range_ptr_ ;
8527          }
8528 
value() const8529          inline T value() const
8530          {
8531             if (initialised_)
8532             {
8533                assert(binary_node<T>::branch_[0].first);
8534                assert(binary_node<T>::branch_[1].first);
8535 
8536                binary_node<T>::branch_[0].first->value();
8537                binary_node<T>::branch_[1].first->value();
8538 
8539                std::size_t str0_r0 = 0;
8540                std::size_t str0_r1 = 0;
8541 
8542                std::size_t str1_r0 = 0;
8543                std::size_t str1_r1 = 0;
8544 
8545                const range_t& range0 = str0_range_ptr_->range_ref();
8546                const range_t& range1 = str1_range_ptr_->range_ref();
8547 
8548                if (
8549                     range0(str0_r0, str0_r1, str0_base_ptr_->size()) &&
8550                     range1(str1_r0, str1_r1, str1_base_ptr_->size())
8551                   )
8552                {
8553                   const std::size_t size0 = (str0_r1 - str0_r0) + 1;
8554                   const std::size_t size1 = (str1_r1 - str1_r0) + 1;
8555 
8556                   value_.assign(str0_base_ptr_->base() + str0_r0, size0);
8557                   value_.append(str1_base_ptr_->base() + str1_r0, size1);
8558 
8559                   range_.n1_c.second  = value_.size() - 1;
8560                   range_.cache.second = range_.n1_c.second;
8561                }
8562             }
8563 
8564             return std::numeric_limits<T>::quiet_NaN();
8565          }
8566 
str() const8567          std::string str() const
8568          {
8569             return value_;
8570          }
8571 
base() const8572          char_cptr base() const
8573          {
8574             return &value_[0];
8575          }
8576 
size() const8577          std::size_t size() const
8578          {
8579             return value_.size();
8580          }
8581 
range_ref()8582          range_t& range_ref()
8583          {
8584             return range_;
8585          }
8586 
range_ref() const8587          const range_t& range_ref() const
8588          {
8589             return range_;
8590          }
8591 
type() const8592          inline typename expression_node<T>::node_type type() const
8593          {
8594             return expression_node<T>::e_strconcat;
8595          }
8596 
8597       private:
8598 
8599          bool initialised_;
8600          str_base_ptr str0_base_ptr_;
8601          str_base_ptr str1_base_ptr_;
8602          irange_ptr   str0_range_ptr_;
8603          irange_ptr   str1_range_ptr_;
8604          mutable range_t     range_;
8605          mutable std::string value_;
8606       };
8607 
8608       template <typename T>
8609       class swap_string_node : public binary_node     <T>,
8610                                public string_base_node<T>,
8611                                public range_interface <T>
8612       {
8613       public:
8614 
8615          typedef expression_node <T>*  expression_ptr;
8616          typedef stringvar_node  <T>* strvar_node_ptr;
8617          typedef string_base_node<T>*    str_base_ptr;
8618          typedef range_pack      <T>          range_t;
8619          typedef range_t*                   range_ptr;
8620          typedef range_interface<T>          irange_t;
8621          typedef irange_t*                 irange_ptr;
8622 
swap_string_node(expression_ptr branch0,expression_ptr branch1)8623          swap_string_node(expression_ptr branch0, expression_ptr branch1)
8624          : binary_node<T>(details::e_swap, branch0, branch1),
8625            initialised_(false),
8626            str0_node_ptr_(0),
8627            str1_node_ptr_(0)
8628          {
8629             if (is_string_node(binary_node<T>::branch_[0].first))
8630             {
8631                str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first);
8632             }
8633 
8634             if (is_string_node(binary_node<T>::branch_[1].first))
8635             {
8636                str1_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[1].first);
8637             }
8638 
8639             initialised_ = (str0_node_ptr_ && str1_node_ptr_);
8640          }
8641 
value() const8642          inline T value() const
8643          {
8644             if (initialised_)
8645             {
8646                assert(binary_node<T>::branch_[0].first);
8647                assert(binary_node<T>::branch_[1].first);
8648 
8649                binary_node<T>::branch_[0].first->value();
8650                binary_node<T>::branch_[1].first->value();
8651 
8652                std::swap(str0_node_ptr_->ref(), str1_node_ptr_->ref());
8653             }
8654 
8655             return std::numeric_limits<T>::quiet_NaN();
8656          }
8657 
str() const8658          std::string str() const
8659          {
8660             return str0_node_ptr_->str();
8661          }
8662 
base() const8663          char_cptr base() const
8664          {
8665            return str0_node_ptr_->base();
8666          }
8667 
size() const8668          std::size_t size() const
8669          {
8670             return str0_node_ptr_->size();
8671          }
8672 
range_ref()8673          range_t& range_ref()
8674          {
8675             return str0_node_ptr_->range_ref();
8676          }
8677 
range_ref() const8678          const range_t& range_ref() const
8679          {
8680             return str0_node_ptr_->range_ref();
8681          }
8682 
type() const8683          inline typename expression_node<T>::node_type type() const
8684          {
8685             return expression_node<T>::e_strswap;
8686          }
8687 
8688       private:
8689 
8690          bool initialised_;
8691          strvar_node_ptr str0_node_ptr_;
8692          strvar_node_ptr str1_node_ptr_;
8693       };
8694 
8695       template <typename T>
8696       class swap_genstrings_node : public binary_node<T>
8697       {
8698       public:
8699 
8700          typedef expression_node <T>* expression_ptr;
8701          typedef string_base_node<T>*   str_base_ptr;
8702          typedef range_pack      <T>         range_t;
8703          typedef range_t*                  range_ptr;
8704          typedef range_interface<T>         irange_t;
8705          typedef irange_t*                irange_ptr;
8706 
swap_genstrings_node(expression_ptr branch0,expression_ptr branch1)8707          swap_genstrings_node(expression_ptr branch0,
8708                               expression_ptr branch1)
8709          : binary_node<T>(details::e_default, branch0, branch1),
8710            str0_base_ptr_ (0),
8711            str1_base_ptr_ (0),
8712            str0_range_ptr_(0),
8713            str1_range_ptr_(0),
8714            initialised_(false)
8715          {
8716             if (is_generally_string_node(binary_node<T>::branch_[0].first))
8717             {
8718                str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
8719 
8720                if (0 == str0_base_ptr_)
8721                   return;
8722 
8723                irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
8724 
8725                if (0 == range)
8726                   return;
8727 
8728                str0_range_ptr_ = &(range->range_ref());
8729             }
8730 
8731             if (is_generally_string_node(binary_node<T>::branch_[1].first))
8732             {
8733                str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
8734 
8735                if (0 == str1_base_ptr_)
8736                   return;
8737 
8738                irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
8739 
8740                if (0 == range)
8741                   return;
8742 
8743                str1_range_ptr_ = &(range->range_ref());
8744             }
8745 
8746             initialised_ = str0_base_ptr_  &&
8747                            str1_base_ptr_  &&
8748                            str0_range_ptr_ &&
8749                            str1_range_ptr_ ;
8750          }
8751 
value() const8752          inline T value() const
8753          {
8754             if (initialised_)
8755             {
8756                assert(binary_node<T>::branch_[0].first);
8757                assert(binary_node<T>::branch_[1].first);
8758 
8759                binary_node<T>::branch_[0].first->value();
8760                binary_node<T>::branch_[1].first->value();
8761 
8762                std::size_t str0_r0 = 0;
8763                std::size_t str0_r1 = 0;
8764 
8765                std::size_t str1_r0 = 0;
8766                std::size_t str1_r1 = 0;
8767 
8768                const range_t& range0 = (*str0_range_ptr_);
8769                const range_t& range1 = (*str1_range_ptr_);
8770 
8771                if (
8772                     range0(str0_r0, str0_r1, str0_base_ptr_->size()) &&
8773                     range1(str1_r0, str1_r1, str1_base_ptr_->size())
8774                   )
8775                {
8776                   const std::size_t size0    = range0.cache_size();
8777                   const std::size_t size1    = range1.cache_size();
8778                   const std::size_t max_size = std::min(size0,size1);
8779 
8780                   char_ptr s0 = const_cast<char_ptr>(str0_base_ptr_->base() + str0_r0);
8781                   char_ptr s1 = const_cast<char_ptr>(str1_base_ptr_->base() + str1_r0);
8782 
8783                   loop_unroll::details lud(max_size);
8784                   char_cptr upper_bound = s0 + lud.upper_bound;
8785 
8786                   while (s0 < upper_bound)
8787                   {
8788                      #define exprtk_loop(N)   \
8789                      std::swap(s0[N], s1[N]); \
8790 
8791                      exprtk_loop( 0) exprtk_loop( 1)
8792                      exprtk_loop( 2) exprtk_loop( 3)
8793                      #ifndef exprtk_disable_superscalar_unroll
8794                      exprtk_loop( 4) exprtk_loop( 5)
8795                      exprtk_loop( 6) exprtk_loop( 7)
8796                      exprtk_loop( 8) exprtk_loop( 9)
8797                      exprtk_loop(10) exprtk_loop(11)
8798                      exprtk_loop(12) exprtk_loop(13)
8799                      exprtk_loop(14) exprtk_loop(15)
8800                      #endif
8801 
8802                      s0 += lud.batch_size;
8803                      s1 += lud.batch_size;
8804                   }
8805 
8806                   int i = 0;
8807 
8808                   exprtk_disable_fallthrough_begin
8809                   switch (lud.remainder)
8810                   {
8811                      #define case_stmt(N)                       \
8812                      case N : { std::swap(s0[i], s1[i]); ++i; } \
8813 
8814                      #ifndef exprtk_disable_superscalar_unroll
8815                      case_stmt(15) case_stmt(14)
8816                      case_stmt(13) case_stmt(12)
8817                      case_stmt(11) case_stmt(10)
8818                      case_stmt( 9) case_stmt( 8)
8819                      case_stmt( 7) case_stmt( 6)
8820                      case_stmt( 5) case_stmt( 4)
8821                      #endif
8822                      case_stmt( 3) case_stmt( 2)
8823                      case_stmt( 1)
8824                   }
8825                   exprtk_disable_fallthrough_end
8826 
8827                   #undef exprtk_loop
8828                   #undef case_stmt
8829                }
8830             }
8831 
8832             return std::numeric_limits<T>::quiet_NaN();
8833          }
8834 
type() const8835          inline typename expression_node<T>::node_type type() const
8836          {
8837             return expression_node<T>::e_strswap;
8838          }
8839 
8840       private:
8841 
8842          swap_genstrings_node(swap_genstrings_node<T>&);
8843          swap_genstrings_node<T>& operator=(swap_genstrings_node<T>&);
8844 
8845          str_base_ptr str0_base_ptr_;
8846          str_base_ptr str1_base_ptr_;
8847          range_ptr    str0_range_ptr_;
8848          range_ptr    str1_range_ptr_;
8849          bool         initialised_;
8850       };
8851 
8852       template <typename T>
8853       class stringvar_size_node : public expression_node<T>
8854       {
8855       public:
8856 
8857          static std::string null_value;
8858 
stringvar_size_node()8859          explicit stringvar_size_node()
8860          : value_(&null_value)
8861          {}
8862 
stringvar_size_node(std::string & v)8863          explicit stringvar_size_node(std::string& v)
8864          : value_(&v)
8865          {}
8866 
value() const8867          inline T value() const
8868          {
8869             return T((*value_).size());
8870          }
8871 
type() const8872          inline typename expression_node<T>::node_type type() const
8873          {
8874             return expression_node<T>::e_stringvarsize;
8875          }
8876 
8877       private:
8878 
8879          std::string* value_;
8880       };
8881 
8882       template <typename T>
8883       std::string stringvar_size_node<T>::null_value = std::string("");
8884 
8885       template <typename T>
8886       class string_size_node : public expression_node<T>
8887       {
8888       public:
8889 
8890          typedef expression_node <T>*      expression_ptr;
8891          typedef string_base_node<T>*        str_base_ptr;
8892          typedef std::pair<expression_ptr,bool>  branch_t;
8893 
8894 
string_size_node(expression_ptr branch)8895          explicit string_size_node(expression_ptr branch)
8896          : str_base_ptr_(0)
8897          {
8898             construct_branch_pair(branch_, branch);
8899 
8900             if (is_generally_string_node(branch_.first))
8901             {
8902                str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_.first);
8903 
8904                if (0 == str_base_ptr_)
8905                   return;
8906             }
8907          }
8908 
value() const8909          inline T value() const
8910          {
8911             T result = std::numeric_limits<T>::quiet_NaN();
8912 
8913             if (str_base_ptr_)
8914             {
8915                branch_.first->value();
8916                result = T(str_base_ptr_->size());
8917             }
8918 
8919             return result;
8920          }
8921 
type() const8922          inline typename expression_node<T>::node_type type() const
8923          {
8924             return expression_node<T>::e_stringsize;
8925          }
8926 
collect_nodes(typename expression_node<T>::noderef_list_t & node_delete_list)8927          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
8928          {
8929             expression_node<T>::ndb_t::collect(branch_, node_delete_list);
8930          }
8931 
node_depth() const8932          std::size_t node_depth() const
8933          {
8934             return expression_node<T>::ndb_t::compute_node_depth(branch_);
8935          }
8936 
8937       private:
8938 
8939          branch_t           branch_;
8940          str_base_ptr str_base_ptr_;
8941       };
8942 
8943       struct asn_assignment
8944       {
executeexprtk::details::asn_assignment8945          static inline void execute(std::string& s, char_cptr data, const std::size_t size)
8946          { s.assign(data,size); }
8947       };
8948 
8949       struct asn_addassignment
8950       {
executeexprtk::details::asn_addassignment8951          static inline void execute(std::string& s, char_cptr data, const std::size_t size)
8952          { s.append(data,size); }
8953       };
8954 
8955       template <typename T, typename AssignmentProcess = asn_assignment>
8956       class assignment_string_node : public binary_node     <T>,
8957                                      public string_base_node<T>,
8958                                      public range_interface <T>
8959       {
8960       public:
8961 
8962          typedef expression_node <T>*  expression_ptr;
8963          typedef stringvar_node  <T>* strvar_node_ptr;
8964          typedef string_base_node<T>*    str_base_ptr;
8965          typedef range_pack      <T>          range_t;
8966          typedef range_t*                   range_ptr;
8967          typedef range_interface<T>          irange_t;
8968          typedef irange_t*                 irange_ptr;
8969 
assignment_string_node(const operator_type & opr,expression_ptr branch0,expression_ptr branch1)8970          assignment_string_node(const operator_type& opr,
8971                                 expression_ptr branch0,
8972                                 expression_ptr branch1)
8973          : binary_node<T>(opr, branch0, branch1),
8974            initialised_(false),
8975            str0_base_ptr_ (0),
8976            str1_base_ptr_ (0),
8977            str0_node_ptr_ (0),
8978            str1_range_ptr_(0)
8979          {
8980             if (is_string_node(binary_node<T>::branch_[0].first))
8981             {
8982                str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first);
8983 
8984                str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
8985             }
8986 
8987             if (is_generally_string_node(binary_node<T>::branch_[1].first))
8988             {
8989                str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
8990 
8991                if (0 == str1_base_ptr_)
8992                   return;
8993 
8994                irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
8995 
8996                if (0 == range)
8997                   return;
8998 
8999                str1_range_ptr_ = &(range->range_ref());
9000             }
9001 
9002             initialised_ = str0_base_ptr_  &&
9003                            str1_base_ptr_  &&
9004                            str0_node_ptr_  &&
9005                            str1_range_ptr_ ;
9006          }
9007 
value() const9008          inline T value() const
9009          {
9010             if (initialised_)
9011             {
9012                assert(binary_node<T>::branch_[0].first);
9013                assert(binary_node<T>::branch_[1].first);
9014 
9015                binary_node<T>::branch_[1].first->value();
9016 
9017                std::size_t r0 = 0;
9018                std::size_t r1 = 0;
9019 
9020                const range_t& range = (*str1_range_ptr_);
9021 
9022                if (range(r0, r1, str1_base_ptr_->size()))
9023                {
9024                   AssignmentProcess::execute(str0_node_ptr_->ref(),
9025                                              str1_base_ptr_->base() + r0,
9026                                              (r1 - r0) + 1);
9027 
9028                   binary_node<T>::branch_[0].first->value();
9029                }
9030             }
9031 
9032             return std::numeric_limits<T>::quiet_NaN();
9033          }
9034 
str() const9035          std::string str() const
9036          {
9037             return str0_node_ptr_->str();
9038          }
9039 
base() const9040          char_cptr base() const
9041          {
9042            return str0_node_ptr_->base();
9043          }
9044 
size() const9045          std::size_t size() const
9046          {
9047             return str0_node_ptr_->size();
9048          }
9049 
range_ref()9050          range_t& range_ref()
9051          {
9052             return str0_node_ptr_->range_ref();
9053          }
9054 
range_ref() const9055          const range_t& range_ref() const
9056          {
9057             return str0_node_ptr_->range_ref();
9058          }
9059 
type() const9060          inline typename expression_node<T>::node_type type() const
9061          {
9062             return expression_node<T>::e_strass;
9063          }
9064 
9065       private:
9066 
9067          bool            initialised_;
9068          str_base_ptr    str0_base_ptr_;
9069          str_base_ptr    str1_base_ptr_;
9070          strvar_node_ptr str0_node_ptr_;
9071          range_ptr       str1_range_ptr_;
9072       };
9073 
9074       template <typename T, typename AssignmentProcess = asn_assignment>
9075       class assignment_string_range_node : public binary_node     <T>,
9076                                            public string_base_node<T>,
9077                                            public range_interface <T>
9078       {
9079       public:
9080 
9081          typedef expression_node  <T>*   expression_ptr;
9082          typedef stringvar_node   <T>*  strvar_node_ptr;
9083          typedef string_range_node<T>* str_rng_node_ptr;
9084          typedef string_base_node <T>*     str_base_ptr;
9085          typedef range_pack       <T>           range_t;
9086          typedef range_t*                     range_ptr;
9087          typedef range_interface<T>            irange_t;
9088          typedef irange_t*                   irange_ptr;
9089 
assignment_string_range_node(const operator_type & opr,expression_ptr branch0,expression_ptr branch1)9090          assignment_string_range_node(const operator_type& opr,
9091                                       expression_ptr branch0,
9092                                       expression_ptr branch1)
9093          : binary_node<T>(opr, branch0, branch1),
9094            initialised_(false),
9095            str0_base_ptr_     (0),
9096            str1_base_ptr_     (0),
9097            str0_rng_node_ptr_ (0),
9098            str0_range_ptr_    (0),
9099            str1_range_ptr_    (0)
9100          {
9101             if (is_string_range_node(binary_node<T>::branch_[0].first))
9102             {
9103                str0_rng_node_ptr_ = static_cast<str_rng_node_ptr>(binary_node<T>::branch_[0].first);
9104 
9105                str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
9106 
9107                irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
9108 
9109                if (0 == range)
9110                   return;
9111 
9112                str0_range_ptr_ = &(range->range_ref());
9113             }
9114 
9115             if (is_generally_string_node(binary_node<T>::branch_[1].first))
9116             {
9117                str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
9118 
9119                if (0 == str1_base_ptr_)
9120                   return;
9121 
9122                irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
9123 
9124                if (0 == range)
9125                   return;
9126 
9127                str1_range_ptr_ = &(range->range_ref());
9128             }
9129 
9130             initialised_ = str0_base_ptr_     &&
9131                            str1_base_ptr_     &&
9132                            str0_rng_node_ptr_ &&
9133                            str0_range_ptr_    &&
9134                            str1_range_ptr_    ;
9135          }
9136 
value() const9137          inline T value() const
9138          {
9139             if (initialised_)
9140             {
9141                assert(binary_node<T>::branch_[0].first);
9142                assert(binary_node<T>::branch_[1].first);
9143 
9144                binary_node<T>::branch_[0].first->value();
9145                binary_node<T>::branch_[1].first->value();
9146 
9147                std::size_t s0_r0 = 0;
9148                std::size_t s0_r1 = 0;
9149 
9150                std::size_t s1_r0 = 0;
9151                std::size_t s1_r1 = 0;
9152 
9153                const range_t& range0 = (*str0_range_ptr_);
9154                const range_t& range1 = (*str1_range_ptr_);
9155 
9156                if (
9157                     range0(s0_r0, s0_r1, str0_base_ptr_->size()) &&
9158                     range1(s1_r0, s1_r1, str1_base_ptr_->size())
9159                   )
9160                {
9161                   const std::size_t size = std::min((s0_r1 - s0_r0), (s1_r1 - s1_r0)) + 1;
9162 
9163                   std::copy(str1_base_ptr_->base() + s1_r0,
9164                             str1_base_ptr_->base() + s1_r0 + size,
9165                             const_cast<char_ptr>(base() + s0_r0));
9166                }
9167             }
9168 
9169             return std::numeric_limits<T>::quiet_NaN();
9170          }
9171 
str() const9172          std::string str() const
9173          {
9174             return str0_base_ptr_->str();
9175          }
9176 
base() const9177          char_cptr base() const
9178          {
9179             return str0_base_ptr_->base();
9180          }
9181 
size() const9182          std::size_t size() const
9183          {
9184             return str0_base_ptr_->size();
9185          }
9186 
range_ref()9187          range_t& range_ref()
9188          {
9189             return str0_rng_node_ptr_->range_ref();
9190          }
9191 
range_ref() const9192          const range_t& range_ref() const
9193          {
9194             return str0_rng_node_ptr_->range_ref();
9195          }
9196 
type() const9197          inline typename expression_node<T>::node_type type() const
9198          {
9199             return expression_node<T>::e_strass;
9200          }
9201 
9202       private:
9203 
9204          bool             initialised_;
9205          str_base_ptr     str0_base_ptr_;
9206          str_base_ptr     str1_base_ptr_;
9207          str_rng_node_ptr str0_rng_node_ptr_;
9208          range_ptr        str0_range_ptr_;
9209          range_ptr        str1_range_ptr_;
9210       };
9211 
9212       template <typename T>
9213       class conditional_string_node : public trinary_node    <T>,
9214                                       public string_base_node<T>,
9215                                       public range_interface <T>
9216       {
9217       public:
9218 
9219          typedef expression_node <T>* expression_ptr;
9220          typedef string_base_node<T>*   str_base_ptr;
9221          typedef range_pack      <T>         range_t;
9222          typedef range_t*                  range_ptr;
9223          typedef range_interface<T>         irange_t;
9224          typedef irange_t*                irange_ptr;
9225 
conditional_string_node(expression_ptr condition,expression_ptr consequent,expression_ptr alternative)9226          conditional_string_node(expression_ptr condition,
9227                                  expression_ptr consequent,
9228                                  expression_ptr alternative)
9229          : trinary_node<T>(details::e_default,consequent,alternative,condition),
9230            initialised_(false),
9231            str0_base_ptr_ (0),
9232            str1_base_ptr_ (0),
9233            str0_range_ptr_(0),
9234            str1_range_ptr_(0),
9235            condition_    (condition),
9236            consequent_  (consequent),
9237            alternative_(alternative)
9238          {
9239             range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
9240             range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
9241 
9242             range_.cache.first  = range_.n0_c.second;
9243             range_.cache.second = range_.n1_c.second;
9244 
9245             if (is_generally_string_node(trinary_node<T>::branch_[0].first))
9246             {
9247                str0_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[0].first);
9248 
9249                if (0 == str0_base_ptr_)
9250                   return;
9251 
9252                str0_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[0].first);
9253 
9254                if (0 == str0_range_ptr_)
9255                   return;
9256             }
9257 
9258             if (is_generally_string_node(trinary_node<T>::branch_[1].first))
9259             {
9260                str1_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[1].first);
9261 
9262                if (0 == str1_base_ptr_)
9263                   return;
9264 
9265                str1_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[1].first);
9266 
9267                if (0 == str1_range_ptr_)
9268                   return;
9269             }
9270 
9271             initialised_ = str0_base_ptr_  &&
9272                            str1_base_ptr_  &&
9273                            str0_range_ptr_ &&
9274                            str1_range_ptr_ ;
9275 
9276          }
9277 
value() const9278          inline T value() const
9279          {
9280             if (initialised_)
9281             {
9282                assert(condition_  );
9283                assert(consequent_ );
9284                assert(alternative_);
9285 
9286                std::size_t r0 = 0;
9287                std::size_t r1 = 0;
9288 
9289                if (is_true(condition_))
9290                {
9291                   consequent_->value();
9292 
9293                   const range_t& range = str0_range_ptr_->range_ref();
9294 
9295                   if (range(r0, r1, str0_base_ptr_->size()))
9296                   {
9297                      const std::size_t size = (r1 - r0) + 1;
9298 
9299                      value_.assign(str0_base_ptr_->base() + r0, size);
9300 
9301                      range_.n1_c.second  = value_.size() - 1;
9302                      range_.cache.second = range_.n1_c.second;
9303 
9304                      return T(1);
9305                   }
9306                }
9307                else
9308                {
9309                   alternative_->value();
9310 
9311                   const range_t& range = str1_range_ptr_->range_ref();
9312 
9313                   if (range(r0, r1, str1_base_ptr_->size()))
9314                   {
9315                      const std::size_t size = (r1 - r0) + 1;
9316 
9317                      value_.assign(str1_base_ptr_->base() + r0, size);
9318 
9319                      range_.n1_c.second  = value_.size() - 1;
9320                      range_.cache.second = range_.n1_c.second;
9321 
9322                      return T(0);
9323                   }
9324                }
9325             }
9326 
9327             return std::numeric_limits<T>::quiet_NaN();
9328          }
9329 
str() const9330          std::string str() const
9331          {
9332             return value_;
9333          }
9334 
base() const9335          char_cptr base() const
9336          {
9337             return &value_[0];
9338          }
9339 
size() const9340          std::size_t size() const
9341          {
9342             return value_.size();
9343          }
9344 
range_ref()9345          range_t& range_ref()
9346          {
9347             return range_;
9348          }
9349 
range_ref() const9350          const range_t& range_ref() const
9351          {
9352             return range_;
9353          }
9354 
type() const9355          inline typename expression_node<T>::node_type type() const
9356          {
9357             return expression_node<T>::e_strcondition;
9358          }
9359 
9360       private:
9361 
9362          bool initialised_;
9363          str_base_ptr str0_base_ptr_;
9364          str_base_ptr str1_base_ptr_;
9365          irange_ptr   str0_range_ptr_;
9366          irange_ptr   str1_range_ptr_;
9367          mutable range_t     range_;
9368          mutable std::string value_;
9369 
9370          expression_ptr condition_;
9371          expression_ptr consequent_;
9372          expression_ptr alternative_;
9373       };
9374 
9375       template <typename T>
9376       class cons_conditional_str_node : public binary_node     <T>,
9377                                         public string_base_node<T>,
9378                                         public range_interface <T>
9379       {
9380       public:
9381 
9382          typedef expression_node <T>* expression_ptr;
9383          typedef string_base_node<T>*   str_base_ptr;
9384          typedef range_pack      <T>         range_t;
9385          typedef range_t*                  range_ptr;
9386          typedef range_interface<T>         irange_t;
9387          typedef irange_t*                irange_ptr;
9388 
cons_conditional_str_node(expression_ptr condition,expression_ptr consequent)9389          cons_conditional_str_node(expression_ptr condition,
9390                                    expression_ptr consequent)
9391          : binary_node<T>(details::e_default, consequent, condition),
9392            initialised_(false),
9393            str0_base_ptr_ (0),
9394            str0_range_ptr_(0),
9395            condition_ (condition),
9396            consequent_(consequent)
9397          {
9398             range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
9399             range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
9400 
9401             range_.cache.first  = range_.n0_c.second;
9402             range_.cache.second = range_.n1_c.second;
9403 
9404             if (is_generally_string_node(binary_node<T>::branch_[0].first))
9405             {
9406                str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
9407 
9408                if (0 == str0_base_ptr_)
9409                   return;
9410 
9411                str0_range_ptr_ = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
9412 
9413                if (0 == str0_range_ptr_)
9414                   return;
9415             }
9416 
9417             initialised_ = str0_base_ptr_ && str0_range_ptr_ ;
9418          }
9419 
value() const9420          inline T value() const
9421          {
9422             if (initialised_)
9423             {
9424                assert(condition_ );
9425                assert(consequent_);
9426 
9427                if (is_true(condition_))
9428                {
9429                   consequent_->value();
9430 
9431                   const range_t& range = str0_range_ptr_->range_ref();
9432 
9433                   std::size_t r0 = 0;
9434                   std::size_t r1 = 0;
9435 
9436                   if (range(r0, r1, str0_base_ptr_->size()))
9437                   {
9438                      const std::size_t size = (r1 - r0) + 1;
9439 
9440                      value_.assign(str0_base_ptr_->base() + r0, size);
9441 
9442                      range_.n1_c.second  = value_.size() - 1;
9443                      range_.cache.second = range_.n1_c.second;
9444 
9445                      return T(1);
9446                   }
9447                }
9448             }
9449 
9450             return std::numeric_limits<T>::quiet_NaN();
9451          }
9452 
str() const9453          std::string str() const
9454          {
9455             return value_;
9456          }
9457 
base() const9458          char_cptr base() const
9459          {
9460             return &value_[0];
9461          }
9462 
size() const9463          std::size_t size() const
9464          {
9465             return value_.size();
9466          }
9467 
range_ref()9468          range_t& range_ref()
9469          {
9470             return range_;
9471          }
9472 
range_ref() const9473          const range_t& range_ref() const
9474          {
9475             return range_;
9476          }
9477 
type() const9478          inline typename expression_node<T>::node_type type() const
9479          {
9480             return expression_node<T>::e_strccondition;
9481          }
9482 
9483       private:
9484 
9485          bool initialised_;
9486          str_base_ptr str0_base_ptr_;
9487          irange_ptr   str0_range_ptr_;
9488          mutable range_t     range_;
9489          mutable std::string value_;
9490 
9491          expression_ptr condition_;
9492          expression_ptr consequent_;
9493       };
9494 
9495       template <typename T, typename VarArgFunction>
9496       class str_vararg_node  : public expression_node <T>,
9497                                public string_base_node<T>,
9498                                public range_interface <T>
9499       {
9500       public:
9501 
9502          typedef expression_node <T>*     expression_ptr;
9503          typedef string_base_node<T>*       str_base_ptr;
9504          typedef range_pack      <T>             range_t;
9505          typedef range_t*                      range_ptr;
9506          typedef range_interface<T>             irange_t;
9507          typedef irange_t*                    irange_ptr;
9508          typedef std::pair<expression_ptr,bool> branch_t;
9509 
9510          template <typename Allocator,
9511                    template <typename, typename> class Sequence>
str_vararg_node(const Sequence<expression_ptr,Allocator> & arg_list)9512          explicit str_vararg_node(const Sequence<expression_ptr,Allocator>& arg_list)
9513          : initialised_(false),
9514            str_base_ptr_ (0),
9515            str_range_ptr_(0)
9516          {
9517             construct_branch_pair(final_node_, const_cast<expression_ptr>(arg_list.back()));
9518 
9519             if (0 == final_node_.first)
9520                return;
9521             else if (!is_generally_string_node(final_node_.first))
9522                return;
9523 
9524             str_base_ptr_ = dynamic_cast<str_base_ptr>(final_node_.first);
9525 
9526             if (0 == str_base_ptr_)
9527                return;
9528 
9529             str_range_ptr_ = dynamic_cast<irange_ptr>(final_node_.first);
9530 
9531             if (0 == str_range_ptr_)
9532                return;
9533 
9534             initialised_ = str_base_ptr_  && str_range_ptr_;
9535 
9536             if (arg_list.size() > 1)
9537             {
9538                const std::size_t arg_list_size = arg_list.size() - 1;
9539 
9540                arg_list_.resize(arg_list_size);
9541 
9542                for (std::size_t i = 0; i < arg_list_size; ++i)
9543                {
9544                   if (arg_list[i])
9545                   {
9546                      construct_branch_pair(arg_list_[i], arg_list[i]);
9547                   }
9548                   else
9549                   {
9550                      arg_list_.clear();
9551                      return;
9552                   }
9553                }
9554             }
9555          }
9556 
value() const9557          inline T value() const
9558          {
9559             if (!arg_list_.empty())
9560             {
9561                VarArgFunction::process(arg_list_);
9562             }
9563 
9564             final_node_.first->value();
9565 
9566             return std::numeric_limits<T>::quiet_NaN();
9567          }
9568 
str() const9569          std::string str() const
9570          {
9571             return str_base_ptr_->str();
9572          }
9573 
base() const9574          char_cptr base() const
9575          {
9576             return str_base_ptr_->base();
9577          }
9578 
size() const9579          std::size_t size() const
9580          {
9581             return str_base_ptr_->size();
9582          }
9583 
range_ref()9584          range_t& range_ref()
9585          {
9586             return str_range_ptr_->range_ref();
9587          }
9588 
range_ref() const9589          const range_t& range_ref() const
9590          {
9591             return str_range_ptr_->range_ref();
9592          }
9593 
type() const9594          inline typename expression_node<T>::node_type type() const
9595          {
9596             return expression_node<T>::e_stringvararg;
9597          }
9598 
collect_nodes(typename expression_node<T>::noderef_list_t & node_delete_list)9599          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
9600          {
9601             expression_node<T>::ndb_t::collect(final_node_, node_delete_list);
9602             expression_node<T>::ndb_t::collect(arg_list_  , node_delete_list);
9603          }
9604 
node_depth() const9605          std::size_t node_depth() const
9606          {
9607             return std::max(
9608                expression_node<T>::ndb_t::compute_node_depth(final_node_),
9609                expression_node<T>::ndb_t::compute_node_depth(arg_list_  ));
9610          }
9611 
9612       private:
9613 
9614          bool                  initialised_;
9615          branch_t              final_node_;
9616          str_base_ptr          str_base_ptr_;
9617          irange_ptr            str_range_ptr_;
9618          std::vector<branch_t> arg_list_;
9619       };
9620       #endif
9621 
9622       template <typename T, std::size_t N>
axn(T a,T x)9623       inline T axn(T a, T x)
9624       {
9625          // a*x^n
9626          return a * exprtk::details::numeric::fast_exp<T,N>::result(x);
9627       }
9628 
9629       template <typename T, std::size_t N>
axnb(T a,T x,T b)9630       inline T axnb(T a, T x, T b)
9631       {
9632          // a*x^n+b
9633          return a * exprtk::details::numeric::fast_exp<T,N>::result(x) + b;
9634       }
9635 
9636       template <typename T>
9637       struct sf_base
9638       {
9639          typedef typename details::functor_t<T>::Type Type;
9640          typedef typename details::functor_t<T> functor_t;
9641          typedef typename functor_t::qfunc_t quaternary_functor_t;
9642          typedef typename functor_t::tfunc_t    trinary_functor_t;
9643          typedef typename functor_t::bfunc_t     binary_functor_t;
9644          typedef typename functor_t::ufunc_t      unary_functor_t;
9645       };
9646 
9647       #define define_sfop3(NN,OP0,OP1)                   \
9648       template <typename T>                              \
9649       struct sf##NN##_op : public sf_base<T>             \
9650       {                                                  \
9651          typedef typename sf_base<T>::Type const Type;   \
9652          static inline T process(Type x, Type y, Type z) \
9653          {                                               \
9654             return (OP0);                                \
9655          }                                               \
9656          static inline std::string id()                  \
9657          {                                               \
9658             return (OP1);                                \
9659          }                                               \
9660       };                                                 \
9661 
9662       define_sfop3(00,(x + y) / z       ,"(t+t)/t")
9663       define_sfop3(01,(x + y) * z       ,"(t+t)*t")
9664       define_sfop3(02,(x + y) - z       ,"(t+t)-t")
9665       define_sfop3(03,(x + y) + z       ,"(t+t)+t")
9666       define_sfop3(04,(x - y) + z       ,"(t-t)+t")
9667       define_sfop3(05,(x - y) / z       ,"(t-t)/t")
9668       define_sfop3(06,(x - y) * z       ,"(t-t)*t")
9669       define_sfop3(07,(x * y) + z       ,"(t*t)+t")
9670       define_sfop3(08,(x * y) - z       ,"(t*t)-t")
9671       define_sfop3(09,(x * y) / z       ,"(t*t)/t")
9672       define_sfop3(10,(x * y) * z       ,"(t*t)*t")
9673       define_sfop3(11,(x / y) + z       ,"(t/t)+t")
9674       define_sfop3(12,(x / y) - z       ,"(t/t)-t")
9675       define_sfop3(13,(x / y) / z       ,"(t/t)/t")
9676       define_sfop3(14,(x / y) * z       ,"(t/t)*t")
9677       define_sfop3(15,x / (y + z)       ,"t/(t+t)")
9678       define_sfop3(16,x / (y - z)       ,"t/(t-t)")
9679       define_sfop3(17,x / (y * z)       ,"t/(t*t)")
9680       define_sfop3(18,x / (y / z)       ,"t/(t/t)")
9681       define_sfop3(19,x * (y + z)       ,"t*(t+t)")
9682       define_sfop3(20,x * (y - z)       ,"t*(t-t)")
9683       define_sfop3(21,x * (y * z)       ,"t*(t*t)")
9684       define_sfop3(22,x * (y / z)       ,"t*(t/t)")
9685       define_sfop3(23,x - (y + z)       ,"t-(t+t)")
9686       define_sfop3(24,x - (y - z)       ,"t-(t-t)")
9687       define_sfop3(25,x - (y / z)       ,"t-(t/t)")
9688       define_sfop3(26,x - (y * z)       ,"t-(t*t)")
9689       define_sfop3(27,x + (y * z)       ,"t+(t*t)")
9690       define_sfop3(28,x + (y / z)       ,"t+(t/t)")
9691       define_sfop3(29,x + (y + z)       ,"t+(t+t)")
9692       define_sfop3(30,x + (y - z)       ,"t+(t-t)")
9693       define_sfop3(31,(axnb<T,2>(x,y,z)),"       ")
9694       define_sfop3(32,(axnb<T,3>(x,y,z)),"       ")
9695       define_sfop3(33,(axnb<T,4>(x,y,z)),"       ")
9696       define_sfop3(34,(axnb<T,5>(x,y,z)),"       ")
9697       define_sfop3(35,(axnb<T,6>(x,y,z)),"       ")
9698       define_sfop3(36,(axnb<T,7>(x,y,z)),"       ")
9699       define_sfop3(37,(axnb<T,8>(x,y,z)),"       ")
9700       define_sfop3(38,(axnb<T,9>(x,y,z)),"       ")
9701       define_sfop3(39,x * numeric::log(y)   + z,"")
9702       define_sfop3(40,x * numeric::log(y)   - z,"")
9703       define_sfop3(41,x * numeric::log10(y) + z,"")
9704       define_sfop3(42,x * numeric::log10(y) - z,"")
9705       define_sfop3(43,x * numeric::sin(y) + z  ,"")
9706       define_sfop3(44,x * numeric::sin(y) - z  ,"")
9707       define_sfop3(45,x * numeric::cos(y) + z  ,"")
9708       define_sfop3(46,x * numeric::cos(y) - z  ,"")
9709       define_sfop3(47,details::is_true(x) ? y : z,"")
9710 
9711       #define define_sfop4(NN,OP0,OP1)                           \
9712       template <typename T>                                      \
9713       struct sf##NN##_op : public sf_base<T>                     \
9714       {                                                          \
9715          typedef typename sf_base<T>::Type const Type;           \
9716          static inline T process(Type x, Type y, Type z, Type w) \
9717          {                                                       \
9718             return (OP0);                                        \
9719          }                                                       \
9720          static inline std::string id()                          \
9721          {                                                       \
9722             return (OP1);                                        \
9723          }                                                       \
9724       };                                                         \
9725 
9726       define_sfop4(48,(x + ((y + z) / w)),"t+((t+t)/t)")
9727       define_sfop4(49,(x + ((y + z) * w)),"t+((t+t)*t)")
9728       define_sfop4(50,(x + ((y - z) / w)),"t+((t-t)/t)")
9729       define_sfop4(51,(x + ((y - z) * w)),"t+((t-t)*t)")
9730       define_sfop4(52,(x + ((y * z) / w)),"t+((t*t)/t)")
9731       define_sfop4(53,(x + ((y * z) * w)),"t+((t*t)*t)")
9732       define_sfop4(54,(x + ((y / z) + w)),"t+((t/t)+t)")
9733       define_sfop4(55,(x + ((y / z) / w)),"t+((t/t)/t)")
9734       define_sfop4(56,(x + ((y / z) * w)),"t+((t/t)*t)")
9735       define_sfop4(57,(x - ((y + z) / w)),"t-((t+t)/t)")
9736       define_sfop4(58,(x - ((y + z) * w)),"t-((t+t)*t)")
9737       define_sfop4(59,(x - ((y - z) / w)),"t-((t-t)/t)")
9738       define_sfop4(60,(x - ((y - z) * w)),"t-((t-t)*t)")
9739       define_sfop4(61,(x - ((y * z) / w)),"t-((t*t)/t)")
9740       define_sfop4(62,(x - ((y * z) * w)),"t-((t*t)*t)")
9741       define_sfop4(63,(x - ((y / z) / w)),"t-((t/t)/t)")
9742       define_sfop4(64,(x - ((y / z) * w)),"t-((t/t)*t)")
9743       define_sfop4(65,(((x + y) * z) - w),"((t+t)*t)-t")
9744       define_sfop4(66,(((x - y) * z) - w),"((t-t)*t)-t")
9745       define_sfop4(67,(((x * y) * z) - w),"((t*t)*t)-t")
9746       define_sfop4(68,(((x / y) * z) - w),"((t/t)*t)-t")
9747       define_sfop4(69,(((x + y) / z) - w),"((t+t)/t)-t")
9748       define_sfop4(70,(((x - y) / z) - w),"((t-t)/t)-t")
9749       define_sfop4(71,(((x * y) / z) - w),"((t*t)/t)-t")
9750       define_sfop4(72,(((x / y) / z) - w),"((t/t)/t)-t")
9751       define_sfop4(73,((x * y) + (z * w)),"(t*t)+(t*t)")
9752       define_sfop4(74,((x * y) - (z * w)),"(t*t)-(t*t)")
9753       define_sfop4(75,((x * y) + (z / w)),"(t*t)+(t/t)")
9754       define_sfop4(76,((x * y) - (z / w)),"(t*t)-(t/t)")
9755       define_sfop4(77,((x / y) + (z / w)),"(t/t)+(t/t)")
9756       define_sfop4(78,((x / y) - (z / w)),"(t/t)-(t/t)")
9757       define_sfop4(79,((x / y) - (z * w)),"(t/t)-(t*t)")
9758       define_sfop4(80,(x / (y + (z * w))),"t/(t+(t*t))")
9759       define_sfop4(81,(x / (y - (z * w))),"t/(t-(t*t))")
9760       define_sfop4(82,(x * (y + (z * w))),"t*(t+(t*t))")
9761       define_sfop4(83,(x * (y - (z * w))),"t*(t-(t*t))")
9762 
9763       define_sfop4(84,(axn<T,2>(x,y) + axn<T,2>(z,w)),"")
9764       define_sfop4(85,(axn<T,3>(x,y) + axn<T,3>(z,w)),"")
9765       define_sfop4(86,(axn<T,4>(x,y) + axn<T,4>(z,w)),"")
9766       define_sfop4(87,(axn<T,5>(x,y) + axn<T,5>(z,w)),"")
9767       define_sfop4(88,(axn<T,6>(x,y) + axn<T,6>(z,w)),"")
9768       define_sfop4(89,(axn<T,7>(x,y) + axn<T,7>(z,w)),"")
9769       define_sfop4(90,(axn<T,8>(x,y) + axn<T,8>(z,w)),"")
9770       define_sfop4(91,(axn<T,9>(x,y) + axn<T,9>(z,w)),"")
9771       define_sfop4(92,((details::is_true(x) && details::is_true(y)) ? z : w),"")
9772       define_sfop4(93,((details::is_true(x) || details::is_true(y)) ? z : w),"")
9773       define_sfop4(94,((x <  y) ? z : w),"")
9774       define_sfop4(95,((x <= y) ? z : w),"")
9775       define_sfop4(96,((x >  y) ? z : w),"")
9776       define_sfop4(97,((x >= y) ? z : w),"")
9777       define_sfop4(98,(details::is_true(numeric::equal(x,y)) ? z : w),"")
9778       define_sfop4(99,(x * numeric::sin(y) + z * numeric::cos(w)),"")
9779 
9780       define_sfop4(ext00,((x + y) - (z * w)),"(t+t)-(t*t)")
9781       define_sfop4(ext01,((x + y) - (z / w)),"(t+t)-(t/t)")
9782       define_sfop4(ext02,((x + y) + (z * w)),"(t+t)+(t*t)")
9783       define_sfop4(ext03,((x + y) + (z / w)),"(t+t)+(t/t)")
9784       define_sfop4(ext04,((x - y) + (z * w)),"(t-t)+(t*t)")
9785       define_sfop4(ext05,((x - y) + (z / w)),"(t-t)+(t/t)")
9786       define_sfop4(ext06,((x - y) - (z * w)),"(t-t)-(t*t)")
9787       define_sfop4(ext07,((x - y) - (z / w)),"(t-t)-(t/t)")
9788       define_sfop4(ext08,((x + y) - (z - w)),"(t+t)-(t-t)")
9789       define_sfop4(ext09,((x + y) + (z - w)),"(t+t)+(t-t)")
9790       define_sfop4(ext10,((x + y) + (z + w)),"(t+t)+(t+t)")
9791       define_sfop4(ext11,((x + y) * (z - w)),"(t+t)*(t-t)")
9792       define_sfop4(ext12,((x + y) / (z - w)),"(t+t)/(t-t)")
9793       define_sfop4(ext13,((x - y) - (z + w)),"(t-t)-(t+t)")
9794       define_sfop4(ext14,((x - y) + (z + w)),"(t-t)+(t+t)")
9795       define_sfop4(ext15,((x - y) * (z + w)),"(t-t)*(t+t)")
9796       define_sfop4(ext16,((x - y) / (z + w)),"(t-t)/(t+t)")
9797       define_sfop4(ext17,((x * y) - (z + w)),"(t*t)-(t+t)")
9798       define_sfop4(ext18,((x / y) - (z + w)),"(t/t)-(t+t)")
9799       define_sfop4(ext19,((x * y) + (z + w)),"(t*t)+(t+t)")
9800       define_sfop4(ext20,((x / y) + (z + w)),"(t/t)+(t+t)")
9801       define_sfop4(ext21,((x * y) + (z - w)),"(t*t)+(t-t)")
9802       define_sfop4(ext22,((x / y) + (z - w)),"(t/t)+(t-t)")
9803       define_sfop4(ext23,((x * y) - (z - w)),"(t*t)-(t-t)")
9804       define_sfop4(ext24,((x / y) - (z - w)),"(t/t)-(t-t)")
9805       define_sfop4(ext25,((x + y) * (z * w)),"(t+t)*(t*t)")
9806       define_sfop4(ext26,((x + y) * (z / w)),"(t+t)*(t/t)")
9807       define_sfop4(ext27,((x + y) / (z * w)),"(t+t)/(t*t)")
9808       define_sfop4(ext28,((x + y) / (z / w)),"(t+t)/(t/t)")
9809       define_sfop4(ext29,((x - y) / (z * w)),"(t-t)/(t*t)")
9810       define_sfop4(ext30,((x - y) / (z / w)),"(t-t)/(t/t)")
9811       define_sfop4(ext31,((x - y) * (z * w)),"(t-t)*(t*t)")
9812       define_sfop4(ext32,((x - y) * (z / w)),"(t-t)*(t/t)")
9813       define_sfop4(ext33,((x * y) * (z + w)),"(t*t)*(t+t)")
9814       define_sfop4(ext34,((x / y) * (z + w)),"(t/t)*(t+t)")
9815       define_sfop4(ext35,((x * y) / (z + w)),"(t*t)/(t+t)")
9816       define_sfop4(ext36,((x / y) / (z + w)),"(t/t)/(t+t)")
9817       define_sfop4(ext37,((x * y) / (z - w)),"(t*t)/(t-t)")
9818       define_sfop4(ext38,((x / y) / (z - w)),"(t/t)/(t-t)")
9819       define_sfop4(ext39,((x * y) * (z - w)),"(t*t)*(t-t)")
9820       define_sfop4(ext40,((x * y) / (z * w)),"(t*t)/(t*t)")
9821       define_sfop4(ext41,((x / y) * (z / w)),"(t/t)*(t/t)")
9822       define_sfop4(ext42,((x / y) * (z - w)),"(t/t)*(t-t)")
9823       define_sfop4(ext43,((x * y) * (z * w)),"(t*t)*(t*t)")
9824       define_sfop4(ext44,(x + (y * (z / w))),"t+(t*(t/t))")
9825       define_sfop4(ext45,(x - (y * (z / w))),"t-(t*(t/t))")
9826       define_sfop4(ext46,(x + (y / (z * w))),"t+(t/(t*t))")
9827       define_sfop4(ext47,(x - (y / (z * w))),"t-(t/(t*t))")
9828       define_sfop4(ext48,(((x - y) - z) * w),"((t-t)-t)*t")
9829       define_sfop4(ext49,(((x - y) - z) / w),"((t-t)-t)/t")
9830       define_sfop4(ext50,(((x - y) + z) * w),"((t-t)+t)*t")
9831       define_sfop4(ext51,(((x - y) + z) / w),"((t-t)+t)/t")
9832       define_sfop4(ext52,((x + (y - z)) * w),"(t+(t-t))*t")
9833       define_sfop4(ext53,((x + (y - z)) / w),"(t+(t-t))/t")
9834       define_sfop4(ext54,((x + y) / (z + w)),"(t+t)/(t+t)")
9835       define_sfop4(ext55,((x - y) / (z - w)),"(t-t)/(t-t)")
9836       define_sfop4(ext56,((x + y) * (z + w)),"(t+t)*(t+t)")
9837       define_sfop4(ext57,((x - y) * (z - w)),"(t-t)*(t-t)")
9838       define_sfop4(ext58,((x - y) + (z - w)),"(t-t)+(t-t)")
9839       define_sfop4(ext59,((x - y) - (z - w)),"(t-t)-(t-t)")
9840       define_sfop4(ext60,((x / y) + (z * w)),"(t/t)+(t*t)")
9841       define_sfop4(ext61,(((x * y) * z) / w),"((t*t)*t)/t")
9842 
9843       #undef define_sfop3
9844       #undef define_sfop4
9845 
9846       template <typename T, typename SpecialFunction>
9847       class sf3_node : public trinary_node<T>
9848       {
9849       public:
9850 
9851          typedef expression_node<T>* expression_ptr;
9852 
sf3_node(const operator_type & opr,expression_ptr branch0,expression_ptr branch1,expression_ptr branch2)9853          sf3_node(const operator_type& opr,
9854                   expression_ptr branch0,
9855                   expression_ptr branch1,
9856                   expression_ptr branch2)
9857          : trinary_node<T>(opr, branch0, branch1, branch2)
9858          {}
9859 
value() const9860          inline T value() const
9861          {
9862             assert(trinary_node<T>::branch_[0].first);
9863             assert(trinary_node<T>::branch_[1].first);
9864             assert(trinary_node<T>::branch_[2].first);
9865 
9866             const T x = trinary_node<T>::branch_[0].first->value();
9867             const T y = trinary_node<T>::branch_[1].first->value();
9868             const T z = trinary_node<T>::branch_[2].first->value();
9869 
9870             return SpecialFunction::process(x, y, z);
9871          }
9872       };
9873 
9874       template <typename T, typename SpecialFunction>
9875       class sf4_node : public quaternary_node<T>
9876       {
9877       public:
9878 
9879          typedef expression_node<T>* expression_ptr;
9880 
sf4_node(const operator_type & opr,expression_ptr branch0,expression_ptr branch1,expression_ptr branch2,expression_ptr branch3)9881          sf4_node(const operator_type& opr,
9882                   expression_ptr branch0,
9883                   expression_ptr branch1,
9884                   expression_ptr branch2,
9885                   expression_ptr branch3)
9886          : quaternary_node<T>(opr, branch0, branch1, branch2, branch3)
9887          {}
9888 
value() const9889          inline T value() const
9890          {
9891             assert(quaternary_node<T>::branch_[0].first);
9892             assert(quaternary_node<T>::branch_[1].first);
9893             assert(quaternary_node<T>::branch_[2].first);
9894             assert(quaternary_node<T>::branch_[3].first);
9895 
9896             const T x = quaternary_node<T>::branch_[0].first->value();
9897             const T y = quaternary_node<T>::branch_[1].first->value();
9898             const T z = quaternary_node<T>::branch_[2].first->value();
9899             const T w = quaternary_node<T>::branch_[3].first->value();
9900 
9901             return SpecialFunction::process(x, y, z, w);
9902          }
9903       };
9904 
9905       template <typename T, typename SpecialFunction>
9906       class sf3_var_node : public expression_node<T>
9907       {
9908       public:
9909 
9910          typedef expression_node<T>* expression_ptr;
9911 
sf3_var_node(const T & v0,const T & v1,const T & v2)9912          sf3_var_node(const T& v0, const T& v1, const T& v2)
9913          : v0_(v0),
9914            v1_(v1),
9915            v2_(v2)
9916          {}
9917 
value() const9918          inline T value() const
9919          {
9920             return SpecialFunction::process(v0_, v1_, v2_);
9921          }
9922 
type() const9923          inline typename expression_node<T>::node_type type() const
9924          {
9925             return expression_node<T>::e_trinary;
9926          }
9927 
9928       private:
9929 
9930          sf3_var_node(sf3_var_node<T,SpecialFunction>&);
9931          sf3_var_node<T,SpecialFunction>& operator=(sf3_var_node<T,SpecialFunction>&);
9932 
9933          const T& v0_;
9934          const T& v1_;
9935          const T& v2_;
9936       };
9937 
9938       template <typename T, typename SpecialFunction>
9939       class sf4_var_node : public expression_node<T>
9940       {
9941       public:
9942 
9943          typedef expression_node<T>* expression_ptr;
9944 
sf4_var_node(const T & v0,const T & v1,const T & v2,const T & v3)9945          sf4_var_node(const T& v0, const T& v1, const T& v2, const T& v3)
9946          : v0_(v0),
9947            v1_(v1),
9948            v2_(v2),
9949            v3_(v3)
9950          {}
9951 
value() const9952          inline T value() const
9953          {
9954             return SpecialFunction::process(v0_, v1_, v2_, v3_);
9955          }
9956 
type() const9957          inline typename expression_node<T>::node_type type() const
9958          {
9959             return expression_node<T>::e_trinary;
9960          }
9961 
9962       private:
9963 
9964          sf4_var_node(sf4_var_node<T,SpecialFunction>&);
9965          sf4_var_node<T,SpecialFunction>& operator=(sf4_var_node<T,SpecialFunction>&);
9966 
9967          const T& v0_;
9968          const T& v1_;
9969          const T& v2_;
9970          const T& v3_;
9971       };
9972 
9973       template <typename T, typename VarArgFunction>
9974       class vararg_node : public expression_node<T>
9975       {
9976       public:
9977 
9978          typedef expression_node<T>* expression_ptr;
9979          typedef std::pair<expression_ptr,bool> branch_t;
9980 
9981          template <typename Allocator,
9982                    template <typename, typename> class Sequence>
vararg_node(const Sequence<expression_ptr,Allocator> & arg_list)9983          explicit vararg_node(const Sequence<expression_ptr,Allocator>& arg_list)
9984          {
9985             arg_list_.resize(arg_list.size());
9986 
9987             for (std::size_t i = 0; i < arg_list.size(); ++i)
9988             {
9989                if (arg_list[i])
9990                {
9991                   construct_branch_pair(arg_list_[i],arg_list[i]);
9992                }
9993                else
9994                {
9995                   arg_list_.clear();
9996                   return;
9997                }
9998             }
9999          }
10000 
value() const10001          inline T value() const
10002          {
10003             return VarArgFunction::process(arg_list_);
10004          }
10005 
type() const10006          inline typename expression_node<T>::node_type type() const
10007          {
10008             return expression_node<T>::e_vararg;
10009          }
10010 
collect_nodes(typename expression_node<T>::noderef_list_t & node_delete_list)10011          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
10012          {
10013             expression_node<T>::ndb_t::collect(arg_list_, node_delete_list);
10014          }
10015 
node_depth() const10016          std::size_t node_depth() const
10017          {
10018             return expression_node<T>::ndb_t::compute_node_depth(arg_list_);
10019          }
10020 
10021       private:
10022 
10023          std::vector<branch_t> arg_list_;
10024       };
10025 
10026       template <typename T, typename VarArgFunction>
10027       class vararg_varnode : public expression_node<T>
10028       {
10029       public:
10030 
10031          typedef expression_node<T>* expression_ptr;
10032 
10033          template <typename Allocator,
10034                    template <typename, typename> class Sequence>
vararg_varnode(const Sequence<expression_ptr,Allocator> & arg_list)10035          explicit vararg_varnode(const Sequence<expression_ptr,Allocator>& arg_list)
10036          {
10037             arg_list_.resize(arg_list.size());
10038 
10039             for (std::size_t i = 0; i < arg_list.size(); ++i)
10040             {
10041                if (arg_list[i] && is_variable_node(arg_list[i]))
10042                {
10043                   variable_node<T>* var_node_ptr = static_cast<variable_node<T>*>(arg_list[i]);
10044                   arg_list_[i] = (&var_node_ptr->ref());
10045                }
10046                else
10047                {
10048                   arg_list_.clear();
10049                   return;
10050                }
10051             }
10052          }
10053 
value() const10054          inline T value() const
10055          {
10056             if (!arg_list_.empty())
10057                return VarArgFunction::process(arg_list_);
10058             else
10059                return std::numeric_limits<T>::quiet_NaN();
10060          }
10061 
type() const10062          inline typename expression_node<T>::node_type type() const
10063          {
10064             return expression_node<T>::e_vararg;
10065          }
10066 
10067       private:
10068 
10069          std::vector<const T*> arg_list_;
10070       };
10071 
10072       template <typename T, typename VecFunction>
10073       class vectorize_node : public expression_node<T>
10074       {
10075       public:
10076 
10077          typedef expression_node<T>* expression_ptr;
10078          typedef std::pair<expression_ptr,bool> branch_t;
10079 
vectorize_node(const expression_ptr v)10080          explicit vectorize_node(const expression_ptr v)
10081          : ivec_ptr_(0)
10082          {
10083             construct_branch_pair(v_, v);
10084 
10085             if (is_ivector_node(v_.first))
10086             {
10087                ivec_ptr_ = dynamic_cast<vector_interface<T>*>(v_.first);
10088             }
10089             else
10090                ivec_ptr_ = 0;
10091          }
10092 
value() const10093          inline T value() const
10094          {
10095             if (ivec_ptr_)
10096             {
10097                assert(v_.first);
10098 
10099                v_.first->value();
10100 
10101                return VecFunction::process(ivec_ptr_);
10102             }
10103             else
10104                return std::numeric_limits<T>::quiet_NaN();
10105          }
10106 
type() const10107          inline typename expression_node<T>::node_type type() const
10108          {
10109             return expression_node<T>::e_vecfunc;
10110          }
10111 
collect_nodes(typename expression_node<T>::noderef_list_t & node_delete_list)10112          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
10113          {
10114             expression_node<T>::ndb_t::collect(v_, node_delete_list);
10115          }
10116 
node_depth() const10117          std::size_t node_depth() const
10118          {
10119             return expression_node<T>::ndb_t::compute_node_depth(v_);
10120          }
10121 
10122       private:
10123 
10124          vector_interface<T>* ivec_ptr_;
10125          branch_t                    v_;
10126       };
10127 
10128       template <typename T>
10129       class assignment_node : public binary_node<T>
10130       {
10131       public:
10132 
10133          typedef expression_node<T>* expression_ptr;
10134 
assignment_node(const operator_type & opr,expression_ptr branch0,expression_ptr branch1)10135          assignment_node(const operator_type& opr,
10136                          expression_ptr branch0,
10137                          expression_ptr branch1)
10138          : binary_node<T>(opr, branch0, branch1),
10139            var_node_ptr_(0)
10140          {
10141             if (is_variable_node(binary_node<T>::branch_[0].first))
10142             {
10143                var_node_ptr_ = static_cast<variable_node<T>*>(binary_node<T>::branch_[0].first);
10144             }
10145          }
10146 
value() const10147          inline T value() const
10148          {
10149             if (var_node_ptr_)
10150             {
10151                assert(binary_node<T>::branch_[1].first);
10152 
10153                T& result = var_node_ptr_->ref();
10154 
10155                result = binary_node<T>::branch_[1].first->value();
10156 
10157                return result;
10158             }
10159             else
10160                return std::numeric_limits<T>::quiet_NaN();
10161          }
10162 
10163       private:
10164 
10165          variable_node<T>* var_node_ptr_;
10166       };
10167 
10168       template <typename T>
10169       class assignment_vec_elem_node : public binary_node<T>
10170       {
10171       public:
10172 
10173          typedef expression_node<T>* expression_ptr;
10174 
assignment_vec_elem_node(const operator_type & opr,expression_ptr branch0,expression_ptr branch1)10175          assignment_vec_elem_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)
10180          {
10181             if (is_vector_elem_node(binary_node<T>::branch_[0].first))
10182             {
10183                vec_node_ptr_ = static_cast<vector_elem_node<T>*>(binary_node<T>::branch_[0].first);
10184             }
10185          }
10186 
value() const10187          inline T value() const
10188          {
10189             if (vec_node_ptr_)
10190             {
10191                assert(binary_node<T>::branch_[1].first);
10192 
10193                T& result = vec_node_ptr_->ref();
10194 
10195                result = binary_node<T>::branch_[1].first->value();
10196 
10197                return result;
10198             }
10199             else
10200                return std::numeric_limits<T>::quiet_NaN();
10201          }
10202 
10203       private:
10204 
10205          vector_elem_node<T>* vec_node_ptr_;
10206       };
10207 
10208       template <typename T>
10209       class assignment_rebasevec_elem_node : public binary_node<T>
10210       {
10211       public:
10212 
10213          typedef expression_node<T>* expression_ptr;
10214 
assignment_rebasevec_elem_node(const operator_type & opr,expression_ptr branch0,expression_ptr branch1)10215          assignment_rebasevec_elem_node(const operator_type& opr,
10216                                         expression_ptr branch0,
10217                                         expression_ptr branch1)
10218          : binary_node<T>(opr, branch0, branch1),
10219            rbvec_node_ptr_(0)
10220          {
10221             if (is_rebasevector_elem_node(binary_node<T>::branch_[0].first))
10222             {
10223                rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(binary_node<T>::branch_[0].first);
10224             }
10225          }
10226 
value() const10227          inline T value() const
10228          {
10229             if (rbvec_node_ptr_)
10230             {
10231                assert(binary_node<T>::branch_[1].first);
10232 
10233                T& result = rbvec_node_ptr_->ref();
10234 
10235                result = binary_node<T>::branch_[1].first->value();
10236 
10237                return result;
10238             }
10239             else
10240                return std::numeric_limits<T>::quiet_NaN();
10241          }
10242 
10243       private:
10244 
10245          rebasevector_elem_node<T>* rbvec_node_ptr_;
10246       };
10247 
10248       template <typename T>
10249       class assignment_rebasevec_celem_node : public binary_node<T>
10250       {
10251       public:
10252 
10253          typedef expression_node<T>* expression_ptr;
10254 
assignment_rebasevec_celem_node(const operator_type & opr,expression_ptr branch0,expression_ptr branch1)10255          assignment_rebasevec_celem_node(const operator_type& opr,
10256                                          expression_ptr branch0,
10257                                          expression_ptr branch1)
10258          : binary_node<T>(opr, branch0, branch1),
10259            rbvec_node_ptr_(0)
10260          {
10261             if (is_rebasevector_celem_node(binary_node<T>::branch_[0].first))
10262             {
10263                rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(binary_node<T>::branch_[0].first);
10264             }
10265          }
10266 
value() const10267          inline T value() const
10268          {
10269             if (rbvec_node_ptr_)
10270             {
10271                assert(binary_node<T>::branch_[1].first);
10272 
10273                T& result = rbvec_node_ptr_->ref();
10274 
10275                result = binary_node<T>::branch_[1].first->value();
10276 
10277                return result;
10278             }
10279             else
10280                return std::numeric_limits<T>::quiet_NaN();
10281          }
10282 
10283       private:
10284 
10285          rebasevector_celem_node<T>* rbvec_node_ptr_;
10286       };
10287 
10288       template <typename T>
10289       class assignment_vec_node : public binary_node     <T>,
10290                                   public vector_interface<T>
10291       {
10292       public:
10293 
10294          typedef expression_node<T>* expression_ptr;
10295          typedef vector_node<T>*    vector_node_ptr;
10296          typedef vec_data_store<T>            vds_t;
10297 
assignment_vec_node(const operator_type & opr,expression_ptr branch0,expression_ptr branch1)10298          assignment_vec_node(const operator_type& opr,
10299                              expression_ptr branch0,
10300                              expression_ptr branch1)
10301          : binary_node<T>(opr, branch0, branch1),
10302            vec_node_ptr_(0)
10303          {
10304             if (is_vector_node(binary_node<T>::branch_[0].first))
10305             {
10306                vec_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
10307                vds()         = vec_node_ptr_->vds();
10308             }
10309          }
10310 
value() const10311          inline T value() const
10312          {
10313             if (vec_node_ptr_)
10314             {
10315                assert(binary_node<T>::branch_[1].first);
10316 
10317                const T v = binary_node<T>::branch_[1].first->value();
10318 
10319                T* vec = vds().data();
10320 
10321                loop_unroll::details lud(size());
10322                const T* upper_bound = vec + lud.upper_bound;
10323 
10324                while (vec < upper_bound)
10325                {
10326                   #define exprtk_loop(N) \
10327                   vec[N] = v;            \
10328 
10329                   exprtk_loop( 0) exprtk_loop( 1)
10330                   exprtk_loop( 2) exprtk_loop( 3)
10331                   #ifndef exprtk_disable_superscalar_unroll
10332                   exprtk_loop( 4) exprtk_loop( 5)
10333                   exprtk_loop( 6) exprtk_loop( 7)
10334                   exprtk_loop( 8) exprtk_loop( 9)
10335                   exprtk_loop(10) exprtk_loop(11)
10336                   exprtk_loop(12) exprtk_loop(13)
10337                   exprtk_loop(14) exprtk_loop(15)
10338                   #endif
10339 
10340                   vec += lud.batch_size;
10341                }
10342 
10343                exprtk_disable_fallthrough_begin
10344                switch (lud.remainder)
10345                {
10346                   #define case_stmt(N) \
10347                   case N : *vec++ = v; \
10348 
10349                   #ifndef exprtk_disable_superscalar_unroll
10350                   case_stmt(15) case_stmt(14)
10351                   case_stmt(13) case_stmt(12)
10352                   case_stmt(11) case_stmt(10)
10353                   case_stmt( 9) case_stmt( 8)
10354                   case_stmt( 7) case_stmt( 6)
10355                   case_stmt( 5) case_stmt( 4)
10356                   #endif
10357                   case_stmt( 3) case_stmt( 2)
10358                   case_stmt( 1)
10359                }
10360                exprtk_disable_fallthrough_end
10361 
10362                #undef exprtk_loop
10363                #undef case_stmt
10364 
10365                return vec_node_ptr_->value();
10366             }
10367             else
10368                return std::numeric_limits<T>::quiet_NaN();
10369          }
10370 
vec() const10371          vector_node_ptr vec() const
10372          {
10373             return vec_node_ptr_;
10374          }
10375 
vec()10376          vector_node_ptr vec()
10377          {
10378             return vec_node_ptr_;
10379          }
10380 
type() const10381          inline typename expression_node<T>::node_type type() const
10382          {
10383             return expression_node<T>::e_vecvalass;
10384          }
10385 
size() const10386          std::size_t size() const
10387          {
10388             return vds().size();
10389          }
10390 
vds()10391          vds_t& vds()
10392          {
10393             return vds_;
10394          }
10395 
vds() const10396          const vds_t& vds() const
10397          {
10398             return vds_;
10399          }
10400 
10401       private:
10402 
10403          vector_node<T>* vec_node_ptr_;
10404          vds_t           vds_;
10405       };
10406 
10407       template <typename T>
10408       class assignment_vecvec_node : public binary_node     <T>,
10409                                      public vector_interface<T>
10410       {
10411       public:
10412 
10413          typedef expression_node<T>*  expression_ptr;
10414          typedef vector_node<T>*     vector_node_ptr;
10415          typedef vec_data_store<T>             vds_t;
10416 
assignment_vecvec_node(const operator_type & opr,expression_ptr branch0,expression_ptr branch1)10417          assignment_vecvec_node(const operator_type& opr,
10418                                 expression_ptr branch0,
10419                                 expression_ptr branch1)
10420          : binary_node<T>(opr, branch0, branch1),
10421            vec0_node_ptr_(0),
10422            vec1_node_ptr_(0),
10423            initialised_(false),
10424            src_is_ivec_(false)
10425          {
10426             if (is_vector_node(binary_node<T>::branch_[0].first))
10427             {
10428                vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
10429                vds()          = vec0_node_ptr_->vds();
10430             }
10431 
10432             if (is_vector_node(binary_node<T>::branch_[1].first))
10433             {
10434                vec1_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first);
10435                vds_t::match_sizes(vds(),vec1_node_ptr_->vds());
10436             }
10437             else if (is_ivector_node(binary_node<T>::branch_[1].first))
10438             {
10439                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
10440 
10441                if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
10442                {
10443                   vec1_node_ptr_ = vi->vec();
10444 
10445                   if (!vi->side_effect())
10446                   {
10447                      vi->vds()    = vds();
10448                      src_is_ivec_ = true;
10449                   }
10450                   else
10451                      vds_t::match_sizes(vds(),vi->vds());
10452                }
10453             }
10454 
10455             initialised_ = (vec0_node_ptr_ && vec1_node_ptr_);
10456          }
10457 
value() const10458          inline T value() const
10459          {
10460             if (initialised_)
10461             {
10462                assert(binary_node<T>::branch_[1].first);
10463 
10464                binary_node<T>::branch_[1].first->value();
10465 
10466                if (src_is_ivec_)
10467                   return vec0_node_ptr_->value();
10468 
10469                T* vec0 = vec0_node_ptr_->vds().data();
10470                T* vec1 = vec1_node_ptr_->vds().data();
10471 
10472                loop_unroll::details lud(size());
10473                const T* upper_bound = vec0 + lud.upper_bound;
10474 
10475                while (vec0 < upper_bound)
10476                {
10477                   #define exprtk_loop(N) \
10478                   vec0[N] = vec1[N];     \
10479 
10480                   exprtk_loop( 0) exprtk_loop( 1)
10481                   exprtk_loop( 2) exprtk_loop( 3)
10482                   #ifndef exprtk_disable_superscalar_unroll
10483                   exprtk_loop( 4) exprtk_loop( 5)
10484                   exprtk_loop( 6) exprtk_loop( 7)
10485                   exprtk_loop( 8) exprtk_loop( 9)
10486                   exprtk_loop(10) exprtk_loop(11)
10487                   exprtk_loop(12) exprtk_loop(13)
10488                   exprtk_loop(14) exprtk_loop(15)
10489                   #endif
10490 
10491                   vec0 += lud.batch_size;
10492                   vec1 += lud.batch_size;
10493                }
10494 
10495                exprtk_disable_fallthrough_begin
10496                switch (lud.remainder)
10497                {
10498                   #define case_stmt(N)        \
10499                   case N : *vec0++ = *vec1++; \
10500 
10501                   #ifndef exprtk_disable_superscalar_unroll
10502                   case_stmt(15) case_stmt(14)
10503                   case_stmt(13) case_stmt(12)
10504                   case_stmt(11) case_stmt(10)
10505                   case_stmt( 9) case_stmt( 8)
10506                   case_stmt( 7) case_stmt( 6)
10507                   case_stmt( 5) case_stmt( 4)
10508                   #endif
10509                   case_stmt( 3) case_stmt( 2)
10510                   case_stmt( 1)
10511                }
10512                exprtk_disable_fallthrough_end
10513 
10514                #undef exprtk_loop
10515                #undef case_stmt
10516 
10517                return vec0_node_ptr_->value();
10518             }
10519             else
10520                return std::numeric_limits<T>::quiet_NaN();
10521          }
10522 
vec() const10523          vector_node_ptr vec() const
10524          {
10525             return vec0_node_ptr_;
10526          }
10527 
vec()10528          vector_node_ptr vec()
10529          {
10530             return vec0_node_ptr_;
10531          }
10532 
type() const10533          inline typename expression_node<T>::node_type type() const
10534          {
10535             return expression_node<T>::e_vecvecass;
10536          }
10537 
size() const10538          std::size_t size() const
10539          {
10540             return vds().size();
10541          }
10542 
vds()10543          vds_t& vds()
10544          {
10545             return vds_;
10546          }
10547 
vds() const10548          const vds_t& vds() const
10549          {
10550             return vds_;
10551          }
10552 
10553       private:
10554 
10555          vector_node<T>* vec0_node_ptr_;
10556          vector_node<T>* vec1_node_ptr_;
10557          bool            initialised_;
10558          bool            src_is_ivec_;
10559          vds_t           vds_;
10560       };
10561 
10562       template <typename T, typename Operation>
10563       class assignment_op_node : public binary_node<T>
10564       {
10565       public:
10566 
10567          typedef expression_node<T>* expression_ptr;
10568 
assignment_op_node(const operator_type & opr,expression_ptr branch0,expression_ptr branch1)10569          assignment_op_node(const operator_type& opr,
10570                             expression_ptr branch0,
10571                             expression_ptr branch1)
10572          : binary_node<T>(opr, branch0, branch1),
10573            var_node_ptr_(0)
10574          {
10575             if (is_variable_node(binary_node<T>::branch_[0].first))
10576             {
10577                var_node_ptr_ = static_cast<variable_node<T>*>(binary_node<T>::branch_[0].first);
10578             }
10579          }
10580 
value() const10581          inline T value() const
10582          {
10583             if (var_node_ptr_)
10584             {
10585                assert(binary_node<T>::branch_[1].first);
10586 
10587                T& v = var_node_ptr_->ref();
10588                v = Operation::process(v,binary_node<T>::branch_[1].first->value());
10589 
10590                return v;
10591             }
10592             else
10593                return std::numeric_limits<T>::quiet_NaN();
10594          }
10595 
10596       private:
10597 
10598          variable_node<T>* var_node_ptr_;
10599       };
10600 
10601       template <typename T, typename Operation>
10602       class assignment_vec_elem_op_node : public binary_node<T>
10603       {
10604       public:
10605 
10606          typedef expression_node<T>* expression_ptr;
10607 
assignment_vec_elem_op_node(const operator_type & opr,expression_ptr branch0,expression_ptr branch1)10608          assignment_vec_elem_op_node(const operator_type& opr,
10609                                      expression_ptr branch0,
10610                                      expression_ptr branch1)
10611          : binary_node<T>(opr, branch0, branch1),
10612            vec_node_ptr_(0)
10613          {
10614             if (is_vector_elem_node(binary_node<T>::branch_[0].first))
10615             {
10616                vec_node_ptr_ = static_cast<vector_elem_node<T>*>(binary_node<T>::branch_[0].first);
10617             }
10618          }
10619 
value() const10620          inline T value() const
10621          {
10622             if (vec_node_ptr_)
10623             {
10624                assert(binary_node<T>::branch_[1].first);
10625 
10626                T& v = vec_node_ptr_->ref();
10627                   v = Operation::process(v,binary_node<T>::branch_[1].first->value());
10628 
10629                return v;
10630             }
10631             else
10632                return std::numeric_limits<T>::quiet_NaN();
10633          }
10634 
10635       private:
10636 
10637          vector_elem_node<T>* vec_node_ptr_;
10638       };
10639 
10640       template <typename T, typename Operation>
10641       class assignment_rebasevec_elem_op_node : public binary_node<T>
10642       {
10643       public:
10644 
10645          typedef expression_node<T>* expression_ptr;
10646 
assignment_rebasevec_elem_op_node(const operator_type & opr,expression_ptr branch0,expression_ptr branch1)10647          assignment_rebasevec_elem_op_node(const operator_type& opr,
10648                                            expression_ptr branch0,
10649                                            expression_ptr branch1)
10650          : binary_node<T>(opr, branch0, branch1),
10651            rbvec_node_ptr_(0)
10652          {
10653             if (is_rebasevector_elem_node(binary_node<T>::branch_[0].first))
10654             {
10655                rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(binary_node<T>::branch_[0].first);
10656             }
10657          }
10658 
value() const10659          inline T value() const
10660          {
10661             if (rbvec_node_ptr_)
10662             {
10663                assert(binary_node<T>::branch_[1].first);
10664 
10665                T& v = rbvec_node_ptr_->ref();
10666                   v = Operation::process(v,binary_node<T>::branch_[1].first->value());
10667 
10668                return v;
10669             }
10670             else
10671                return std::numeric_limits<T>::quiet_NaN();
10672          }
10673 
10674       private:
10675 
10676          rebasevector_elem_node<T>* rbvec_node_ptr_;
10677       };
10678 
10679       template <typename T, typename Operation>
10680       class assignment_rebasevec_celem_op_node : public binary_node<T>
10681       {
10682       public:
10683 
10684          typedef expression_node<T>* expression_ptr;
10685 
assignment_rebasevec_celem_op_node(const operator_type & opr,expression_ptr branch0,expression_ptr branch1)10686          assignment_rebasevec_celem_op_node(const operator_type& opr,
10687                                             expression_ptr branch0,
10688                                             expression_ptr branch1)
10689          : binary_node<T>(opr, branch0, branch1),
10690            rbvec_node_ptr_(0)
10691          {
10692             if (is_rebasevector_celem_node(binary_node<T>::branch_[0].first))
10693             {
10694                rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(binary_node<T>::branch_[0].first);
10695             }
10696          }
10697 
value() const10698          inline T value() const
10699          {
10700             if (rbvec_node_ptr_)
10701             {
10702                assert(binary_node<T>::branch_[1].first);
10703 
10704                T& v = rbvec_node_ptr_->ref();
10705                   v = Operation::process(v,binary_node<T>::branch_[1].first->value());
10706 
10707                return v;
10708             }
10709             else
10710                return std::numeric_limits<T>::quiet_NaN();
10711          }
10712 
10713       private:
10714 
10715          rebasevector_celem_node<T>* rbvec_node_ptr_;
10716       };
10717 
10718       template <typename T, typename Operation>
10719       class assignment_vec_op_node : public binary_node     <T>,
10720                                      public vector_interface<T>
10721       {
10722       public:
10723 
10724          typedef expression_node<T>*  expression_ptr;
10725          typedef vector_node<T>*     vector_node_ptr;
10726          typedef vec_data_store<T>             vds_t;
10727 
assignment_vec_op_node(const operator_type & opr,expression_ptr branch0,expression_ptr branch1)10728          assignment_vec_op_node(const operator_type& opr,
10729                                 expression_ptr branch0,
10730                                 expression_ptr branch1)
10731          : binary_node<T>(opr, branch0, branch1),
10732            vec_node_ptr_(0)
10733          {
10734             if (is_vector_node(binary_node<T>::branch_[0].first))
10735             {
10736                vec_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
10737                vds()         = vec_node_ptr_->vds();
10738             }
10739          }
10740 
value() const10741          inline T value() const
10742          {
10743             if (vec_node_ptr_)
10744             {
10745                assert(binary_node<T>::branch_[1].first);
10746 
10747                const T v = binary_node<T>::branch_[1].first->value();
10748 
10749                T* vec = vds().data();
10750 
10751                loop_unroll::details lud(size());
10752                const T* upper_bound = vec + lud.upper_bound;
10753 
10754                while (vec < upper_bound)
10755                {
10756                   #define exprtk_loop(N)       \
10757                   Operation::assign(vec[N],v); \
10758 
10759                   exprtk_loop( 0) exprtk_loop( 1)
10760                   exprtk_loop( 2) exprtk_loop( 3)
10761                   #ifndef exprtk_disable_superscalar_unroll
10762                   exprtk_loop( 4) exprtk_loop( 5)
10763                   exprtk_loop( 6) exprtk_loop( 7)
10764                   exprtk_loop( 8) exprtk_loop( 9)
10765                   exprtk_loop(10) exprtk_loop(11)
10766                   exprtk_loop(12) exprtk_loop(13)
10767                   exprtk_loop(14) exprtk_loop(15)
10768                   #endif
10769 
10770                   vec += lud.batch_size;
10771                }
10772 
10773                exprtk_disable_fallthrough_begin
10774                switch (lud.remainder)
10775                {
10776                   #define case_stmt(N)                  \
10777                   case N : Operation::assign(*vec++,v); \
10778 
10779                   #ifndef exprtk_disable_superscalar_unroll
10780                   case_stmt(15) case_stmt(14)
10781                   case_stmt(13) case_stmt(12)
10782                   case_stmt(11) case_stmt(10)
10783                   case_stmt( 9) case_stmt( 8)
10784                   case_stmt( 7) case_stmt( 6)
10785                   case_stmt( 5) case_stmt( 4)
10786                   #endif
10787                   case_stmt( 3) case_stmt( 2)
10788                   case_stmt( 1)
10789                }
10790                exprtk_disable_fallthrough_end
10791 
10792 
10793                #undef exprtk_loop
10794                #undef case_stmt
10795 
10796                return vec_node_ptr_->value();
10797             }
10798             else
10799                return std::numeric_limits<T>::quiet_NaN();
10800          }
10801 
vec() const10802          vector_node_ptr vec() const
10803          {
10804             return vec_node_ptr_;
10805          }
10806 
vec()10807          vector_node_ptr vec()
10808          {
10809             return vec_node_ptr_;
10810          }
10811 
type() const10812          inline typename expression_node<T>::node_type type() const
10813          {
10814             return expression_node<T>::e_vecopvalass;
10815          }
10816 
size() const10817          std::size_t size() const
10818          {
10819             return vds().size();
10820          }
10821 
vds()10822          vds_t& vds()
10823          {
10824             return vds_;
10825          }
10826 
vds() const10827          const vds_t& vds() const
10828          {
10829             return vds_;
10830          }
10831 
side_effect() const10832          bool side_effect() const
10833          {
10834             return true;
10835          }
10836 
10837       private:
10838 
10839          vector_node<T>* vec_node_ptr_;
10840          vds_t           vds_;
10841       };
10842 
10843       template <typename T, typename Operation>
10844       class assignment_vecvec_op_node : public binary_node     <T>,
10845                                         public vector_interface<T>
10846       {
10847       public:
10848 
10849          typedef expression_node<T>*  expression_ptr;
10850          typedef vector_node<T>*     vector_node_ptr;
10851          typedef vec_data_store<T>             vds_t;
10852 
assignment_vecvec_op_node(const operator_type & opr,expression_ptr branch0,expression_ptr branch1)10853          assignment_vecvec_op_node(const operator_type& opr,
10854                                    expression_ptr branch0,
10855                                    expression_ptr branch1)
10856          : binary_node<T>(opr, branch0, branch1),
10857            vec0_node_ptr_(0),
10858            vec1_node_ptr_(0),
10859            initialised_(false)
10860          {
10861             if (is_vector_node(binary_node<T>::branch_[0].first))
10862             {
10863                vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
10864                vds()          = vec0_node_ptr_->vds();
10865             }
10866 
10867             if (is_vector_node(binary_node<T>::branch_[1].first))
10868             {
10869                vec1_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first);
10870                vec1_node_ptr_->vds() = vds();
10871             }
10872             else if (is_ivector_node(binary_node<T>::branch_[1].first))
10873             {
10874                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
10875 
10876                if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
10877                {
10878                   vec1_node_ptr_ = vi->vec();
10879                   vec1_node_ptr_->vds() = vds();
10880                }
10881                else
10882                   vds_t::match_sizes(vds(),vec1_node_ptr_->vds());
10883             }
10884 
10885             initialised_ = (vec0_node_ptr_ && vec1_node_ptr_);
10886          }
10887 
value() const10888          inline T value() const
10889          {
10890             if (initialised_)
10891             {
10892                assert(binary_node<T>::branch_[0].first);
10893                assert(binary_node<T>::branch_[1].first);
10894 
10895                binary_node<T>::branch_[0].first->value();
10896                binary_node<T>::branch_[1].first->value();
10897 
10898                      T* vec0 = vec0_node_ptr_->vds().data();
10899                const T* vec1 = vec1_node_ptr_->vds().data();
10900 
10901                loop_unroll::details lud(size());
10902                const T* upper_bound = vec0 + lud.upper_bound;
10903 
10904                while (vec0 < upper_bound)
10905                {
10906                   #define exprtk_loop(N)                          \
10907                   vec0[N] = Operation::process(vec0[N], vec1[N]); \
10908 
10909                   exprtk_loop( 0) exprtk_loop( 1)
10910                   exprtk_loop( 2) exprtk_loop( 3)
10911                   #ifndef exprtk_disable_superscalar_unroll
10912                   exprtk_loop( 4) exprtk_loop( 5)
10913                   exprtk_loop( 6) exprtk_loop( 7)
10914                   exprtk_loop( 8) exprtk_loop( 9)
10915                   exprtk_loop(10) exprtk_loop(11)
10916                   exprtk_loop(12) exprtk_loop(13)
10917                   exprtk_loop(14) exprtk_loop(15)
10918                   #endif
10919 
10920                   vec0 += lud.batch_size;
10921                   vec1 += lud.batch_size;
10922                }
10923 
10924                int i = 0;
10925 
10926                exprtk_disable_fallthrough_begin
10927                switch (lud.remainder)
10928                {
10929                   #define case_stmt(N)                                              \
10930                   case N : { vec0[i] = Operation::process(vec0[i], vec1[i]); ++i; } \
10931 
10932                   #ifndef exprtk_disable_superscalar_unroll
10933                   case_stmt(15) case_stmt(14)
10934                   case_stmt(13) case_stmt(12)
10935                   case_stmt(11) case_stmt(10)
10936                   case_stmt( 9) case_stmt( 8)
10937                   case_stmt( 7) case_stmt( 6)
10938                   case_stmt( 5) case_stmt( 4)
10939                   #endif
10940                   case_stmt( 3) case_stmt( 2)
10941                   case_stmt( 1)
10942                }
10943                exprtk_disable_fallthrough_end
10944 
10945                #undef exprtk_loop
10946                #undef case_stmt
10947 
10948                return vec0_node_ptr_->value();
10949             }
10950             else
10951                return std::numeric_limits<T>::quiet_NaN();
10952          }
10953 
vec() const10954          vector_node_ptr vec() const
10955          {
10956             return vec0_node_ptr_;
10957          }
10958 
vec()10959          vector_node_ptr vec()
10960          {
10961             return vec0_node_ptr_;
10962          }
10963 
type() const10964          inline typename expression_node<T>::node_type type() const
10965          {
10966             return expression_node<T>::e_vecopvecass;
10967          }
10968 
size() const10969          std::size_t size() const
10970          {
10971             return vds().size();
10972          }
10973 
vds()10974          vds_t& vds()
10975          {
10976             return vds_;
10977          }
10978 
vds() const10979          const vds_t& vds() const
10980          {
10981             return vds_;
10982          }
10983 
side_effect() const10984          bool side_effect() const
10985          {
10986             return true;
10987          }
10988 
10989       private:
10990 
10991          vector_node<T>* vec0_node_ptr_;
10992          vector_node<T>* vec1_node_ptr_;
10993          bool            initialised_;
10994          vds_t           vds_;
10995       };
10996 
10997       template <typename T, typename Operation>
10998       class vec_binop_vecvec_node : public binary_node     <T>,
10999                                     public vector_interface<T>
11000       {
11001       public:
11002 
11003          typedef expression_node<T>*    expression_ptr;
11004          typedef vector_node<T>*       vector_node_ptr;
11005          typedef vector_holder<T>*   vector_holder_ptr;
11006          typedef vec_data_store<T>               vds_t;
11007 
vec_binop_vecvec_node(const operator_type & opr,expression_ptr branch0,expression_ptr branch1)11008          vec_binop_vecvec_node(const operator_type& opr,
11009                                expression_ptr branch0,
11010                                expression_ptr branch1)
11011          : binary_node<T>(opr, branch0, branch1),
11012            vec0_node_ptr_(0),
11013            vec1_node_ptr_(0),
11014            temp_         (0),
11015            temp_vec_node_(0),
11016            initialised_(false)
11017          {
11018             bool v0_is_ivec = false;
11019             bool v1_is_ivec = false;
11020 
11021             if (is_vector_node(binary_node<T>::branch_[0].first))
11022             {
11023                vec0_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[0].first);
11024             }
11025             else if (is_ivector_node(binary_node<T>::branch_[0].first))
11026             {
11027                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
11028 
11029                if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
11030                {
11031                   vec0_node_ptr_ = vi->vec();
11032                   v0_is_ivec     = true;
11033                }
11034             }
11035 
11036             if (is_vector_node(binary_node<T>::branch_[1].first))
11037             {
11038                vec1_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[1].first);
11039             }
11040             else if (is_ivector_node(binary_node<T>::branch_[1].first))
11041             {
11042                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
11043 
11044                if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
11045                {
11046                   vec1_node_ptr_ = vi->vec();
11047                   v1_is_ivec     = true;
11048                }
11049             }
11050 
11051             if (vec0_node_ptr_ && vec1_node_ptr_)
11052             {
11053                vector_holder<T>& vec0 = vec0_node_ptr_->vec_holder();
11054                vector_holder<T>& vec1 = vec1_node_ptr_->vec_holder();
11055 
11056                if (v0_is_ivec && (vec0.size() <= vec1.size()))
11057                   vds_ = vds_t(vec0_node_ptr_->vds());
11058                else if (v1_is_ivec && (vec1.size() <= vec0.size()))
11059                   vds_ = vds_t(vec1_node_ptr_->vds());
11060                else
11061                   vds_ = vds_t(std::min(vec0.size(),vec1.size()));
11062 
11063                temp_          = new vector_holder<T>(vds().data(),vds().size());
11064                temp_vec_node_ = new vector_node<T>  (vds(),temp_);
11065 
11066                initialised_ = true;
11067             }
11068          }
11069 
~vec_binop_vecvec_node()11070         ~vec_binop_vecvec_node()
11071          {
11072             delete temp_;
11073             delete temp_vec_node_;
11074          }
11075 
value() const11076          inline T value() const
11077          {
11078             if (initialised_)
11079             {
11080                assert(binary_node<T>::branch_[0].first);
11081                assert(binary_node<T>::branch_[1].first);
11082 
11083                binary_node<T>::branch_[0].first->value();
11084                binary_node<T>::branch_[1].first->value();
11085 
11086                const T* vec0 = vec0_node_ptr_->vds().data();
11087                const T* vec1 = vec1_node_ptr_->vds().data();
11088                      T* vec2 = vds().data();
11089 
11090                loop_unroll::details lud(size());
11091                const T* upper_bound = vec2 + lud.upper_bound;
11092 
11093                while (vec2 < upper_bound)
11094                {
11095                   #define exprtk_loop(N)                          \
11096                   vec2[N] = Operation::process(vec0[N], vec1[N]); \
11097 
11098                   exprtk_loop( 0) exprtk_loop( 1)
11099                   exprtk_loop( 2) exprtk_loop( 3)
11100                   #ifndef exprtk_disable_superscalar_unroll
11101                   exprtk_loop( 4) exprtk_loop( 5)
11102                   exprtk_loop( 6) exprtk_loop( 7)
11103                   exprtk_loop( 8) exprtk_loop( 9)
11104                   exprtk_loop(10) exprtk_loop(11)
11105                   exprtk_loop(12) exprtk_loop(13)
11106                   exprtk_loop(14) exprtk_loop(15)
11107                   #endif
11108 
11109                   vec0 += lud.batch_size;
11110                   vec1 += lud.batch_size;
11111                   vec2 += lud.batch_size;
11112                }
11113 
11114                int i = 0;
11115 
11116                exprtk_disable_fallthrough_begin
11117                switch (lud.remainder)
11118                {
11119                   #define case_stmt(N)                                              \
11120                   case N : { vec2[i] = Operation::process(vec0[i], vec1[i]); ++i; } \
11121 
11122                   #ifndef exprtk_disable_superscalar_unroll
11123                   case_stmt(15) case_stmt(14)
11124                   case_stmt(13) case_stmt(12)
11125                   case_stmt(11) case_stmt(10)
11126                   case_stmt( 9) case_stmt( 8)
11127                   case_stmt( 7) case_stmt( 6)
11128                   case_stmt( 5) case_stmt( 4)
11129                   #endif
11130                   case_stmt( 3) case_stmt( 2)
11131                   case_stmt( 1)
11132                }
11133                exprtk_disable_fallthrough_end
11134 
11135                #undef exprtk_loop
11136                #undef case_stmt
11137 
11138                return (vds().data())[0];
11139             }
11140             else
11141                return std::numeric_limits<T>::quiet_NaN();
11142          }
11143 
vec() const11144          vector_node_ptr vec() const
11145          {
11146             return temp_vec_node_;
11147          }
11148 
vec()11149          vector_node_ptr vec()
11150          {
11151             return temp_vec_node_;
11152          }
11153 
type() const11154          inline typename expression_node<T>::node_type type() const
11155          {
11156             return expression_node<T>::e_vecvecarith;
11157          }
11158 
size() const11159          std::size_t size() const
11160          {
11161             return vds_.size();
11162          }
11163 
vds()11164          vds_t& vds()
11165          {
11166             return vds_;
11167          }
11168 
vds() const11169          const vds_t& vds() const
11170          {
11171             return vds_;
11172          }
11173 
11174       private:
11175 
11176          vector_node_ptr   vec0_node_ptr_;
11177          vector_node_ptr   vec1_node_ptr_;
11178          vector_holder_ptr temp_;
11179          vector_node_ptr   temp_vec_node_;
11180          bool              initialised_;
11181          vds_t             vds_;
11182       };
11183 
11184       template <typename T, typename Operation>
11185       class vec_binop_vecval_node : public binary_node     <T>,
11186                                     public vector_interface<T>
11187       {
11188       public:
11189 
11190          typedef expression_node<T>*    expression_ptr;
11191          typedef vector_node<T>*       vector_node_ptr;
11192          typedef vector_holder<T>*   vector_holder_ptr;
11193          typedef vec_data_store<T>               vds_t;
11194 
vec_binop_vecval_node(const operator_type & opr,expression_ptr branch0,expression_ptr branch1)11195          vec_binop_vecval_node(const operator_type& opr,
11196                                expression_ptr branch0,
11197                                expression_ptr branch1)
11198          : binary_node<T>(opr, branch0, branch1),
11199            vec0_node_ptr_(0),
11200            temp_         (0),
11201            temp_vec_node_(0)
11202          {
11203             bool v0_is_ivec = false;
11204 
11205             if (is_vector_node(binary_node<T>::branch_[0].first))
11206             {
11207                vec0_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[0].first);
11208             }
11209             else if (is_ivector_node(binary_node<T>::branch_[0].first))
11210             {
11211                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
11212 
11213                if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
11214                {
11215                   vec0_node_ptr_ = vi->vec();
11216                   v0_is_ivec     = true;
11217                }
11218             }
11219 
11220             if (vec0_node_ptr_)
11221             {
11222                if (v0_is_ivec)
11223                   vds() = vec0_node_ptr_->vds();
11224                else
11225                   vds() = vds_t(vec0_node_ptr_->size());
11226 
11227                temp_          = new vector_holder<T>(vds());
11228                temp_vec_node_ = new vector_node<T>  (vds(),temp_);
11229             }
11230          }
11231 
~vec_binop_vecval_node()11232         ~vec_binop_vecval_node()
11233          {
11234             delete temp_;
11235             delete temp_vec_node_;
11236          }
11237 
value() const11238          inline T value() const
11239          {
11240             if (vec0_node_ptr_)
11241             {
11242                assert(binary_node<T>::branch_[0].first);
11243                assert(binary_node<T>::branch_[1].first);
11244 
11245                            binary_node<T>::branch_[0].first->value();
11246                const T v = binary_node<T>::branch_[1].first->value();
11247 
11248                const T* vec0 = vec0_node_ptr_->vds().data();
11249                      T* vec1 = vds().data();
11250 
11251                loop_unroll::details lud(size());
11252                const T* upper_bound = vec0 + lud.upper_bound;
11253 
11254                while (vec0 < upper_bound)
11255                {
11256                   #define exprtk_loop(N)                    \
11257                   vec1[N] = Operation::process(vec0[N], v); \
11258 
11259                   exprtk_loop( 0) exprtk_loop( 1)
11260                   exprtk_loop( 2) exprtk_loop( 3)
11261                   #ifndef exprtk_disable_superscalar_unroll
11262                   exprtk_loop( 4) exprtk_loop( 5)
11263                   exprtk_loop( 6) exprtk_loop( 7)
11264                   exprtk_loop( 8) exprtk_loop( 9)
11265                   exprtk_loop(10) exprtk_loop(11)
11266                   exprtk_loop(12) exprtk_loop(13)
11267                   exprtk_loop(14) exprtk_loop(15)
11268                   #endif
11269 
11270                   vec0 += lud.batch_size;
11271                   vec1 += lud.batch_size;
11272                }
11273 
11274                int i = 0;
11275 
11276                exprtk_disable_fallthrough_begin
11277                switch (lud.remainder)
11278                {
11279                   #define case_stmt(N)                                        \
11280                   case N : { vec1[i] = Operation::process(vec0[i], v); ++i; } \
11281 
11282                   #ifndef exprtk_disable_superscalar_unroll
11283                   case_stmt(15) case_stmt(14)
11284                   case_stmt(13) case_stmt(12)
11285                   case_stmt(11) case_stmt(10)
11286                   case_stmt( 9) case_stmt( 8)
11287                   case_stmt( 7) case_stmt( 6)
11288                   case_stmt( 5) case_stmt( 4)
11289                   #endif
11290                   case_stmt( 3) case_stmt( 2)
11291                   case_stmt( 1)
11292                }
11293                exprtk_disable_fallthrough_end
11294 
11295                #undef exprtk_loop
11296                #undef case_stmt
11297 
11298                return (vds().data())[0];
11299             }
11300             else
11301                return std::numeric_limits<T>::quiet_NaN();
11302          }
11303 
vec() const11304          vector_node_ptr vec() const
11305          {
11306             return temp_vec_node_;
11307          }
11308 
vec()11309          vector_node_ptr vec()
11310          {
11311             return temp_vec_node_;
11312          }
11313 
type() const11314          inline typename expression_node<T>::node_type type() const
11315          {
11316             return expression_node<T>::e_vecvalarith;
11317          }
11318 
size() const11319          std::size_t size() const
11320          {
11321             return vds().size();
11322          }
11323 
vds()11324          vds_t& vds()
11325          {
11326             return vds_;
11327          }
11328 
vds() const11329          const vds_t& vds() const
11330          {
11331             return vds_;
11332          }
11333 
11334       private:
11335 
11336          vector_node_ptr   vec0_node_ptr_;
11337          vector_holder_ptr temp_;
11338          vector_node_ptr   temp_vec_node_;
11339          vds_t             vds_;
11340       };
11341 
11342       template <typename T, typename Operation>
11343       class vec_binop_valvec_node : public binary_node     <T>,
11344                                     public vector_interface<T>
11345       {
11346       public:
11347 
11348          typedef expression_node<T>*    expression_ptr;
11349          typedef vector_node<T>*       vector_node_ptr;
11350          typedef vector_holder<T>*   vector_holder_ptr;
11351          typedef vec_data_store<T>               vds_t;
11352 
vec_binop_valvec_node(const operator_type & opr,expression_ptr branch0,expression_ptr branch1)11353          vec_binop_valvec_node(const operator_type& opr,
11354                                expression_ptr branch0,
11355                                expression_ptr branch1)
11356          : binary_node<T>(opr, branch0, branch1),
11357            vec1_node_ptr_(0),
11358            temp_         (0),
11359            temp_vec_node_(0)
11360          {
11361             bool v1_is_ivec = false;
11362 
11363             if (is_vector_node(binary_node<T>::branch_[1].first))
11364             {
11365                vec1_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[1].first);
11366             }
11367             else if (is_ivector_node(binary_node<T>::branch_[1].first))
11368             {
11369                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
11370 
11371                if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
11372                {
11373                   vec1_node_ptr_ = vi->vec();
11374                   v1_is_ivec     = true;
11375                }
11376             }
11377 
11378             if (vec1_node_ptr_)
11379             {
11380                if (v1_is_ivec)
11381                   vds() = vec1_node_ptr_->vds();
11382                else
11383                   vds() = vds_t(vec1_node_ptr_->size());
11384 
11385                temp_          = new vector_holder<T>(vds());
11386                temp_vec_node_ = new vector_node<T>  (vds(),temp_);
11387             }
11388          }
11389 
~vec_binop_valvec_node()11390         ~vec_binop_valvec_node()
11391          {
11392             delete temp_;
11393             delete temp_vec_node_;
11394          }
11395 
value() const11396          inline T value() const
11397          {
11398             if (vec1_node_ptr_)
11399             {
11400                assert(binary_node<T>::branch_[0].first);
11401                assert(binary_node<T>::branch_[1].first);
11402 
11403                const T v = binary_node<T>::branch_[0].first->value();
11404                            binary_node<T>::branch_[1].first->value();
11405 
11406                      T* vec0 = vds().data();
11407                const T* vec1 = vec1_node_ptr_->vds().data();
11408 
11409                loop_unroll::details lud(size());
11410                const T* upper_bound = vec0 + lud.upper_bound;
11411 
11412                while (vec0 < upper_bound)
11413                {
11414                   #define exprtk_loop(N)                    \
11415                   vec0[N] = Operation::process(v, vec1[N]); \
11416 
11417                   exprtk_loop( 0) exprtk_loop( 1)
11418                   exprtk_loop( 2) exprtk_loop( 3)
11419                   #ifndef exprtk_disable_superscalar_unroll
11420                   exprtk_loop( 4) exprtk_loop( 5)
11421                   exprtk_loop( 6) exprtk_loop( 7)
11422                   exprtk_loop( 8) exprtk_loop( 9)
11423                   exprtk_loop(10) exprtk_loop(11)
11424                   exprtk_loop(12) exprtk_loop(13)
11425                   exprtk_loop(14) exprtk_loop(15)
11426                   #endif
11427 
11428                   vec0 += lud.batch_size;
11429                   vec1 += lud.batch_size;
11430                }
11431 
11432                int i = 0;
11433 
11434                exprtk_disable_fallthrough_begin
11435                switch (lud.remainder)
11436                {
11437                   #define case_stmt(N)                                        \
11438                   case N : { vec0[i] = Operation::process(v, vec1[i]); ++i; } \
11439 
11440                   #ifndef exprtk_disable_superscalar_unroll
11441                   case_stmt(15) case_stmt(14)
11442                   case_stmt(13) case_stmt(12)
11443                   case_stmt(11) case_stmt(10)
11444                   case_stmt( 9) case_stmt( 8)
11445                   case_stmt( 7) case_stmt( 6)
11446                   case_stmt( 5) case_stmt( 4)
11447                   #endif
11448                   case_stmt( 3) case_stmt( 2)
11449                   case_stmt( 1)
11450                }
11451                exprtk_disable_fallthrough_end
11452 
11453                #undef exprtk_loop
11454                #undef case_stmt
11455 
11456                return (vds().data())[0];
11457             }
11458             else
11459                return std::numeric_limits<T>::quiet_NaN();
11460          }
11461 
vec() const11462          vector_node_ptr vec() const
11463          {
11464             return temp_vec_node_;
11465          }
11466 
vec()11467          vector_node_ptr vec()
11468          {
11469             return temp_vec_node_;
11470          }
11471 
type() const11472          inline typename expression_node<T>::node_type type() const
11473          {
11474             return expression_node<T>::e_vecvalarith;
11475          }
11476 
size() const11477          std::size_t size() const
11478          {
11479             return vds().size();
11480          }
11481 
vds()11482          vds_t& vds()
11483          {
11484             return vds_;
11485          }
11486 
vds() const11487          const vds_t& vds() const
11488          {
11489             return vds_;
11490          }
11491 
11492       private:
11493 
11494          vector_node_ptr   vec1_node_ptr_;
11495          vector_holder_ptr temp_;
11496          vector_node_ptr   temp_vec_node_;
11497          vds_t             vds_;
11498       };
11499 
11500       template <typename T, typename Operation>
11501       class unary_vector_node : public unary_node      <T>,
11502                                 public vector_interface<T>
11503       {
11504       public:
11505 
11506          typedef expression_node<T>*    expression_ptr;
11507          typedef vector_node<T>*       vector_node_ptr;
11508          typedef vector_holder<T>*   vector_holder_ptr;
11509          typedef vec_data_store<T>               vds_t;
11510 
unary_vector_node(const operator_type & opr,expression_ptr branch0)11511          unary_vector_node(const operator_type& opr, expression_ptr branch0)
11512          : unary_node<T>(opr, branch0),
11513            vec0_node_ptr_(0),
11514            temp_         (0),
11515            temp_vec_node_(0)
11516          {
11517             bool vec0_is_ivec = false;
11518 
11519             if (is_vector_node(unary_node<T>::branch_.first))
11520             {
11521                vec0_node_ptr_ = static_cast<vector_node_ptr>(unary_node<T>::branch_.first);
11522             }
11523             else if (is_ivector_node(unary_node<T>::branch_.first))
11524             {
11525                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
11526 
11527                if (0 != (vi = dynamic_cast<vector_interface<T>*>(unary_node<T>::branch_.first)))
11528                {
11529                   vec0_node_ptr_ = vi->vec();
11530                   vec0_is_ivec   = true;
11531                }
11532             }
11533 
11534             if (vec0_node_ptr_)
11535             {
11536                if (vec0_is_ivec)
11537                   vds_ = vec0_node_ptr_->vds();
11538                else
11539                   vds_ = vds_t(vec0_node_ptr_->size());
11540 
11541                temp_          = new vector_holder<T>(vds());
11542                temp_vec_node_ = new vector_node<T>  (vds(),temp_);
11543             }
11544          }
11545 
~unary_vector_node()11546         ~unary_vector_node()
11547          {
11548             delete temp_;
11549             delete temp_vec_node_;
11550          }
11551 
value() const11552          inline T value() const
11553          {
11554             assert(unary_node<T>::branch_.first);
11555 
11556             unary_node<T>::branch_.first->value();
11557 
11558             if (vec0_node_ptr_)
11559             {
11560                const T* vec0 = vec0_node_ptr_->vds().data();
11561                      T* vec1 = vds().data();
11562 
11563                loop_unroll::details lud(size());
11564                const T* upper_bound = vec0 + lud.upper_bound;
11565 
11566                while (vec0 < upper_bound)
11567                {
11568                   #define exprtk_loop(N)                 \
11569                   vec1[N] = Operation::process(vec0[N]); \
11570 
11571                   exprtk_loop( 0) exprtk_loop( 1)
11572                   exprtk_loop( 2) exprtk_loop( 3)
11573                   #ifndef exprtk_disable_superscalar_unroll
11574                   exprtk_loop( 4) exprtk_loop( 5)
11575                   exprtk_loop( 6) exprtk_loop( 7)
11576                   exprtk_loop( 8) exprtk_loop( 9)
11577                   exprtk_loop(10) exprtk_loop(11)
11578                   exprtk_loop(12) exprtk_loop(13)
11579                   exprtk_loop(14) exprtk_loop(15)
11580                   #endif
11581 
11582                   vec0 += lud.batch_size;
11583                   vec1 += lud.batch_size;
11584                }
11585 
11586                int i = 0;
11587 
11588                exprtk_disable_fallthrough_begin
11589                switch (lud.remainder)
11590                {
11591                   #define case_stmt(N)                                     \
11592                   case N : { vec1[i] = Operation::process(vec0[i]); ++i; } \
11593 
11594                   #ifndef exprtk_disable_superscalar_unroll
11595                   case_stmt(15) case_stmt(14)
11596                   case_stmt(13) case_stmt(12)
11597                   case_stmt(11) case_stmt(10)
11598                   case_stmt( 9) case_stmt( 8)
11599                   case_stmt( 7) case_stmt( 6)
11600                   case_stmt( 5) case_stmt( 4)
11601                   #endif
11602                   case_stmt( 3) case_stmt( 2)
11603                   case_stmt( 1)
11604                }
11605                exprtk_disable_fallthrough_end
11606 
11607                #undef exprtk_loop
11608                #undef case_stmt
11609 
11610                return (vds().data())[0];
11611             }
11612             else
11613                return std::numeric_limits<T>::quiet_NaN();
11614          }
11615 
vec() const11616          vector_node_ptr vec() const
11617          {
11618             return temp_vec_node_;
11619          }
11620 
vec()11621          vector_node_ptr vec()
11622          {
11623             return temp_vec_node_;
11624          }
11625 
type() const11626          inline typename expression_node<T>::node_type type() const
11627          {
11628             return expression_node<T>::e_vecunaryop;
11629          }
11630 
size() const11631          std::size_t size() const
11632          {
11633             return vds().size();
11634          }
11635 
vds()11636          vds_t& vds()
11637          {
11638             return vds_;
11639          }
11640 
vds() const11641          const vds_t& vds() const
11642          {
11643             return vds_;
11644          }
11645 
11646       private:
11647 
11648          vector_node_ptr   vec0_node_ptr_;
11649          vector_holder_ptr temp_;
11650          vector_node_ptr   temp_vec_node_;
11651          vds_t             vds_;
11652       };
11653 
11654       template <typename T>
11655       class scand_node : public binary_node<T>
11656       {
11657       public:
11658 
11659          typedef expression_node<T>* expression_ptr;
11660 
scand_node(const operator_type & opr,expression_ptr branch0,expression_ptr branch1)11661          scand_node(const operator_type& opr,
11662                     expression_ptr branch0,
11663                     expression_ptr branch1)
11664          : binary_node<T>(opr, branch0, branch1)
11665          {}
11666 
value() const11667          inline T value() const
11668          {
11669             assert(binary_node<T>::branch_[0].first);
11670             assert(binary_node<T>::branch_[1].first);
11671 
11672             return (
11673                      std::not_equal_to<T>()
11674                         (T(0),binary_node<T>::branch_[0].first->value()) &&
11675                      std::not_equal_to<T>()
11676                         (T(0),binary_node<T>::branch_[1].first->value())
11677                    ) ? T(1) : T(0);
11678          }
11679       };
11680 
11681       template <typename T>
11682       class scor_node : public binary_node<T>
11683       {
11684       public:
11685 
11686          typedef expression_node<T>* expression_ptr;
11687 
scor_node(const operator_type & opr,expression_ptr branch0,expression_ptr branch1)11688          scor_node(const operator_type& opr,
11689                    expression_ptr branch0,
11690                    expression_ptr branch1)
11691          : binary_node<T>(opr, branch0, branch1)
11692          {}
11693 
value() const11694          inline T value() const
11695          {
11696             assert(binary_node<T>::branch_[0].first);
11697             assert(binary_node<T>::branch_[1].first);
11698 
11699             return (
11700                      std::not_equal_to<T>()
11701                         (T(0),binary_node<T>::branch_[0].first->value()) ||
11702                      std::not_equal_to<T>()
11703                         (T(0),binary_node<T>::branch_[1].first->value())
11704                    ) ? T(1) : T(0);
11705          }
11706       };
11707 
11708       template <typename T, typename IFunction, std::size_t N>
11709       class function_N_node : public expression_node<T>
11710       {
11711       public:
11712 
11713          // Function of N paramters.
11714          typedef expression_node<T>* expression_ptr;
11715          typedef std::pair<expression_ptr,bool> branch_t;
11716          typedef IFunction ifunction;
11717 
function_N_node(ifunction * func)11718          explicit function_N_node(ifunction* func)
11719          : function_((N == func->param_count) ? func : reinterpret_cast<ifunction*>(0)),
11720            parameter_count_(func->param_count)
11721          {}
11722 
11723          template <std::size_t NumBranches>
init_branches(expression_ptr (& b)[NumBranches])11724          bool init_branches(expression_ptr (&b)[NumBranches])
11725          {
11726             // Needed for incompetent and broken msvc compiler versions
11727             #ifdef _MSC_VER
11728              #pragma warning(push)
11729              #pragma warning(disable: 4127)
11730             #endif
11731             if (N != NumBranches)
11732                return false;
11733             else
11734             {
11735                for (std::size_t i = 0; i < NumBranches; ++i)
11736                {
11737                   if (b[i])
11738                      branch_[i] = std::make_pair(b[i],branch_deletable(b[i]));
11739                   else
11740                      return false;
11741                }
11742                return true;
11743             }
11744             #ifdef _MSC_VER
11745              #pragma warning(pop)
11746             #endif
11747          }
11748 
operator <(const function_N_node<T,IFunction,N> & fn) const11749          inline bool operator <(const function_N_node<T,IFunction,N>& fn) const
11750          {
11751             return this < (&fn);
11752          }
11753 
value() const11754          inline T value() const
11755          {
11756             // Needed for incompetent and broken msvc compiler versions
11757             #ifdef _MSC_VER
11758              #pragma warning(push)
11759              #pragma warning(disable: 4127)
11760             #endif
11761             if ((0 == function_) || (0 == N))
11762                return std::numeric_limits<T>::quiet_NaN();
11763             else
11764             {
11765                T v[N];
11766                evaluate_branches<T,N>::execute(v,branch_);
11767                return invoke<T,N>::execute(*function_,v);
11768             }
11769             #ifdef _MSC_VER
11770              #pragma warning(pop)
11771             #endif
11772          }
11773 
11774          template <typename T_, std::size_t BranchCount>
11775          struct evaluate_branches
11776          {
executeexprtk::details::function_N_node::evaluate_branches11777             static inline void execute(T_ (&v)[BranchCount], const branch_t (&b)[BranchCount])
11778             {
11779                for (std::size_t i = 0; i < BranchCount; ++i)
11780                {
11781                   v[i] = b[i].first->value();
11782                }
11783             }
11784          };
11785 
11786          template <typename T_>
11787          struct evaluate_branches <T_,5>
11788          {
executeexprtk::details::function_N_node::evaluate_branches11789             static inline void execute(T_ (&v)[5], const branch_t (&b)[5])
11790             {
11791                v[0] = b[0].first->value();
11792                v[1] = b[1].first->value();
11793                v[2] = b[2].first->value();
11794                v[3] = b[3].first->value();
11795                v[4] = b[4].first->value();
11796             }
11797          };
11798 
11799          template <typename T_>
11800          struct evaluate_branches <T_,4>
11801          {
executeexprtk::details::function_N_node::evaluate_branches11802             static inline void execute(T_ (&v)[4], const branch_t (&b)[4])
11803             {
11804                v[0] = b[0].first->value();
11805                v[1] = b[1].first->value();
11806                v[2] = b[2].first->value();
11807                v[3] = b[3].first->value();
11808             }
11809          };
11810 
11811          template <typename T_>
11812          struct evaluate_branches <T_,3>
11813          {
executeexprtk::details::function_N_node::evaluate_branches11814             static inline void execute(T_ (&v)[3], const branch_t (&b)[3])
11815             {
11816                v[0] = b[0].first->value();
11817                v[1] = b[1].first->value();
11818                v[2] = b[2].first->value();
11819             }
11820          };
11821 
11822          template <typename T_>
11823          struct evaluate_branches <T_,2>
11824          {
executeexprtk::details::function_N_node::evaluate_branches11825             static inline void execute(T_ (&v)[2], const branch_t (&b)[2])
11826             {
11827                v[0] = b[0].first->value();
11828                v[1] = b[1].first->value();
11829             }
11830          };
11831 
11832          template <typename T_>
11833          struct evaluate_branches <T_,1>
11834          {
executeexprtk::details::function_N_node::evaluate_branches11835             static inline void execute(T_ (&v)[1], const branch_t (&b)[1])
11836             {
11837                v[0] = b[0].first->value();
11838             }
11839          };
11840 
11841          template <typename T_, std::size_t ParamCount>
executeexprtk::details::function_N_node::invoke11842          struct invoke { static inline T execute(ifunction&, branch_t (&)[ParamCount]) { return std::numeric_limits<T_>::quiet_NaN(); } };
11843 
11844          template <typename T_>
11845          struct invoke<T_,20>
11846          {
executeexprtk::details::function_N_node::invoke11847             static inline T_ execute(ifunction& f, T_ (&v)[20])
11848             { 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]); }
11849          };
11850 
11851          template <typename T_>
11852          struct invoke<T_,19>
11853          {
executeexprtk::details::function_N_node::invoke11854             static inline T_ execute(ifunction& f, T_ (&v)[19])
11855             { 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]); }
11856          };
11857 
11858          template <typename T_>
11859          struct invoke<T_,18>
11860          {
executeexprtk::details::function_N_node::invoke11861             static inline T_ execute(ifunction& f, T_ (&v)[18])
11862             { 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]); }
11863          };
11864 
11865          template <typename T_>
11866          struct invoke<T_,17>
11867          {
executeexprtk::details::function_N_node::invoke11868             static inline T_ execute(ifunction& f, T_ (&v)[17])
11869             { 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]); }
11870          };
11871 
11872          template <typename T_>
11873          struct invoke<T_,16>
11874          {
executeexprtk::details::function_N_node::invoke11875             static inline T_ execute(ifunction& f, T_ (&v)[16])
11876             { 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]); }
11877          };
11878 
11879          template <typename T_>
11880          struct invoke<T_,15>
11881          {
executeexprtk::details::function_N_node::invoke11882             static inline T_ execute(ifunction& f, T_ (&v)[15])
11883             { 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]); }
11884          };
11885 
11886          template <typename T_>
11887          struct invoke<T_,14>
11888          {
executeexprtk::details::function_N_node::invoke11889             static inline T_ execute(ifunction& f, T_ (&v)[14])
11890             { 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]); }
11891          };
11892 
11893          template <typename T_>
11894          struct invoke<T_,13>
11895          {
executeexprtk::details::function_N_node::invoke11896             static inline T_ execute(ifunction& f, T_ (&v)[13])
11897             { 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]); }
11898          };
11899 
11900          template <typename T_>
11901          struct invoke<T_,12>
11902          {
executeexprtk::details::function_N_node::invoke11903             static inline T_ execute(ifunction& f, T_ (&v)[12])
11904             { 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]); }
11905          };
11906 
11907          template <typename T_>
11908          struct invoke<T_,11>
11909          {
executeexprtk::details::function_N_node::invoke11910             static inline T_ execute(ifunction& f, T_ (&v)[11])
11911             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10]); }
11912          };
11913 
11914          template <typename T_>
11915          struct invoke<T_,10>
11916          {
executeexprtk::details::function_N_node::invoke11917             static inline T_ execute(ifunction& f, T_ (&v)[10])
11918             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9]); }
11919          };
11920 
11921          template <typename T_>
11922          struct invoke<T_,9>
11923          {
executeexprtk::details::function_N_node::invoke11924             static inline T_ execute(ifunction& f, T_ (&v)[9])
11925             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8]); }
11926          };
11927 
11928          template <typename T_>
11929          struct invoke<T_,8>
11930          {
executeexprtk::details::function_N_node::invoke11931             static inline T_ execute(ifunction& f, T_ (&v)[8])
11932             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]); }
11933          };
11934 
11935          template <typename T_>
11936          struct invoke<T_,7>
11937          {
executeexprtk::details::function_N_node::invoke11938             static inline T_ execute(ifunction& f, T_ (&v)[7])
11939             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6]); }
11940          };
11941 
11942          template <typename T_>
11943          struct invoke<T_,6>
11944          {
executeexprtk::details::function_N_node::invoke11945             static inline T_ execute(ifunction& f, T_ (&v)[6])
11946             { return f(v[0],v[1],v[2],v[3],v[4],v[5]); }
11947          };
11948 
11949          template <typename T_>
11950          struct invoke<T_,5>
11951          {
executeexprtk::details::function_N_node::invoke11952             static inline T_ execute(ifunction& f, T_ (&v)[5])
11953             { return f(v[0],v[1],v[2],v[3],v[4]); }
11954          };
11955 
11956          template <typename T_>
11957          struct invoke<T_,4>
11958          {
executeexprtk::details::function_N_node::invoke11959             static inline T_ execute(ifunction& f, T_ (&v)[4])
11960             { return f(v[0],v[1],v[2],v[3]); }
11961          };
11962 
11963          template <typename T_>
11964          struct invoke<T_,3>
11965          {
executeexprtk::details::function_N_node::invoke11966             static inline T_ execute(ifunction& f, T_ (&v)[3])
11967             { return f(v[0],v[1],v[2]); }
11968          };
11969 
11970          template <typename T_>
11971          struct invoke<T_,2>
11972          {
executeexprtk::details::function_N_node::invoke11973             static inline T_ execute(ifunction& f, T_ (&v)[2])
11974             { return f(v[0],v[1]); }
11975          };
11976 
11977          template <typename T_>
11978          struct invoke<T_,1>
11979          {
executeexprtk::details::function_N_node::invoke11980             static inline T_ execute(ifunction& f, T_ (&v)[1])
11981             { return f(v[0]); }
11982          };
11983 
type() const11984          inline typename expression_node<T>::node_type type() const
11985          {
11986             return expression_node<T>::e_function;
11987          }
11988 
collect_nodes(typename expression_node<T>::noderef_list_t & node_delete_list)11989          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
11990          {
11991             expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
11992          }
11993 
node_depth() const11994          std::size_t node_depth() const
11995          {
11996             return expression_node<T>::ndb_t::template compute_node_depth<N>(branch_);
11997          }
11998 
11999       private:
12000 
12001          ifunction*  function_;
12002          std::size_t parameter_count_;
12003          branch_t    branch_[N];
12004       };
12005 
12006       template <typename T, typename IFunction>
12007       class function_N_node<T,IFunction,0> : public expression_node<T>
12008       {
12009       public:
12010 
12011          typedef expression_node<T>* expression_ptr;
12012          typedef IFunction ifunction;
12013 
function_N_node(ifunction * func)12014          explicit function_N_node(ifunction* func)
12015          : function_((0 == func->param_count) ? func : reinterpret_cast<ifunction*>(0))
12016          {}
12017 
operator <(const function_N_node<T,IFunction,0> & fn) const12018          inline bool operator <(const function_N_node<T,IFunction,0>& fn) const
12019          {
12020             return this < (&fn);
12021          }
12022 
value() const12023          inline T value() const
12024          {
12025             if (function_)
12026                return (*function_)();
12027             else
12028                return std::numeric_limits<T>::quiet_NaN();
12029          }
12030 
type() const12031          inline typename expression_node<T>::node_type type() const
12032          {
12033             return expression_node<T>::e_function;
12034          }
12035 
12036       private:
12037 
12038          ifunction* function_;
12039       };
12040 
12041       template <typename T, typename VarArgFunction>
12042       class vararg_function_node : public expression_node<T>
12043       {
12044       public:
12045 
12046          typedef expression_node<T>* expression_ptr;
12047 
vararg_function_node(VarArgFunction * func,const std::vector<expression_ptr> & arg_list)12048          vararg_function_node(VarArgFunction*  func,
12049                               const std::vector<expression_ptr>& arg_list)
12050          : function_(func),
12051            arg_list_(arg_list)
12052          {
12053             value_list_.resize(arg_list.size(),std::numeric_limits<T>::quiet_NaN());
12054          }
12055 
operator <(const vararg_function_node<T,VarArgFunction> & fn) const12056          inline bool operator <(const vararg_function_node<T,VarArgFunction>& fn) const
12057          {
12058             return this < (&fn);
12059          }
12060 
value() const12061          inline T value() const
12062          {
12063             if (function_)
12064             {
12065                populate_value_list();
12066                return (*function_)(value_list_);
12067             }
12068             else
12069                return std::numeric_limits<T>::quiet_NaN();
12070          }
12071 
type() const12072          inline typename expression_node<T>::node_type type() const
12073          {
12074             return expression_node<T>::e_vafunction;
12075          }
12076 
collect_nodes(typename expression_node<T>::noderef_list_t & node_delete_list)12077          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
12078          {
12079             for (std::size_t i = 0; i < arg_list_.size(); ++i)
12080             {
12081                if (arg_list_[i] && !details::is_variable_node(arg_list_[i]))
12082                {
12083                   node_delete_list.push_back(&arg_list_[i]);
12084                }
12085             }
12086          }
12087 
node_depth() const12088          std::size_t node_depth() const
12089          {
12090             return expression_node<T>::ndb_t::compute_node_depth(arg_list_);
12091          }
12092 
12093       private:
12094 
populate_value_list() const12095          inline void populate_value_list() const
12096          {
12097             for (std::size_t i = 0; i < arg_list_.size(); ++i)
12098             {
12099                value_list_[i] = arg_list_[i]->value();
12100             }
12101          }
12102 
12103          VarArgFunction* function_;
12104          std::vector<expression_ptr> arg_list_;
12105          mutable std::vector<T> value_list_;
12106       };
12107 
12108       template <typename T, typename GenericFunction>
12109       class generic_function_node : public expression_node<T>
12110       {
12111       public:
12112 
12113          typedef type_store<T>                         type_store_t;
12114          typedef expression_node<T>*                 expression_ptr;
12115          typedef variable_node<T>                   variable_node_t;
12116          typedef vector_node<T>                       vector_node_t;
12117          typedef variable_node_t*               variable_node_ptr_t;
12118          typedef vector_node_t*                   vector_node_ptr_t;
12119          typedef range_interface<T>               range_interface_t;
12120          typedef range_data_type<T>               range_data_type_t;
12121          typedef range_pack<T>                              range_t;
12122          typedef std::pair<expression_ptr,bool>            branch_t;
12123          typedef std::pair<void*,std::size_t>                void_t;
12124          typedef std::vector<T>                            tmp_vs_t;
12125          typedef std::vector<type_store_t>         typestore_list_t;
12126          typedef std::vector<range_data_type_t>        range_list_t;
12127 
generic_function_node(const std::vector<expression_ptr> & arg_list,GenericFunction * func=reinterpret_cast<GenericFunction * > (0))12128          explicit generic_function_node(const std::vector<expression_ptr>& arg_list,
12129                                         GenericFunction* func = reinterpret_cast<GenericFunction*>(0))
12130          : function_(func),
12131            arg_list_(arg_list)
12132          {}
12133 
~generic_function_node()12134          virtual ~generic_function_node()
12135          {}
12136 
collect_nodes(typename expression_node<T>::noderef_list_t & node_delete_list)12137          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
12138          {
12139             expression_node<T>::ndb_t::collect(branch_, node_delete_list);
12140          }
12141 
node_depth() const12142          std::size_t node_depth() const
12143          {
12144             return expression_node<T>::ndb_t::compute_node_depth(branch_);
12145          }
12146 
init_branches()12147          virtual bool init_branches()
12148          {
12149             expr_as_vec1_store_.resize(arg_list_.size(),T(0)               );
12150             typestore_list_    .resize(arg_list_.size(),type_store_t()     );
12151             range_list_        .resize(arg_list_.size(),range_data_type_t());
12152             branch_            .resize(arg_list_.size(),branch_t(reinterpret_cast<expression_ptr>(0),false));
12153 
12154             for (std::size_t i = 0; i < arg_list_.size(); ++i)
12155             {
12156                type_store_t& ts = typestore_list_[i];
12157 
12158                if (0 == arg_list_[i])
12159                   return false;
12160                else if (is_ivector_node(arg_list_[i]))
12161                {
12162                   vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
12163 
12164                   if (0 == (vi = dynamic_cast<vector_interface<T>*>(arg_list_[i])))
12165                      return false;
12166 
12167                   ts.size = vi->size();
12168                   ts.data = vi->vds().data();
12169                   ts.type = type_store_t::e_vector;
12170                   vi->vec()->vec_holder().set_ref(&ts.vec_data);
12171                }
12172                #ifndef exprtk_disable_string_capabilities
12173                else if (is_generally_string_node(arg_list_[i]))
12174                {
12175                   string_base_node<T>* sbn = reinterpret_cast<string_base_node<T>*>(0);
12176 
12177                   if (0 == (sbn = dynamic_cast<string_base_node<T>*>(arg_list_[i])))
12178                      return false;
12179 
12180                   ts.size = sbn->size();
12181                   ts.data = reinterpret_cast<void*>(const_cast<char_ptr>(sbn->base()));
12182                   ts.type = type_store_t::e_string;
12183 
12184                   range_list_[i].data      = ts.data;
12185                   range_list_[i].size      = ts.size;
12186                   range_list_[i].type_size = sizeof(char);
12187                   range_list_[i].str_node  = sbn;
12188 
12189                   range_interface_t* ri = reinterpret_cast<range_interface_t*>(0);
12190 
12191                   if (0 == (ri = dynamic_cast<range_interface_t*>(arg_list_[i])))
12192                      return false;
12193 
12194                   const range_t& rp = ri->range_ref();
12195 
12196                   if (
12197                        rp.const_range() &&
12198                        is_const_string_range_node(arg_list_[i])
12199                      )
12200                   {
12201                      ts.size = rp.const_size();
12202                      ts.data = static_cast<char_ptr>(ts.data) + rp.n0_c.second;
12203                      range_list_[i].range = reinterpret_cast<range_t*>(0);
12204                   }
12205                   else
12206                      range_list_[i].range = &(ri->range_ref());
12207                }
12208                #endif
12209                else if (is_variable_node(arg_list_[i]))
12210                {
12211                   variable_node_ptr_t var = variable_node_ptr_t(0);
12212 
12213                   if (0 == (var = dynamic_cast<variable_node_ptr_t>(arg_list_[i])))
12214                      return false;
12215 
12216                   ts.size = 1;
12217                   ts.data = &var->ref();
12218                   ts.type = type_store_t::e_scalar;
12219                }
12220                else
12221                {
12222                   ts.size = 1;
12223                   ts.data = reinterpret_cast<void*>(&expr_as_vec1_store_[i]);
12224                   ts.type = type_store_t::e_scalar;
12225                }
12226 
12227                branch_[i] = std::make_pair(arg_list_[i],branch_deletable(arg_list_[i]));
12228             }
12229 
12230             return true;
12231          }
12232 
operator <(const generic_function_node<T,GenericFunction> & fn) const12233          inline bool operator <(const generic_function_node<T,GenericFunction>& fn) const
12234          {
12235             return this < (&fn);
12236          }
12237 
value() const12238          inline T value() const
12239          {
12240             if (function_)
12241             {
12242                if (populate_value_list())
12243                {
12244                   typedef typename GenericFunction::parameter_list_t parameter_list_t;
12245 
12246                   return (*function_)(parameter_list_t(typestore_list_));
12247                }
12248             }
12249 
12250             return std::numeric_limits<T>::quiet_NaN();
12251          }
12252 
type() const12253          inline typename expression_node<T>::node_type type() const
12254          {
12255             return expression_node<T>::e_genfunction;
12256          }
12257 
12258       protected:
12259 
populate_value_list() const12260          inline virtual bool populate_value_list() const
12261          {
12262             for (std::size_t i = 0; i < branch_.size(); ++i)
12263             {
12264                expr_as_vec1_store_[i] = branch_[i].first->value();
12265             }
12266 
12267             for (std::size_t i = 0; i < branch_.size(); ++i)
12268             {
12269                range_data_type_t& rdt = range_list_[i];
12270 
12271                if (rdt.range)
12272                {
12273                   const range_t& rp = (*rdt.range);
12274                   std::size_t r0    = 0;
12275                   std::size_t r1    = 0;
12276 
12277                   if (rp(r0, r1, rdt.size))
12278                   {
12279                      type_store_t& ts = typestore_list_[i];
12280 
12281                      ts.size = rp.cache_size();
12282                      #ifndef exprtk_disable_string_capabilities
12283                      if (ts.type == type_store_t::e_string)
12284                         ts.data = const_cast<char_ptr>(rdt.str_node->base()) + rp.cache.first;
12285                      else
12286                      #endif
12287                         ts.data = static_cast<char_ptr>(rdt.data) + (rp.cache.first * rdt.type_size);
12288                   }
12289                   else
12290                      return false;
12291                }
12292             }
12293 
12294             return true;
12295          }
12296 
12297          GenericFunction* function_;
12298          mutable typestore_list_t typestore_list_;
12299 
12300       private:
12301 
12302          std::vector<expression_ptr> arg_list_;
12303          std::vector<branch_t>         branch_;
12304          mutable tmp_vs_t  expr_as_vec1_store_;
12305          mutable range_list_t      range_list_;
12306       };
12307 
12308       #ifndef exprtk_disable_string_capabilities
12309       template <typename T, typename StringFunction>
12310       class string_function_node : public generic_function_node<T,StringFunction>,
12311                                    public string_base_node<T>,
12312                                    public range_interface <T>
12313       {
12314       public:
12315 
12316          typedef generic_function_node<T,StringFunction> gen_function_t;
12317          typedef range_pack<T> range_t;
12318 
string_function_node(StringFunction * func,const std::vector<typename gen_function_t::expression_ptr> & arg_list)12319          string_function_node(StringFunction* func,
12320                               const std::vector<typename gen_function_t::expression_ptr>& arg_list)
12321          : gen_function_t(arg_list,func)
12322          {
12323             range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
12324             range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
12325             range_.cache.first  = range_.n0_c.second;
12326             range_.cache.second = range_.n1_c.second;
12327          }
12328 
operator <(const string_function_node<T,StringFunction> & fn) const12329          inline bool operator <(const string_function_node<T,StringFunction>& fn) const
12330          {
12331             return this < (&fn);
12332          }
12333 
value() const12334          inline T value() const
12335          {
12336             if (gen_function_t::function_)
12337             {
12338                if (gen_function_t::populate_value_list())
12339                {
12340                   typedef typename StringFunction::parameter_list_t parameter_list_t;
12341 
12342                   const T result = (*gen_function_t::function_)
12343                                       (
12344                                         ret_string_,
12345                                         parameter_list_t(gen_function_t::typestore_list_)
12346                                       );
12347 
12348                   range_.n1_c.second  = ret_string_.size() - 1;
12349                   range_.cache.second = range_.n1_c.second;
12350 
12351                   return result;
12352                }
12353             }
12354 
12355             return std::numeric_limits<T>::quiet_NaN();
12356          }
12357 
type() const12358          inline typename expression_node<T>::node_type type() const
12359          {
12360             return expression_node<T>::e_strfunction;
12361          }
12362 
str() const12363          std::string str() const
12364          {
12365             return ret_string_;
12366          }
12367 
base() const12368          char_cptr base() const
12369          {
12370            return &ret_string_[0];
12371          }
12372 
size() const12373          std::size_t size() const
12374          {
12375             return ret_string_.size();
12376          }
12377 
range_ref()12378          range_t& range_ref()
12379          {
12380             return range_;
12381          }
12382 
range_ref() const12383          const range_t& range_ref() const
12384          {
12385             return range_;
12386          }
12387 
12388       protected:
12389 
12390          mutable range_t     range_;
12391          mutable std::string ret_string_;
12392       };
12393       #endif
12394 
12395       template <typename T, typename GenericFunction>
12396       class multimode_genfunction_node : public generic_function_node<T,GenericFunction>
12397       {
12398       public:
12399 
12400          typedef generic_function_node<T,GenericFunction> gen_function_t;
12401          typedef range_pack<T> range_t;
12402 
multimode_genfunction_node(GenericFunction * func,const std::size_t & param_seq_index,const std::vector<typename gen_function_t::expression_ptr> & arg_list)12403          multimode_genfunction_node(GenericFunction* func,
12404                                     const std::size_t& param_seq_index,
12405                                     const std::vector<typename gen_function_t::expression_ptr>& arg_list)
12406          : gen_function_t(arg_list,func),
12407            param_seq_index_(param_seq_index)
12408          {}
12409 
value() const12410          inline T value() const
12411          {
12412             if (gen_function_t::function_)
12413             {
12414                if (gen_function_t::populate_value_list())
12415                {
12416                   typedef typename GenericFunction::parameter_list_t parameter_list_t;
12417 
12418                   return (*gen_function_t::function_)
12419                             (
12420                               param_seq_index_,
12421                               parameter_list_t(gen_function_t::typestore_list_)
12422                             );
12423                }
12424             }
12425 
12426             return std::numeric_limits<T>::quiet_NaN();
12427          }
12428 
type() const12429          inline typename expression_node<T>::node_type type() const
12430          {
12431             return expression_node<T>::e_genfunction;
12432          }
12433 
12434       private:
12435 
12436          std::size_t param_seq_index_;
12437       };
12438 
12439       #ifndef exprtk_disable_string_capabilities
12440       template <typename T, typename StringFunction>
12441       class multimode_strfunction_node : public string_function_node<T,StringFunction>
12442       {
12443       public:
12444 
12445          typedef string_function_node<T,StringFunction> str_function_t;
12446          typedef range_pack<T> range_t;
12447 
multimode_strfunction_node(StringFunction * func,const std::size_t & param_seq_index,const std::vector<typename str_function_t::expression_ptr> & arg_list)12448          multimode_strfunction_node(StringFunction* func,
12449                                     const std::size_t& param_seq_index,
12450                                     const std::vector<typename str_function_t::expression_ptr>& arg_list)
12451          : str_function_t(func,arg_list),
12452            param_seq_index_(param_seq_index)
12453          {}
12454 
value() const12455          inline T value() const
12456          {
12457             if (str_function_t::function_)
12458             {
12459                if (str_function_t::populate_value_list())
12460                {
12461                   typedef typename StringFunction::parameter_list_t parameter_list_t;
12462 
12463                   const T result = (*str_function_t::function_)
12464                                       (
12465                                         param_seq_index_,
12466                                         str_function_t::ret_string_,
12467                                         parameter_list_t(str_function_t::typestore_list_)
12468                                       );
12469 
12470                   str_function_t::range_.n1_c.second  = str_function_t::ret_string_.size() - 1;
12471                   str_function_t::range_.cache.second = str_function_t::range_.n1_c.second;
12472 
12473                   return result;
12474                }
12475             }
12476 
12477             return std::numeric_limits<T>::quiet_NaN();
12478          }
12479 
type() const12480          inline typename expression_node<T>::node_type type() const
12481          {
12482             return expression_node<T>::e_strfunction;
12483          }
12484 
12485       private:
12486 
12487          const std::size_t param_seq_index_;
12488       };
12489       #endif
12490 
12491       class return_exception
12492       {};
12493 
12494       template <typename T>
12495       class null_igenfunc
12496       {
12497       public:
12498 
~null_igenfunc()12499          virtual ~null_igenfunc()
12500          {}
12501 
12502          typedef type_store<T> generic_type;
12503          typedef typename generic_type::parameter_list parameter_list_t;
12504 
operator ()(parameter_list_t)12505          inline virtual T operator() (parameter_list_t)
12506          {
12507             return std::numeric_limits<T>::quiet_NaN();
12508          }
12509       };
12510 
12511       #ifndef exprtk_disable_return_statement
12512       template <typename T>
12513       class return_node : public generic_function_node<T,null_igenfunc<T> >
12514       {
12515       public:
12516 
12517          typedef null_igenfunc<T> igeneric_function_t;
12518          typedef igeneric_function_t* igeneric_function_ptr;
12519          typedef generic_function_node<T,igeneric_function_t> gen_function_t;
12520          typedef results_context<T> results_context_t;
12521 
return_node(const std::vector<typename gen_function_t::expression_ptr> & arg_list,results_context_t & rc)12522          return_node(const std::vector<typename gen_function_t::expression_ptr>& arg_list,
12523                      results_context_t& rc)
12524          : gen_function_t  (arg_list),
12525            results_context_(&rc)
12526          {}
12527 
value() const12528          inline T value() const
12529          {
12530             if (
12531                  (0 != results_context_) &&
12532                  gen_function_t::populate_value_list()
12533                )
12534             {
12535                typedef typename type_store<T>::parameter_list parameter_list_t;
12536 
12537                results_context_->
12538                   assign(parameter_list_t(gen_function_t::typestore_list_));
12539 
12540                throw return_exception();
12541             }
12542 
12543             return std::numeric_limits<T>::quiet_NaN();
12544          }
12545 
type() const12546          inline typename expression_node<T>::node_type type() const
12547          {
12548             return expression_node<T>::e_return;
12549          }
12550 
12551       private:
12552 
12553          results_context_t* results_context_;
12554       };
12555 
12556       template <typename T>
12557       class return_envelope_node : public expression_node<T>
12558       {
12559       public:
12560 
12561          typedef expression_node<T>* expression_ptr;
12562          typedef results_context<T>  results_context_t;
12563          typedef std::pair<expression_ptr,bool> branch_t;
12564 
return_envelope_node(expression_ptr body,results_context_t & rc)12565          return_envelope_node(expression_ptr body, results_context_t& rc)
12566          : results_context_(&rc  ),
12567            return_invoked_ (false)
12568          {
12569             construct_branch_pair(body_, body);
12570          }
12571 
value() const12572          inline T value() const
12573          {
12574             assert(body_.first);
12575 
12576             try
12577             {
12578                return_invoked_ = false;
12579                results_context_->clear();
12580 
12581                return body_.first->value();
12582             }
12583             catch(const return_exception&)
12584             {
12585                return_invoked_ = true;
12586                return std::numeric_limits<T>::quiet_NaN();
12587             }
12588          }
12589 
type() const12590          inline typename expression_node<T>::node_type type() const
12591          {
12592             return expression_node<T>::e_retenv;
12593          }
12594 
retinvk_ptr()12595          inline bool* retinvk_ptr()
12596          {
12597             return &return_invoked_;
12598          }
12599 
collect_nodes(typename expression_node<T>::noderef_list_t & node_delete_list)12600          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
12601          {
12602             expression_node<T>::ndb_t::collect(body_, node_delete_list);
12603          }
12604 
node_depth() const12605          std::size_t node_depth() const
12606          {
12607             return expression_node<T>::ndb_t::compute_node_depth(body_);
12608          }
12609 
12610       private:
12611 
12612          results_context_t* results_context_;
12613          mutable bool        return_invoked_;
12614          branch_t                      body_;
12615       };
12616       #endif
12617 
12618       #define exprtk_define_unary_op(OpName)                    \
12619       template <typename T>                                     \
12620       struct OpName##_op                                        \
12621       {                                                         \
12622          typedef typename functor_t<T>::Type Type;              \
12623          typedef typename expression_node<T>::node_type node_t; \
12624                                                                 \
12625          static inline T process(Type v)                        \
12626          {                                                      \
12627             return numeric:: OpName (v);                        \
12628          }                                                      \
12629                                                                 \
12630          static inline node_t type()                            \
12631          {                                                      \
12632             return expression_node<T>::e_##OpName;              \
12633          }                                                      \
12634                                                                 \
12635          static inline details::operator_type operation()       \
12636          {                                                      \
12637             return details::e_##OpName;                         \
12638          }                                                      \
12639       };                                                        \
12640 
12641       exprtk_define_unary_op(abs  )
12642       exprtk_define_unary_op(acos )
12643       exprtk_define_unary_op(acosh)
12644       exprtk_define_unary_op(asin )
12645       exprtk_define_unary_op(asinh)
12646       exprtk_define_unary_op(atan )
12647       exprtk_define_unary_op(atanh)
12648       exprtk_define_unary_op(ceil )
12649       exprtk_define_unary_op(cos  )
12650       exprtk_define_unary_op(cosh )
12651       exprtk_define_unary_op(cot  )
12652       exprtk_define_unary_op(csc  )
12653       exprtk_define_unary_op(d2g  )
12654       exprtk_define_unary_op(d2r  )
12655       exprtk_define_unary_op(erf  )
12656       exprtk_define_unary_op(erfc )
12657       exprtk_define_unary_op(exp  )
12658       exprtk_define_unary_op(expm1)
12659       exprtk_define_unary_op(floor)
12660       exprtk_define_unary_op(frac )
12661       exprtk_define_unary_op(g2d  )
12662       exprtk_define_unary_op(log  )
12663       exprtk_define_unary_op(log10)
12664       exprtk_define_unary_op(log2 )
12665       exprtk_define_unary_op(log1p)
12666       exprtk_define_unary_op(ncdf )
12667       exprtk_define_unary_op(neg  )
12668       exprtk_define_unary_op(notl )
12669       exprtk_define_unary_op(pos  )
12670       exprtk_define_unary_op(r2d  )
12671       exprtk_define_unary_op(round)
12672       exprtk_define_unary_op(sec  )
12673       exprtk_define_unary_op(sgn  )
12674       exprtk_define_unary_op(sin  )
12675       exprtk_define_unary_op(sinc )
12676       exprtk_define_unary_op(sinh )
12677       exprtk_define_unary_op(sqrt )
12678       exprtk_define_unary_op(tan  )
12679       exprtk_define_unary_op(tanh )
12680       exprtk_define_unary_op(trunc)
12681       #undef exprtk_define_unary_op
12682 
12683       template <typename T>
12684       struct opr_base
12685       {
12686          typedef typename details::functor_t<T>::Type    Type;
12687          typedef typename details::functor_t<T>::RefType RefType;
12688          typedef typename details::functor_t<T>          functor_t;
12689          typedef typename functor_t::qfunc_t  quaternary_functor_t;
12690          typedef typename functor_t::tfunc_t     trinary_functor_t;
12691          typedef typename functor_t::bfunc_t      binary_functor_t;
12692          typedef typename functor_t::ufunc_t       unary_functor_t;
12693       };
12694 
12695       template <typename T>
12696       struct add_op : public opr_base<T>
12697       {
12698          typedef typename opr_base<T>::Type    Type;
12699          typedef typename opr_base<T>::RefType RefType;
12700 
processexprtk::details::add_op12701          static inline T process(Type t1, Type t2) { return t1 + t2; }
processexprtk::details::add_op12702          static inline T process(Type t1, Type t2, Type t3) { return t1 + t2 + t3; }
assignexprtk::details::add_op12703          static inline void assign(RefType t1, Type t2) { t1 += t2; }
typeexprtk::details::add_op12704          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_add; }
operationexprtk::details::add_op12705          static inline details::operator_type operation() { return details::e_add; }
12706       };
12707 
12708       template <typename T>
12709       struct mul_op : public opr_base<T>
12710       {
12711          typedef typename opr_base<T>::Type    Type;
12712          typedef typename opr_base<T>::RefType RefType;
12713 
processexprtk::details::mul_op12714          static inline T process(Type t1, Type t2) { return t1 * t2; }
processexprtk::details::mul_op12715          static inline T process(Type t1, Type t2, Type t3) { return t1 * t2 * t3; }
assignexprtk::details::mul_op12716          static inline void assign(RefType t1, Type t2) { t1 *= t2; }
typeexprtk::details::mul_op12717          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mul; }
operationexprtk::details::mul_op12718          static inline details::operator_type operation() { return details::e_mul; }
12719       };
12720 
12721       template <typename T>
12722       struct sub_op : public opr_base<T>
12723       {
12724          typedef typename opr_base<T>::Type    Type;
12725          typedef typename opr_base<T>::RefType RefType;
12726 
processexprtk::details::sub_op12727          static inline T process(Type t1, Type t2) { return t1 - t2; }
processexprtk::details::sub_op12728          static inline T process(Type t1, Type t2, Type t3) { return t1 - t2 - t3; }
assignexprtk::details::sub_op12729          static inline void assign(RefType t1, Type t2) { t1 -= t2; }
typeexprtk::details::sub_op12730          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_sub; }
operationexprtk::details::sub_op12731          static inline details::operator_type operation() { return details::e_sub; }
12732       };
12733 
12734       template <typename T>
12735       struct div_op : public opr_base<T>
12736       {
12737          typedef typename opr_base<T>::Type    Type;
12738          typedef typename opr_base<T>::RefType RefType;
12739 
processexprtk::details::div_op12740          static inline T process(Type t1, Type t2) { return t1 / t2; }
processexprtk::details::div_op12741          static inline T process(Type t1, Type t2, Type t3) { return t1 / t2 / t3; }
assignexprtk::details::div_op12742          static inline void assign(RefType t1, Type t2) { t1 /= t2; }
typeexprtk::details::div_op12743          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_div; }
operationexprtk::details::div_op12744          static inline details::operator_type operation() { return details::e_div; }
12745       };
12746 
12747       template <typename T>
12748       struct mod_op : public opr_base<T>
12749       {
12750          typedef typename opr_base<T>::Type    Type;
12751          typedef typename opr_base<T>::RefType RefType;
12752 
processexprtk::details::mod_op12753          static inline T process(Type t1, Type t2) { return numeric::modulus<T>(t1,t2); }
assignexprtk::details::mod_op12754          static inline void assign(RefType t1, Type t2) { t1 = numeric::modulus<T>(t1,t2); }
typeexprtk::details::mod_op12755          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mod; }
operationexprtk::details::mod_op12756          static inline details::operator_type operation() { return details::e_mod; }
12757       };
12758 
12759       template <typename T>
12760       struct pow_op : public opr_base<T>
12761       {
12762          typedef typename opr_base<T>::Type    Type;
12763          typedef typename opr_base<T>::RefType RefType;
12764 
processexprtk::details::pow_op12765          static inline T process(Type t1, Type t2) { return numeric::pow<T>(t1,t2); }
assignexprtk::details::pow_op12766          static inline void assign(RefType t1, Type t2) { t1 = numeric::pow<T>(t1,t2); }
typeexprtk::details::pow_op12767          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_pow; }
operationexprtk::details::pow_op12768          static inline details::operator_type operation() { return details::e_pow; }
12769       };
12770 
12771       template <typename T>
12772       struct lt_op : public opr_base<T>
12773       {
12774          typedef typename opr_base<T>::Type Type;
12775 
processexprtk::details::lt_op12776          static inline T process(Type t1, Type t2) { return ((t1 < t2) ? T(1) : T(0)); }
processexprtk::details::lt_op12777          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 < t2) ? T(1) : T(0)); }
typeexprtk::details::lt_op12778          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lt; }
operationexprtk::details::lt_op12779          static inline details::operator_type operation() { return details::e_lt; }
12780       };
12781 
12782       template <typename T>
12783       struct lte_op : public opr_base<T>
12784       {
12785          typedef typename opr_base<T>::Type Type;
12786 
processexprtk::details::lte_op12787          static inline T process(Type t1, Type t2) { return ((t1 <= t2) ? T(1) : T(0)); }
processexprtk::details::lte_op12788          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 <= t2) ? T(1) : T(0)); }
typeexprtk::details::lte_op12789          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lte; }
operationexprtk::details::lte_op12790          static inline details::operator_type operation() { return details::e_lte; }
12791       };
12792 
12793       template <typename T>
12794       struct gt_op : public opr_base<T>
12795       {
12796          typedef typename opr_base<T>::Type Type;
12797 
processexprtk::details::gt_op12798          static inline T process(Type t1, Type t2) { return ((t1 > t2) ? T(1) : T(0)); }
processexprtk::details::gt_op12799          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 > t2) ? T(1) : T(0)); }
typeexprtk::details::gt_op12800          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gt; }
operationexprtk::details::gt_op12801          static inline details::operator_type operation() { return details::e_gt; }
12802       };
12803 
12804       template <typename T>
12805       struct gte_op : public opr_base<T>
12806       {
12807          typedef typename opr_base<T>::Type Type;
12808 
processexprtk::details::gte_op12809          static inline T process(Type t1, Type t2) { return ((t1 >= t2) ? T(1) : T(0)); }
processexprtk::details::gte_op12810          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 >= t2) ? T(1) : T(0)); }
typeexprtk::details::gte_op12811          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gte; }
operationexprtk::details::gte_op12812          static inline details::operator_type operation() { return details::e_gte; }
12813       };
12814 
12815       template <typename T>
12816       struct eq_op : public opr_base<T>
12817       {
12818          typedef typename opr_base<T>::Type Type;
processexprtk::details::eq_op12819          static inline T process(Type t1, Type t2) { return (std::equal_to<T>()(t1,t2) ? T(1) : T(0)); }
processexprtk::details::eq_op12820          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); }
typeexprtk::details::eq_op12821          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_eq; }
operationexprtk::details::eq_op12822          static inline details::operator_type operation() { return details::e_eq; }
12823       };
12824 
12825       template <typename T>
12826       struct equal_op : public opr_base<T>
12827       {
12828          typedef typename opr_base<T>::Type Type;
12829 
processexprtk::details::equal_op12830          static inline T process(Type t1, Type t2) { return numeric::equal(t1,t2); }
processexprtk::details::equal_op12831          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); }
typeexprtk::details::equal_op12832          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_eq; }
operationexprtk::details::equal_op12833          static inline details::operator_type operation() { return details::e_equal; }
12834       };
12835 
12836       template <typename T>
12837       struct ne_op : public opr_base<T>
12838       {
12839          typedef typename opr_base<T>::Type Type;
12840 
processexprtk::details::ne_op12841          static inline T process(Type t1, Type t2) { return (std::not_equal_to<T>()(t1,t2) ? T(1) : T(0)); }
processexprtk::details::ne_op12842          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 != t2) ? T(1) : T(0)); }
typeexprtk::details::ne_op12843          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ne; }
operationexprtk::details::ne_op12844          static inline details::operator_type operation() { return details::e_ne; }
12845       };
12846 
12847       template <typename T>
12848       struct and_op : public opr_base<T>
12849       {
12850          typedef typename opr_base<T>::Type Type;
12851 
processexprtk::details::and_op12852          static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(1) : T(0); }
typeexprtk::details::and_op12853          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_and; }
operationexprtk::details::and_op12854          static inline details::operator_type operation() { return details::e_and; }
12855       };
12856 
12857       template <typename T>
12858       struct nand_op : public opr_base<T>
12859       {
12860          typedef typename opr_base<T>::Type Type;
12861 
processexprtk::details::nand_op12862          static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(0) : T(1); }
typeexprtk::details::nand_op12863          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nand; }
operationexprtk::details::nand_op12864          static inline details::operator_type operation() { return details::e_nand; }
12865       };
12866 
12867       template <typename T>
12868       struct or_op : public opr_base<T>
12869       {
12870          typedef typename opr_base<T>::Type Type;
12871 
processexprtk::details::or_op12872          static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(1) : T(0); }
typeexprtk::details::or_op12873          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_or; }
operationexprtk::details::or_op12874          static inline details::operator_type operation() { return details::e_or; }
12875       };
12876 
12877       template <typename T>
12878       struct nor_op : public opr_base<T>
12879       {
12880          typedef typename opr_base<T>::Type Type;
12881 
processexprtk::details::nor_op12882          static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(0) : T(1); }
typeexprtk::details::nor_op12883          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
operationexprtk::details::nor_op12884          static inline details::operator_type operation() { return details::e_nor; }
12885       };
12886 
12887       template <typename T>
12888       struct xor_op : public opr_base<T>
12889       {
12890          typedef typename opr_base<T>::Type Type;
12891 
processexprtk::details::xor_op12892          static inline T process(Type t1, Type t2) { return numeric::xor_opr<T>(t1,t2); }
typeexprtk::details::xor_op12893          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
operationexprtk::details::xor_op12894          static inline details::operator_type operation() { return details::e_xor; }
12895       };
12896 
12897       template <typename T>
12898       struct xnor_op : public opr_base<T>
12899       {
12900          typedef typename opr_base<T>::Type Type;
12901 
processexprtk::details::xnor_op12902          static inline T process(Type t1, Type t2) { return numeric::xnor_opr<T>(t1,t2); }
typeexprtk::details::xnor_op12903          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
operationexprtk::details::xnor_op12904          static inline details::operator_type operation() { return details::e_xnor; }
12905       };
12906 
12907       template <typename T>
12908       struct in_op : public opr_base<T>
12909       {
12910          typedef typename opr_base<T>::Type Type;
12911 
processexprtk::details::in_op12912          static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
processexprtk::details::in_op12913          static inline T process(const std::string& t1, const std::string& t2) { return ((std::string::npos != t2.find(t1)) ? T(1) : T(0)); }
typeexprtk::details::in_op12914          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_in; }
operationexprtk::details::in_op12915          static inline details::operator_type operation() { return details::e_in; }
12916       };
12917 
12918       template <typename T>
12919       struct like_op : public opr_base<T>
12920       {
12921          typedef typename opr_base<T>::Type Type;
12922 
processexprtk::details::like_op12923          static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
processexprtk::details::like_op12924          static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_match(t2,t1) ? T(1) : T(0)); }
typeexprtk::details::like_op12925          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_like; }
operationexprtk::details::like_op12926          static inline details::operator_type operation() { return details::e_like; }
12927       };
12928 
12929       template <typename T>
12930       struct ilike_op : public opr_base<T>
12931       {
12932          typedef typename opr_base<T>::Type Type;
12933 
processexprtk::details::ilike_op12934          static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
processexprtk::details::ilike_op12935          static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_imatch(t2,t1) ? T(1) : T(0)); }
typeexprtk::details::ilike_op12936          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ilike; }
operationexprtk::details::ilike_op12937          static inline details::operator_type operation() { return details::e_ilike; }
12938       };
12939 
12940       template <typename T>
12941       struct inrange_op : public opr_base<T>
12942       {
12943          typedef typename opr_base<T>::Type Type;
12944 
processexprtk::details::inrange_op12945          static inline T process(const T& t0, const T& t1, const T& t2) { return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); }
processexprtk::details::inrange_op12946          static inline T process(const std::string& t0, const std::string& t1, const std::string& t2)
12947          {
12948             return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0);
12949          }
typeexprtk::details::inrange_op12950          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_inranges; }
operationexprtk::details::inrange_op12951          static inline details::operator_type operation() { return details::e_inrange; }
12952       };
12953 
12954       template <typename T>
value(details::expression_node<T> * n)12955       inline T value(details::expression_node<T>* n)
12956       {
12957          return n->value();
12958       }
12959 
12960       template <typename T>
value(std::pair<details::expression_node<T> *,bool> n)12961       inline T value(std::pair<details::expression_node<T>*,bool> n)
12962       {
12963          return n.first->value();
12964       }
12965 
12966       template <typename T>
value(const T * t)12967       inline T value(const T* t)
12968       {
12969          return (*t);
12970       }
12971 
12972       template <typename T>
value(const T & t)12973       inline T value(const T& t)
12974       {
12975          return t;
12976       }
12977 
12978       template <typename T>
12979       struct vararg_add_op : public opr_base<T>
12980       {
12981          typedef typename opr_base<T>::Type Type;
12982 
12983          template <typename Type,
12984                    typename Allocator,
12985                    template <typename, typename> class Sequence>
processexprtk::details::vararg_add_op12986          static inline T process(const Sequence<Type,Allocator>& arg_list)
12987          {
12988             switch (arg_list.size())
12989             {
12990                case 0  : return T(0);
12991                case 1  : return process_1(arg_list);
12992                case 2  : return process_2(arg_list);
12993                case 3  : return process_3(arg_list);
12994                case 4  : return process_4(arg_list);
12995                case 5  : return process_5(arg_list);
12996                default :
12997                          {
12998                             T result = T(0);
12999 
13000                             for (std::size_t i = 0; i < arg_list.size(); ++i)
13001                             {
13002                               result += value(arg_list[i]);
13003                             }
13004 
13005                             return result;
13006                          }
13007             }
13008          }
13009 
13010          template <typename Sequence>
process_1exprtk::details::vararg_add_op13011          static inline T process_1(const Sequence& arg_list)
13012          {
13013             return value(arg_list[0]);
13014          }
13015 
13016          template <typename Sequence>
process_2exprtk::details::vararg_add_op13017          static inline T process_2(const Sequence& arg_list)
13018          {
13019             return value(arg_list[0]) + value(arg_list[1]);
13020          }
13021 
13022          template <typename Sequence>
process_3exprtk::details::vararg_add_op13023          static inline T process_3(const Sequence& arg_list)
13024          {
13025             return value(arg_list[0]) + value(arg_list[1]) +
13026                    value(arg_list[2]) ;
13027          }
13028 
13029          template <typename Sequence>
process_4exprtk::details::vararg_add_op13030          static inline T process_4(const Sequence& arg_list)
13031          {
13032             return value(arg_list[0]) + value(arg_list[1]) +
13033                    value(arg_list[2]) + value(arg_list[3]) ;
13034          }
13035 
13036          template <typename Sequence>
process_5exprtk::details::vararg_add_op13037          static inline T process_5(const Sequence& arg_list)
13038          {
13039             return value(arg_list[0]) + value(arg_list[1]) +
13040                    value(arg_list[2]) + value(arg_list[3]) +
13041                    value(arg_list[4]) ;
13042          }
13043       };
13044 
13045       template <typename T>
13046       struct vararg_mul_op : public opr_base<T>
13047       {
13048          typedef typename opr_base<T>::Type Type;
13049 
13050          template <typename Type,
13051                    typename Allocator,
13052                    template <typename, typename> class Sequence>
processexprtk::details::vararg_mul_op13053          static inline T process(const Sequence<Type,Allocator>& arg_list)
13054          {
13055             switch (arg_list.size())
13056             {
13057                case 0  : return T(0);
13058                case 1  : return process_1(arg_list);
13059                case 2  : return process_2(arg_list);
13060                case 3  : return process_3(arg_list);
13061                case 4  : return process_4(arg_list);
13062                case 5  : return process_5(arg_list);
13063                default :
13064                          {
13065                             T result = T(value(arg_list[0]));
13066 
13067                             for (std::size_t i = 1; i < arg_list.size(); ++i)
13068                             {
13069                                result *= value(arg_list[i]);
13070                             }
13071 
13072                             return result;
13073                          }
13074             }
13075          }
13076 
13077          template <typename Sequence>
process_1exprtk::details::vararg_mul_op13078          static inline T process_1(const Sequence& arg_list)
13079          {
13080             return value(arg_list[0]);
13081          }
13082 
13083          template <typename Sequence>
process_2exprtk::details::vararg_mul_op13084          static inline T process_2(const Sequence& arg_list)
13085          {
13086             return value(arg_list[0]) * value(arg_list[1]);
13087          }
13088 
13089          template <typename Sequence>
process_3exprtk::details::vararg_mul_op13090          static inline T process_3(const Sequence& arg_list)
13091          {
13092             return value(arg_list[0]) * value(arg_list[1]) *
13093                    value(arg_list[2]) ;
13094          }
13095 
13096          template <typename Sequence>
process_4exprtk::details::vararg_mul_op13097          static inline T process_4(const Sequence& arg_list)
13098          {
13099             return value(arg_list[0]) * value(arg_list[1]) *
13100                    value(arg_list[2]) * value(arg_list[3]) ;
13101          }
13102 
13103          template <typename Sequence>
process_5exprtk::details::vararg_mul_op13104          static inline T process_5(const Sequence& arg_list)
13105          {
13106             return value(arg_list[0]) * value(arg_list[1]) *
13107                    value(arg_list[2]) * value(arg_list[3]) *
13108                    value(arg_list[4]) ;
13109          }
13110       };
13111 
13112       template <typename T>
13113       struct vararg_avg_op : public opr_base<T>
13114       {
13115          typedef typename opr_base<T>::Type Type;
13116 
13117          template <typename Type,
13118                    typename Allocator,
13119                    template <typename, typename> class Sequence>
processexprtk::details::vararg_avg_op13120          static inline T process(const Sequence<Type,Allocator>& arg_list)
13121          {
13122             switch (arg_list.size())
13123             {
13124                case 0  : return T(0);
13125                case 1  : return process_1(arg_list);
13126                case 2  : return process_2(arg_list);
13127                case 3  : return process_3(arg_list);
13128                case 4  : return process_4(arg_list);
13129                case 5  : return process_5(arg_list);
13130                default : return vararg_add_op<T>::process(arg_list) / arg_list.size();
13131             }
13132          }
13133 
13134          template <typename Sequence>
process_1exprtk::details::vararg_avg_op13135          static inline T process_1(const Sequence& arg_list)
13136          {
13137             return value(arg_list[0]);
13138          }
13139 
13140          template <typename Sequence>
process_2exprtk::details::vararg_avg_op13141          static inline T process_2(const Sequence& arg_list)
13142          {
13143             return (value(arg_list[0]) + value(arg_list[1])) / T(2);
13144          }
13145 
13146          template <typename Sequence>
process_3exprtk::details::vararg_avg_op13147          static inline T process_3(const Sequence& arg_list)
13148          {
13149             return (value(arg_list[0]) + value(arg_list[1]) + value(arg_list[2])) / T(3);
13150          }
13151 
13152          template <typename Sequence>
process_4exprtk::details::vararg_avg_op13153          static inline T process_4(const Sequence& arg_list)
13154          {
13155             return (value(arg_list[0]) + value(arg_list[1]) +
13156                     value(arg_list[2]) + value(arg_list[3])) / T(4);
13157          }
13158 
13159          template <typename Sequence>
process_5exprtk::details::vararg_avg_op13160          static inline T process_5(const Sequence& arg_list)
13161          {
13162             return (value(arg_list[0]) + value(arg_list[1]) +
13163                     value(arg_list[2]) + value(arg_list[3]) +
13164                     value(arg_list[4])) / T(5);
13165          }
13166       };
13167 
13168       template <typename T>
13169       struct vararg_min_op : public opr_base<T>
13170       {
13171          typedef typename opr_base<T>::Type Type;
13172 
13173          template <typename Type,
13174                    typename Allocator,
13175                    template <typename, typename> class Sequence>
processexprtk::details::vararg_min_op13176          static inline T process(const Sequence<Type,Allocator>& arg_list)
13177          {
13178             switch (arg_list.size())
13179             {
13180                case 0  : return T(0);
13181                case 1  : return process_1(arg_list);
13182                case 2  : return process_2(arg_list);
13183                case 3  : return process_3(arg_list);
13184                case 4  : return process_4(arg_list);
13185                case 5  : return process_5(arg_list);
13186                default :
13187                          {
13188                             T result = T(value(arg_list[0]));
13189 
13190                             for (std::size_t i = 1; i < arg_list.size(); ++i)
13191                             {
13192                                const T v = value(arg_list[i]);
13193 
13194                                if (v < result)
13195                                   result = v;
13196                             }
13197 
13198                             return result;
13199                          }
13200             }
13201          }
13202 
13203          template <typename Sequence>
process_1exprtk::details::vararg_min_op13204          static inline T process_1(const Sequence& arg_list)
13205          {
13206             return value(arg_list[0]);
13207          }
13208 
13209          template <typename Sequence>
process_2exprtk::details::vararg_min_op13210          static inline T process_2(const Sequence& arg_list)
13211          {
13212             return std::min<T>(value(arg_list[0]),value(arg_list[1]));
13213          }
13214 
13215          template <typename Sequence>
process_3exprtk::details::vararg_min_op13216          static inline T process_3(const Sequence& arg_list)
13217          {
13218             return std::min<T>(std::min<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2]));
13219          }
13220 
13221          template <typename Sequence>
process_4exprtk::details::vararg_min_op13222          static inline T process_4(const Sequence& arg_list)
13223          {
13224             return std::min<T>(
13225                         std::min<T>(value(arg_list[0]), value(arg_list[1])),
13226                         std::min<T>(value(arg_list[2]), value(arg_list[3])));
13227          }
13228 
13229          template <typename Sequence>
process_5exprtk::details::vararg_min_op13230          static inline T process_5(const Sequence& arg_list)
13231          {
13232             return std::min<T>(
13233                    std::min<T>(std::min<T>(value(arg_list[0]), value(arg_list[1])),
13234                                std::min<T>(value(arg_list[2]), value(arg_list[3]))),
13235                                value(arg_list[4]));
13236          }
13237       };
13238 
13239       template <typename T>
13240       struct vararg_max_op : public opr_base<T>
13241       {
13242          typedef typename opr_base<T>::Type Type;
13243 
13244          template <typename Type,
13245                    typename Allocator,
13246                    template <typename, typename> class Sequence>
processexprtk::details::vararg_max_op13247          static inline T process(const Sequence<Type,Allocator>& arg_list)
13248          {
13249             switch (arg_list.size())
13250             {
13251                case 0  : return T(0);
13252                case 1  : return process_1(arg_list);
13253                case 2  : return process_2(arg_list);
13254                case 3  : return process_3(arg_list);
13255                case 4  : return process_4(arg_list);
13256                case 5  : return process_5(arg_list);
13257                default :
13258                          {
13259                             T result = T(value(arg_list[0]));
13260 
13261                             for (std::size_t i = 1; i < arg_list.size(); ++i)
13262                             {
13263                                const T v = value(arg_list[i]);
13264 
13265                                if (v > result)
13266                                   result = v;
13267                             }
13268 
13269                             return result;
13270                          }
13271             }
13272          }
13273 
13274          template <typename Sequence>
process_1exprtk::details::vararg_max_op13275          static inline T process_1(const Sequence& arg_list)
13276          {
13277             return value(arg_list[0]);
13278          }
13279 
13280          template <typename Sequence>
process_2exprtk::details::vararg_max_op13281          static inline T process_2(const Sequence& arg_list)
13282          {
13283             return std::max<T>(value(arg_list[0]),value(arg_list[1]));
13284          }
13285 
13286          template <typename Sequence>
process_3exprtk::details::vararg_max_op13287          static inline T process_3(const Sequence& arg_list)
13288          {
13289             return std::max<T>(std::max<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2]));
13290          }
13291 
13292          template <typename Sequence>
process_4exprtk::details::vararg_max_op13293          static inline T process_4(const Sequence& arg_list)
13294          {
13295             return std::max<T>(
13296                         std::max<T>(value(arg_list[0]), value(arg_list[1])),
13297                         std::max<T>(value(arg_list[2]), value(arg_list[3])));
13298          }
13299 
13300          template <typename Sequence>
process_5exprtk::details::vararg_max_op13301          static inline T process_5(const Sequence& arg_list)
13302          {
13303             return std::max<T>(
13304                    std::max<T>(std::max<T>(value(arg_list[0]), value(arg_list[1])),
13305                                std::max<T>(value(arg_list[2]), value(arg_list[3]))),
13306                                value(arg_list[4]));
13307          }
13308       };
13309 
13310       template <typename T>
13311       struct vararg_mand_op : public opr_base<T>
13312       {
13313          typedef typename opr_base<T>::Type Type;
13314 
13315          template <typename Type,
13316                    typename Allocator,
13317                    template <typename, typename> class Sequence>
processexprtk::details::vararg_mand_op13318          static inline T process(const Sequence<Type,Allocator>& arg_list)
13319          {
13320             switch (arg_list.size())
13321             {
13322                case 1  : return process_1(arg_list);
13323                case 2  : return process_2(arg_list);
13324                case 3  : return process_3(arg_list);
13325                case 4  : return process_4(arg_list);
13326                case 5  : return process_5(arg_list);
13327                default :
13328                          {
13329                             for (std::size_t i = 0; i < arg_list.size(); ++i)
13330                             {
13331                                if (std::equal_to<T>()(T(0), value(arg_list[i])))
13332                                   return T(0);
13333                             }
13334 
13335                             return T(1);
13336                          }
13337             }
13338          }
13339 
13340          template <typename Sequence>
process_1exprtk::details::vararg_mand_op13341          static inline T process_1(const Sequence& arg_list)
13342          {
13343             return std::not_equal_to<T>()
13344                       (T(0), value(arg_list[0])) ? T(1) : T(0);
13345          }
13346 
13347          template <typename Sequence>
process_2exprtk::details::vararg_mand_op13348          static inline T process_2(const Sequence& arg_list)
13349          {
13350             return (
13351                      std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
13352                      std::not_equal_to<T>()(T(0), value(arg_list[1]))
13353                    ) ? T(1) : T(0);
13354          }
13355 
13356          template <typename Sequence>
process_3exprtk::details::vararg_mand_op13357          static inline T process_3(const Sequence& arg_list)
13358          {
13359             return (
13360                      std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
13361                      std::not_equal_to<T>()(T(0), value(arg_list[1])) &&
13362                      std::not_equal_to<T>()(T(0), value(arg_list[2]))
13363                    ) ? T(1) : T(0);
13364          }
13365 
13366          template <typename Sequence>
process_4exprtk::details::vararg_mand_op13367          static inline T process_4(const Sequence& arg_list)
13368          {
13369             return (
13370                      std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
13371                      std::not_equal_to<T>()(T(0), value(arg_list[1])) &&
13372                      std::not_equal_to<T>()(T(0), value(arg_list[2])) &&
13373                      std::not_equal_to<T>()(T(0), value(arg_list[3]))
13374                    ) ? T(1) : T(0);
13375          }
13376 
13377          template <typename Sequence>
process_5exprtk::details::vararg_mand_op13378          static inline T process_5(const Sequence& arg_list)
13379          {
13380             return (
13381                      std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
13382                      std::not_equal_to<T>()(T(0), value(arg_list[1])) &&
13383                      std::not_equal_to<T>()(T(0), value(arg_list[2])) &&
13384                      std::not_equal_to<T>()(T(0), value(arg_list[3])) &&
13385                      std::not_equal_to<T>()(T(0), value(arg_list[4]))
13386                    ) ? T(1) : T(0);
13387          }
13388       };
13389 
13390       template <typename T>
13391       struct vararg_mor_op : public opr_base<T>
13392       {
13393          typedef typename opr_base<T>::Type Type;
13394 
13395          template <typename Type,
13396                    typename Allocator,
13397                    template <typename, typename> class Sequence>
processexprtk::details::vararg_mor_op13398          static inline T process(const Sequence<Type,Allocator>& arg_list)
13399          {
13400             switch (arg_list.size())
13401             {
13402                case 1  : return process_1(arg_list);
13403                case 2  : return process_2(arg_list);
13404                case 3  : return process_3(arg_list);
13405                case 4  : return process_4(arg_list);
13406                case 5  : return process_5(arg_list);
13407                default :
13408                          {
13409                             for (std::size_t i = 0; i < arg_list.size(); ++i)
13410                             {
13411                                if (std::not_equal_to<T>()(T(0), value(arg_list[i])))
13412                                   return T(1);
13413                             }
13414 
13415                             return T(0);
13416                          }
13417             }
13418          }
13419 
13420          template <typename Sequence>
process_1exprtk::details::vararg_mor_op13421          static inline T process_1(const Sequence& arg_list)
13422          {
13423             return std::not_equal_to<T>()
13424                       (T(0), value(arg_list[0])) ? T(1) : T(0);
13425          }
13426 
13427          template <typename Sequence>
process_2exprtk::details::vararg_mor_op13428          static inline T process_2(const Sequence& arg_list)
13429          {
13430             return (
13431                      std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
13432                      std::not_equal_to<T>()(T(0), value(arg_list[1]))
13433                    ) ? T(1) : T(0);
13434          }
13435 
13436          template <typename Sequence>
process_3exprtk::details::vararg_mor_op13437          static inline T process_3(const Sequence& arg_list)
13438          {
13439             return (
13440                      std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
13441                      std::not_equal_to<T>()(T(0), value(arg_list[1])) ||
13442                      std::not_equal_to<T>()(T(0), value(arg_list[2]))
13443                    ) ? T(1) : T(0);
13444          }
13445 
13446          template <typename Sequence>
process_4exprtk::details::vararg_mor_op13447          static inline T process_4(const Sequence& arg_list)
13448          {
13449             return (
13450                      std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
13451                      std::not_equal_to<T>()(T(0), value(arg_list[1])) ||
13452                      std::not_equal_to<T>()(T(0), value(arg_list[2])) ||
13453                      std::not_equal_to<T>()(T(0), value(arg_list[3]))
13454                    ) ? T(1) : T(0);
13455          }
13456 
13457          template <typename Sequence>
process_5exprtk::details::vararg_mor_op13458          static inline T process_5(const Sequence& arg_list)
13459          {
13460             return (
13461                      std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
13462                      std::not_equal_to<T>()(T(0), value(arg_list[1])) ||
13463                      std::not_equal_to<T>()(T(0), value(arg_list[2])) ||
13464                      std::not_equal_to<T>()(T(0), value(arg_list[3])) ||
13465                      std::not_equal_to<T>()(T(0), value(arg_list[4]))
13466                    ) ? T(1) : T(0);
13467          }
13468       };
13469 
13470       template <typename T>
13471       struct vararg_multi_op : public opr_base<T>
13472       {
13473          typedef typename opr_base<T>::Type Type;
13474 
13475          template <typename Type,
13476                    typename Allocator,
13477                    template <typename, typename> class Sequence>
processexprtk::details::vararg_multi_op13478          static inline T process(const Sequence<Type,Allocator>& arg_list)
13479          {
13480             switch (arg_list.size())
13481             {
13482                case 0  : return std::numeric_limits<T>::quiet_NaN();
13483                case 1  : return process_1(arg_list);
13484                case 2  : return process_2(arg_list);
13485                case 3  : return process_3(arg_list);
13486                case 4  : return process_4(arg_list);
13487                case 5  : return process_5(arg_list);
13488                case 6  : return process_6(arg_list);
13489                case 7  : return process_7(arg_list);
13490                case 8  : return process_8(arg_list);
13491                default :
13492                          {
13493                             for (std::size_t i = 0; i < (arg_list.size() - 1); ++i)
13494                             {
13495                                value(arg_list[i]);
13496                             }
13497 
13498                             return value(arg_list.back());
13499                          }
13500             }
13501          }
13502 
13503          template <typename Sequence>
process_1exprtk::details::vararg_multi_op13504          static inline T process_1(const Sequence& arg_list)
13505          {
13506             return value(arg_list[0]);
13507          }
13508 
13509          template <typename Sequence>
process_2exprtk::details::vararg_multi_op13510          static inline T process_2(const Sequence& arg_list)
13511          {
13512                    value(arg_list[0]);
13513             return value(arg_list[1]);
13514          }
13515 
13516          template <typename Sequence>
process_3exprtk::details::vararg_multi_op13517          static inline T process_3(const Sequence& arg_list)
13518          {
13519                    value(arg_list[0]);
13520                    value(arg_list[1]);
13521             return value(arg_list[2]);
13522          }
13523 
13524          template <typename Sequence>
process_4exprtk::details::vararg_multi_op13525          static inline T process_4(const Sequence& arg_list)
13526          {
13527                    value(arg_list[0]);
13528                    value(arg_list[1]);
13529                    value(arg_list[2]);
13530             return value(arg_list[3]);
13531          }
13532 
13533          template <typename Sequence>
process_5exprtk::details::vararg_multi_op13534          static inline T process_5(const Sequence& arg_list)
13535          {
13536                    value(arg_list[0]);
13537                    value(arg_list[1]);
13538                    value(arg_list[2]);
13539                    value(arg_list[3]);
13540             return value(arg_list[4]);
13541          }
13542 
13543          template <typename Sequence>
process_6exprtk::details::vararg_multi_op13544          static inline T process_6(const Sequence& arg_list)
13545          {
13546                    value(arg_list[0]);
13547                    value(arg_list[1]);
13548                    value(arg_list[2]);
13549                    value(arg_list[3]);
13550                    value(arg_list[4]);
13551             return value(arg_list[5]);
13552          }
13553 
13554          template <typename Sequence>
process_7exprtk::details::vararg_multi_op13555          static inline T process_7(const Sequence& arg_list)
13556          {
13557                    value(arg_list[0]);
13558                    value(arg_list[1]);
13559                    value(arg_list[2]);
13560                    value(arg_list[3]);
13561                    value(arg_list[4]);
13562                    value(arg_list[5]);
13563             return value(arg_list[6]);
13564          }
13565 
13566          template <typename Sequence>
process_8exprtk::details::vararg_multi_op13567          static inline T process_8(const Sequence& arg_list)
13568          {
13569                    value(arg_list[0]);
13570                    value(arg_list[1]);
13571                    value(arg_list[2]);
13572                    value(arg_list[3]);
13573                    value(arg_list[4]);
13574                    value(arg_list[5]);
13575                    value(arg_list[6]);
13576             return value(arg_list[7]);
13577          }
13578       };
13579 
13580       template <typename T>
13581       struct vec_add_op
13582       {
13583          typedef vector_interface<T>* ivector_ptr;
13584 
processexprtk::details::vec_add_op13585          static inline T process(const ivector_ptr v)
13586          {
13587             const T* vec = v->vec()->vds().data();
13588             const std::size_t vec_size = v->vec()->vds().size();
13589 
13590             loop_unroll::details lud(vec_size);
13591 
13592             if (vec_size <= static_cast<std::size_t>(lud.batch_size))
13593             {
13594                T result = T(0);
13595                int i    = 0;
13596 
13597                exprtk_disable_fallthrough_begin
13598                switch (vec_size)
13599                {
13600                   #define case_stmt(N)         \
13601                   case N : result += vec[i++]; \
13602 
13603                   #ifndef exprtk_disable_superscalar_unroll
13604                   case_stmt(16) case_stmt(15)
13605                   case_stmt(14) case_stmt(13)
13606                   case_stmt(12) case_stmt(11)
13607                   case_stmt(10) case_stmt( 9)
13608                   case_stmt( 8) case_stmt( 7)
13609                   case_stmt( 6) case_stmt( 5)
13610                   #endif
13611                   case_stmt( 4) case_stmt( 3)
13612                   case_stmt( 2) case_stmt( 1)
13613                }
13614                exprtk_disable_fallthrough_end
13615 
13616                #undef case_stmt
13617 
13618                return result;
13619             }
13620 
13621             T r[] = {
13622                       T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0),
13623                       T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0)
13624                     };
13625 
13626             const T* upper_bound = vec + lud.upper_bound;
13627 
13628             while (vec < upper_bound)
13629             {
13630                #define exprtk_loop(N) \
13631                r[N] += vec[N];        \
13632 
13633                exprtk_loop( 0) exprtk_loop( 1)
13634                exprtk_loop( 2) exprtk_loop( 3)
13635                #ifndef exprtk_disable_superscalar_unroll
13636                exprtk_loop( 4) exprtk_loop( 5)
13637                exprtk_loop( 6) exprtk_loop( 7)
13638                exprtk_loop( 8) exprtk_loop( 9)
13639                exprtk_loop(10) exprtk_loop(11)
13640                exprtk_loop(12) exprtk_loop(13)
13641                exprtk_loop(14) exprtk_loop(15)
13642                #endif
13643 
13644                vec += lud.batch_size;
13645             }
13646 
13647             int i = 0;
13648 
13649             exprtk_disable_fallthrough_begin
13650             switch (lud.remainder)
13651             {
13652                #define case_stmt(N)       \
13653                case N : r[0] += vec[i++]; \
13654 
13655                #ifndef exprtk_disable_superscalar_unroll
13656                case_stmt(15) case_stmt(14)
13657                case_stmt(13) case_stmt(12)
13658                case_stmt(11) case_stmt(10)
13659                case_stmt( 9) case_stmt( 8)
13660                case_stmt( 7) case_stmt( 6)
13661                case_stmt( 5) case_stmt( 4)
13662                #endif
13663                case_stmt( 3) case_stmt( 2)
13664                case_stmt( 1)
13665             }
13666             exprtk_disable_fallthrough_end
13667 
13668             #undef exprtk_loop
13669             #undef case_stmt
13670 
13671             return (r[ 0] + r[ 1] + r[ 2] + r[ 3])
13672                    #ifndef exprtk_disable_superscalar_unroll
13673                  + (r[ 4] + r[ 5] + r[ 6] + r[ 7])
13674                  + (r[ 8] + r[ 9] + r[10] + r[11])
13675                  + (r[12] + r[13] + r[14] + r[15])
13676                    #endif
13677                    ;
13678          }
13679       };
13680 
13681       template <typename T>
13682       struct vec_mul_op
13683       {
13684          typedef vector_interface<T>* ivector_ptr;
13685 
processexprtk::details::vec_mul_op13686          static inline T process(const ivector_ptr v)
13687          {
13688             const T* vec = v->vec()->vds().data();
13689             const std::size_t vec_size = v->vec()->vds().size();
13690 
13691             loop_unroll::details lud(vec_size);
13692 
13693             if (vec_size <= static_cast<std::size_t>(lud.batch_size))
13694             {
13695                T result = T(1);
13696                int i    = 0;
13697 
13698                exprtk_disable_fallthrough_begin
13699                switch (vec_size)
13700                {
13701                   #define case_stmt(N)         \
13702                   case N : result *= vec[i++]; \
13703 
13704                   #ifndef exprtk_disable_superscalar_unroll
13705                   case_stmt(16) case_stmt(15)
13706                   case_stmt(14) case_stmt(13)
13707                   case_stmt(12) case_stmt(11)
13708                   case_stmt(10) case_stmt( 9)
13709                   case_stmt( 8) case_stmt( 7)
13710                   case_stmt( 6) case_stmt( 5)
13711                   #endif
13712                   case_stmt( 4) case_stmt( 3)
13713                   case_stmt( 2) case_stmt( 1)
13714                }
13715                exprtk_disable_fallthrough_end
13716 
13717                #undef case_stmt
13718 
13719                return result;
13720             }
13721 
13722             T r[] = {
13723                       T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1),
13724                       T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1)
13725                     };
13726 
13727             const T* upper_bound = vec + lud.upper_bound;
13728 
13729             while (vec < upper_bound)
13730             {
13731                #define exprtk_loop(N) \
13732                r[N] *= vec[N];        \
13733 
13734                exprtk_loop( 0) exprtk_loop( 1)
13735                exprtk_loop( 2) exprtk_loop( 3)
13736                #ifndef exprtk_disable_superscalar_unroll
13737                exprtk_loop( 4) exprtk_loop( 5)
13738                exprtk_loop( 6) exprtk_loop( 7)
13739                exprtk_loop( 8) exprtk_loop( 9)
13740                exprtk_loop(10) exprtk_loop(11)
13741                exprtk_loop(12) exprtk_loop(13)
13742                exprtk_loop(14) exprtk_loop(15)
13743                #endif
13744 
13745                vec += lud.batch_size;
13746             }
13747 
13748             int i = 0;
13749 
13750             exprtk_disable_fallthrough_begin
13751             switch (lud.remainder)
13752             {
13753                #define case_stmt(N)       \
13754                case N : r[0] *= vec[i++]; \
13755 
13756                #ifndef exprtk_disable_superscalar_unroll
13757                case_stmt(15) case_stmt(14)
13758                case_stmt(13) case_stmt(12)
13759                case_stmt(11) case_stmt(10)
13760                case_stmt( 9) case_stmt( 8)
13761                case_stmt( 7) case_stmt( 6)
13762                case_stmt( 5) case_stmt( 4)
13763                #endif
13764                case_stmt( 3) case_stmt( 2)
13765                case_stmt( 1)
13766             }
13767             exprtk_disable_fallthrough_end
13768 
13769             #undef exprtk_loop
13770             #undef case_stmt
13771 
13772             return (r[ 0] * r[ 1] * r[ 2] * r[ 3])
13773                    #ifndef exprtk_disable_superscalar_unroll
13774                  + (r[ 4] * r[ 5] * r[ 6] * r[ 7])
13775                  + (r[ 8] * r[ 9] * r[10] * r[11])
13776                  + (r[12] * r[13] * r[14] * r[15])
13777                    #endif
13778                    ;
13779          }
13780       };
13781 
13782       template <typename T>
13783       struct vec_avg_op
13784       {
13785          typedef vector_interface<T>* ivector_ptr;
13786 
processexprtk::details::vec_avg_op13787          static inline T process(const ivector_ptr v)
13788          {
13789             const std::size_t vec_size = v->vec()->vds().size();
13790 
13791             return vec_add_op<T>::process(v) / vec_size;
13792          }
13793       };
13794 
13795       template <typename T>
13796       struct vec_min_op
13797       {
13798          typedef vector_interface<T>* ivector_ptr;
13799 
processexprtk::details::vec_min_op13800          static inline T process(const ivector_ptr v)
13801          {
13802             const T* vec = v->vec()->vds().data();
13803             const std::size_t vec_size = v->vec()->vds().size();
13804 
13805             T result = vec[0];
13806 
13807             for (std::size_t i = 1; i < vec_size; ++i)
13808             {
13809                const T v_i = vec[i];
13810 
13811                if (v_i < result)
13812                   result = v_i;
13813             }
13814 
13815             return result;
13816          }
13817       };
13818 
13819       template <typename T>
13820       struct vec_max_op
13821       {
13822          typedef vector_interface<T>* ivector_ptr;
13823 
processexprtk::details::vec_max_op13824          static inline T process(const ivector_ptr v)
13825          {
13826             const T* vec = v->vec()->vds().data();
13827             const std::size_t vec_size = v->vec()->vds().size();
13828 
13829             T result = vec[0];
13830 
13831             for (std::size_t i = 1; i < vec_size; ++i)
13832             {
13833                const T v_i = vec[i];
13834 
13835                if (v_i > result)
13836                   result = v_i;
13837             }
13838 
13839             return result;
13840          }
13841       };
13842 
13843       template <typename T>
13844       class vov_base_node : public expression_node<T>
13845       {
13846       public:
13847 
~vov_base_node()13848          virtual ~vov_base_node()
13849          {}
13850 
operation() const13851          inline virtual operator_type operation() const
13852          {
13853             return details::e_default;
13854          }
13855 
13856          virtual const T& v0() const = 0;
13857 
13858          virtual const T& v1() const = 0;
13859       };
13860 
13861       template <typename T>
13862       class cov_base_node : public expression_node<T>
13863       {
13864       public:
13865 
~cov_base_node()13866        virtual ~cov_base_node()
13867           {}
13868 
operation() const13869          inline virtual operator_type operation() const
13870          {
13871             return details::e_default;
13872          }
13873 
13874          virtual const T c() const = 0;
13875 
13876          virtual const T& v() const = 0;
13877       };
13878 
13879       template <typename T>
13880       class voc_base_node : public expression_node<T>
13881       {
13882       public:
13883 
~voc_base_node()13884          virtual ~voc_base_node()
13885          {}
13886 
operation() const13887          inline virtual operator_type operation() const
13888          {
13889             return details::e_default;
13890          }
13891 
13892          virtual const T c() const = 0;
13893 
13894          virtual const T& v() const = 0;
13895       };
13896 
13897       template <typename T>
13898       class vob_base_node : public expression_node<T>
13899       {
13900       public:
13901 
~vob_base_node()13902          virtual ~vob_base_node()
13903          {}
13904 
13905          virtual const T& v() const = 0;
13906       };
13907 
13908       template <typename T>
13909       class bov_base_node : public expression_node<T>
13910       {
13911       public:
13912 
~bov_base_node()13913          virtual ~bov_base_node()
13914          {}
13915 
13916          virtual const T& v() const = 0;
13917       };
13918 
13919       template <typename T>
13920       class cob_base_node : public expression_node<T>
13921       {
13922       public:
13923 
~cob_base_node()13924          virtual ~cob_base_node()
13925          {}
13926 
operation() const13927          inline virtual operator_type operation() const
13928          {
13929             return details::e_default;
13930          }
13931 
13932          virtual const T c() const = 0;
13933 
13934          virtual void set_c(const T) = 0;
13935 
13936          virtual expression_node<T>* move_branch(const std::size_t& index) = 0;
13937       };
13938 
13939       template <typename T>
13940       class boc_base_node : public expression_node<T>
13941       {
13942       public:
13943 
~boc_base_node()13944          virtual ~boc_base_node()
13945          {}
13946 
operation() const13947          inline virtual operator_type operation() const
13948          {
13949             return details::e_default;
13950          }
13951 
13952          virtual const T c() const = 0;
13953 
13954          virtual void set_c(const T) = 0;
13955 
13956          virtual expression_node<T>* move_branch(const std::size_t& index) = 0;
13957       };
13958 
13959       template <typename T>
13960       class uv_base_node : public expression_node<T>
13961       {
13962       public:
13963 
~uv_base_node()13964          virtual ~uv_base_node()
13965          {}
13966 
operation() const13967          inline virtual operator_type operation() const
13968          {
13969             return details::e_default;
13970          }
13971 
13972          virtual const T& v() const = 0;
13973       };
13974 
13975       template <typename T>
13976       class sos_base_node : public expression_node<T>
13977       {
13978       public:
13979 
~sos_base_node()13980          virtual ~sos_base_node()
13981          {}
13982 
operation() const13983          inline virtual operator_type operation() const
13984          {
13985             return details::e_default;
13986          }
13987       };
13988 
13989       template <typename T>
13990       class sosos_base_node : public expression_node<T>
13991       {
13992       public:
13993 
~sosos_base_node()13994          virtual ~sosos_base_node()
13995          {}
13996 
operation() const13997          inline virtual operator_type operation() const
13998          {
13999             return details::e_default;
14000          }
14001       };
14002 
14003       template <typename T>
14004       class T0oT1oT2_base_node : public expression_node<T>
14005       {
14006       public:
14007 
~T0oT1oT2_base_node()14008          virtual ~T0oT1oT2_base_node()
14009          {}
14010 
14011          virtual std::string type_id() const = 0;
14012       };
14013 
14014       template <typename T>
14015       class T0oT1oT2oT3_base_node : public expression_node<T>
14016       {
14017       public:
14018 
~T0oT1oT2oT3_base_node()14019          virtual ~T0oT1oT2oT3_base_node()
14020          {}
14021 
14022          virtual std::string type_id() const = 0;
14023       };
14024 
14025       template <typename T, typename Operation>
14026       class unary_variable_node : public uv_base_node<T>
14027       {
14028       public:
14029 
14030          typedef expression_node<T>* expression_ptr;
14031          typedef Operation operation_t;
14032 
unary_variable_node(const T & var)14033          explicit unary_variable_node(const T& var)
14034          : v_(var)
14035          {}
14036 
value() const14037          inline T value() const
14038          {
14039             return Operation::process(v_);
14040          }
14041 
type() const14042          inline typename expression_node<T>::node_type type() const
14043          {
14044             return Operation::type();
14045          }
14046 
operation() const14047          inline operator_type operation() const
14048          {
14049             return Operation::operation();
14050          }
14051 
v() const14052          inline const T& v() const
14053          {
14054             return v_;
14055          }
14056 
14057       private:
14058 
14059          unary_variable_node(unary_variable_node<T,Operation>&);
14060          unary_variable_node<T,Operation>& operator=(unary_variable_node<T,Operation>&);
14061 
14062          const T& v_;
14063       };
14064 
14065       template <typename T>
14066       class uvouv_node : public expression_node<T>
14067       {
14068       public:
14069 
14070          // UOpr1(v0) Op UOpr2(v1)
14071 
14072          typedef expression_node<T>* expression_ptr;
14073          typedef typename details::functor_t<T> functor_t;
14074          typedef typename functor_t::bfunc_t      bfunc_t;
14075          typedef typename functor_t::ufunc_t      ufunc_t;
14076 
uvouv_node(const T & var0,const T & var1,ufunc_t uf0,ufunc_t uf1,bfunc_t bf)14077          explicit uvouv_node(const T& var0,const T& var1,
14078                              ufunc_t uf0, ufunc_t uf1, bfunc_t bf)
14079          : v0_(var0),
14080            v1_(var1),
14081            u0_(uf0 ),
14082            u1_(uf1 ),
14083            f_ (bf  )
14084          {}
14085 
value() const14086          inline T value() const
14087          {
14088             return f_(u0_(v0_),u1_(v1_));
14089          }
14090 
type() const14091          inline typename expression_node<T>::node_type type() const
14092          {
14093             return expression_node<T>::e_uvouv;
14094          }
14095 
operation() const14096          inline operator_type operation() const
14097          {
14098             return details::e_default;
14099          }
14100 
v0()14101          inline const T& v0()
14102          {
14103             return v0_;
14104          }
14105 
v1()14106          inline const T& v1()
14107          {
14108             return v1_;
14109          }
14110 
u0()14111          inline ufunc_t u0()
14112          {
14113             return u0_;
14114          }
14115 
u1()14116          inline ufunc_t u1()
14117          {
14118             return u1_;
14119          }
14120 
f()14121          inline ufunc_t f()
14122          {
14123             return f_;
14124          }
14125 
14126       private:
14127 
14128          uvouv_node(uvouv_node<T>&);
14129          uvouv_node<T>& operator=(uvouv_node<T>&);
14130 
14131          const T& v0_;
14132          const T& v1_;
14133          const ufunc_t u0_;
14134          const ufunc_t u1_;
14135          const bfunc_t f_;
14136       };
14137 
14138       template <typename T, typename Operation>
14139       class unary_branch_node : public expression_node<T>
14140       {
14141       public:
14142 
14143          typedef expression_node<T>* expression_ptr;
14144          typedef std::pair<expression_ptr,bool> branch_t;
14145          typedef Operation operation_t;
14146 
unary_branch_node(expression_ptr branch)14147          explicit unary_branch_node(expression_ptr branch)
14148          {
14149             construct_branch_pair(branch_, branch);
14150          }
14151 
value() const14152          inline T value() const
14153          {
14154             return Operation::process(branch_.first->value());
14155          }
14156 
type() const14157          inline typename expression_node<T>::node_type type() const
14158          {
14159             return Operation::type();
14160          }
14161 
operation() const14162          inline operator_type operation() const
14163          {
14164             return Operation::operation();
14165          }
14166 
branch(const std::size_t &) const14167          inline expression_node<T>* branch(const std::size_t&) const
14168          {
14169             return branch_.first;
14170          }
14171 
release()14172          inline void release()
14173          {
14174             branch_.second = false;
14175          }
14176 
collect_nodes(typename expression_node<T>::noderef_list_t & node_delete_list)14177          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
14178          {
14179             expression_node<T>::ndb_t::collect(branch_, node_delete_list);
14180          }
14181 
node_depth() const14182          std::size_t node_depth() const
14183          {
14184             return expression_node<T>::ndb_t::compute_node_depth(branch_);
14185          }
14186 
14187       private:
14188 
14189          unary_branch_node(unary_branch_node<T,Operation>&);
14190          unary_branch_node<T,Operation>& operator=(unary_branch_node<T,Operation>&);
14191 
14192          branch_t branch_;
14193       };
14194 
14195       template <typename T> struct is_const                { enum {result = 0}; };
14196       template <typename T> struct is_const <const T>      { enum {result = 1}; };
14197       template <typename T> struct is_const_ref            { enum {result = 0}; };
14198       template <typename T> struct is_const_ref <const T&> { enum {result = 1}; };
14199       template <typename T> struct is_ref                  { enum {result = 0}; };
14200       template <typename T> struct is_ref<T&>              { enum {result = 1}; };
14201       template <typename T> struct is_ref<const T&>        { enum {result = 0}; };
14202 
14203       template <std::size_t State>
resultexprtk::details::param_to_str14204       struct param_to_str { static std::string result() { static const std::string r("v"); return r; } };
14205 
14206       template <>
resultexprtk::details::param_to_str14207       struct param_to_str<0> { static std::string result() { static const std::string r("c"); return r; } };
14208 
14209       #define exprtk_crtype(Type)                          \
14210       param_to_str<is_const_ref< Type >::result>::result() \
14211 
14212       template <typename T>
14213       struct T0oT1oT2process
14214       {
14215          typedef typename details::functor_t<T> functor_t;
14216          typedef typename functor_t::bfunc_t      bfunc_t;
14217 
14218          struct mode0
14219          {
processexprtk::details::T0oT1oT2process::mode014220             static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1)
14221             {
14222                // (T0 o0 T1) o1 T2
14223                return bf1(bf0(t0,t1),t2);
14224             }
14225 
14226             template <typename T0, typename T1, typename T2>
idexprtk::details::T0oT1oT2process::mode014227             static inline std::string id()
14228             {
14229                static const std::string result = "(" + exprtk_crtype(T0) + "o"   +
14230                                                        exprtk_crtype(T1) + ")o(" +
14231                                                        exprtk_crtype(T2) + ")"   ;
14232                return result;
14233             }
14234          };
14235 
14236          struct mode1
14237          {
processexprtk::details::T0oT1oT2process::mode114238             static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1)
14239             {
14240                // T0 o0 (T1 o1 T2)
14241                return bf0(t0,bf1(t1,t2));
14242             }
14243 
14244             template <typename T0, typename T1, typename T2>
idexprtk::details::T0oT1oT2process::mode114245             static inline std::string id()
14246             {
14247                static const std::string result = "(" + exprtk_crtype(T0) + ")o(" +
14248                                                        exprtk_crtype(T1) + "o"   +
14249                                                        exprtk_crtype(T2) + ")"   ;
14250                return result;
14251             }
14252          };
14253       };
14254 
14255       template <typename T>
14256       struct T0oT1oT20T3process
14257       {
14258          typedef typename details::functor_t<T> functor_t;
14259          typedef typename functor_t::bfunc_t      bfunc_t;
14260 
14261          struct mode0
14262          {
processexprtk::details::T0oT1oT20T3process::mode014263             static inline T process(const T& t0, const T& t1,
14264                                     const T& t2, const T& t3,
14265                                     const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
14266             {
14267                // (T0 o0 T1) o1 (T2 o2 T3)
14268                return bf1(bf0(t0,t1),bf2(t2,t3));
14269             }
14270 
14271             template <typename T0, typename T1, typename T2, typename T3>
idexprtk::details::T0oT1oT20T3process::mode014272             static inline std::string id()
14273             {
14274                static const std::string result = "(" + exprtk_crtype(T0) + "o"  +
14275                                                        exprtk_crtype(T1) + ")o" +
14276                                                  "(" + exprtk_crtype(T2) + "o"  +
14277                                                        exprtk_crtype(T3) + ")"  ;
14278                return result;
14279             }
14280          };
14281 
14282          struct mode1
14283          {
processexprtk::details::T0oT1oT20T3process::mode114284             static inline T process(const T& t0, const T& t1,
14285                                     const T& t2, const T& t3,
14286                                     const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
14287             {
14288                // (T0 o0 (T1 o1 (T2 o2 T3))
14289                return bf0(t0,bf1(t1,bf2(t2,t3)));
14290             }
14291             template <typename T0, typename T1, typename T2, typename T3>
idexprtk::details::T0oT1oT20T3process::mode114292             static inline std::string id()
14293             {
14294                static const std::string result = "(" + exprtk_crtype(T0) +  ")o((" +
14295                                                        exprtk_crtype(T1) +  ")o("  +
14296                                                        exprtk_crtype(T2) +  "o"    +
14297                                                        exprtk_crtype(T3) +  "))"   ;
14298                return result;
14299             }
14300          };
14301 
14302          struct mode2
14303          {
processexprtk::details::T0oT1oT20T3process::mode214304             static inline T process(const T& t0, const T& t1,
14305                                     const T& t2, const T& t3,
14306                                     const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
14307             {
14308                // (T0 o0 ((T1 o1 T2) o2 T3)
14309                return bf0(t0,bf2(bf1(t1,t2),t3));
14310             }
14311 
14312             template <typename T0, typename T1, typename T2, typename T3>
idexprtk::details::T0oT1oT20T3process::mode214313             static inline std::string id()
14314             {
14315                static const std::string result = "(" + exprtk_crtype(T0) + ")o((" +
14316                                                        exprtk_crtype(T1) + "o"    +
14317                                                        exprtk_crtype(T2) + ")o("  +
14318                                                        exprtk_crtype(T3) + "))"   ;
14319                return result;
14320             }
14321          };
14322 
14323          struct mode3
14324          {
processexprtk::details::T0oT1oT20T3process::mode314325             static inline T process(const T& t0, const T& t1,
14326                                     const T& t2, const T& t3,
14327                                     const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
14328             {
14329                // (((T0 o0 T1) o1 T2) o2 T3)
14330                return bf2(bf1(bf0(t0,t1),t2),t3);
14331             }
14332 
14333             template <typename T0, typename T1, typename T2, typename T3>
idexprtk::details::T0oT1oT20T3process::mode314334             static inline std::string id()
14335             {
14336                static const std::string result = "((" + exprtk_crtype(T0) + "o"    +
14337                                                         exprtk_crtype(T1) + ")o("  +
14338                                                         exprtk_crtype(T2) + "))o(" +
14339                                                         exprtk_crtype(T3) + ")";
14340                return result;
14341             }
14342          };
14343 
14344          struct mode4
14345          {
processexprtk::details::T0oT1oT20T3process::mode414346             static inline T process(const T& t0, const T& t1,
14347                                     const T& t2, const T& t3,
14348                                     const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
14349             {
14350                // ((T0 o0 (T1 o1 T2)) o2 T3
14351                return bf2(bf0(t0,bf1(t1,t2)),t3);
14352             }
14353 
14354             template <typename T0, typename T1, typename T2, typename T3>
idexprtk::details::T0oT1oT20T3process::mode414355             static inline std::string id()
14356             {
14357                static const std::string result = "((" + exprtk_crtype(T0) + ")o("  +
14358                                                         exprtk_crtype(T1) + "o"    +
14359                                                         exprtk_crtype(T2) + "))o(" +
14360                                                         exprtk_crtype(T3) + ")"    ;
14361                return result;
14362             }
14363          };
14364       };
14365 
14366       #undef exprtk_crtype
14367 
14368       template <typename T, typename T0, typename T1>
14369       struct nodetype_T0oT1 { static const typename expression_node<T>::node_type result; };
14370       template <typename T, typename T0, typename T1>
14371       const typename expression_node<T>::node_type nodetype_T0oT1<T,T0,T1>::result = expression_node<T>::e_none;
14372 
14373       #define synthesis_node_type_define(T0_,T1_,v_)                                                            \
14374       template <typename T, typename T0, typename T1>                                                           \
14375       struct nodetype_T0oT1<T,T0_,T1_> { static const typename expression_node<T>::node_type result; };         \
14376       template <typename T, typename T0, typename T1>                                                           \
14377       const typename expression_node<T>::node_type nodetype_T0oT1<T,T0_,T1_>::result = expression_node<T>:: v_; \
14378 
14379       synthesis_node_type_define(const T0&, const T1&,  e_vov)
14380       synthesis_node_type_define(const T0&, const T1 ,  e_voc)
14381       synthesis_node_type_define(const T0 , const T1&,  e_cov)
14382       synthesis_node_type_define(      T0&,       T1&, e_none)
14383       synthesis_node_type_define(const T0 , const T1 , e_none)
14384       synthesis_node_type_define(      T0&, const T1 , e_none)
14385       synthesis_node_type_define(const T0 ,       T1&, e_none)
14386       synthesis_node_type_define(const T0&,       T1&, e_none)
14387       synthesis_node_type_define(      T0&, const T1&, e_none)
14388       #undef synthesis_node_type_define
14389 
14390       template <typename T, typename T0, typename T1, typename T2>
14391       struct nodetype_T0oT1oT2 { static const typename expression_node<T>::node_type result; };
14392       template <typename T, typename T0, typename T1, typename T2>
14393       const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0,T1,T2>::result = expression_node<T>::e_none;
14394 
14395       #define synthesis_node_type_define(T0_,T1_,T2_,v_)                                                               \
14396       template <typename T, typename T0, typename T1, typename T2>                                                     \
14397       struct nodetype_T0oT1oT2<T,T0_,T1_,T2_> { static const typename expression_node<T>::node_type result; };         \
14398       template <typename T, typename T0, typename T1, typename T2>                                                     \
14399       const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0_,T1_,T2_>::result = expression_node<T>:: v_; \
14400 
14401       synthesis_node_type_define(const T0&, const T1&, const T2&, e_vovov)
14402       synthesis_node_type_define(const T0&, const T1&, const T2 , e_vovoc)
14403       synthesis_node_type_define(const T0&, const T1 , const T2&, e_vocov)
14404       synthesis_node_type_define(const T0 , const T1&, const T2&, e_covov)
14405       synthesis_node_type_define(const T0 , const T1&, const T2 , e_covoc)
14406       synthesis_node_type_define(const T0 , const T1 , const T2 , e_none )
14407       synthesis_node_type_define(const T0 , const T1 , const T2&, e_none )
14408       synthesis_node_type_define(const T0&, const T1 , const T2 , e_none )
14409       synthesis_node_type_define(      T0&,       T1&,       T2&, e_none )
14410       #undef synthesis_node_type_define
14411 
14412       template <typename T, typename T0, typename T1, typename T2, typename T3>
14413       struct nodetype_T0oT1oT2oT3 { static const typename expression_node<T>::node_type result; };
14414       template <typename T, typename T0, typename T1, typename T2, typename T3>
14415       const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result = expression_node<T>::e_none;
14416 
14417       #define synthesis_node_type_define(T0_,T1_,T2_,T3_,v_)                                                                  \
14418       template <typename T, typename T0, typename T1, typename T2, typename T3>                                               \
14419       struct nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_> { static const typename expression_node<T>::node_type result; };         \
14420       template <typename T, typename T0, typename T1, typename T2, typename T3>                                               \
14421       const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_>::result = expression_node<T>:: v_; \
14422 
14423       synthesis_node_type_define(const T0&, const T1&, const T2&, const T3&, e_vovovov)
14424       synthesis_node_type_define(const T0&, const T1&, const T2&, const T3 , e_vovovoc)
14425       synthesis_node_type_define(const T0&, const T1&, const T2 , const T3&, e_vovocov)
14426       synthesis_node_type_define(const T0&, const T1 , const T2&, const T3&, e_vocovov)
14427       synthesis_node_type_define(const T0 , const T1&, const T2&, const T3&, e_covovov)
14428       synthesis_node_type_define(const T0 , const T1&, const T2 , const T3&, e_covocov)
14429       synthesis_node_type_define(const T0&, const T1 , const T2&, const T3 , e_vocovoc)
14430       synthesis_node_type_define(const T0 , const T1&, const T2&, const T3 , e_covovoc)
14431       synthesis_node_type_define(const T0&, const T1 , const T2 , const T3&, e_vococov)
14432       synthesis_node_type_define(const T0 , const T1 , const T2 , const T3 , e_none   )
14433       synthesis_node_type_define(const T0 , const T1 , const T2 , const T3&, e_none   )
14434       synthesis_node_type_define(const T0 , const T1 , const T2&, const T3 , e_none   )
14435       synthesis_node_type_define(const T0 , const T1&, const T2 , const T3 , e_none   )
14436       synthesis_node_type_define(const T0&, const T1 , const T2 , const T3 , e_none   )
14437       synthesis_node_type_define(const T0 , const T1 , const T2&, const T3&, e_none   )
14438       synthesis_node_type_define(const T0&, const T1&, const T2 , const T3 , e_none   )
14439       #undef synthesis_node_type_define
14440 
14441       template <typename T, typename T0, typename T1>
14442       class T0oT1 : public expression_node<T>
14443       {
14444       public:
14445 
14446          typedef typename details::functor_t<T> functor_t;
14447          typedef typename functor_t::bfunc_t      bfunc_t;
14448          typedef T value_type;
14449          typedef T0oT1<T,T0,T1> node_type;
14450 
T0oT1(T0 p0,T1 p1,const bfunc_t p2)14451          T0oT1(T0 p0, T1 p1, const bfunc_t p2)
14452          : t0_(p0),
14453            t1_(p1),
14454            f_ (p2)
14455          {}
14456 
type() const14457          inline typename expression_node<T>::node_type type() const
14458          {
14459             static const typename expression_node<T>::node_type result = nodetype_T0oT1<T,T0,T1>::result;
14460             return result;
14461          }
14462 
operation() const14463          inline operator_type operation() const
14464          {
14465             return e_default;
14466          }
14467 
value() const14468          inline T value() const
14469          {
14470             return f_(t0_,t1_);
14471          }
14472 
t0() const14473          inline T0 t0() const
14474          {
14475             return t0_;
14476          }
14477 
t1() const14478          inline T1 t1() const
14479          {
14480             return t1_;
14481          }
14482 
f() const14483          inline bfunc_t f() const
14484          {
14485             return f_;
14486          }
14487 
14488          template <typename Allocator>
allocate(Allocator & allocator,T0 p0,T1 p1,bfunc_t p2)14489          static inline expression_node<T>* allocate(Allocator& allocator,
14490                                                     T0 p0, T1 p1,
14491                                                     bfunc_t p2)
14492          {
14493             return allocator
14494                      .template allocate_type<node_type, T0, T1, bfunc_t&>
14495                         (p0, p1, p2);
14496          }
14497 
14498       private:
14499 
T0oT1(T0oT1<T,T0,T1> &)14500          T0oT1(T0oT1<T,T0,T1>&) {}
operator =(T0oT1<T,T0,T1> &)14501          T0oT1<T,T0,T1>& operator=(T0oT1<T,T0,T1>&) { return (*this); }
14502 
14503          T0 t0_;
14504          T1 t1_;
14505          const bfunc_t f_;
14506       };
14507 
14508       template <typename T, typename T0, typename T1, typename T2, typename ProcessMode>
14509       class T0oT1oT2 : public T0oT1oT2_base_node<T>
14510       {
14511       public:
14512 
14513          typedef typename details::functor_t<T> functor_t;
14514          typedef typename functor_t::bfunc_t      bfunc_t;
14515          typedef T value_type;
14516          typedef T0oT1oT2<T,T0,T1,T2,ProcessMode> node_type;
14517          typedef ProcessMode process_mode_t;
14518 
T0oT1oT2(T0 p0,T1 p1,T2 p2,const bfunc_t p3,const bfunc_t p4)14519          T0oT1oT2(T0 p0, T1 p1, T2 p2, const bfunc_t p3, const bfunc_t p4)
14520          : t0_(p0),
14521            t1_(p1),
14522            t2_(p2),
14523            f0_(p3),
14524            f1_(p4)
14525          {}
14526 
type() const14527          inline typename expression_node<T>::node_type type() const
14528          {
14529             static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
14530             return result;
14531          }
14532 
operation() const14533          inline operator_type operation() const
14534          {
14535             return e_default;
14536          }
14537 
value() const14538          inline T value() const
14539          {
14540             return ProcessMode::process(t0_, t1_, t2_, f0_, f1_);
14541          }
14542 
t0() const14543          inline T0 t0() const
14544          {
14545             return t0_;
14546          }
14547 
t1() const14548          inline T1 t1() const
14549          {
14550             return t1_;
14551          }
14552 
t2() const14553          inline T2 t2() const
14554          {
14555             return t2_;
14556          }
14557 
f0() const14558          bfunc_t f0() const
14559          {
14560             return f0_;
14561          }
14562 
f1() const14563          bfunc_t f1() const
14564          {
14565             return f1_;
14566          }
14567 
type_id() const14568          std::string type_id() const
14569          {
14570             return id();
14571          }
14572 
id()14573          static inline std::string id()
14574          {
14575             return process_mode_t::template id<T0,T1,T2>();
14576          }
14577 
14578          template <typename Allocator>
allocate(Allocator & allocator,T0 p0,T1 p1,T2 p2,bfunc_t p3,bfunc_t p4)14579          static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, bfunc_t p3, bfunc_t p4)
14580          {
14581             return allocator
14582                       .template allocate_type<node_type, T0, T1, T2, bfunc_t, bfunc_t>
14583                          (p0, p1, p2, p3, p4);
14584          }
14585 
14586       private:
14587 
T0oT1oT2(node_type &)14588          T0oT1oT2(node_type&) {}
operator =(node_type &)14589          node_type& operator=(node_type&) { return (*this); }
14590 
14591          T0 t0_;
14592          T1 t1_;
14593          T2 t2_;
14594          const bfunc_t f0_;
14595          const bfunc_t f1_;
14596       };
14597 
14598       template <typename T, typename T0_, typename T1_, typename T2_, typename T3_, typename ProcessMode>
14599       class T0oT1oT2oT3 : public T0oT1oT2oT3_base_node<T>
14600       {
14601       public:
14602 
14603          typedef typename details::functor_t<T> functor_t;
14604          typedef typename functor_t::bfunc_t      bfunc_t;
14605          typedef T value_type;
14606          typedef T0_ T0;
14607          typedef T1_ T1;
14608          typedef T2_ T2;
14609          typedef T3_ T3;
14610          typedef T0oT1oT2oT3<T,T0,T1,T2,T3,ProcessMode> node_type;
14611          typedef ProcessMode process_mode_t;
14612 
T0oT1oT2oT3(T0 p0,T1 p1,T2 p2,T3 p3,bfunc_t p4,bfunc_t p5,bfunc_t p6)14613          T0oT1oT2oT3(T0 p0, T1 p1, T2 p2, T3 p3, bfunc_t p4, bfunc_t p5, bfunc_t p6)
14614          : t0_(p0),
14615            t1_(p1),
14616            t2_(p2),
14617            t3_(p3),
14618            f0_(p4),
14619            f1_(p5),
14620            f2_(p6)
14621          {}
14622 
value() const14623          inline T value() const
14624          {
14625             return ProcessMode::process(t0_, t1_, t2_, t3_, f0_, f1_, f2_);
14626          }
14627 
t0() const14628          inline T0 t0() const
14629          {
14630             return t0_;
14631          }
14632 
t1() const14633          inline T1 t1() const
14634          {
14635             return t1_;
14636          }
14637 
t2() const14638          inline T2 t2() const
14639          {
14640             return t2_;
14641          }
14642 
t3() const14643          inline T3 t3() const
14644          {
14645             return t3_;
14646          }
14647 
f0() const14648          inline bfunc_t f0() const
14649          {
14650             return f0_;
14651          }
14652 
f1() const14653          inline bfunc_t f1() const
14654          {
14655             return f1_;
14656          }
14657 
f2() const14658          inline bfunc_t f2() const
14659          {
14660             return f2_;
14661          }
14662 
type_id() const14663          inline std::string type_id() const
14664          {
14665             return id();
14666          }
14667 
id()14668          static inline std::string id()
14669          {
14670             return process_mode_t::template id<T0, T1, T2, T3>();
14671          }
14672 
14673          template <typename Allocator>
allocate(Allocator & allocator,T0 p0,T1 p1,T2 p2,T3 p3,bfunc_t p4,bfunc_t p5,bfunc_t p6)14674          static inline expression_node<T>* allocate(Allocator& allocator,
14675                                                     T0 p0, T1 p1, T2 p2, T3 p3,
14676                                                     bfunc_t p4, bfunc_t p5, bfunc_t p6)
14677          {
14678             return allocator
14679                       .template allocate_type<node_type, T0, T1, T2, T3, bfunc_t, bfunc_t>
14680                          (p0, p1, p2, p3, p4, p5, p6);
14681          }
14682 
14683       private:
14684 
T0oT1oT2oT3(node_type &)14685          T0oT1oT2oT3(node_type&) {}
operator =(node_type &)14686          node_type& operator=(node_type&) { return (*this); }
14687 
14688          T0 t0_;
14689          T1 t1_;
14690          T2 t2_;
14691          T3 t3_;
14692          const bfunc_t f0_;
14693          const bfunc_t f1_;
14694          const bfunc_t f2_;
14695       };
14696 
14697       template <typename T, typename T0, typename T1, typename T2>
14698       class T0oT1oT2_sf3 : public T0oT1oT2_base_node<T>
14699       {
14700       public:
14701 
14702          typedef typename details::functor_t<T> functor_t;
14703          typedef typename functor_t::tfunc_t      tfunc_t;
14704          typedef T value_type;
14705          typedef T0oT1oT2_sf3<T,T0,T1,T2> node_type;
14706 
T0oT1oT2_sf3(T0 p0,T1 p1,T2 p2,const tfunc_t p3)14707          T0oT1oT2_sf3(T0 p0, T1 p1, T2 p2, const tfunc_t p3)
14708          : t0_(p0),
14709            t1_(p1),
14710            t2_(p2),
14711            f_ (p3)
14712          {}
14713 
type() const14714          inline typename expression_node<T>::node_type type() const
14715          {
14716             static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
14717             return result;
14718          }
14719 
operation() const14720          inline operator_type operation() const
14721          {
14722             return e_default;
14723          }
14724 
value() const14725          inline T value() const
14726          {
14727             return f_(t0_, t1_, t2_);
14728          }
14729 
t0() const14730          inline T0 t0() const
14731          {
14732             return t0_;
14733          }
14734 
t1() const14735          inline T1 t1() const
14736          {
14737             return t1_;
14738          }
14739 
t2() const14740          inline T2 t2() const
14741          {
14742             return t2_;
14743          }
14744 
f() const14745          tfunc_t f() const
14746          {
14747             return f_;
14748          }
14749 
type_id() const14750          std::string type_id() const
14751          {
14752             return id();
14753          }
14754 
id()14755          static inline std::string id()
14756          {
14757             return "sf3";
14758          }
14759 
14760          template <typename Allocator>
allocate(Allocator & allocator,T0 p0,T1 p1,T2 p2,tfunc_t p3)14761          static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, tfunc_t p3)
14762          {
14763             return allocator
14764                      .template allocate_type<node_type, T0, T1, T2, tfunc_t>
14765                         (p0, p1, p2, p3);
14766          }
14767 
14768       private:
14769 
T0oT1oT2_sf3(node_type &)14770          T0oT1oT2_sf3(node_type&) {}
operator =(node_type &)14771          node_type& operator=(node_type&) { return (*this); }
14772 
14773          T0 t0_;
14774          T1 t1_;
14775          T2 t2_;
14776          const tfunc_t f_;
14777       };
14778 
14779       template <typename T, typename T0, typename T1, typename T2>
14780       class sf3ext_type_node : public T0oT1oT2_base_node<T>
14781       {
14782       public:
14783 
~sf3ext_type_node()14784          virtual ~sf3ext_type_node()
14785          {}
14786 
14787          virtual T0 t0() const = 0;
14788 
14789          virtual T1 t1() const = 0;
14790 
14791          virtual T2 t2() const = 0;
14792       };
14793 
14794       template <typename T, typename T0, typename T1, typename T2, typename SF3Operation>
14795       class T0oT1oT2_sf3ext : public sf3ext_type_node<T,T0,T1,T2>
14796       {
14797       public:
14798 
14799          typedef typename details::functor_t<T> functor_t;
14800          typedef typename functor_t::tfunc_t      tfunc_t;
14801          typedef T value_type;
14802          typedef T0oT1oT2_sf3ext<T,T0,T1,T2,SF3Operation> node_type;
14803 
T0oT1oT2_sf3ext(T0 p0,T1 p1,T2 p2)14804          T0oT1oT2_sf3ext(T0 p0, T1 p1, T2 p2)
14805          : t0_(p0),
14806            t1_(p1),
14807            t2_(p2)
14808          {}
14809 
type() const14810          inline typename expression_node<T>::node_type type() const
14811          {
14812             static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
14813             return result;
14814          }
14815 
operation() const14816          inline operator_type operation() const
14817          {
14818             return e_default;
14819          }
14820 
value() const14821          inline T value() const
14822          {
14823             return SF3Operation::process(t0_, t1_, t2_);
14824          }
14825 
t0() const14826          T0 t0() const
14827          {
14828             return t0_;
14829          }
14830 
t1() const14831          T1 t1() const
14832          {
14833             return t1_;
14834          }
14835 
t2() const14836          T2 t2() const
14837          {
14838             return t2_;
14839          }
14840 
type_id() const14841          std::string type_id() const
14842          {
14843             return id();
14844          }
14845 
id()14846          static inline std::string id()
14847          {
14848             return SF3Operation::id();
14849          }
14850 
14851          template <typename Allocator>
allocate(Allocator & allocator,T0 p0,T1 p1,T2 p2)14852          static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2)
14853          {
14854             return allocator
14855                      .template allocate_type<node_type, T0, T1, T2>
14856                         (p0, p1, p2);
14857          }
14858 
14859       private:
14860 
T0oT1oT2_sf3ext(node_type &)14861          T0oT1oT2_sf3ext(node_type&) {}
operator =(node_type &)14862          node_type& operator=(node_type&) { return (*this); }
14863 
14864          T0 t0_;
14865          T1 t1_;
14866          T2 t2_;
14867       };
14868 
14869       template <typename T>
is_sf3ext_node(const expression_node<T> * n)14870       inline bool is_sf3ext_node(const expression_node<T>* n)
14871       {
14872          switch (n->type())
14873          {
14874             case expression_node<T>::e_vovov : return true;
14875             case expression_node<T>::e_vovoc : return true;
14876             case expression_node<T>::e_vocov : return true;
14877             case expression_node<T>::e_covov : return true;
14878             case expression_node<T>::e_covoc : return true;
14879             default                          : return false;
14880          }
14881       }
14882 
14883       template <typename T, typename T0, typename T1, typename T2, typename T3>
14884       class T0oT1oT2oT3_sf4 : public T0oT1oT2_base_node<T>
14885       {
14886       public:
14887 
14888          typedef typename details::functor_t<T> functor_t;
14889          typedef typename functor_t::qfunc_t      qfunc_t;
14890          typedef T value_type;
14891          typedef T0oT1oT2oT3_sf4<T,T0,T1,T2,T3> node_type;
14892 
T0oT1oT2oT3_sf4(T0 p0,T1 p1,T2 p2,T3 p3,const qfunc_t p4)14893          T0oT1oT2oT3_sf4(T0 p0, T1 p1, T2 p2, T3 p3, const qfunc_t p4)
14894          : t0_(p0),
14895            t1_(p1),
14896            t2_(p2),
14897            t3_(p3),
14898            f_ (p4)
14899          {}
14900 
type() const14901          inline typename expression_node<T>::node_type type() const
14902          {
14903             static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result;
14904             return result;
14905          }
14906 
operation() const14907          inline operator_type operation() const
14908          {
14909             return e_default;
14910          }
14911 
value() const14912          inline T value() const
14913          {
14914             return f_(t0_, t1_, t2_, t3_);
14915          }
14916 
t0() const14917          inline T0 t0() const
14918          {
14919             return t0_;
14920          }
14921 
t1() const14922          inline T1 t1() const
14923          {
14924             return t1_;
14925          }
14926 
t2() const14927          inline T2 t2() const
14928          {
14929             return t2_;
14930          }
14931 
t3() const14932          inline T3 t3() const
14933          {
14934             return t3_;
14935          }
14936 
f() const14937          qfunc_t f() const
14938          {
14939             return f_;
14940          }
14941 
type_id() const14942          std::string type_id() const
14943          {
14944             return id();
14945          }
14946 
id()14947          static inline std::string id()
14948          {
14949             return "sf4";
14950          }
14951 
14952          template <typename Allocator>
allocate(Allocator & allocator,T0 p0,T1 p1,T2 p2,T3 p3,qfunc_t p4)14953          static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3, qfunc_t p4)
14954          {
14955             return allocator
14956                      .template allocate_type<node_type, T0, T1, T2, T3, qfunc_t>
14957                         (p0, p1, p2, p3, p4);
14958          }
14959 
14960       private:
14961 
T0oT1oT2oT3_sf4(node_type &)14962          T0oT1oT2oT3_sf4(node_type&) {}
operator =(node_type &)14963          node_type& operator=(node_type&) { return (*this); }
14964 
14965          T0 t0_;
14966          T1 t1_;
14967          T2 t2_;
14968          T3 t3_;
14969          const qfunc_t f_;
14970       };
14971 
14972       template <typename T, typename T0, typename T1, typename T2, typename T3, typename SF4Operation>
14973       class T0oT1oT2oT3_sf4ext : public T0oT1oT2oT3_base_node<T>
14974       {
14975       public:
14976 
14977          typedef typename details::functor_t<T> functor_t;
14978          typedef typename functor_t::tfunc_t      tfunc_t;
14979          typedef T value_type;
14980          typedef T0oT1oT2oT3_sf4ext<T,T0,T1,T2,T3,SF4Operation> node_type;
14981 
T0oT1oT2oT3_sf4ext(T0 p0,T1 p1,T2 p2,T3 p3)14982          T0oT1oT2oT3_sf4ext(T0 p0, T1 p1, T2 p2, T3 p3)
14983          : t0_(p0),
14984            t1_(p1),
14985            t2_(p2),
14986            t3_(p3)
14987          {}
14988 
type() const14989          inline typename expression_node<T>::node_type type() const
14990          {
14991             static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result;
14992             return result;
14993          }
14994 
operation() const14995          inline operator_type operation() const
14996          {
14997             return e_default;
14998          }
14999 
value() const15000          inline T value() const
15001          {
15002             return SF4Operation::process(t0_, t1_, t2_, t3_);
15003          }
15004 
t0() const15005          inline T0 t0() const
15006          {
15007             return t0_;
15008          }
15009 
t1() const15010          inline T1 t1() const
15011          {
15012             return t1_;
15013          }
15014 
t2() const15015          inline T2 t2() const
15016          {
15017             return t2_;
15018          }
15019 
t3() const15020          inline T3 t3() const
15021          {
15022             return t3_;
15023          }
15024 
type_id() const15025          std::string type_id() const
15026          {
15027             return id();
15028          }
15029 
id()15030          static inline std::string id()
15031          {
15032             return SF4Operation::id();
15033          }
15034 
15035          template <typename Allocator>
allocate(Allocator & allocator,T0 p0,T1 p1,T2 p2,T3 p3)15036          static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3)
15037          {
15038             return allocator
15039                      .template allocate_type<node_type, T0, T1, T2, T3>
15040                         (p0, p1, p2, p3);
15041          }
15042 
15043       private:
15044 
T0oT1oT2oT3_sf4ext(node_type &)15045          T0oT1oT2oT3_sf4ext(node_type&) {}
operator =(node_type &)15046          node_type& operator=(node_type&) { return (*this); }
15047 
15048          T0 t0_;
15049          T1 t1_;
15050          T2 t2_;
15051          T3 t3_;
15052       };
15053 
15054       template <typename T>
is_sf4ext_node(const expression_node<T> * n)15055       inline bool is_sf4ext_node(const expression_node<T>* n)
15056       {
15057          switch (n->type())
15058          {
15059             case expression_node<T>::e_vovovov : return true;
15060             case expression_node<T>::e_vovovoc : return true;
15061             case expression_node<T>::e_vovocov : return true;
15062             case expression_node<T>::e_vocovov : return true;
15063             case expression_node<T>::e_covovov : return true;
15064             case expression_node<T>::e_covocov : return true;
15065             case expression_node<T>::e_vocovoc : return true;
15066             case expression_node<T>::e_covovoc : return true;
15067             case expression_node<T>::e_vococov : return true;
15068             default                            : return false;
15069          }
15070       }
15071 
15072       template <typename T, typename T0, typename T1>
15073       struct T0oT1_define
15074       {
15075          typedef details::T0oT1<T, T0, T1> type0;
15076       };
15077 
15078       template <typename T, typename T0, typename T1, typename T2>
15079       struct T0oT1oT2_define
15080       {
15081          typedef details::T0oT1oT2<T, T0, T1, T2, typename T0oT1oT2process<T>::mode0> type0;
15082          typedef details::T0oT1oT2<T, T0, T1, T2, typename T0oT1oT2process<T>::mode1> type1;
15083          typedef details::T0oT1oT2_sf3<T, T0, T1, T2> sf3_type;
15084          typedef details::sf3ext_type_node<T, T0, T1, T2> sf3_type_node;
15085       };
15086 
15087       template <typename T, typename T0, typename T1, typename T2, typename T3>
15088       struct T0oT1oT2oT3_define
15089       {
15090          typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode0> type0;
15091          typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode1> type1;
15092          typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode2> type2;
15093          typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode3> type3;
15094          typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode4> type4;
15095          typedef details::T0oT1oT2oT3_sf4<T, T0, T1, T2, T3> sf4_type;
15096       };
15097 
15098       template <typename T, typename Operation>
15099       class vov_node : public vov_base_node<T>
15100       {
15101       public:
15102 
15103          typedef expression_node<T>* expression_ptr;
15104          typedef Operation operation_t;
15105 
15106          // variable op variable node
vov_node(const T & var0,const T & var1)15107          explicit vov_node(const T& var0, const T& var1)
15108          : v0_(var0),
15109            v1_(var1)
15110          {}
15111 
value() const15112          inline T value() const
15113          {
15114             return Operation::process(v0_,v1_);
15115          }
15116 
type() const15117          inline typename expression_node<T>::node_type type() const
15118          {
15119             return Operation::type();
15120          }
15121 
operation() const15122          inline operator_type operation() const
15123          {
15124             return Operation::operation();
15125          }
15126 
v0() const15127          inline const T& v0() const
15128          {
15129             return v0_;
15130          }
15131 
v1() const15132          inline const T& v1() const
15133          {
15134             return v1_;
15135          }
15136 
15137       protected:
15138 
15139          const T& v0_;
15140          const T& v1_;
15141 
15142       private:
15143 
15144          vov_node(vov_node<T,Operation>&);
15145          vov_node<T,Operation>& operator=(vov_node<T,Operation>&);
15146       };
15147 
15148       template <typename T, typename Operation>
15149       class cov_node : public cov_base_node<T>
15150       {
15151       public:
15152 
15153          typedef expression_node<T>* expression_ptr;
15154          typedef Operation operation_t;
15155 
15156          // constant op variable node
cov_node(const T & const_var,const T & var)15157          explicit cov_node(const T& const_var, const T& var)
15158          : c_(const_var),
15159            v_(var)
15160          {}
15161 
value() const15162          inline T value() const
15163          {
15164             return Operation::process(c_,v_);
15165          }
15166 
type() const15167          inline typename expression_node<T>::node_type type() const
15168          {
15169             return Operation::type();
15170          }
15171 
operation() const15172          inline operator_type operation() const
15173          {
15174             return Operation::operation();
15175          }
15176 
c() const15177          inline const T c() const
15178          {
15179             return c_;
15180          }
15181 
v() const15182          inline const T& v() const
15183          {
15184             return v_;
15185          }
15186 
15187       protected:
15188 
15189          const T  c_;
15190          const T& v_;
15191 
15192       private:
15193 
15194          cov_node(const cov_node<T,Operation>&);
15195          cov_node<T,Operation>& operator=(const cov_node<T,Operation>&);
15196       };
15197 
15198       template <typename T, typename Operation>
15199       class voc_node : public voc_base_node<T>
15200       {
15201       public:
15202 
15203          typedef expression_node<T>* expression_ptr;
15204          typedef Operation operation_t;
15205 
15206          // variable op constant node
voc_node(const T & var,const T & const_var)15207          explicit voc_node(const T& var, const T& const_var)
15208          : v_(var),
15209            c_(const_var)
15210          {}
15211 
value() const15212          inline T value() const
15213          {
15214             return Operation::process(v_,c_);
15215          }
15216 
operation() const15217          inline operator_type operation() const
15218          {
15219             return Operation::operation();
15220          }
15221 
c() const15222          inline const T c() const
15223          {
15224             return c_;
15225          }
15226 
v() const15227          inline const T& v() const
15228          {
15229             return v_;
15230          }
15231 
15232       protected:
15233 
15234          const T& v_;
15235          const T  c_;
15236 
15237       private:
15238 
15239          voc_node(const voc_node<T,Operation>&);
15240          voc_node<T,Operation>& operator=(const voc_node<T,Operation>&);
15241       };
15242 
15243       template <typename T, typename Operation>
15244       class vob_node : public vob_base_node<T>
15245       {
15246       public:
15247 
15248          typedef expression_node<T>* expression_ptr;
15249          typedef std::pair<expression_ptr,bool> branch_t;
15250          typedef Operation operation_t;
15251 
15252          // variable op constant node
vob_node(const T & var,const expression_ptr branch)15253          explicit vob_node(const T& var, const expression_ptr branch)
15254          : v_(var)
15255          {
15256             construct_branch_pair(branch_, branch);
15257          }
15258 
value() const15259          inline T value() const
15260          {
15261             assert(branch_.first);
15262             return Operation::process(v_,branch_.first->value());
15263          }
15264 
operation() const15265          inline operator_type operation() const
15266          {
15267             return Operation::operation();
15268          }
15269 
v() const15270          inline const T& v() const
15271          {
15272             return v_;
15273          }
15274 
branch(const std::size_t &) const15275          inline expression_node<T>* branch(const std::size_t&) const
15276          {
15277             return branch_.first;
15278          }
15279 
collect_nodes(typename expression_node<T>::noderef_list_t & node_delete_list)15280          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
15281          {
15282             expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
15283          }
15284 
node_depth() const15285          std::size_t node_depth() const
15286          {
15287             return expression_node<T>::ndb_t::compute_node_depth(branch_);
15288          }
15289 
15290       private:
15291 
15292          vob_node(const vob_node<T,Operation>&);
15293          vob_node<T,Operation>& operator=(const vob_node<T,Operation>&);
15294 
15295          const T& v_;
15296          branch_t branch_;
15297       };
15298 
15299       template <typename T, typename Operation>
15300       class bov_node : public bov_base_node<T>
15301       {
15302       public:
15303 
15304          typedef expression_node<T>* expression_ptr;
15305          typedef std::pair<expression_ptr,bool> branch_t;
15306          typedef Operation operation_t;
15307 
15308          // variable op constant node
bov_node(const expression_ptr branch,const T & var)15309          explicit bov_node(const expression_ptr branch, const T& var)
15310          : v_(var)
15311          {
15312             construct_branch_pair(branch_, branch);
15313          }
15314 
value() const15315          inline T value() const
15316          {
15317             assert(branch_.first);
15318             return Operation::process(branch_.first->value(),v_);
15319          }
15320 
operation() const15321          inline operator_type operation() const
15322          {
15323             return Operation::operation();
15324          }
15325 
v() const15326          inline const T& v() const
15327          {
15328             return v_;
15329          }
15330 
branch(const std::size_t &) const15331          inline expression_node<T>* branch(const std::size_t&) const
15332          {
15333             return branch_.first;
15334          }
15335 
collect_nodes(typename expression_node<T>::noderef_list_t & node_delete_list)15336          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
15337          {
15338             expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
15339          }
15340 
node_depth() const15341          std::size_t node_depth() const
15342          {
15343             return expression_node<T>::ndb_t::compute_node_depth(branch_);
15344          }
15345 
15346       private:
15347 
15348          bov_node(const bov_node<T,Operation>&);
15349          bov_node<T,Operation>& operator=(const bov_node<T,Operation>&);
15350 
15351          const T& v_;
15352          branch_t branch_;
15353       };
15354 
15355       template <typename T, typename Operation>
15356       class cob_node : public cob_base_node<T>
15357       {
15358       public:
15359 
15360          typedef expression_node<T>* expression_ptr;
15361          typedef std::pair<expression_ptr,bool> branch_t;
15362          typedef Operation operation_t;
15363 
15364          // variable op constant node
cob_node(const T const_var,const expression_ptr branch)15365          explicit cob_node(const T const_var, const expression_ptr branch)
15366          : c_(const_var)
15367          {
15368             construct_branch_pair(branch_, branch);
15369          }
15370 
value() const15371          inline T value() const
15372          {
15373             assert(branch_.first);
15374             return Operation::process(c_,branch_.first->value());
15375          }
15376 
operation() const15377          inline operator_type operation() const
15378          {
15379             return Operation::operation();
15380          }
15381 
c() const15382          inline const T c() const
15383          {
15384             return c_;
15385          }
15386 
set_c(const T new_c)15387          inline void set_c(const T new_c)
15388          {
15389             (*const_cast<T*>(&c_)) = new_c;
15390          }
15391 
branch(const std::size_t &) const15392          inline expression_node<T>* branch(const std::size_t&) const
15393          {
15394             return branch_.first;
15395          }
15396 
move_branch(const std::size_t &)15397          inline expression_node<T>* move_branch(const std::size_t&)
15398          {
15399             branch_.second = false;
15400             return branch_.first;
15401          }
15402 
collect_nodes(typename expression_node<T>::noderef_list_t & node_delete_list)15403          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
15404          {
15405             expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
15406          }
15407 
node_depth() const15408          std::size_t node_depth() const
15409          {
15410             return expression_node<T>::ndb_t::compute_node_depth(branch_);
15411          }
15412 
15413       private:
15414 
15415          cob_node(const cob_node<T,Operation>&);
15416          cob_node<T,Operation>& operator=(const cob_node<T,Operation>&);
15417 
15418          const T  c_;
15419          branch_t branch_;
15420       };
15421 
15422       template <typename T, typename Operation>
15423       class boc_node : public boc_base_node<T>
15424       {
15425       public:
15426 
15427          typedef expression_node<T>* expression_ptr;
15428          typedef std::pair<expression_ptr,bool> branch_t;
15429          typedef Operation operation_t;
15430 
15431          // variable op constant node
boc_node(const expression_ptr branch,const T const_var)15432          explicit boc_node(const expression_ptr branch, const T const_var)
15433          : c_(const_var)
15434          {
15435             construct_branch_pair(branch_, branch);
15436          }
15437 
value() const15438          inline T value() const
15439          {
15440             assert(branch_.first);
15441             return Operation::process(branch_.first->value(),c_);
15442          }
15443 
operation() const15444          inline operator_type operation() const
15445          {
15446             return Operation::operation();
15447          }
15448 
c() const15449          inline const T c() const
15450          {
15451             return c_;
15452          }
15453 
set_c(const T new_c)15454          inline void set_c(const T new_c)
15455          {
15456             (*const_cast<T*>(&c_)) = new_c;
15457          }
15458 
branch(const std::size_t &) const15459          inline expression_node<T>* branch(const std::size_t&) const
15460          {
15461             return branch_.first;
15462          }
15463 
move_branch(const std::size_t &)15464          inline expression_node<T>* move_branch(const std::size_t&)
15465          {
15466             branch_.second = false;
15467             return branch_.first;
15468          }
15469 
collect_nodes(typename expression_node<T>::noderef_list_t & node_delete_list)15470          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
15471          {
15472             expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
15473          }
15474 
node_depth() const15475          std::size_t node_depth() const
15476          {
15477             return expression_node<T>::ndb_t::compute_node_depth(branch_);
15478          }
15479 
15480       private:
15481 
15482          boc_node(const boc_node<T,Operation>&);
15483          boc_node<T,Operation>& operator=(const boc_node<T,Operation>&);
15484 
15485          const T  c_;
15486          branch_t branch_;
15487       };
15488 
15489       #ifndef exprtk_disable_string_capabilities
15490       template <typename T, typename SType0, typename SType1, typename Operation>
15491       class sos_node : public sos_base_node<T>
15492       {
15493       public:
15494 
15495          typedef expression_node<T>* expression_ptr;
15496          typedef Operation operation_t;
15497 
15498          // string op string node
sos_node(SType0 p0,SType1 p1)15499          explicit sos_node(SType0 p0, SType1 p1)
15500          : s0_(p0),
15501            s1_(p1)
15502          {}
15503 
value() const15504          inline T value() const
15505          {
15506             return Operation::process(s0_,s1_);
15507          }
15508 
type() const15509          inline typename expression_node<T>::node_type type() const
15510          {
15511             return Operation::type();
15512          }
15513 
operation() const15514          inline operator_type operation() const
15515          {
15516             return Operation::operation();
15517          }
15518 
s0()15519          inline std::string& s0()
15520          {
15521             return s0_;
15522          }
15523 
s1()15524          inline std::string& s1()
15525          {
15526             return s1_;
15527          }
15528 
15529       protected:
15530 
15531          SType0 s0_;
15532          SType1 s1_;
15533 
15534       private:
15535 
15536          sos_node(sos_node<T,SType0,SType1,Operation>&);
15537          sos_node<T,SType0,SType1,Operation>& operator=(sos_node<T,SType0,SType1,Operation>&);
15538       };
15539 
15540       template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
15541       class str_xrox_node : public sos_base_node<T>
15542       {
15543       public:
15544 
15545          typedef expression_node<T>* expression_ptr;
15546          typedef Operation operation_t;
15547 
15548          // string-range op string node
str_xrox_node(SType0 p0,SType1 p1,RangePack rp0)15549          explicit str_xrox_node(SType0 p0, SType1 p1, RangePack rp0)
15550          : s0_ (p0 ),
15551            s1_ (p1 ),
15552            rp0_(rp0)
15553          {}
15554 
~str_xrox_node()15555         ~str_xrox_node()
15556          {
15557             rp0_.free();
15558          }
15559 
value() const15560          inline T value() const
15561          {
15562             std::size_t r0 = 0;
15563             std::size_t r1 = 0;
15564 
15565             if (rp0_(r0, r1, s0_.size()))
15566                return Operation::process(s0_.substr(r0, (r1 - r0) + 1), s1_);
15567             else
15568                return T(0);
15569          }
15570 
type() const15571          inline typename expression_node<T>::node_type type() const
15572          {
15573             return Operation::type();
15574          }
15575 
operation() const15576          inline operator_type operation() const
15577          {
15578             return Operation::operation();
15579          }
15580 
s0()15581          inline std::string& s0()
15582          {
15583             return s0_;
15584          }
15585 
s1()15586          inline std::string& s1()
15587          {
15588             return s1_;
15589          }
15590 
15591       protected:
15592 
15593          SType0    s0_;
15594          SType1    s1_;
15595          RangePack rp0_;
15596 
15597       private:
15598 
15599          str_xrox_node(str_xrox_node<T,SType0,SType1,RangePack,Operation>&);
15600          str_xrox_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xrox_node<T,SType0,SType1,RangePack,Operation>&);
15601       };
15602 
15603       template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
15604       class str_xoxr_node : public sos_base_node<T>
15605       {
15606       public:
15607 
15608          typedef expression_node<T>* expression_ptr;
15609          typedef Operation operation_t;
15610 
15611          // string op string range node
str_xoxr_node(SType0 p0,SType1 p1,RangePack rp1)15612          explicit str_xoxr_node(SType0 p0, SType1 p1, RangePack rp1)
15613          : s0_ (p0 ),
15614            s1_ (p1 ),
15615            rp1_(rp1)
15616          {}
15617 
~str_xoxr_node()15618         ~str_xoxr_node()
15619          {
15620             rp1_.free();
15621          }
15622 
value() const15623          inline T value() const
15624          {
15625             std::size_t r0 = 0;
15626             std::size_t r1 = 0;
15627 
15628             if (rp1_(r0, r1, s1_.size()))
15629                return Operation::process(s0_, s1_.substr(r0, (r1 - r0) + 1));
15630             else
15631                return T(0);
15632          }
15633 
type() const15634          inline typename expression_node<T>::node_type type() const
15635          {
15636             return Operation::type();
15637          }
15638 
operation() const15639          inline operator_type operation() const
15640          {
15641             return Operation::operation();
15642          }
15643 
s0()15644          inline std::string& s0()
15645          {
15646             return s0_;
15647          }
15648 
s1()15649          inline std::string& s1()
15650          {
15651             return s1_;
15652          }
15653 
15654       protected:
15655 
15656          SType0    s0_;
15657          SType1    s1_;
15658          RangePack rp1_;
15659 
15660       private:
15661 
15662          str_xoxr_node(str_xoxr_node<T,SType0,SType1,RangePack,Operation>&);
15663          str_xoxr_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xoxr_node<T,SType0,SType1,RangePack,Operation>&);
15664       };
15665 
15666       template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
15667       class str_xroxr_node : public sos_base_node<T>
15668       {
15669       public:
15670 
15671          typedef expression_node<T>* expression_ptr;
15672          typedef Operation operation_t;
15673 
15674          // string-range op string-range node
str_xroxr_node(SType0 p0,SType1 p1,RangePack rp0,RangePack rp1)15675          explicit str_xroxr_node(SType0 p0, SType1 p1, RangePack rp0, RangePack rp1)
15676          : s0_ (p0 ),
15677            s1_ (p1 ),
15678            rp0_(rp0),
15679            rp1_(rp1)
15680          {}
15681 
~str_xroxr_node()15682         ~str_xroxr_node()
15683          {
15684             rp0_.free();
15685             rp1_.free();
15686          }
15687 
value() const15688          inline T value() const
15689          {
15690             std::size_t r0_0 = 0;
15691             std::size_t r0_1 = 0;
15692             std::size_t r1_0 = 0;
15693             std::size_t r1_1 = 0;
15694 
15695             if (
15696                  rp0_(r0_0, r1_0, s0_.size()) &&
15697                  rp1_(r0_1, r1_1, s1_.size())
15698                )
15699             {
15700                return Operation::process(
15701                                           s0_.substr(r0_0, (r1_0 - r0_0) + 1),
15702                                           s1_.substr(r0_1, (r1_1 - r0_1) + 1)
15703                                         );
15704             }
15705             else
15706                return T(0);
15707          }
15708 
type() const15709          inline typename expression_node<T>::node_type type() const
15710          {
15711             return Operation::type();
15712          }
15713 
operation() const15714          inline operator_type operation() const
15715          {
15716             return Operation::operation();
15717          }
15718 
s0()15719          inline std::string& s0()
15720          {
15721             return s0_;
15722          }
15723 
s1()15724          inline std::string& s1()
15725          {
15726             return s1_;
15727          }
15728 
15729       protected:
15730 
15731          SType0    s0_;
15732          SType1    s1_;
15733          RangePack rp0_;
15734          RangePack rp1_;
15735 
15736       private:
15737 
15738          str_xroxr_node(str_xroxr_node<T,SType0,SType1,RangePack,Operation>&);
15739          str_xroxr_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xroxr_node<T,SType0,SType1,RangePack,Operation>&);
15740       };
15741 
15742       template <typename T, typename Operation>
15743       class str_sogens_node : public binary_node<T>
15744       {
15745       public:
15746 
15747          typedef expression_node <T>* expression_ptr;
15748          typedef string_base_node<T>*   str_base_ptr;
15749          typedef range_pack      <T>         range_t;
15750          typedef range_t*                  range_ptr;
15751          typedef range_interface<T>         irange_t;
15752          typedef irange_t*                irange_ptr;
15753 
str_sogens_node(const operator_type & opr,expression_ptr branch0,expression_ptr branch1)15754          str_sogens_node(const operator_type& opr,
15755                          expression_ptr branch0,
15756                          expression_ptr branch1)
15757          : binary_node<T>(opr, branch0, branch1),
15758            str0_base_ptr_ (0),
15759            str1_base_ptr_ (0),
15760            str0_range_ptr_(0),
15761            str1_range_ptr_(0)
15762          {
15763             if (is_generally_string_node(binary_node<T>::branch_[0].first))
15764             {
15765                str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
15766 
15767                if (0 == str0_base_ptr_)
15768                   return;
15769 
15770                irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
15771 
15772                if (0 == range)
15773                   return;
15774 
15775                str0_range_ptr_ = &(range->range_ref());
15776             }
15777 
15778             if (is_generally_string_node(binary_node<T>::branch_[1].first))
15779             {
15780                str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
15781 
15782                if (0 == str1_base_ptr_)
15783                   return;
15784 
15785                irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
15786 
15787                if (0 == range)
15788                   return;
15789 
15790                str1_range_ptr_ = &(range->range_ref());
15791             }
15792          }
15793 
value() const15794          inline T value() const
15795          {
15796             if (
15797                  str0_base_ptr_  &&
15798                  str1_base_ptr_  &&
15799                  str0_range_ptr_ &&
15800                  str1_range_ptr_
15801                )
15802             {
15803                binary_node<T>::branch_[0].first->value();
15804                binary_node<T>::branch_[1].first->value();
15805 
15806                std::size_t str0_r0 = 0;
15807                std::size_t str0_r1 = 0;
15808 
15809                std::size_t str1_r0 = 0;
15810                std::size_t str1_r1 = 0;
15811 
15812                const range_t& range0 = (*str0_range_ptr_);
15813                const range_t& range1 = (*str1_range_ptr_);
15814 
15815                if (
15816                     range0(str0_r0, str0_r1, str0_base_ptr_->size()) &&
15817                     range1(str1_r0, str1_r1, str1_base_ptr_->size())
15818                   )
15819                {
15820                   return Operation::process(
15821                                              str0_base_ptr_->str().substr(str0_r0,(str0_r1 - str0_r0) + 1),
15822                                              str1_base_ptr_->str().substr(str1_r0,(str1_r1 - str1_r0) + 1)
15823                                            );
15824                }
15825             }
15826 
15827             return std::numeric_limits<T>::quiet_NaN();
15828          }
15829 
type() const15830          inline typename expression_node<T>::node_type type() const
15831          {
15832             return Operation::type();
15833          }
15834 
operation() const15835          inline operator_type operation() const
15836          {
15837             return Operation::operation();
15838          }
15839 
15840       private:
15841 
15842          str_sogens_node(str_sogens_node<T,Operation>&);
15843          str_sogens_node<T,Operation>& operator=(str_sogens_node<T,Operation>&);
15844 
15845          str_base_ptr str0_base_ptr_;
15846          str_base_ptr str1_base_ptr_;
15847          range_ptr    str0_range_ptr_;
15848          range_ptr    str1_range_ptr_;
15849       };
15850 
15851       template <typename T, typename SType0, typename SType1, typename SType2, typename Operation>
15852       class sosos_node : public sosos_base_node<T>
15853       {
15854       public:
15855 
15856          typedef expression_node<T>* expression_ptr;
15857          typedef Operation operation_t;
15858 
15859          // variable op variable node
sosos_node(SType0 p0,SType1 p1,SType2 p2)15860          explicit sosos_node(SType0 p0, SType1 p1, SType2 p2)
15861          : s0_(p0),
15862            s1_(p1),
15863            s2_(p2)
15864          {}
15865 
value() const15866          inline T value() const
15867          {
15868             return Operation::process(s0_,s1_,s2_);
15869          }
15870 
type() const15871          inline typename expression_node<T>::node_type type() const
15872          {
15873             return Operation::type();
15874          }
15875 
operation() const15876          inline operator_type operation() const
15877          {
15878             return Operation::operation();
15879          }
15880 
s0()15881          inline std::string& s0()
15882          {
15883             return s0_;
15884          }
15885 
s1()15886          inline std::string& s1()
15887          {
15888             return s1_;
15889          }
15890 
s2()15891          inline std::string& s2()
15892          {
15893             return s2_;
15894          }
15895 
15896       protected:
15897 
15898          SType0 s0_;
15899          SType1 s1_;
15900          SType2 s2_;
15901 
15902       private:
15903 
15904          sosos_node(sosos_node<T,SType0,SType1,SType2,Operation>&);
15905          sosos_node<T,SType0,SType1,SType2,Operation>& operator=(sosos_node<T,SType0,SType1,SType2,Operation>&);
15906       };
15907       #endif
15908 
15909       template <typename T, typename PowOp>
15910       class ipow_node : public expression_node<T>
15911       {
15912       public:
15913 
15914          typedef expression_node<T>* expression_ptr;
15915          typedef PowOp operation_t;
15916 
ipow_node(const T & v)15917          explicit ipow_node(const T& v)
15918          : v_(v)
15919          {}
15920 
value() const15921          inline T value() const
15922          {
15923             return PowOp::result(v_);
15924          }
15925 
type() const15926          inline typename expression_node<T>::node_type type() const
15927          {
15928             return expression_node<T>::e_ipow;
15929          }
15930 
15931       private:
15932 
15933          ipow_node(const ipow_node<T,PowOp>&);
15934          ipow_node<T,PowOp>& operator=(const ipow_node<T,PowOp>&);
15935 
15936          const T& v_;
15937       };
15938 
15939       template <typename T, typename PowOp>
15940       class bipow_node : public expression_node<T>
15941       {
15942       public:
15943 
15944          typedef expression_node<T>* expression_ptr;
15945          typedef std::pair<expression_ptr, bool> branch_t;
15946          typedef PowOp operation_t;
15947 
bipow_node(expression_ptr branch)15948          explicit bipow_node(expression_ptr branch)
15949          {
15950             construct_branch_pair(branch_, branch);
15951          }
15952 
value() const15953          inline T value() const
15954          {
15955             assert(branch_.first);
15956             return PowOp::result(branch_.first->value());
15957          }
15958 
type() const15959          inline typename expression_node<T>::node_type type() const
15960          {
15961             return expression_node<T>::e_ipow;
15962          }
15963 
collect_nodes(typename expression_node<T>::noderef_list_t & node_delete_list)15964          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
15965          {
15966             expression_node<T>::ndb_t::collect(branch_, node_delete_list);
15967          }
15968 
node_depth() const15969          std::size_t node_depth() const
15970          {
15971             return expression_node<T>::ndb_t::compute_node_depth(branch_);
15972          }
15973 
15974       private:
15975 
15976          bipow_node(const bipow_node<T,PowOp>&);
15977          bipow_node<T,PowOp>& operator=(const bipow_node<T,PowOp>&);
15978 
15979          branch_t branch_;
15980       };
15981 
15982       template <typename T, typename PowOp>
15983       class ipowinv_node : public expression_node<T>
15984       {
15985       public:
15986 
15987          typedef expression_node<T>* expression_ptr;
15988          typedef PowOp operation_t;
15989 
ipowinv_node(const T & v)15990          explicit ipowinv_node(const T& v)
15991          : v_(v)
15992          {}
15993 
value() const15994          inline T value() const
15995          {
15996             return (T(1) / PowOp::result(v_));
15997          }
15998 
type() const15999          inline typename expression_node<T>::node_type type() const
16000          {
16001             return expression_node<T>::e_ipowinv;
16002          }
16003 
16004       private:
16005 
16006          ipowinv_node(const ipowinv_node<T,PowOp>&);
16007          ipowinv_node<T,PowOp>& operator=(const ipowinv_node<T,PowOp>&);
16008 
16009          const T& v_;
16010       };
16011 
16012       template <typename T, typename PowOp>
16013       class bipowninv_node : public expression_node<T>
16014       {
16015       public:
16016 
16017          typedef expression_node<T>* expression_ptr;
16018          typedef std::pair<expression_ptr, bool> branch_t;
16019          typedef PowOp operation_t;
16020 
bipowninv_node(expression_ptr branch)16021          explicit bipowninv_node(expression_ptr branch)
16022          {
16023             construct_branch_pair(branch_, branch);
16024          }
16025 
value() const16026          inline T value() const
16027          {
16028             assert(branch_.first);
16029             return (T(1) / PowOp::result(branch_.first->value()));
16030          }
16031 
type() const16032          inline typename expression_node<T>::node_type type() const
16033          {
16034             return expression_node<T>::e_ipowinv;
16035          }
16036 
collect_nodes(typename expression_node<T>::noderef_list_t & node_delete_list)16037          void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list)
16038          {
16039             expression_node<T>::ndb_t::template collect(branch_, node_delete_list);
16040          }
16041 
node_depth() const16042          std::size_t node_depth() const
16043          {
16044             return expression_node<T>::ndb_t::compute_node_depth(branch_);
16045          }
16046 
16047       private:
16048 
16049          bipowninv_node(const bipowninv_node<T,PowOp>&);
16050          bipowninv_node<T,PowOp>& operator=(const bipowninv_node<T,PowOp>&);
16051 
16052          branch_t branch_;
16053       };
16054 
16055       template <typename T>
is_vov_node(const expression_node<T> * node)16056       inline bool is_vov_node(const expression_node<T>* node)
16057       {
16058          return (0 != dynamic_cast<const vov_base_node<T>*>(node));
16059       }
16060 
16061       template <typename T>
is_cov_node(const expression_node<T> * node)16062       inline bool is_cov_node(const expression_node<T>* node)
16063       {
16064          return (0 != dynamic_cast<const cov_base_node<T>*>(node));
16065       }
16066 
16067       template <typename T>
is_voc_node(const expression_node<T> * node)16068       inline bool is_voc_node(const expression_node<T>* node)
16069       {
16070          return (0 != dynamic_cast<const voc_base_node<T>*>(node));
16071       }
16072 
16073       template <typename T>
is_cob_node(const expression_node<T> * node)16074       inline bool is_cob_node(const expression_node<T>* node)
16075       {
16076          return (0 != dynamic_cast<const cob_base_node<T>*>(node));
16077       }
16078 
16079       template <typename T>
is_boc_node(const expression_node<T> * node)16080       inline bool is_boc_node(const expression_node<T>* node)
16081       {
16082          return (0 != dynamic_cast<const boc_base_node<T>*>(node));
16083       }
16084 
16085       template <typename T>
is_t0ot1ot2_node(const expression_node<T> * node)16086       inline bool is_t0ot1ot2_node(const expression_node<T>* node)
16087       {
16088          return (0 != dynamic_cast<const T0oT1oT2_base_node<T>*>(node));
16089       }
16090 
16091       template <typename T>
is_t0ot1ot2ot3_node(const expression_node<T> * node)16092       inline bool is_t0ot1ot2ot3_node(const expression_node<T>* node)
16093       {
16094          return (0 != dynamic_cast<const T0oT1oT2oT3_base_node<T>*>(node));
16095       }
16096 
16097       template <typename T>
is_uv_node(const expression_node<T> * node)16098       inline bool is_uv_node(const expression_node<T>* node)
16099       {
16100          return (0 != dynamic_cast<const uv_base_node<T>*>(node));
16101       }
16102 
16103       template <typename T>
is_string_node(const expression_node<T> * node)16104       inline bool is_string_node(const expression_node<T>* node)
16105       {
16106          return node && (expression_node<T>::e_stringvar == node->type());
16107       }
16108 
16109       template <typename T>
is_string_range_node(const expression_node<T> * node)16110       inline bool is_string_range_node(const expression_node<T>* node)
16111       {
16112          return node && (expression_node<T>::e_stringvarrng == node->type());
16113       }
16114 
16115       template <typename T>
is_const_string_node(const expression_node<T> * node)16116       inline bool is_const_string_node(const expression_node<T>* node)
16117       {
16118          return node && (expression_node<T>::e_stringconst == node->type());
16119       }
16120 
16121       template <typename T>
is_const_string_range_node(const expression_node<T> * node)16122       inline bool is_const_string_range_node(const expression_node<T>* node)
16123       {
16124          return node && (expression_node<T>::e_cstringvarrng == node->type());
16125       }
16126 
16127       template <typename T>
is_string_assignment_node(const expression_node<T> * node)16128       inline bool is_string_assignment_node(const expression_node<T>* node)
16129       {
16130          return node && (expression_node<T>::e_strass == node->type());
16131       }
16132 
16133       template <typename T>
is_string_concat_node(const expression_node<T> * node)16134       inline bool is_string_concat_node(const expression_node<T>* node)
16135       {
16136          return node && (expression_node<T>::e_strconcat == node->type());
16137       }
16138 
16139       template <typename T>
is_string_function_node(const expression_node<T> * node)16140       inline bool is_string_function_node(const expression_node<T>* node)
16141       {
16142          return node && (expression_node<T>::e_strfunction == node->type());
16143       }
16144 
16145       template <typename T>
is_string_condition_node(const expression_node<T> * node)16146       inline bool is_string_condition_node(const expression_node<T>* node)
16147       {
16148          return node && (expression_node<T>::e_strcondition == node->type());
16149       }
16150 
16151       template <typename T>
is_string_ccondition_node(const expression_node<T> * node)16152       inline bool is_string_ccondition_node(const expression_node<T>* node)
16153       {
16154          return node && (expression_node<T>::e_strccondition == node->type());
16155       }
16156 
16157       template <typename T>
is_string_vararg_node(const expression_node<T> * node)16158       inline bool is_string_vararg_node(const expression_node<T>* node)
16159       {
16160          return node && (expression_node<T>::e_stringvararg == node->type());
16161       }
16162 
16163       template <typename T>
is_genricstring_range_node(const expression_node<T> * node)16164       inline bool is_genricstring_range_node(const expression_node<T>* node)
16165       {
16166          return node && (expression_node<T>::e_strgenrange == node->type());
16167       }
16168 
16169       template <typename T>
is_generally_string_node(const expression_node<T> * node)16170       inline bool is_generally_string_node(const expression_node<T>* node)
16171       {
16172          if (node)
16173          {
16174             switch (node->type())
16175             {
16176                case expression_node<T>::e_stringvar     :
16177                case expression_node<T>::e_stringconst   :
16178                case expression_node<T>::e_stringvarrng  :
16179                case expression_node<T>::e_cstringvarrng :
16180                case expression_node<T>::e_strgenrange   :
16181                case expression_node<T>::e_strass        :
16182                case expression_node<T>::e_strconcat     :
16183                case expression_node<T>::e_strfunction   :
16184                case expression_node<T>::e_strcondition  :
16185                case expression_node<T>::e_strccondition :
16186                case expression_node<T>::e_stringvararg  : return true;
16187                default                                  : return false;
16188             }
16189          }
16190 
16191          return false;
16192       }
16193 
16194       class node_allocator
16195       {
16196       public:
16197 
16198          template <typename ResultNode, typename OpType, typename ExprNode>
allocate(OpType & operation,ExprNode (& branch)[1])16199          inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[1])
16200          {
16201             expression_node<typename ResultNode::value_type>* result =
16202                allocate<ResultNode>(operation, branch[0]);
16203             result->node_depth();
16204             return result;
16205          }
16206 
16207          template <typename ResultNode, typename OpType, typename ExprNode>
allocate(OpType & operation,ExprNode (& branch)[2])16208          inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[2])
16209          {
16210             expression_node<typename ResultNode::value_type>* result =
16211                allocate<ResultNode>(operation, branch[0], branch[1]);
16212             result->node_depth();
16213             return result;
16214          }
16215 
16216          template <typename ResultNode, typename OpType, typename ExprNode>
allocate(OpType & operation,ExprNode (& branch)[3])16217          inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[3])
16218          {
16219             expression_node<typename ResultNode::value_type>* result =
16220                allocate<ResultNode>(operation, branch[0], branch[1], branch[2]);
16221             result->node_depth();
16222             return result;
16223          }
16224 
16225          template <typename ResultNode, typename OpType, typename ExprNode>
allocate(OpType & operation,ExprNode (& branch)[4])16226          inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[4])
16227          {
16228             expression_node<typename ResultNode::value_type>* result =
16229                allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3]);
16230             result->node_depth();
16231             return result;
16232          }
16233 
16234          template <typename ResultNode, typename OpType, typename ExprNode>
allocate(OpType & operation,ExprNode (& branch)[5])16235          inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[5])
16236          {
16237             expression_node<typename ResultNode::value_type>* result =
16238                allocate<ResultNode>(operation, branch[0],branch[1], branch[2], branch[3], branch[4]);
16239             result->node_depth();
16240             return result;
16241          }
16242 
16243          template <typename ResultNode, typename OpType, typename ExprNode>
allocate(OpType & operation,ExprNode (& branch)[6])16244          inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[6])
16245          {
16246             expression_node<typename ResultNode::value_type>* result =
16247                allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3], branch[4], branch[5]);
16248             result->node_depth();
16249             return result;
16250          }
16251 
16252          template <typename node_type>
allocate() const16253          inline expression_node<typename node_type::value_type>* allocate() const
16254          {
16255             return (new node_type());
16256          }
16257 
16258          template <typename node_type,
16259                    typename Type,
16260                    typename Allocator,
16261                    template <typename, typename> class Sequence>
allocate(const Sequence<Type,Allocator> & seq) const16262          inline expression_node<typename node_type::value_type>* allocate(const Sequence<Type,Allocator>& seq) const
16263          {
16264             expression_node<typename node_type::value_type>*
16265             result = (new node_type(seq));
16266             result->node_depth();
16267             return result;
16268          }
16269 
16270          template <typename node_type, typename T1>
allocate(T1 & t1) const16271          inline expression_node<typename node_type::value_type>* allocate(T1& t1) const
16272          {
16273             expression_node<typename node_type::value_type>*
16274             result = (new node_type(t1));
16275             result->node_depth();
16276             return result;
16277          }
16278 
16279          template <typename node_type, typename T1>
allocate_c(const T1 & t1) const16280          inline expression_node<typename node_type::value_type>* allocate_c(const T1& t1) const
16281          {
16282             expression_node<typename node_type::value_type>*
16283             result = (new node_type(t1));
16284             result->node_depth();
16285             return result;
16286          }
16287 
16288          template <typename node_type,
16289                    typename T1, typename T2>
allocate(const T1 & t1,const T2 & t2) const16290          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2) const
16291          {
16292             expression_node<typename node_type::value_type>*
16293             result = (new node_type(t1, t2));
16294             result->node_depth();
16295             return result;
16296          }
16297 
16298          template <typename node_type,
16299                    typename T1, typename T2>
allocate_cr(const T1 & t1,T2 & t2) const16300          inline expression_node<typename node_type::value_type>* allocate_cr(const T1& t1, T2& t2) const
16301          {
16302             expression_node<typename node_type::value_type>*
16303             result = (new node_type(t1, t2));
16304             result->node_depth();
16305             return result;
16306          }
16307 
16308          template <typename node_type,
16309                    typename T1, typename T2>
allocate_rc(T1 & t1,const T2 & t2) const16310          inline expression_node<typename node_type::value_type>* allocate_rc(T1& t1, const T2& t2) const
16311          {
16312             expression_node<typename node_type::value_type>*
16313             result = (new node_type(t1, t2));
16314             result->node_depth();
16315             return result;
16316          }
16317 
16318          template <typename node_type,
16319                    typename T1, typename T2>
allocate_rr(T1 & t1,T2 & t2) const16320          inline expression_node<typename node_type::value_type>* allocate_rr(T1& t1, T2& t2) const
16321          {
16322             expression_node<typename node_type::value_type>*
16323             result = (new node_type(t1, t2));
16324             result->node_depth();
16325             return result;
16326          }
16327 
16328          template <typename node_type,
16329                    typename T1, typename T2>
allocate_tt(T1 t1,T2 t2) const16330          inline expression_node<typename node_type::value_type>* allocate_tt(T1 t1, T2 t2) const
16331          {
16332             expression_node<typename node_type::value_type>*
16333             result = (new node_type(t1, t2));
16334             result->node_depth();
16335             return result;
16336          }
16337 
16338          template <typename node_type,
16339                    typename T1, typename T2, typename T3>
allocate_ttt(T1 t1,T2 t2,T3 t3) const16340          inline expression_node<typename node_type::value_type>* allocate_ttt(T1 t1, T2 t2, T3 t3) const
16341          {
16342             expression_node<typename node_type::value_type>*
16343             result = (new node_type(t1, t2, t3));
16344             result->node_depth();
16345             return result;
16346          }
16347 
16348          template <typename node_type,
16349                    typename T1, typename T2, typename T3, typename T4>
allocate_tttt(T1 t1,T2 t2,T3 t3,T4 t4) const16350          inline expression_node<typename node_type::value_type>* allocate_tttt(T1 t1, T2 t2, T3 t3, T4 t4) const
16351          {
16352             expression_node<typename node_type::value_type>*
16353             result = (new node_type(t1, t2, t3, t4));
16354             result->node_depth();
16355             return result;
16356          }
16357 
16358          template <typename node_type,
16359                    typename T1, typename T2, typename T3>
allocate_rrr(T1 & t1,T2 & t2,T3 & t3) const16360          inline expression_node<typename node_type::value_type>* allocate_rrr(T1& t1, T2& t2, T3& t3) const
16361          {
16362             expression_node<typename node_type::value_type>*
16363             result = (new node_type(t1, t2, t3));
16364             result->node_depth();
16365             return result;
16366          }
16367 
16368          template <typename node_type,
16369                    typename T1, typename T2, typename T3, typename T4>
allocate_rrrr(T1 & t1,T2 & t2,T3 & t3,T4 & t4) const16370          inline expression_node<typename node_type::value_type>* allocate_rrrr(T1& t1, T2& t2, T3& t3, T4& t4) const
16371          {
16372             expression_node<typename node_type::value_type>*
16373             result = (new node_type(t1, t2, t3, t4));
16374             result->node_depth();
16375             return result;
16376          }
16377 
16378          template <typename node_type,
16379                    typename T1, typename T2, typename T3, typename T4, typename T5>
allocate_rrrrr(T1 & t1,T2 & t2,T3 & t3,T4 & t4,T5 & t5) const16380          inline expression_node<typename node_type::value_type>* allocate_rrrrr(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5) const
16381          {
16382             expression_node<typename node_type::value_type>*
16383             result = (new node_type(t1, t2, t3, t4, t5));
16384             result->node_depth();
16385             return result;
16386          }
16387 
16388          template <typename node_type,
16389                    typename T1, typename T2, typename T3>
allocate(const T1 & t1,const T2 & t2,const T3 & t3) const16390          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
16391                                                                           const T3& t3) const
16392          {
16393             expression_node<typename node_type::value_type>*
16394             result = (new node_type(t1, t2, t3));
16395             result->node_depth();
16396             return result;
16397          }
16398 
16399          template <typename node_type,
16400                    typename T1, typename T2,
16401                    typename T3, typename T4>
allocate(const T1 & t1,const T2 & t2,const T3 & t3,const T4 & t4) const16402          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
16403                                                                           const T3& t3, const T4& t4) const
16404          {
16405             expression_node<typename node_type::value_type>*
16406             result = (new node_type(t1, t2, t3, t4));
16407             result->node_depth();
16408             return result;
16409          }
16410 
16411          template <typename node_type,
16412                    typename T1, typename T2,
16413                    typename T3, typename T4, typename T5>
allocate(const T1 & t1,const T2 & t2,const T3 & t3,const T4 & t4,const T5 & t5) const16414          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
16415                                                                           const T3& t3, const T4& t4,
16416                                                                           const T5& t5) const
16417          {
16418             expression_node<typename node_type::value_type>*
16419             result = (new node_type(t1, t2, t3, t4, t5));
16420             result->node_depth();
16421             return result;
16422          }
16423 
16424          template <typename node_type,
16425                    typename T1, typename T2,
16426                    typename T3, typename T4, typename T5, typename T6>
allocate(const T1 & t1,const T2 & t2,const T3 & t3,const T4 & t4,const T5 & t5,const T6 & t6) const16427          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
16428                                                                           const T3& t3, const T4& t4,
16429                                                                           const T5& t5, const T6& t6) const
16430          {
16431             expression_node<typename node_type::value_type>*
16432             result = (new node_type(t1, t2, t3, t4, t5, t6));
16433             result->node_depth();
16434             return result;
16435          }
16436 
16437          template <typename node_type,
16438                    typename T1, typename T2,
16439                    typename T3, typename T4,
16440                    typename T5, typename T6, typename T7>
allocate(const T1 & t1,const T2 & t2,const T3 & t3,const T4 & t4,const T5 & t5,const T6 & t6,const T7 & t7) const16441          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
16442                                                                           const T3& t3, const T4& t4,
16443                                                                           const T5& t5, const T6& t6,
16444                                                                           const T7& t7) const
16445          {
16446             expression_node<typename node_type::value_type>*
16447             result = (new node_type(t1, t2, t3, t4, t5, t6, t7));
16448             result->node_depth();
16449             return result;
16450          }
16451 
16452          template <typename node_type,
16453                    typename T1, typename T2,
16454                    typename T3, typename T4,
16455                    typename T5, typename T6,
16456                    typename T7, typename T8>
allocate(const T1 & t1,const T2 & t2,const T3 & t3,const T4 & t4,const T5 & t5,const T6 & t6,const T7 & t7,const T8 & t8) const16457          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
16458                                                                           const T3& t3, const T4& t4,
16459                                                                           const T5& t5, const T6& t6,
16460                                                                           const T7& t7, const T8& t8) const
16461          {
16462             expression_node<typename node_type::value_type>*
16463             result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8));
16464             result->node_depth();
16465             return result;
16466          }
16467 
16468          template <typename node_type,
16469                    typename T1, typename T2,
16470                    typename T3, typename T4,
16471                    typename T5, typename T6,
16472                    typename T7, typename T8, typename T9>
allocate(const T1 & t1,const T2 & t2,const T3 & t3,const T4 & t4,const T5 & t5,const T6 & t6,const T7 & t7,const T8 & t8,const T9 & t9) const16473          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
16474                                                                           const T3& t3, const T4& t4,
16475                                                                           const T5& t5, const T6& t6,
16476                                                                           const T7& t7, const T8& t8,
16477                                                                           const T9& t9) const
16478          {
16479             expression_node<typename node_type::value_type>*
16480             result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9));
16481             result->node_depth();
16482             return result;
16483          }
16484 
16485          template <typename node_type,
16486                    typename T1, typename T2,
16487                    typename T3, typename T4,
16488                    typename T5, typename T6,
16489                    typename T7, typename T8,
16490                    typename T9, typename T10>
allocate(const T1 & t1,const T2 & t2,const T3 & t3,const T4 & t4,const T5 & t5,const T6 & t6,const T7 & t7,const T8 & t8,const T9 & t9,const T10 & t10) const16491          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const  T2&  t2,
16492                                                                           const T3& t3, const  T4&  t4,
16493                                                                           const T5& t5, const  T6&  t6,
16494                                                                           const T7& t7, const  T8&  t8,
16495                                                                           const T9& t9, const T10& t10) const
16496          {
16497             expression_node<typename node_type::value_type>*
16498             result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10));
16499             result->node_depth();
16500             return result;
16501          }
16502 
16503          template <typename node_type,
16504                    typename T1, typename T2, typename T3>
allocate_type(T1 t1,T2 t2,T3 t3) const16505          inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, T3 t3) const
16506          {
16507             expression_node<typename node_type::value_type>*
16508             result = (new node_type(t1, t2, t3));
16509             result->node_depth();
16510             return result;
16511          }
16512 
16513          template <typename node_type,
16514                    typename T1, typename T2,
16515                    typename T3, typename T4>
allocate_type(T1 t1,T2 t2,T3 t3,T4 t4) const16516          inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
16517                                                                                T3 t3, T4 t4) const
16518          {
16519             expression_node<typename node_type::value_type>*
16520             result = (new node_type(t1, t2, t3, t4));
16521             result->node_depth();
16522             return result;
16523          }
16524 
16525          template <typename node_type,
16526                    typename T1, typename T2,
16527                    typename T3, typename T4,
16528                    typename T5>
allocate_type(T1 t1,T2 t2,T3 t3,T4 t4,T5 t5) const16529          inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
16530                                                                                T3 t3, T4 t4,
16531                                                                                T5 t5) const
16532          {
16533             expression_node<typename node_type::value_type>*
16534             result = (new node_type(t1, t2, t3, t4, t5));
16535             result->node_depth();
16536             return result;
16537          }
16538 
16539          template <typename node_type,
16540                    typename T1, typename T2,
16541                    typename T3, typename T4,
16542                    typename T5, typename T6>
allocate_type(T1 t1,T2 t2,T3 t3,T4 t4,T5 t5,T6 t6) const16543          inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
16544                                                                                T3 t3, T4 t4,
16545                                                                                T5 t5, T6 t6) const
16546          {
16547             expression_node<typename node_type::value_type>*
16548             result = (new node_type(t1, t2, t3, t4, t5, t6));
16549             result->node_depth();
16550             return result;
16551          }
16552 
16553          template <typename node_type,
16554                    typename T1, typename T2,
16555                    typename T3, typename T4,
16556                    typename T5, typename T6, typename T7>
allocate_type(T1 t1,T2 t2,T3 t3,T4 t4,T5 t5,T6 t6,T7 t7) const16557          inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
16558                                                                                T3 t3, T4 t4,
16559                                                                                T5 t5, T6 t6,
16560                                                                                T7 t7) const
16561          {
16562             expression_node<typename node_type::value_type>*
16563             result = (new node_type(t1, t2, t3, t4, t5, t6, t7));
16564             result->node_depth();
16565             return result;
16566          }
16567 
16568          template <typename T>
free(expression_node<T> * & e) const16569          void inline free(expression_node<T>*& e) const
16570          {
16571             exprtk_debug(("node_allocator::free() - deleting expression_node "
16572                           "type: %03d addr: %p\n",
16573                           static_cast<int>(e->type()),
16574                           reinterpret_cast<void*>(e)));
16575             delete e;
16576             e = 0;
16577          }
16578       };
16579 
load_operations_map(std::multimap<std::string,details::base_operation_t,details::ilesscompare> & m)16580       inline void load_operations_map(std::multimap<std::string,details::base_operation_t,details::ilesscompare>& m)
16581       {
16582          #define register_op(Symbol,Type,Args)                                               \
16583          m.insert(std::make_pair(std::string(Symbol),details::base_operation_t(Type,Args))); \
16584 
16585          register_op(      "abs", e_abs     , 1)
16586          register_op(     "acos", e_acos    , 1)
16587          register_op(    "acosh", e_acosh   , 1)
16588          register_op(     "asin", e_asin    , 1)
16589          register_op(    "asinh", e_asinh   , 1)
16590          register_op(     "atan", e_atan    , 1)
16591          register_op(    "atanh", e_atanh   , 1)
16592          register_op(     "ceil", e_ceil    , 1)
16593          register_op(      "cos", e_cos     , 1)
16594          register_op(     "cosh", e_cosh    , 1)
16595          register_op(      "exp", e_exp     , 1)
16596          register_op(    "expm1", e_expm1   , 1)
16597          register_op(    "floor", e_floor   , 1)
16598          register_op(      "log", e_log     , 1)
16599          register_op(    "log10", e_log10   , 1)
16600          register_op(     "log2", e_log2    , 1)
16601          register_op(    "log1p", e_log1p   , 1)
16602          register_op(    "round", e_round   , 1)
16603          register_op(      "sin", e_sin     , 1)
16604          register_op(     "sinc", e_sinc    , 1)
16605          register_op(     "sinh", e_sinh    , 1)
16606          register_op(      "sec", e_sec     , 1)
16607          register_op(      "csc", e_csc     , 1)
16608          register_op(     "sqrt", e_sqrt    , 1)
16609          register_op(      "tan", e_tan     , 1)
16610          register_op(     "tanh", e_tanh    , 1)
16611          register_op(      "cot", e_cot     , 1)
16612          register_op(  "rad2deg", e_r2d     , 1)
16613          register_op(  "deg2rad", e_d2r     , 1)
16614          register_op( "deg2grad", e_d2g     , 1)
16615          register_op( "grad2deg", e_g2d     , 1)
16616          register_op(      "sgn", e_sgn     , 1)
16617          register_op(      "not", e_notl    , 1)
16618          register_op(      "erf", e_erf     , 1)
16619          register_op(     "erfc", e_erfc    , 1)
16620          register_op(     "ncdf", e_ncdf    , 1)
16621          register_op(     "frac", e_frac    , 1)
16622          register_op(    "trunc", e_trunc   , 1)
16623          register_op(    "atan2", e_atan2   , 2)
16624          register_op(      "mod", e_mod     , 2)
16625          register_op(     "logn", e_logn    , 2)
16626          register_op(      "pow", e_pow     , 2)
16627          register_op(     "root", e_root    , 2)
16628          register_op(   "roundn", e_roundn  , 2)
16629          register_op(    "equal", e_equal   , 2)
16630          register_op("not_equal", e_nequal  , 2)
16631          register_op(    "hypot", e_hypot   , 2)
16632          register_op(      "shr", e_shr     , 2)
16633          register_op(      "shl", e_shl     , 2)
16634          register_op(    "clamp", e_clamp   , 3)
16635          register_op(   "iclamp", e_iclamp  , 3)
16636          register_op(  "inrange", e_inrange , 3)
16637          #undef register_op
16638       }
16639 
16640    } // namespace details
16641 
16642    class function_traits
16643    {
16644    public:
16645 
function_traits()16646       function_traits()
16647       : allow_zero_parameters_(false),
16648         has_side_effects_(true),
16649         min_num_args_(0),
16650         max_num_args_(std::numeric_limits<std::size_t>::max())
16651       {}
16652 
allow_zero_parameters()16653       inline bool& allow_zero_parameters()
16654       {
16655          return allow_zero_parameters_;
16656       }
16657 
has_side_effects()16658       inline bool& has_side_effects()
16659       {
16660          return has_side_effects_;
16661       }
16662 
min_num_args()16663       std::size_t& min_num_args()
16664       {
16665          return min_num_args_;
16666       }
16667 
max_num_args()16668       std::size_t& max_num_args()
16669       {
16670          return max_num_args_;
16671       }
16672 
16673    private:
16674 
16675       bool allow_zero_parameters_;
16676       bool has_side_effects_;
16677       std::size_t min_num_args_;
16678       std::size_t max_num_args_;
16679    };
16680 
16681    template <typename FunctionType>
enable_zero_parameters(FunctionType & func)16682    void enable_zero_parameters(FunctionType& func)
16683    {
16684       func.allow_zero_parameters() = true;
16685 
16686       if (0 != func.min_num_args())
16687       {
16688          func.min_num_args() = 0;
16689       }
16690    }
16691 
16692    template <typename FunctionType>
disable_zero_parameters(FunctionType & func)16693    void disable_zero_parameters(FunctionType& func)
16694    {
16695       func.allow_zero_parameters() = false;
16696    }
16697 
16698    template <typename FunctionType>
enable_has_side_effects(FunctionType & func)16699    void enable_has_side_effects(FunctionType& func)
16700    {
16701       func.has_side_effects() = true;
16702    }
16703 
16704    template <typename FunctionType>
disable_has_side_effects(FunctionType & func)16705    void disable_has_side_effects(FunctionType& func)
16706    {
16707       func.has_side_effects() = false;
16708    }
16709 
16710    template <typename FunctionType>
set_min_num_args(FunctionType & func,const std::size_t & num_args)16711    void set_min_num_args(FunctionType& func, const std::size_t& num_args)
16712    {
16713       func.min_num_args() = num_args;
16714 
16715       if ((0 != func.min_num_args()) && func.allow_zero_parameters())
16716          func.allow_zero_parameters() = false;
16717    }
16718 
16719    template <typename FunctionType>
set_max_num_args(FunctionType & func,const std::size_t & num_args)16720    void set_max_num_args(FunctionType& func, const std::size_t& num_args)
16721    {
16722       func.max_num_args() = num_args;
16723    }
16724 
16725    template <typename T>
16726    class ifunction : public function_traits
16727    {
16728    public:
16729 
ifunction(const std::size_t & pc)16730       explicit ifunction(const std::size_t& pc)
16731       : param_count(pc)
16732       {}
16733 
~ifunction()16734       virtual ~ifunction()
16735       {}
16736 
16737       #define empty_method_body(N)                   \
16738       {                                              \
16739          exprtk_debug(("ifunction::operator() - Operator(" #N ") has not been overridden\n")); \
16740          return std::numeric_limits<T>::quiet_NaN(); \
16741       }                                              \
16742 
16743       inline virtual T operator() ()
16744       empty_method_body(0)
16745 
16746       inline virtual T operator() (const T&)
16747       empty_method_body(1)
16748 
16749       inline virtual T operator() (const T&,const T&)
16750       empty_method_body(2)
16751 
16752       inline virtual T operator() (const T&, const T&, const T&)
16753       empty_method_body(3)
16754 
16755       inline virtual T operator() (const T&, const T&, const T&, const T&)
16756       empty_method_body(4)
16757 
16758       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&)
16759       empty_method_body(5)
16760 
16761       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&)
16762       empty_method_body(6)
16763 
16764       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16765       empty_method_body(7)
16766 
16767       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16768       empty_method_body(8)
16769 
16770       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16771       empty_method_body(9)
16772 
16773       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16774       empty_method_body(10)
16775 
16776       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16777                                    const T&)
16778       empty_method_body(11)
16779 
16780       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16781                                    const T&, const T&)
16782       empty_method_body(12)
16783 
16784       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16785                                    const T&, const T&, const T&)
16786       empty_method_body(13)
16787 
16788       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16789                                    const T&, const T&, const T&, const T&)
16790       empty_method_body(14)
16791 
16792       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16793                                    const T&, const T&, const T&, const T&, const T&)
16794       empty_method_body(15)
16795 
16796       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16797                                    const T&, const T&, const T&, const T&, const T&, const T&)
16798       empty_method_body(16)
16799 
16800       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16801                                    const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16802       empty_method_body(17)
16803 
16804       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16805                                    const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16806       empty_method_body(18)
16807 
16808       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16809                                    const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16810       empty_method_body(19)
16811 
16812       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16813                                    const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16814       empty_method_body(20)
16815 
16816       #undef empty_method_body
16817 
16818       std::size_t param_count;
16819    };
16820 
16821    template <typename T>
16822    class ivararg_function : public function_traits
16823    {
16824    public:
16825 
~ivararg_function()16826       virtual ~ivararg_function()
16827       {}
16828 
operator ()(const std::vector<T> &)16829       inline virtual T operator() (const std::vector<T>&)
16830       {
16831          exprtk_debug(("ivararg_function::operator() - Operator has not been overridden\n"));
16832          return std::numeric_limits<T>::quiet_NaN();
16833       }
16834    };
16835 
16836    template <typename T>
16837    class igeneric_function : public function_traits
16838    {
16839    public:
16840 
16841       enum return_type
16842       {
16843          e_rtrn_scalar   = 0,
16844          e_rtrn_string   = 1,
16845          e_rtrn_overload = 2
16846       };
16847 
16848       typedef T type;
16849       typedef type_store<T> generic_type;
16850       typedef typename generic_type::parameter_list parameter_list_t;
16851 
igeneric_function(const std::string & param_seq="",const return_type rtr_type=e_rtrn_scalar)16852       igeneric_function(const std::string& param_seq = "", const return_type rtr_type = e_rtrn_scalar)
16853       : parameter_sequence(param_seq),
16854         rtrn_type(rtr_type)
16855       {}
16856 
~igeneric_function()16857       virtual ~igeneric_function()
16858       {}
16859 
16860       #define igeneric_function_empty_body(N)        \
16861       {                                              \
16862          exprtk_debug(("igeneric_function::operator() - Operator(" #N ") has not been overridden\n")); \
16863          return std::numeric_limits<T>::quiet_NaN(); \
16864       }                                              \
16865 
16866       // f(i_0,i_1,....,i_N) --> Scalar
16867       inline virtual T operator() (parameter_list_t)
16868       igeneric_function_empty_body(1)
16869 
16870       // f(i_0,i_1,....,i_N) --> String
16871       inline virtual T operator() (std::string&, parameter_list_t)
16872       igeneric_function_empty_body(2)
16873 
16874       // f(psi,i_0,i_1,....,i_N) --> Scalar
16875       inline virtual T operator() (const std::size_t&, parameter_list_t)
16876       igeneric_function_empty_body(3)
16877 
16878       // f(psi,i_0,i_1,....,i_N) --> String
16879       inline virtual T operator() (const std::size_t&, std::string&, parameter_list_t)
16880       igeneric_function_empty_body(4)
16881 
16882       std::string parameter_sequence;
16883       return_type rtrn_type;
16884    };
16885 
16886    template <typename T> class parser;
16887    template <typename T> class expression_helper;
16888 
16889    template <typename T>
16890    class symbol_table
16891    {
16892    public:
16893 
16894       typedef T (*ff00_functor)();
16895       typedef T (*ff01_functor)(T);
16896       typedef T (*ff02_functor)(T, T);
16897       typedef T (*ff03_functor)(T, T, T);
16898       typedef T (*ff04_functor)(T, T, T, T);
16899       typedef T (*ff05_functor)(T, T, T, T, T);
16900       typedef T (*ff06_functor)(T, T, T, T, T, T);
16901       typedef T (*ff07_functor)(T, T, T, T, T, T, T);
16902       typedef T (*ff08_functor)(T, T, T, T, T, T, T, T);
16903       typedef T (*ff09_functor)(T, T, T, T, T, T, T, T, T);
16904       typedef T (*ff10_functor)(T, T, T, T, T, T, T, T, T, T);
16905       typedef T (*ff11_functor)(T, T, T, T, T, T, T, T, T, T, T);
16906       typedef T (*ff12_functor)(T, T, T, T, T, T, T, T, T, T, T, T);
16907       typedef T (*ff13_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T);
16908       typedef T (*ff14_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T);
16909       typedef T (*ff15_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T);
16910 
16911    protected:
16912 
16913        struct freefunc00 : public exprtk::ifunction<T>
16914        {
16915           using exprtk::ifunction<T>::operator();
16916 
freefunc00exprtk::symbol_table::freefunc0016917           explicit freefunc00(ff00_functor ff) : exprtk::ifunction<T>(0), f(ff) {}
operator ()exprtk::symbol_table::freefunc0016918           inline T operator() ()
16919           { return f(); }
16920           ff00_functor f;
16921        };
16922 
16923       struct freefunc01 : public exprtk::ifunction<T>
16924       {
16925          using exprtk::ifunction<T>::operator();
16926 
freefunc01exprtk::symbol_table::freefunc0116927          explicit freefunc01(ff01_functor ff) : exprtk::ifunction<T>(1), f(ff) {}
operator ()exprtk::symbol_table::freefunc0116928          inline T operator() (const T& v0)
16929          { return f(v0); }
16930          ff01_functor f;
16931       };
16932 
16933       struct freefunc02 : public exprtk::ifunction<T>
16934       {
16935          using exprtk::ifunction<T>::operator();
16936 
freefunc02exprtk::symbol_table::freefunc0216937          explicit freefunc02(ff02_functor ff) : exprtk::ifunction<T>(2), f(ff) {}
operator ()exprtk::symbol_table::freefunc0216938          inline T operator() (const T& v0, const T& v1)
16939          { return f(v0, v1); }
16940          ff02_functor f;
16941       };
16942 
16943       struct freefunc03 : public exprtk::ifunction<T>
16944       {
16945          using exprtk::ifunction<T>::operator();
16946 
freefunc03exprtk::symbol_table::freefunc0316947          explicit freefunc03(ff03_functor ff) : exprtk::ifunction<T>(3), f(ff) {}
operator ()exprtk::symbol_table::freefunc0316948          inline T operator() (const T& v0, const T& v1, const T& v2)
16949          { return f(v0, v1, v2); }
16950          ff03_functor f;
16951       };
16952 
16953       struct freefunc04 : public exprtk::ifunction<T>
16954       {
16955          using exprtk::ifunction<T>::operator();
16956 
freefunc04exprtk::symbol_table::freefunc0416957          explicit freefunc04(ff04_functor ff) : exprtk::ifunction<T>(4), f(ff) {}
operator ()exprtk::symbol_table::freefunc0416958          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3)
16959          { return f(v0, v1, v2, v3); }
16960          ff04_functor f;
16961       };
16962 
16963       struct freefunc05 : public exprtk::ifunction<T>
16964       {
16965          using exprtk::ifunction<T>::operator();
16966 
freefunc05exprtk::symbol_table::freefunc0516967          explicit freefunc05(ff05_functor ff) : exprtk::ifunction<T>(5), f(ff) {}
operator ()exprtk::symbol_table::freefunc0516968          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4)
16969          { return f(v0, v1, v2, v3, v4); }
16970          ff05_functor f;
16971       };
16972 
16973       struct freefunc06 : public exprtk::ifunction<T>
16974       {
16975          using exprtk::ifunction<T>::operator();
16976 
freefunc06exprtk::symbol_table::freefunc0616977          explicit freefunc06(ff06_functor ff) : exprtk::ifunction<T>(6), f(ff) {}
operator ()exprtk::symbol_table::freefunc0616978          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5)
16979          { return f(v0, v1, v2, v3, v4, v5); }
16980          ff06_functor f;
16981       };
16982 
16983       struct freefunc07 : public exprtk::ifunction<T>
16984       {
16985          using exprtk::ifunction<T>::operator();
16986 
freefunc07exprtk::symbol_table::freefunc0716987          explicit freefunc07(ff07_functor ff) : exprtk::ifunction<T>(7), f(ff) {}
operator ()exprtk::symbol_table::freefunc0716988          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
16989                               const T& v5, const T& v6)
16990          { return f(v0, v1, v2, v3, v4, v5, v6); }
16991          ff07_functor f;
16992       };
16993 
16994       struct freefunc08 : public exprtk::ifunction<T>
16995       {
16996          using exprtk::ifunction<T>::operator();
16997 
freefunc08exprtk::symbol_table::freefunc0816998          explicit freefunc08(ff08_functor ff) : exprtk::ifunction<T>(8), f(ff) {}
operator ()exprtk::symbol_table::freefunc0816999          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
17000                               const T& v5, const T& v6, const T& v7)
17001          { return f(v0, v1, v2, v3, v4, v5, v6, v7); }
17002          ff08_functor f;
17003       };
17004 
17005       struct freefunc09 : public exprtk::ifunction<T>
17006       {
17007          using exprtk::ifunction<T>::operator();
17008 
freefunc09exprtk::symbol_table::freefunc0917009          explicit freefunc09(ff09_functor ff) : exprtk::ifunction<T>(9), f(ff) {}
operator ()exprtk::symbol_table::freefunc0917010          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
17011                               const T& v5, const T& v6, const T& v7, const T& v8)
17012          { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8); }
17013          ff09_functor f;
17014       };
17015 
17016       struct freefunc10 : public exprtk::ifunction<T>
17017       {
17018          using exprtk::ifunction<T>::operator();
17019 
freefunc10exprtk::symbol_table::freefunc1017020          explicit freefunc10(ff10_functor ff) : exprtk::ifunction<T>(10), f(ff) {}
operator ()exprtk::symbol_table::freefunc1017021          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
17022                               const T& v5, const T& v6, const T& v7, const T& v8, const T& v9)
17023          { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9); }
17024          ff10_functor f;
17025       };
17026 
17027       struct freefunc11 : public exprtk::ifunction<T>
17028       {
17029          using exprtk::ifunction<T>::operator();
17030 
freefunc11exprtk::symbol_table::freefunc1117031          explicit freefunc11(ff11_functor ff) : exprtk::ifunction<T>(11), f(ff) {}
operator ()exprtk::symbol_table::freefunc1117032          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
17033                               const T& v5, const T& v6, const T& v7, const T& v8, const T& v9, const T& v10)
17034          { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10); }
17035          ff11_functor f;
17036       };
17037 
17038       struct freefunc12 : public exprtk::ifunction<T>
17039       {
17040          using exprtk::ifunction<T>::operator();
17041 
freefunc12exprtk::symbol_table::freefunc1217042          explicit freefunc12(ff12_functor ff) : exprtk::ifunction<T>(12), f(ff) {}
operator ()exprtk::symbol_table::freefunc1217043          inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
17044                               const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
17045                               const T& v10, const T& v11)
17046          { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11); }
17047          ff12_functor f;
17048       };
17049 
17050       struct freefunc13 : public exprtk::ifunction<T>
17051       {
17052          using exprtk::ifunction<T>::operator();
17053 
freefunc13exprtk::symbol_table::freefunc1317054          explicit freefunc13(ff13_functor ff) : exprtk::ifunction<T>(13), f(ff) {}
operator ()exprtk::symbol_table::freefunc1317055          inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
17056                               const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
17057                               const T& v10, const T& v11, const T& v12)
17058          { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12); }
17059          ff13_functor f;
17060       };
17061 
17062       struct freefunc14 : public exprtk::ifunction<T>
17063       {
17064          using exprtk::ifunction<T>::operator();
17065 
freefunc14exprtk::symbol_table::freefunc1417066          explicit freefunc14(ff14_functor ff) : exprtk::ifunction<T>(14), f(ff) {}
operator ()exprtk::symbol_table::freefunc1417067          inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
17068                               const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
17069                               const T& v10, const T& v11, const T& v12, const T& v13)
17070          { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13); }
17071          ff14_functor f;
17072       };
17073 
17074       struct freefunc15 : public exprtk::ifunction<T>
17075       {
17076          using exprtk::ifunction<T>::operator();
17077 
freefunc15exprtk::symbol_table::freefunc1517078          explicit freefunc15(ff15_functor ff) : exprtk::ifunction<T>(15), f(ff) {}
operator ()exprtk::symbol_table::freefunc1517079          inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
17080                               const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
17081                               const T& v10, const T& v11, const T& v12, const T& v13, const T& v14)
17082          { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13, v14); }
17083          ff15_functor f;
17084       };
17085 
17086       template <typename Type, typename RawType>
17087       struct type_store
17088       {
17089          typedef details::expression_node<T>*        expression_ptr;
17090          typedef typename details::variable_node<T>  variable_node_t;
17091          typedef ifunction<T>                        ifunction_t;
17092          typedef ivararg_function<T>                 ivararg_function_t;
17093          typedef igeneric_function<T>                igeneric_function_t;
17094          typedef details::vector_holder<T>           vector_t;
17095          #ifndef exprtk_disable_string_capabilities
17096          typedef typename details::stringvar_node<T> stringvar_node_t;
17097          #endif
17098 
17099          typedef Type type_t;
17100          typedef type_t* type_ptr;
17101          typedef std::pair<bool,type_ptr> type_pair_t;
17102          typedef std::map<std::string,type_pair_t,details::ilesscompare> type_map_t;
17103          typedef typename type_map_t::iterator tm_itr_t;
17104          typedef typename type_map_t::const_iterator tm_const_itr_t;
17105 
17106          enum { lut_size = 256 };
17107 
17108          type_map_t  map;
17109          std::size_t size;
17110 
type_storeexprtk::symbol_table::type_store17111          type_store()
17112          : size(0)
17113          {}
17114 
17115          struct deleter
17116          {
17117             #define exprtk_define_process(Type)                  \
17118             static inline void process(std::pair<bool,Type*>& n) \
17119             {                                                    \
17120                delete n.second;                                  \
17121             }                                                    \
17122 
17123             exprtk_define_process(variable_node_t )
exprtk_define_processexprtk::symbol_table::type_store::deleter17124             exprtk_define_process(vector_t        )
17125             #ifndef exprtk_disable_string_capabilities
17126             exprtk_define_process(stringvar_node_t)
17127             #endif
17128 
17129             #undef exprtk_define_process
17130 
17131             template <typename DeleteType>
17132             static inline void process(std::pair<bool,DeleteType*>&)
17133             {}
17134          };
17135 
symbol_existsexprtk::symbol_table::type_store17136          inline bool symbol_exists(const std::string& symbol_name) const
17137          {
17138             if (symbol_name.empty())
17139                return false;
17140             else if (map.end() != map.find(symbol_name))
17141                return true;
17142             else
17143                return false;
17144          }
17145 
17146          template <typename PtrType>
entity_nameexprtk::symbol_table::type_store17147          inline std::string entity_name(const PtrType& ptr) const
17148          {
17149             if (map.empty())
17150                return std::string();
17151 
17152             tm_const_itr_t itr = map.begin();
17153 
17154             while (map.end() != itr)
17155             {
17156                if (itr->second.second == ptr)
17157                {
17158                   return itr->first;
17159                }
17160                else
17161                   ++itr;
17162             }
17163 
17164             return std::string();
17165          }
17166 
is_constantexprtk::symbol_table::type_store17167          inline bool is_constant(const std::string& symbol_name) const
17168          {
17169             if (symbol_name.empty())
17170                return false;
17171             else
17172             {
17173                const tm_const_itr_t itr = map.find(symbol_name);
17174 
17175                if (map.end() == itr)
17176                   return false;
17177                else
17178                   return (*itr).second.first;
17179             }
17180          }
17181 
17182          template <typename Tie, typename RType>
add_implexprtk::symbol_table::type_store17183          inline bool add_impl(const std::string& symbol_name, RType t, const bool is_const)
17184          {
17185             if (symbol_name.size() > 1)
17186             {
17187                for (std::size_t i = 0; i < details::reserved_symbols_size; ++i)
17188                {
17189                   if (details::imatch(symbol_name, details::reserved_symbols[i]))
17190                   {
17191                      return false;
17192                   }
17193                }
17194             }
17195 
17196             const tm_itr_t itr = map.find(symbol_name);
17197 
17198             if (map.end() == itr)
17199             {
17200                map[symbol_name] = Tie::make(t,is_const);
17201                ++size;
17202             }
17203 
17204             return true;
17205          }
17206 
17207          struct tie_array
17208          {
makeexprtk::symbol_table::type_store::tie_array17209             static inline std::pair<bool,vector_t*> make(std::pair<T*,std::size_t> v, const bool is_const = false)
17210             {
17211                return std::make_pair(is_const, new vector_t(v.first, v.second));
17212             }
17213          };
17214 
17215          struct tie_stdvec
17216          {
17217             template <typename Allocator>
makeexprtk::symbol_table::type_store::tie_stdvec17218             static inline std::pair<bool,vector_t*> make(std::vector<T,Allocator>& v, const bool is_const = false)
17219             {
17220                return std::make_pair(is_const, new vector_t(v));
17221             }
17222          };
17223 
17224          struct tie_vecview
17225          {
makeexprtk::symbol_table::type_store::tie_vecview17226             static inline std::pair<bool,vector_t*> make(exprtk::vector_view<T>& v, const bool is_const = false)
17227             {
17228                return std::make_pair(is_const, new vector_t(v));
17229             }
17230          };
17231 
17232          struct tie_stddeq
17233          {
17234             template <typename Allocator>
makeexprtk::symbol_table::type_store::tie_stddeq17235             static inline std::pair<bool,vector_t*> make(std::deque<T,Allocator>& v, const bool is_const = false)
17236             {
17237                return std::make_pair(is_const, new vector_t(v));
17238             }
17239          };
17240 
17241          template <std::size_t v_size>
addexprtk::symbol_table::type_store17242          inline bool add(const std::string& symbol_name, T (&v)[v_size], const bool is_const = false)
17243          {
17244             return add_impl<tie_array,std::pair<T*,std::size_t> >
17245                       (symbol_name, std::make_pair(v,v_size), is_const);
17246          }
17247 
addexprtk::symbol_table::type_store17248          inline bool add(const std::string& symbol_name, T* v, const std::size_t v_size, const bool is_const = false)
17249          {
17250             return add_impl<tie_array,std::pair<T*,std::size_t> >
17251                      (symbol_name, std::make_pair(v,v_size), is_const);
17252          }
17253 
17254          template <typename Allocator>
addexprtk::symbol_table::type_store17255          inline bool add(const std::string& symbol_name, std::vector<T,Allocator>& v, const bool is_const = false)
17256          {
17257             return add_impl<tie_stdvec,std::vector<T,Allocator>&>
17258                       (symbol_name, v, is_const);
17259          }
17260 
addexprtk::symbol_table::type_store17261          inline bool add(const std::string& symbol_name, exprtk::vector_view<T>& v, const bool is_const = false)
17262          {
17263             return add_impl<tie_vecview,exprtk::vector_view<T>&>
17264                       (symbol_name, v, is_const);
17265          }
17266 
17267          template <typename Allocator>
addexprtk::symbol_table::type_store17268          inline bool add(const std::string& symbol_name, std::deque<T,Allocator>& v, const bool is_const = false)
17269          {
17270             return add_impl<tie_stddeq,std::deque<T,Allocator>&>
17271                       (symbol_name, v, is_const);
17272          }
17273 
addexprtk::symbol_table::type_store17274          inline bool add(const std::string& symbol_name, RawType& t, const bool is_const = false)
17275          {
17276             struct tie
17277             {
17278                static inline std::pair<bool,variable_node_t*> make(T& t,const bool is_const = false)
17279                {
17280                   return std::make_pair(is_const, new variable_node_t(t));
17281                }
17282 
17283                #ifndef exprtk_disable_string_capabilities
17284                static inline std::pair<bool,stringvar_node_t*> make(std::string& t,const bool is_const = false)
17285                {
17286                   return std::make_pair(is_const, new stringvar_node_t(t));
17287                }
17288                #endif
17289 
17290                static inline std::pair<bool,function_t*> make(function_t& t, const bool is_constant = false)
17291                {
17292                   return std::make_pair(is_constant,&t);
17293                }
17294 
17295                static inline std::pair<bool,vararg_function_t*> make(vararg_function_t& t, const bool is_const = false)
17296                {
17297                   return std::make_pair(is_const,&t);
17298                }
17299 
17300                static inline std::pair<bool,generic_function_t*> make(generic_function_t& t, const bool is_constant = false)
17301                {
17302                   return std::make_pair(is_constant,&t);
17303                }
17304             };
17305 
17306             const tm_itr_t itr = map.find(symbol_name);
17307 
17308             if (map.end() == itr)
17309             {
17310                map[symbol_name] = tie::make(t,is_const);
17311                ++size;
17312             }
17313 
17314             return true;
17315          }
17316 
getexprtk::symbol_table::type_store17317          inline type_ptr get(const std::string& symbol_name) const
17318          {
17319             const tm_const_itr_t itr = map.find(symbol_name);
17320 
17321             if (map.end() == itr)
17322                return reinterpret_cast<type_ptr>(0);
17323             else
17324                return itr->second.second;
17325          }
17326 
17327          template <typename TType, typename TRawType, typename PtrType>
17328          struct ptr_match
17329          {
testexprtk::symbol_table::type_store::ptr_match17330             static inline bool test(const PtrType, const void*)
17331             {
17332                return false;
17333             }
17334          };
17335 
17336          template <typename TType, typename TRawType>
17337          struct ptr_match<TType,TRawType,variable_node_t*>
17338          {
testexprtk::symbol_table::type_store::ptr_match17339             static inline bool test(const variable_node_t* p, const void* ptr)
17340             {
17341                exprtk_debug(("ptr_match::test() - %p <--> %p\n",(void*)(&(p->ref())),ptr));
17342                return (&(p->ref()) == ptr);
17343             }
17344          };
17345 
get_from_varptrexprtk::symbol_table::type_store17346          inline type_ptr get_from_varptr(const void* ptr) const
17347          {
17348             tm_const_itr_t itr = map.begin();
17349 
17350             while (map.end() != itr)
17351             {
17352                type_ptr ret_ptr = itr->second.second;
17353 
17354                if (ptr_match<Type,RawType,type_ptr>::test(ret_ptr,ptr))
17355                {
17356                   return ret_ptr;
17357                }
17358 
17359                ++itr;
17360             }
17361 
17362             return type_ptr(0);
17363          }
17364 
removeexprtk::symbol_table::type_store17365          inline bool remove(const std::string& symbol_name, const bool delete_node = true)
17366          {
17367             const tm_itr_t itr = map.find(symbol_name);
17368 
17369             if (map.end() != itr)
17370             {
17371                if (delete_node)
17372                {
17373                   deleter::process((*itr).second);
17374                }
17375 
17376                map.erase(itr);
17377                --size;
17378 
17379                return true;
17380             }
17381             else
17382                return false;
17383          }
17384 
type_refexprtk::symbol_table::type_store17385          inline RawType& type_ref(const std::string& symbol_name)
17386          {
17387             struct init_type
17388             {
17389                static inline double set(double)           { return (0.0);           }
17390                static inline double set(long double)      { return (0.0);           }
17391                static inline float  set(float)            { return (0.0f);          }
17392                static inline std::string set(std::string) { return std::string(""); }
17393             };
17394 
17395             static RawType null_type = init_type::set(RawType());
17396 
17397             const tm_const_itr_t itr = map.find(symbol_name);
17398 
17399             if (map.end() == itr)
17400                return null_type;
17401             else
17402                return itr->second.second->ref();
17403          }
17404 
clearexprtk::symbol_table::type_store17405          inline void clear(const bool delete_node = true)
17406          {
17407             if (!map.empty())
17408             {
17409                if (delete_node)
17410                {
17411                   tm_itr_t itr = map.begin();
17412                   tm_itr_t end = map.end  ();
17413 
17414                   while (end != itr)
17415                   {
17416                      deleter::process((*itr).second);
17417                      ++itr;
17418                   }
17419                }
17420 
17421                map.clear();
17422             }
17423 
17424             size = 0;
17425          }
17426 
17427          template <typename Allocator,
17428                    template <typename, typename> class Sequence>
get_listexprtk::symbol_table::type_store17429          inline std::size_t get_list(Sequence<std::pair<std::string,RawType>,Allocator>& list) const
17430          {
17431             std::size_t count = 0;
17432 
17433             if (!map.empty())
17434             {
17435                tm_const_itr_t itr = map.begin();
17436                tm_const_itr_t end = map.end  ();
17437 
17438                while (end != itr)
17439                {
17440                   list.push_back(std::make_pair((*itr).first,itr->second.second->ref()));
17441                   ++itr;
17442                   ++count;
17443                }
17444             }
17445 
17446             return count;
17447          }
17448 
17449          template <typename Allocator,
17450                    template <typename, typename> class Sequence>
get_listexprtk::symbol_table::type_store17451          inline std::size_t get_list(Sequence<std::string,Allocator>& vlist) const
17452          {
17453             std::size_t count = 0;
17454 
17455             if (!map.empty())
17456             {
17457                tm_const_itr_t itr = map.begin();
17458                tm_const_itr_t end = map.end  ();
17459 
17460                while (end != itr)
17461                {
17462                   vlist.push_back((*itr).first);
17463                   ++itr;
17464                   ++count;
17465                }
17466             }
17467 
17468             return count;
17469          }
17470       };
17471 
17472       typedef details::expression_node<T>*        expression_ptr;
17473       typedef typename details::variable_node<T>  variable_t;
17474       typedef typename details::vector_holder<T>  vector_holder_t;
17475       typedef variable_t*                         variable_ptr;
17476       #ifndef exprtk_disable_string_capabilities
17477       typedef typename details::stringvar_node<T> stringvar_t;
17478       typedef stringvar_t*                        stringvar_ptr;
17479       #endif
17480       typedef ifunction        <T>                function_t;
17481       typedef ivararg_function <T>                vararg_function_t;
17482       typedef igeneric_function<T>                generic_function_t;
17483       typedef function_t*                         function_ptr;
17484       typedef vararg_function_t*                  vararg_function_ptr;
17485       typedef generic_function_t*                 generic_function_ptr;
17486 
17487       static const std::size_t lut_size = 256;
17488 
17489       // Symbol Table Holder
17490       struct control_block
17491       {
17492          struct st_data
17493          {
17494             type_store<variable_t        , T                 > variable_store;
17495             type_store<function_t        , function_t        > function_store;
17496             type_store<vararg_function_t , vararg_function_t > vararg_function_store;
17497             type_store<generic_function_t, generic_function_t> generic_function_store;
17498             type_store<generic_function_t, generic_function_t> string_function_store;
17499             type_store<generic_function_t, generic_function_t> overload_function_store;
17500             type_store<vector_holder_t   , vector_holder_t   > vector_store;
17501             #ifndef exprtk_disable_string_capabilities
17502             type_store<stringvar_t       , std::string       > stringvar_store;
17503             #endif
17504 
st_dataexprtk::symbol_table::control_block::st_data17505             st_data()
17506             {
17507                for (std::size_t i = 0; i < details::reserved_words_size; ++i)
17508                {
17509                   reserved_symbol_table_.insert(details::reserved_words[i]);
17510                }
17511 
17512                for (std::size_t i = 0; i < details::reserved_symbols_size; ++i)
17513                {
17514                   reserved_symbol_table_.insert(details::reserved_symbols[i]);
17515                }
17516             }
17517 
~st_dataexprtk::symbol_table::control_block::st_data17518            ~st_data()
17519             {
17520                for (std::size_t i = 0; i < free_function_list_.size(); ++i)
17521                {
17522                   delete free_function_list_[i];
17523                }
17524             }
17525 
is_reserved_symbolexprtk::symbol_table::control_block::st_data17526             inline bool is_reserved_symbol(const std::string& symbol) const
17527             {
17528                return (reserved_symbol_table_.end() != reserved_symbol_table_.find(symbol));
17529             }
17530 
createexprtk::symbol_table::control_block::st_data17531             static inline st_data* create()
17532             {
17533                return (new st_data);
17534             }
17535 
destroyexprtk::symbol_table::control_block::st_data17536             static inline void destroy(st_data*& sd)
17537             {
17538                delete sd;
17539                sd = reinterpret_cast<st_data*>(0);
17540             }
17541 
17542             std::list<T>               local_symbol_list_;
17543             std::list<std::string>     local_stringvar_list_;
17544             std::set<std::string>      reserved_symbol_table_;
17545             std::vector<ifunction<T>*> free_function_list_;
17546          };
17547 
control_blockexprtk::symbol_table::control_block17548          control_block()
17549          : ref_count(1),
17550            data_(st_data::create())
17551          {}
17552 
control_blockexprtk::symbol_table::control_block17553          explicit control_block(st_data* data)
17554          : ref_count(1),
17555            data_(data)
17556          {}
17557 
~control_blockexprtk::symbol_table::control_block17558         ~control_block()
17559          {
17560             if (data_ && (0 == ref_count))
17561             {
17562                st_data::destroy(data_);
17563             }
17564          }
17565 
createexprtk::symbol_table::control_block17566          static inline control_block* create()
17567          {
17568             return (new control_block);
17569          }
17570 
17571          template <typename SymTab>
destroyexprtk::symbol_table::control_block17572          static inline void destroy(control_block*& cntrl_blck, SymTab* sym_tab)
17573          {
17574             if (cntrl_blck)
17575             {
17576                if (
17577                     (0 !=   cntrl_blck->ref_count) &&
17578                     (0 == --cntrl_blck->ref_count)
17579                   )
17580                {
17581                   if (sym_tab)
17582                      sym_tab->clear();
17583 
17584                   delete cntrl_blck;
17585                }
17586 
17587                cntrl_blck = 0;
17588             }
17589          }
17590 
17591          std::size_t ref_count;
17592          st_data* data_;
17593       };
17594 
17595    public:
17596 
symbol_table()17597       symbol_table()
17598       : control_block_(control_block::create())
17599       {
17600          clear();
17601       }
17602 
~symbol_table()17603      ~symbol_table()
17604       {
17605          control_block::destroy(control_block_,this);
17606       }
17607 
symbol_table(const symbol_table<T> & st)17608       symbol_table(const symbol_table<T>& st)
17609       {
17610          control_block_ = st.control_block_;
17611          control_block_->ref_count++;
17612       }
17613 
operator =(const symbol_table<T> & st)17614       inline symbol_table<T>& operator=(const symbol_table<T>& st)
17615       {
17616          if (this != &st)
17617          {
17618             control_block::destroy(control_block_,reinterpret_cast<symbol_table<T>*>(0));
17619 
17620             control_block_ = st.control_block_;
17621             control_block_->ref_count++;
17622          }
17623 
17624          return (*this);
17625       }
17626 
operator ==(const symbol_table<T> & st) const17627       inline bool operator==(const symbol_table<T>& st) const
17628       {
17629          return (this == &st) || (control_block_ == st.control_block_);
17630       }
17631 
clear_variables(const bool delete_node=true)17632       inline void clear_variables(const bool delete_node = true)
17633       {
17634          local_data().variable_store.clear(delete_node);
17635       }
17636 
clear_functions()17637       inline void clear_functions()
17638       {
17639          local_data().function_store.clear();
17640       }
17641 
clear_strings()17642       inline void clear_strings()
17643       {
17644          #ifndef exprtk_disable_string_capabilities
17645          local_data().stringvar_store.clear();
17646          #endif
17647       }
17648 
clear_vectors()17649       inline void clear_vectors()
17650       {
17651          local_data().vector_store.clear();
17652       }
17653 
clear_local_constants()17654       inline void clear_local_constants()
17655       {
17656          local_data().local_symbol_list_.clear();
17657       }
17658 
clear()17659       inline void clear()
17660       {
17661          if (!valid()) return;
17662          clear_variables      ();
17663          clear_functions      ();
17664          clear_strings        ();
17665          clear_vectors        ();
17666          clear_local_constants();
17667       }
17668 
variable_count() const17669       inline std::size_t variable_count() const
17670       {
17671          if (valid())
17672             return local_data().variable_store.size;
17673          else
17674             return 0;
17675       }
17676 
17677       #ifndef exprtk_disable_string_capabilities
stringvar_count() const17678       inline std::size_t stringvar_count() const
17679       {
17680          if (valid())
17681             return local_data().stringvar_store.size;
17682          else
17683             return 0;
17684       }
17685       #endif
17686 
function_count() const17687       inline std::size_t function_count() const
17688       {
17689          if (valid())
17690             return local_data().function_store.size;
17691          else
17692             return 0;
17693       }
17694 
vector_count() const17695       inline std::size_t vector_count() const
17696       {
17697          if (valid())
17698             return local_data().vector_store.size;
17699          else
17700             return 0;
17701       }
17702 
get_variable(const std::string & variable_name) const17703       inline variable_ptr get_variable(const std::string& variable_name) const
17704       {
17705          if (!valid())
17706             return reinterpret_cast<variable_ptr>(0);
17707          else if (!valid_symbol(variable_name))
17708             return reinterpret_cast<variable_ptr>(0);
17709          else
17710             return local_data().variable_store.get(variable_name);
17711       }
17712 
get_variable(const T & var_ref) const17713       inline variable_ptr get_variable(const T& var_ref) const
17714       {
17715          if (!valid())
17716             return reinterpret_cast<variable_ptr>(0);
17717          else
17718             return local_data().variable_store.get_from_varptr(
17719                                                   reinterpret_cast<const void*>(&var_ref));
17720       }
17721 
17722       #ifndef exprtk_disable_string_capabilities
get_stringvar(const std::string & string_name) const17723       inline stringvar_ptr get_stringvar(const std::string& string_name) const
17724       {
17725          if (!valid())
17726             return reinterpret_cast<stringvar_ptr>(0);
17727          else if (!valid_symbol(string_name))
17728             return reinterpret_cast<stringvar_ptr>(0);
17729          else
17730             return local_data().stringvar_store.get(string_name);
17731       }
17732       #endif
17733 
get_function(const std::string & function_name) const17734       inline function_ptr get_function(const std::string& function_name) const
17735       {
17736          if (!valid())
17737             return reinterpret_cast<function_ptr>(0);
17738          else if (!valid_symbol(function_name))
17739             return reinterpret_cast<function_ptr>(0);
17740          else
17741             return local_data().function_store.get(function_name);
17742       }
17743 
get_vararg_function(const std::string & vararg_function_name) const17744       inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const
17745       {
17746          if (!valid())
17747             return reinterpret_cast<vararg_function_ptr>(0);
17748          else if (!valid_symbol(vararg_function_name))
17749             return reinterpret_cast<vararg_function_ptr>(0);
17750          else
17751             return local_data().vararg_function_store.get(vararg_function_name);
17752       }
17753 
get_generic_function(const std::string & function_name) const17754       inline generic_function_ptr get_generic_function(const std::string& function_name) const
17755       {
17756          if (!valid())
17757             return reinterpret_cast<generic_function_ptr>(0);
17758          else if (!valid_symbol(function_name))
17759             return reinterpret_cast<generic_function_ptr>(0);
17760          else
17761             return local_data().generic_function_store.get(function_name);
17762       }
17763 
get_string_function(const std::string & function_name) const17764       inline generic_function_ptr get_string_function(const std::string& function_name) const
17765       {
17766          if (!valid())
17767             return reinterpret_cast<generic_function_ptr>(0);
17768          else if (!valid_symbol(function_name))
17769             return reinterpret_cast<generic_function_ptr>(0);
17770          else
17771             return local_data().string_function_store.get(function_name);
17772       }
17773 
get_overload_function(const std::string & function_name) const17774       inline generic_function_ptr get_overload_function(const std::string& function_name) const
17775       {
17776          if (!valid())
17777             return reinterpret_cast<generic_function_ptr>(0);
17778          else if (!valid_symbol(function_name))
17779             return reinterpret_cast<generic_function_ptr>(0);
17780          else
17781             return local_data().overload_function_store.get(function_name);
17782       }
17783 
17784       typedef vector_holder_t* vector_holder_ptr;
17785 
get_vector(const std::string & vector_name) const17786       inline vector_holder_ptr get_vector(const std::string& vector_name) const
17787       {
17788          if (!valid())
17789             return reinterpret_cast<vector_holder_ptr>(0);
17790          else if (!valid_symbol(vector_name))
17791             return reinterpret_cast<vector_holder_ptr>(0);
17792          else
17793             return local_data().vector_store.get(vector_name);
17794       }
17795 
variable_ref(const std::string & symbol_name)17796       inline T& variable_ref(const std::string& symbol_name)
17797       {
17798          static T null_var = T(0);
17799          if (!valid())
17800             return null_var;
17801          else if (!valid_symbol(symbol_name))
17802             return null_var;
17803          else
17804             return local_data().variable_store.type_ref(symbol_name);
17805       }
17806 
17807       #ifndef exprtk_disable_string_capabilities
stringvar_ref(const std::string & symbol_name)17808       inline std::string& stringvar_ref(const std::string& symbol_name)
17809       {
17810          static std::string null_stringvar;
17811          if (!valid())
17812             return null_stringvar;
17813          else if (!valid_symbol(symbol_name))
17814             return null_stringvar;
17815          else
17816             return local_data().stringvar_store.type_ref(symbol_name);
17817       }
17818       #endif
17819 
is_constant_node(const std::string & symbol_name) const17820       inline bool is_constant_node(const std::string& symbol_name) const
17821       {
17822          if (!valid())
17823             return false;
17824          else if (!valid_symbol(symbol_name))
17825             return false;
17826          else
17827             return local_data().variable_store.is_constant(symbol_name);
17828       }
17829 
17830       #ifndef exprtk_disable_string_capabilities
is_constant_string(const std::string & symbol_name) const17831       inline bool is_constant_string(const std::string& symbol_name) const
17832       {
17833          if (!valid())
17834             return false;
17835          else if (!valid_symbol(symbol_name))
17836             return false;
17837          else if (!local_data().stringvar_store.symbol_exists(symbol_name))
17838             return false;
17839          else
17840             return local_data().stringvar_store.is_constant(symbol_name);
17841       }
17842       #endif
17843 
create_variable(const std::string & variable_name,const T & value=T (0))17844       inline bool create_variable(const std::string& variable_name, const T& value = T(0))
17845       {
17846          if (!valid())
17847             return false;
17848          else if (!valid_symbol(variable_name))
17849             return false;
17850          else if (symbol_exists(variable_name))
17851             return false;
17852 
17853          local_data().local_symbol_list_.push_back(value);
17854          T& t = local_data().local_symbol_list_.back();
17855 
17856          return add_variable(variable_name,t);
17857       }
17858 
17859       #ifndef exprtk_disable_string_capabilities
create_stringvar(const std::string & stringvar_name,const std::string & value=std::string (""))17860       inline bool create_stringvar(const std::string& stringvar_name, const std::string& value = std::string(""))
17861       {
17862          if (!valid())
17863             return false;
17864          else if (!valid_symbol(stringvar_name))
17865             return false;
17866          else if (symbol_exists(stringvar_name))
17867             return false;
17868 
17869          local_data().local_stringvar_list_.push_back(value);
17870          std::string& s = local_data().local_stringvar_list_.back();
17871 
17872          return add_stringvar(stringvar_name,s);
17873       }
17874       #endif
17875 
add_variable(const std::string & variable_name,T & t,const bool is_constant=false)17876       inline bool add_variable(const std::string& variable_name, T& t, const bool is_constant = false)
17877       {
17878          if (!valid())
17879             return false;
17880          else if (!valid_symbol(variable_name))
17881             return false;
17882          else if (symbol_exists(variable_name))
17883             return false;
17884          else
17885             return local_data().variable_store.add(variable_name, t, is_constant);
17886       }
17887 
add_constant(const std::string & constant_name,const T & value)17888       inline bool add_constant(const std::string& constant_name, const T& value)
17889       {
17890          if (!valid())
17891             return false;
17892          else if (!valid_symbol(constant_name))
17893             return false;
17894          else if (symbol_exists(constant_name))
17895             return false;
17896 
17897          local_data().local_symbol_list_.push_back(value);
17898          T& t = local_data().local_symbol_list_.back();
17899 
17900          return add_variable(constant_name, t, true);
17901       }
17902 
17903       #ifndef exprtk_disable_string_capabilities
add_stringvar(const std::string & stringvar_name,std::string & s,const bool is_constant=false)17904       inline bool add_stringvar(const std::string& stringvar_name, std::string& s, const bool is_constant = false)
17905       {
17906          if (!valid())
17907             return false;
17908          else if (!valid_symbol(stringvar_name))
17909             return false;
17910          else if (symbol_exists(stringvar_name))
17911             return false;
17912          else
17913             return local_data().stringvar_store.add(stringvar_name, s, is_constant);
17914       }
17915       #endif
17916 
add_function(const std::string & function_name,function_t & function)17917       inline bool add_function(const std::string& function_name, function_t& function)
17918       {
17919          if (!valid())
17920             return false;
17921          else if (!valid_symbol(function_name))
17922             return false;
17923          else if (symbol_exists(function_name))
17924             return false;
17925          else
17926             return local_data().function_store.add(function_name,function);
17927       }
17928 
add_function(const std::string & vararg_function_name,vararg_function_t & vararg_function)17929       inline bool add_function(const std::string& vararg_function_name, vararg_function_t& vararg_function)
17930       {
17931          if (!valid())
17932             return false;
17933          else if (!valid_symbol(vararg_function_name))
17934             return false;
17935          else if (symbol_exists(vararg_function_name))
17936             return false;
17937          else
17938             return local_data().vararg_function_store.add(vararg_function_name,vararg_function);
17939       }
17940 
add_function(const std::string & function_name,generic_function_t & function)17941       inline bool add_function(const std::string& function_name, generic_function_t& function)
17942       {
17943          if (!valid())
17944             return false;
17945          else if (!valid_symbol(function_name))
17946             return false;
17947          else if (symbol_exists(function_name))
17948             return false;
17949          else
17950          {
17951             switch (function.rtrn_type)
17952             {
17953                case generic_function_t::e_rtrn_scalar :
17954                   return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ?
17955                          local_data().generic_function_store.add(function_name,function) : false;
17956 
17957                case generic_function_t::e_rtrn_string :
17958                   return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ?
17959                          local_data().string_function_store.add(function_name,function)  : false;
17960 
17961                case generic_function_t::e_rtrn_overload :
17962                   return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|:")) ?
17963                          local_data().overload_function_store.add(function_name,function) : false;
17964             }
17965          }
17966 
17967          return false;
17968       }
17969 
17970       #define exprtk_define_freefunction(NN)                                                \
17971       inline bool add_function(const std::string& function_name, ff##NN##_functor function) \
17972       {                                                                                     \
17973          if (!valid())                                                                      \
17974          { return false; }                                                                  \
17975          if (!valid_symbol(function_name))                                                  \
17976          { return false; }                                                                  \
17977          if (symbol_exists(function_name))                                                  \
17978          { return false; }                                                                  \
17979                                                                                             \
17980          exprtk::ifunction<T>* ifunc = new freefunc##NN(function);                          \
17981                                                                                             \
17982          local_data().free_function_list_.push_back(ifunc);                                 \
17983                                                                                             \
17984          return add_function(function_name,(*local_data().free_function_list_.back()));     \
17985       }                                                                                     \
17986 
17987       exprtk_define_freefunction(00) exprtk_define_freefunction(01)
17988       exprtk_define_freefunction(02) exprtk_define_freefunction(03)
17989       exprtk_define_freefunction(04) exprtk_define_freefunction(05)
17990       exprtk_define_freefunction(06) exprtk_define_freefunction(07)
17991       exprtk_define_freefunction(08) exprtk_define_freefunction(09)
17992       exprtk_define_freefunction(10) exprtk_define_freefunction(11)
17993       exprtk_define_freefunction(12) exprtk_define_freefunction(13)
17994       exprtk_define_freefunction(14) exprtk_define_freefunction(15)
17995 
17996       #undef exprtk_define_freefunction
17997 
add_reserved_function(const std::string & function_name,function_t & function)17998       inline bool add_reserved_function(const std::string& function_name, function_t& function)
17999       {
18000          if (!valid())
18001             return false;
18002          else if (!valid_symbol(function_name,false))
18003             return false;
18004          else if (symbol_exists(function_name,false))
18005             return false;
18006          else
18007             return local_data().function_store.add(function_name,function);
18008       }
18009 
add_reserved_function(const std::string & vararg_function_name,vararg_function_t & vararg_function)18010       inline bool add_reserved_function(const std::string& vararg_function_name, vararg_function_t& vararg_function)
18011       {
18012          if (!valid())
18013             return false;
18014          else if (!valid_symbol(vararg_function_name,false))
18015             return false;
18016          else if (symbol_exists(vararg_function_name,false))
18017             return false;
18018          else
18019             return local_data().vararg_function_store.add(vararg_function_name,vararg_function);
18020       }
18021 
add_reserved_function(const std::string & function_name,generic_function_t & function)18022       inline bool add_reserved_function(const std::string& function_name, generic_function_t& function)
18023       {
18024          if (!valid())
18025             return false;
18026          else if (!valid_symbol(function_name,false))
18027             return false;
18028          else if (symbol_exists(function_name,false))
18029             return false;
18030          else
18031          {
18032             switch (function.rtrn_type)
18033             {
18034                case generic_function_t::e_rtrn_scalar :
18035                   return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ?
18036                          local_data().generic_function_store.add(function_name,function) : false;
18037 
18038                case generic_function_t::e_rtrn_string :
18039                   return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ?
18040                          local_data().string_function_store.add(function_name,function)  : false;
18041 
18042                case generic_function_t::e_rtrn_overload :
18043                   return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|:")) ?
18044                          local_data().overload_function_store.add(function_name,function) : false;
18045             }
18046          }
18047 
18048          return false;
18049       }
18050 
18051       template <std::size_t N>
add_vector(const std::string & vector_name,T (& v)[N])18052       inline bool add_vector(const std::string& vector_name, T (&v)[N])
18053       {
18054          if (!valid())
18055             return false;
18056          else if (!valid_symbol(vector_name))
18057             return false;
18058          else if (symbol_exists(vector_name))
18059             return false;
18060          else
18061             return local_data().vector_store.add(vector_name,v);
18062       }
18063 
add_vector(const std::string & vector_name,T * v,const std::size_t & v_size)18064       inline bool add_vector(const std::string& vector_name, T* v, const std::size_t& v_size)
18065       {
18066          if (!valid())
18067             return false;
18068          else if (!valid_symbol(vector_name))
18069             return false;
18070          else if (symbol_exists(vector_name))
18071             return false;
18072          else if (0 == v_size)
18073             return false;
18074          else
18075             return local_data().vector_store.add(vector_name, v, v_size);
18076       }
18077 
18078       template <typename Allocator>
add_vector(const std::string & vector_name,std::vector<T,Allocator> & v)18079       inline bool add_vector(const std::string& vector_name, std::vector<T,Allocator>& v)
18080       {
18081          if (!valid())
18082             return false;
18083          else if (!valid_symbol(vector_name))
18084             return false;
18085          else if (symbol_exists(vector_name))
18086             return false;
18087          else if (0 == v.size())
18088             return false;
18089          else
18090             return local_data().vector_store.add(vector_name,v);
18091       }
18092 
add_vector(const std::string & vector_name,exprtk::vector_view<T> & v)18093       inline bool add_vector(const std::string& vector_name, exprtk::vector_view<T>& v)
18094       {
18095          if (!valid())
18096             return false;
18097          else if (!valid_symbol(vector_name))
18098             return false;
18099          else if (symbol_exists(vector_name))
18100             return false;
18101          else if (0 == v.size())
18102             return false;
18103          else
18104             return local_data().vector_store.add(vector_name,v);
18105       }
18106 
remove_variable(const std::string & variable_name,const bool delete_node=true)18107       inline bool remove_variable(const std::string& variable_name, const bool delete_node = true)
18108       {
18109          if (!valid())
18110             return false;
18111          else
18112             return local_data().variable_store.remove(variable_name, delete_node);
18113       }
18114 
18115       #ifndef exprtk_disable_string_capabilities
remove_stringvar(const std::string & string_name)18116       inline bool remove_stringvar(const std::string& string_name)
18117       {
18118          if (!valid())
18119             return false;
18120          else
18121             return local_data().stringvar_store.remove(string_name);
18122       }
18123       #endif
18124 
remove_function(const std::string & function_name)18125       inline bool remove_function(const std::string& function_name)
18126       {
18127          if (!valid())
18128             return false;
18129          else
18130             return local_data().function_store.remove(function_name);
18131       }
18132 
remove_vararg_function(const std::string & vararg_function_name)18133       inline bool remove_vararg_function(const std::string& vararg_function_name)
18134       {
18135          if (!valid())
18136             return false;
18137          else
18138             return local_data().vararg_function_store.remove(vararg_function_name);
18139       }
18140 
remove_vector(const std::string & vector_name)18141       inline bool remove_vector(const std::string& vector_name)
18142       {
18143          if (!valid())
18144             return false;
18145          else
18146             return local_data().vector_store.remove(vector_name);
18147       }
18148 
add_constants()18149       inline bool add_constants()
18150       {
18151          return add_pi      () &&
18152                 add_epsilon () &&
18153                 add_infinity() ;
18154       }
18155 
add_pi()18156       inline bool add_pi()
18157       {
18158          const typename details::numeric::details::number_type<T>::type num_type;
18159          static const T local_pi = details::numeric::details::const_pi_impl<T>(num_type);
18160          return add_constant("pi",local_pi);
18161       }
18162 
add_epsilon()18163       inline bool add_epsilon()
18164       {
18165          static const T local_epsilon = details::numeric::details::epsilon_type<T>::value();
18166          return add_constant("epsilon",local_epsilon);
18167       }
18168 
add_infinity()18169       inline bool add_infinity()
18170       {
18171          static const T local_infinity = std::numeric_limits<T>::infinity();
18172          return add_constant("inf",local_infinity);
18173       }
18174 
18175       template <typename Package>
add_package(Package & package)18176       inline bool add_package(Package& package)
18177       {
18178          return package.register_package(*this);
18179       }
18180 
18181       template <typename Allocator,
18182                 template <typename, typename> class Sequence>
get_variable_list(Sequence<std::pair<std::string,T>,Allocator> & vlist) const18183       inline std::size_t get_variable_list(Sequence<std::pair<std::string,T>,Allocator>& vlist) const
18184       {
18185          if (!valid())
18186             return 0;
18187          else
18188             return local_data().variable_store.get_list(vlist);
18189       }
18190 
18191       template <typename Allocator,
18192                 template <typename, typename> class Sequence>
get_variable_list(Sequence<std::string,Allocator> & vlist) const18193       inline std::size_t get_variable_list(Sequence<std::string,Allocator>& vlist) const
18194       {
18195          if (!valid())
18196             return 0;
18197          else
18198             return local_data().variable_store.get_list(vlist);
18199       }
18200 
18201       #ifndef exprtk_disable_string_capabilities
18202       template <typename Allocator,
18203                 template <typename, typename> class Sequence>
get_stringvar_list(Sequence<std::pair<std::string,std::string>,Allocator> & svlist) const18204       inline std::size_t get_stringvar_list(Sequence<std::pair<std::string,std::string>,Allocator>& svlist) const
18205       {
18206          if (!valid())
18207             return 0;
18208          else
18209             return local_data().stringvar_store.get_list(svlist);
18210       }
18211 
18212       template <typename Allocator,
18213                 template <typename, typename> class Sequence>
get_stringvar_list(Sequence<std::string,Allocator> & svlist) const18214       inline std::size_t get_stringvar_list(Sequence<std::string,Allocator>& svlist) const
18215       {
18216          if (!valid())
18217             return 0;
18218          else
18219             return local_data().stringvar_store.get_list(svlist);
18220       }
18221       #endif
18222 
18223       template <typename Allocator,
18224                 template <typename, typename> class Sequence>
get_vector_list(Sequence<std::string,Allocator> & vlist) const18225       inline std::size_t get_vector_list(Sequence<std::string,Allocator>& vlist) const
18226       {
18227          if (!valid())
18228             return 0;
18229          else
18230             return local_data().vector_store.get_list(vlist);
18231       }
18232 
symbol_exists(const std::string & symbol_name,const bool check_reserved_symb=true) const18233       inline bool symbol_exists(const std::string& symbol_name, const bool check_reserved_symb = true) const
18234       {
18235          /*
18236             Function will return true if symbol_name exists as either a
18237             reserved symbol, variable, stringvar, vector or function name
18238             in any of the type stores.
18239          */
18240          if (!valid())
18241             return false;
18242          else if (local_data().variable_store.symbol_exists(symbol_name))
18243             return true;
18244          #ifndef exprtk_disable_string_capabilities
18245          else if (local_data().stringvar_store.symbol_exists(symbol_name))
18246             return true;
18247          #endif
18248          else if (local_data().vector_store.symbol_exists(symbol_name))
18249             return true;
18250          else if (local_data().function_store.symbol_exists(symbol_name))
18251             return true;
18252          else if (check_reserved_symb && local_data().is_reserved_symbol(symbol_name))
18253             return true;
18254          else
18255             return false;
18256       }
18257 
is_variable(const std::string & variable_name) const18258       inline bool is_variable(const std::string& variable_name) const
18259       {
18260          if (!valid())
18261             return false;
18262          else
18263             return local_data().variable_store.symbol_exists(variable_name);
18264       }
18265 
18266       #ifndef exprtk_disable_string_capabilities
is_stringvar(const std::string & stringvar_name) const18267       inline bool is_stringvar(const std::string& stringvar_name) const
18268       {
18269          if (!valid())
18270             return false;
18271          else
18272             return local_data().stringvar_store.symbol_exists(stringvar_name);
18273       }
18274 
is_conststr_stringvar(const std::string & symbol_name) const18275       inline bool is_conststr_stringvar(const std::string& symbol_name) const
18276       {
18277          if (!valid())
18278             return false;
18279          else if (!valid_symbol(symbol_name))
18280             return false;
18281          else if (!local_data().stringvar_store.symbol_exists(symbol_name))
18282             return false;
18283 
18284          return (
18285                   local_data().stringvar_store.symbol_exists(symbol_name) ||
18286                   local_data().stringvar_store.is_constant  (symbol_name)
18287                 );
18288       }
18289       #endif
18290 
is_function(const std::string & function_name) const18291       inline bool is_function(const std::string& function_name) const
18292       {
18293          if (!valid())
18294             return false;
18295          else
18296             return local_data().function_store.symbol_exists(function_name);
18297       }
18298 
is_vararg_function(const std::string & vararg_function_name) const18299       inline bool is_vararg_function(const std::string& vararg_function_name) const
18300       {
18301          if (!valid())
18302             return false;
18303          else
18304             return local_data().vararg_function_store.symbol_exists(vararg_function_name);
18305       }
18306 
is_vector(const std::string & vector_name) const18307       inline bool is_vector(const std::string& vector_name) const
18308       {
18309          if (!valid())
18310             return false;
18311          else
18312             return local_data().vector_store.symbol_exists(vector_name);
18313       }
18314 
get_variable_name(const expression_ptr & ptr) const18315       inline std::string get_variable_name(const expression_ptr& ptr) const
18316       {
18317          return local_data().variable_store.entity_name(ptr);
18318       }
18319 
get_vector_name(const vector_holder_ptr & ptr) const18320       inline std::string get_vector_name(const vector_holder_ptr& ptr) const
18321       {
18322          return local_data().vector_store.entity_name(ptr);
18323       }
18324 
18325       #ifndef exprtk_disable_string_capabilities
get_stringvar_name(const expression_ptr & ptr) const18326       inline std::string get_stringvar_name(const expression_ptr& ptr) const
18327       {
18328          return local_data().stringvar_store.entity_name(ptr);
18329       }
18330 
get_conststr_stringvar_name(const expression_ptr & ptr) const18331       inline std::string get_conststr_stringvar_name(const expression_ptr& ptr) const
18332       {
18333          return local_data().stringvar_store.entity_name(ptr);
18334       }
18335       #endif
18336 
valid() const18337       inline bool valid() const
18338       {
18339          // Symbol table sanity check.
18340          return control_block_ && control_block_->data_;
18341       }
18342 
load_from(const symbol_table<T> & st)18343       inline void load_from(const symbol_table<T>& st)
18344       {
18345          {
18346             std::vector<std::string> name_list;
18347 
18348             st.local_data().function_store.get_list(name_list);
18349 
18350             if (!name_list.empty())
18351             {
18352                for (std::size_t i = 0; i < name_list.size(); ++i)
18353                {
18354                   exprtk::ifunction<T>& ifunc = *st.get_function(name_list[i]);
18355                   add_function(name_list[i],ifunc);
18356                }
18357             }
18358          }
18359 
18360          {
18361             std::vector<std::string> name_list;
18362 
18363             st.local_data().vararg_function_store.get_list(name_list);
18364 
18365             if (!name_list.empty())
18366             {
18367                for (std::size_t i = 0; i < name_list.size(); ++i)
18368                {
18369                   exprtk::ivararg_function<T>& ivafunc = *st.get_vararg_function(name_list[i]);
18370                   add_function(name_list[i],ivafunc);
18371                }
18372             }
18373          }
18374 
18375          {
18376             std::vector<std::string> name_list;
18377 
18378             st.local_data().generic_function_store.get_list(name_list);
18379 
18380             if (!name_list.empty())
18381             {
18382                for (std::size_t i = 0; i < name_list.size(); ++i)
18383                {
18384                   exprtk::igeneric_function<T>& ifunc = *st.get_generic_function(name_list[i]);
18385                   add_function(name_list[i],ifunc);
18386                }
18387             }
18388          }
18389 
18390          {
18391             std::vector<std::string> name_list;
18392 
18393             st.local_data().string_function_store.get_list(name_list);
18394 
18395             if (!name_list.empty())
18396             {
18397                for (std::size_t i = 0; i < name_list.size(); ++i)
18398                {
18399                   exprtk::igeneric_function<T>& ifunc = *st.get_string_function(name_list[i]);
18400                   add_function(name_list[i],ifunc);
18401                }
18402             }
18403          }
18404 
18405          {
18406             std::vector<std::string> name_list;
18407 
18408             st.local_data().overload_function_store.get_list(name_list);
18409 
18410             if (!name_list.empty())
18411             {
18412                for (std::size_t i = 0; i < name_list.size(); ++i)
18413                {
18414                   exprtk::igeneric_function<T>& ifunc = *st.get_overload_function(name_list[i]);
18415                   add_function(name_list[i],ifunc);
18416                }
18417             }
18418          }
18419       }
18420 
18421    private:
18422 
valid_symbol(const std::string & symbol,const bool check_reserved_symb=true) const18423       inline bool valid_symbol(const std::string& symbol, const bool check_reserved_symb = true) const
18424       {
18425          if (symbol.empty())
18426             return false;
18427          else if (!details::is_letter(symbol[0]))
18428             return false;
18429          else if (symbol.size() > 1)
18430          {
18431             for (std::size_t i = 1; i < symbol.size(); ++i)
18432             {
18433                if (
18434                     !details::is_letter_or_digit(symbol[i]) &&
18435                     ('_' != symbol[i])
18436                   )
18437                {
18438                   if ((i < (symbol.size() - 1)) && ('.' == symbol[i]))
18439                      continue;
18440                   else
18441                      return false;
18442                }
18443             }
18444          }
18445 
18446          return (check_reserved_symb) ? (!local_data().is_reserved_symbol(symbol)) : true;
18447       }
18448 
valid_function(const std::string & symbol) const18449       inline bool valid_function(const std::string& symbol) const
18450       {
18451          if (symbol.empty())
18452             return false;
18453          else if (!details::is_letter(symbol[0]))
18454             return false;
18455          else if (symbol.size() > 1)
18456          {
18457             for (std::size_t i = 1; i < symbol.size(); ++i)
18458             {
18459                if (
18460                     !details::is_letter_or_digit(symbol[i]) &&
18461                     ('_' != symbol[i])
18462                   )
18463                {
18464                   if ((i < (symbol.size() - 1)) && ('.' == symbol[i]))
18465                      continue;
18466                   else
18467                      return false;
18468                }
18469             }
18470          }
18471 
18472          return true;
18473       }
18474 
18475       typedef typename control_block::st_data local_data_t;
18476 
local_data()18477       inline local_data_t& local_data()
18478       {
18479          return *(control_block_->data_);
18480       }
18481 
local_data() const18482       inline const local_data_t& local_data() const
18483       {
18484          return *(control_block_->data_);
18485       }
18486 
18487       control_block* control_block_;
18488 
18489       friend class parser<T>;
18490    };
18491 
18492    template <typename T>
18493    class function_compositor;
18494 
18495    template <typename T>
18496    class expression
18497    {
18498    private:
18499 
18500       typedef details::expression_node<T>*  expression_ptr;
18501       typedef details::vector_holder<T>* vector_holder_ptr;
18502       typedef std::vector<symbol_table<T> >  symtab_list_t;
18503 
18504       struct control_block
18505       {
18506          enum data_type
18507          {
18508             e_unknown  ,
18509             e_expr     ,
18510             e_vecholder,
18511             e_data     ,
18512             e_vecdata  ,
18513             e_string
18514          };
18515 
18516          struct data_pack
18517          {
data_packexprtk::expression::control_block::data_pack18518             data_pack()
18519             : pointer(0),
18520               type(e_unknown),
18521               size(0)
18522             {}
18523 
data_packexprtk::expression::control_block::data_pack18524             data_pack(void* ptr, const data_type dt, const std::size_t sz = 0)
18525             : pointer(ptr),
18526               type(dt),
18527               size(sz)
18528             {}
18529 
18530             void*       pointer;
18531             data_type   type;
18532             std::size_t size;
18533          };
18534 
18535          typedef std::vector<data_pack> local_data_list_t;
18536          typedef results_context<T>     results_context_t;
18537 
control_blockexprtk::expression::control_block18538          control_block()
18539          : ref_count(0),
18540            expr     (0),
18541            results  (0),
18542            retinv_null(false),
18543            return_invoked(&retinv_null)
18544          {}
18545 
control_blockexprtk::expression::control_block18546          explicit control_block(expression_ptr e)
18547          : ref_count(1),
18548            expr     (e),
18549            results  (0),
18550            retinv_null(false),
18551            return_invoked(&retinv_null)
18552          {}
18553 
~control_blockexprtk::expression::control_block18554         ~control_block()
18555          {
18556             if (expr && details::branch_deletable(expr))
18557             {
18558                destroy_node(expr);
18559             }
18560 
18561             if (!local_data_list.empty())
18562             {
18563                for (std::size_t i = 0; i < local_data_list.size(); ++i)
18564                {
18565                   switch (local_data_list[i].type)
18566                   {
18567                      case e_expr      : delete reinterpret_cast<expression_ptr>(local_data_list[i].pointer);
18568                                         break;
18569 
18570                      case e_vecholder : delete reinterpret_cast<vector_holder_ptr>(local_data_list[i].pointer);
18571                                         break;
18572 
18573                      case e_data      : delete reinterpret_cast<T*>(local_data_list[i].pointer);
18574                                         break;
18575 
18576                      case e_vecdata   : delete [] reinterpret_cast<T*>(local_data_list[i].pointer);
18577                                         break;
18578 
18579                      case e_string    : delete reinterpret_cast<std::string*>(local_data_list[i].pointer);
18580                                         break;
18581 
18582                      default          : break;
18583                   }
18584                }
18585             }
18586 
18587             if (results)
18588             {
18589                delete results;
18590             }
18591          }
18592 
createexprtk::expression::control_block18593          static inline control_block* create(expression_ptr e)
18594          {
18595             return new control_block(e);
18596          }
18597 
destroyexprtk::expression::control_block18598          static inline void destroy(control_block*& cntrl_blck)
18599          {
18600             if (cntrl_blck)
18601             {
18602                if (
18603                     (0 !=   cntrl_blck->ref_count) &&
18604                     (0 == --cntrl_blck->ref_count)
18605                   )
18606                {
18607                   delete cntrl_blck;
18608                }
18609 
18610                cntrl_blck = 0;
18611             }
18612          }
18613 
18614          std::size_t ref_count;
18615          expression_ptr expr;
18616          local_data_list_t local_data_list;
18617          results_context_t* results;
18618          bool  retinv_null;
18619          bool* return_invoked;
18620 
18621          friend class function_compositor<T>;
18622       };
18623 
18624    public:
18625 
expression()18626       expression()
18627       : control_block_(0)
18628       {
18629          set_expression(new details::null_node<T>());
18630       }
18631 
expression(const expression<T> & e)18632       expression(const expression<T>& e)
18633       : control_block_    (e.control_block_    ),
18634         symbol_table_list_(e.symbol_table_list_)
18635       {
18636          control_block_->ref_count++;
18637       }
18638 
expression(const symbol_table<T> & symbol_table)18639       explicit expression(const symbol_table<T>& symbol_table)
18640       : control_block_(0)
18641       {
18642          set_expression(new details::null_node<T>());
18643          symbol_table_list_.push_back(symbol_table);
18644       }
18645 
operator =(const expression<T> & e)18646       inline expression<T>& operator=(const expression<T>& e)
18647       {
18648          if (this != &e)
18649          {
18650             if (control_block_)
18651             {
18652                if (
18653                     (0 !=   control_block_->ref_count) &&
18654                     (0 == --control_block_->ref_count)
18655                   )
18656                {
18657                   delete control_block_;
18658                }
18659 
18660                control_block_ = 0;
18661             }
18662 
18663             control_block_ = e.control_block_;
18664             control_block_->ref_count++;
18665             symbol_table_list_ = e.symbol_table_list_;
18666          }
18667 
18668          return *this;
18669       }
18670 
operator ==(const expression<T> & e) const18671       inline bool operator==(const expression<T>& e) const
18672       {
18673          return (this == &e);
18674       }
18675 
operator !() const18676       inline bool operator!() const
18677       {
18678          return (
18679                   (0 == control_block_      ) ||
18680                   (0 == control_block_->expr)
18681                 );
18682       }
18683 
release()18684       inline expression<T>& release()
18685       {
18686          control_block::destroy(control_block_);
18687 
18688          return (*this);
18689       }
18690 
~expression()18691      ~expression()
18692       {
18693          control_block::destroy(control_block_);
18694       }
18695 
value() const18696       inline T value() const
18697       {
18698          assert(control_block_      );
18699          assert(control_block_->expr);
18700 
18701          return control_block_->expr->value();
18702       }
18703 
operator ()() const18704       inline T operator() () const
18705       {
18706          return value();
18707       }
18708 
operator T() const18709       inline operator T() const
18710       {
18711          return value();
18712       }
18713 
operator bool() const18714       inline operator bool() const
18715       {
18716          return details::is_true(value());
18717       }
18718 
register_symbol_table(symbol_table<T> & st)18719       inline void register_symbol_table(symbol_table<T>& st)
18720       {
18721          symbol_table_list_.push_back(st);
18722       }
18723 
get_symbol_table(const std::size_t & index=0) const18724       inline const symbol_table<T>& get_symbol_table(const std::size_t& index = 0) const
18725       {
18726          return symbol_table_list_[index];
18727       }
18728 
get_symbol_table(const std::size_t & index=0)18729       inline symbol_table<T>& get_symbol_table(const std::size_t& index = 0)
18730       {
18731          return symbol_table_list_[index];
18732       }
18733 
18734       typedef results_context<T> results_context_t;
18735 
results() const18736       inline const results_context_t& results() const
18737       {
18738          if (control_block_->results)
18739             return (*control_block_->results);
18740          else
18741          {
18742             static const results_context_t null_results;
18743             return null_results;
18744          }
18745       }
18746 
return_invoked() const18747       inline bool return_invoked() const
18748       {
18749          return (*control_block_->return_invoked);
18750       }
18751 
18752    private:
18753 
get_symbol_table_list() const18754       inline symtab_list_t get_symbol_table_list() const
18755       {
18756          return symbol_table_list_;
18757       }
18758 
set_expression(const expression_ptr expr)18759       inline void set_expression(const expression_ptr expr)
18760       {
18761          if (expr)
18762          {
18763             if (control_block_)
18764             {
18765                if (0 == --control_block_->ref_count)
18766                {
18767                   delete control_block_;
18768                }
18769             }
18770 
18771             control_block_ = control_block::create(expr);
18772          }
18773       }
18774 
register_local_var(expression_ptr expr)18775       inline void register_local_var(expression_ptr expr)
18776       {
18777          if (expr)
18778          {
18779             if (control_block_)
18780             {
18781                control_block_->
18782                   local_data_list.push_back(
18783                      typename expression<T>::control_block::
18784                         data_pack(reinterpret_cast<void*>(expr),
18785                                   control_block::e_expr));
18786             }
18787          }
18788       }
18789 
register_local_var(vector_holder_ptr vec_holder)18790       inline void register_local_var(vector_holder_ptr vec_holder)
18791       {
18792          if (vec_holder)
18793          {
18794             if (control_block_)
18795             {
18796                control_block_->
18797                   local_data_list.push_back(
18798                      typename expression<T>::control_block::
18799                         data_pack(reinterpret_cast<void*>(vec_holder),
18800                                   control_block::e_vecholder));
18801             }
18802          }
18803       }
18804 
register_local_data(void * data,const std::size_t & size=0,const std::size_t data_mode=0)18805       inline void register_local_data(void* data, const std::size_t& size = 0, const std::size_t data_mode = 0)
18806       {
18807          if (data)
18808          {
18809             if (control_block_)
18810             {
18811                typename control_block::data_type dt = control_block::e_data;
18812 
18813                switch (data_mode)
18814                {
18815                   case 0 : dt = control_block::e_data;    break;
18816                   case 1 : dt = control_block::e_vecdata; break;
18817                   case 2 : dt = control_block::e_string;  break;
18818                }
18819 
18820                control_block_->
18821                   local_data_list.push_back(
18822                      typename expression<T>::control_block::
18823                         data_pack(reinterpret_cast<void*>(data), dt, size));
18824             }
18825          }
18826       }
18827 
local_data_list()18828       inline const typename control_block::local_data_list_t& local_data_list()
18829       {
18830          if (control_block_)
18831          {
18832             return control_block_->local_data_list;
18833          }
18834          else
18835          {
18836             static typename control_block::local_data_list_t null_local_data_list;
18837             return null_local_data_list;
18838          }
18839       }
18840 
register_return_results(results_context_t * rc)18841       inline void register_return_results(results_context_t* rc)
18842       {
18843          if (control_block_ && rc)
18844          {
18845             control_block_->results = rc;
18846          }
18847       }
18848 
set_retinvk(bool * retinvk_ptr)18849       inline void set_retinvk(bool* retinvk_ptr)
18850       {
18851          if (control_block_)
18852          {
18853             control_block_->return_invoked = retinvk_ptr;
18854          }
18855       }
18856 
18857       control_block* control_block_;
18858       symtab_list_t  symbol_table_list_;
18859 
18860       friend class parser<T>;
18861       friend class expression_helper<T>;
18862       friend class function_compositor<T>;
18863    };
18864 
18865    template <typename T>
18866    class expression_helper
18867    {
18868    public:
18869 
is_constant(const expression<T> & expr)18870       static inline bool is_constant(const expression<T>& expr)
18871       {
18872          return details::is_constant_node(expr.control_block_->expr);
18873       }
18874 
is_variable(const expression<T> & expr)18875       static inline bool is_variable(const expression<T>& expr)
18876       {
18877          return details::is_variable_node(expr.control_block_->expr);
18878       }
18879 
is_unary(const expression<T> & expr)18880       static inline bool is_unary(const expression<T>& expr)
18881       {
18882          return details::is_unary_node(expr.control_block_->expr);
18883       }
18884 
is_binary(const expression<T> & expr)18885       static inline bool is_binary(const expression<T>& expr)
18886       {
18887          return details::is_binary_node(expr.control_block_->expr);
18888       }
18889 
is_function(const expression<T> & expr)18890       static inline bool is_function(const expression<T>& expr)
18891       {
18892          return details::is_function(expr.control_block_->expr);
18893       }
18894 
is_null(const expression<T> & expr)18895       static inline bool is_null(const expression<T>& expr)
18896       {
18897          return details::is_null_node(expr.control_block_->expr);
18898       }
18899    };
18900 
18901    template <typename T>
is_valid(const expression<T> & expr)18902    inline bool is_valid(const expression<T>& expr)
18903    {
18904       return !expression_helper<T>::is_null(expr);
18905    }
18906 
18907    namespace parser_error
18908    {
18909       enum error_mode
18910       {
18911          e_unknown = 0,
18912          e_syntax  = 1,
18913          e_token   = 2,
18914          e_numeric = 4,
18915          e_symtab  = 5,
18916          e_lexer   = 6,
18917          e_helper  = 7,
18918          e_parser  = 8
18919       };
18920 
18921       struct type
18922       {
typeexprtk::parser_error::type18923          type()
18924          : mode(parser_error::e_unknown),
18925            line_no  (0),
18926            column_no(0)
18927          {}
18928 
18929          lexer::token token;
18930          error_mode mode;
18931          std::string diagnostic;
18932          std::string src_location;
18933          std::string error_line;
18934          std::size_t line_no;
18935          std::size_t column_no;
18936       };
18937 
make_error(const error_mode mode,const std::string & diagnostic="",const std::string & src_location="")18938       inline type make_error(const error_mode mode,
18939                              const std::string& diagnostic   = "",
18940                              const std::string& src_location = "")
18941       {
18942          type t;
18943          t.mode         = mode;
18944          t.token.type   = lexer::token::e_error;
18945          t.diagnostic   = diagnostic;
18946          t.src_location = src_location;
18947          exprtk_debug(("%s\n",diagnostic .c_str()));
18948          return t;
18949       }
18950 
make_error(const error_mode mode,const lexer::token & tk,const std::string & diagnostic="",const std::string & src_location="")18951       inline type make_error(const error_mode mode,
18952                              const lexer::token& tk,
18953                              const std::string& diagnostic   = "",
18954                              const std::string& src_location = "")
18955       {
18956          type t;
18957          t.mode       = mode;
18958          t.token      = tk;
18959          t.diagnostic = diagnostic;
18960          t.src_location = src_location;
18961          exprtk_debug(("%s\n",diagnostic .c_str()));
18962          return t;
18963       }
18964 
to_str(error_mode mode)18965       inline std::string to_str(error_mode mode)
18966       {
18967          switch (mode)
18968          {
18969             case e_unknown : return std::string("Unknown Error");
18970             case e_syntax  : return std::string("Syntax Error" );
18971             case e_token   : return std::string("Token Error"  );
18972             case e_numeric : return std::string("Numeric Error");
18973             case e_symtab  : return std::string("Symbol Error" );
18974             case e_lexer   : return std::string("Lexer Error"  );
18975             case e_helper  : return std::string("Helper Error" );
18976             case e_parser  : return std::string("Parser Error" );
18977             default        : return std::string("Unknown Error");
18978          }
18979       }
18980 
update_error(type & error,const std::string & expression)18981       inline bool update_error(type& error, const std::string& expression)
18982       {
18983          if (
18984               expression.empty()                         ||
18985               (error.token.position > expression.size()) ||
18986               (std::numeric_limits<std::size_t>::max() == error.token.position)
18987             )
18988          {
18989             return false;
18990          }
18991 
18992          std::size_t error_line_start = 0;
18993 
18994          for (std::size_t i = error.token.position; i > 0; --i)
18995          {
18996             const details::char_t c = expression[i];
18997 
18998             if (('\n' == c) || ('\r' == c))
18999             {
19000                error_line_start = i + 1;
19001                break;
19002             }
19003          }
19004 
19005          std::size_t next_nl_position = std::min(expression.size(),
19006                                                  expression.find_first_of('\n',error.token.position + 1));
19007 
19008          error.column_no  = error.token.position - error_line_start;
19009          error.error_line = expression.substr(error_line_start,
19010                                               next_nl_position - error_line_start);
19011 
19012          error.line_no = 0;
19013 
19014          for (std::size_t i = 0; i < next_nl_position; ++i)
19015          {
19016             if ('\n' == expression[i])
19017                ++error.line_no;
19018          }
19019 
19020          return true;
19021       }
19022 
dump_error(const type & error)19023       inline void dump_error(const type& error)
19024       {
19025          printf("Position: %02d   Type: [%s]   Msg: %s\n",
19026                 static_cast<int>(error.token.position),
19027                 exprtk::parser_error::to_str(error.mode).c_str(),
19028                 error.diagnostic.c_str());
19029       }
19030    }
19031 
19032    namespace details
19033    {
19034       template <typename Parser>
disable_type_checking(Parser & p)19035       inline void disable_type_checking(Parser& p)
19036       {
19037          p.state_.type_check_enabled = false;
19038       }
19039    }
19040 
19041    template <typename T>
19042    class parser : public lexer::parser_helper
19043    {
19044    private:
19045 
19046       enum precedence_level
19047       {
19048          e_level00,
19049          e_level01,
19050          e_level02,
19051          e_level03,
19052          e_level04,
19053          e_level05,
19054          e_level06,
19055          e_level07,
19056          e_level08,
19057          e_level09,
19058          e_level10,
19059          e_level11,
19060          e_level12,
19061          e_level13,
19062          e_level14
19063       };
19064 
19065       typedef const T&                                               cref_t;
19066       typedef const T                                               const_t;
19067       typedef ifunction                <T>                                F;
19068       typedef ivararg_function         <T>                              VAF;
19069       typedef igeneric_function        <T>                               GF;
19070       typedef ifunction                <T>                      ifunction_t;
19071       typedef ivararg_function         <T>               ivararg_function_t;
19072       typedef igeneric_function        <T>              igeneric_function_t;
19073       typedef details::expression_node <T>                expression_node_t;
19074       typedef details::literal_node    <T>                   literal_node_t;
19075       typedef details::unary_node      <T>                     unary_node_t;
19076       typedef details::binary_node     <T>                    binary_node_t;
19077       typedef details::trinary_node    <T>                   trinary_node_t;
19078       typedef details::quaternary_node <T>                quaternary_node_t;
19079       typedef details::conditional_node<T>               conditional_node_t;
19080       typedef details::cons_conditional_node<T>     cons_conditional_node_t;
19081       typedef details::while_loop_node <T>                while_loop_node_t;
19082       typedef details::repeat_until_loop_node<T>   repeat_until_loop_node_t;
19083       typedef details::for_loop_node   <T>                  for_loop_node_t;
19084       #ifndef exprtk_disable_break_continue
19085       typedef details::while_loop_bc_node <T>          while_loop_bc_node_t;
19086       typedef details::repeat_until_loop_bc_node<T> repeat_until_loop_bc_node_t;
19087       typedef details::for_loop_bc_node<T>               for_loop_bc_node_t;
19088       #endif
19089       typedef details::switch_node     <T>                    switch_node_t;
19090       typedef details::variable_node   <T>                  variable_node_t;
19091       typedef details::vector_elem_node<T>               vector_elem_node_t;
19092       typedef details::rebasevector_elem_node<T>   rebasevector_elem_node_t;
19093       typedef details::rebasevector_celem_node<T> rebasevector_celem_node_t;
19094       typedef details::vector_node     <T>                    vector_node_t;
19095       typedef details::range_pack      <T>                          range_t;
19096       #ifndef exprtk_disable_string_capabilities
19097       typedef details::stringvar_node     <T>              stringvar_node_t;
19098       typedef details::string_literal_node<T>         string_literal_node_t;
19099       typedef details::string_range_node  <T>           string_range_node_t;
19100       typedef details::const_string_range_node<T> const_string_range_node_t;
19101       typedef details::generic_string_range_node<T> generic_string_range_node_t;
19102       typedef details::string_concat_node <T>          string_concat_node_t;
19103       typedef details::assignment_string_node<T>   assignment_string_node_t;
19104       typedef details::assignment_string_range_node<T> assignment_string_range_node_t;
19105       typedef details::conditional_string_node<T>  conditional_string_node_t;
19106       typedef details::cons_conditional_str_node<T> cons_conditional_str_node_t;
19107       #endif
19108       typedef details::assignment_node<T>                 assignment_node_t;
19109       typedef details::assignment_vec_elem_node       <T> assignment_vec_elem_node_t;
19110       typedef details::assignment_rebasevec_elem_node <T> assignment_rebasevec_elem_node_t;
19111       typedef details::assignment_rebasevec_celem_node<T> assignment_rebasevec_celem_node_t;
19112       typedef details::assignment_vec_node     <T>    assignment_vec_node_t;
19113       typedef details::assignment_vecvec_node  <T> assignment_vecvec_node_t;
19114       typedef details::scand_node<T>                           scand_node_t;
19115       typedef details::scor_node<T>                             scor_node_t;
19116       typedef lexer::token                                          token_t;
19117       typedef expression_node_t*                        expression_node_ptr;
19118       typedef expression<T>                                    expression_t;
19119       typedef symbol_table<T>                                symbol_table_t;
19120       typedef typename expression<T>::symtab_list_t     symbol_table_list_t;
19121       typedef details::vector_holder<T>*                  vector_holder_ptr;
19122 
19123       typedef typename details::functor_t<T>            functor_t;
19124       typedef typename functor_t::qfunc_t    quaternary_functor_t;
19125       typedef typename functor_t::tfunc_t       trinary_functor_t;
19126       typedef typename functor_t::bfunc_t        binary_functor_t;
19127       typedef typename functor_t::ufunc_t         unary_functor_t;
19128 
19129       typedef details::operator_type operator_t;
19130 
19131       typedef std::map<operator_t,  unary_functor_t>   unary_op_map_t;
19132       typedef std::map<operator_t, binary_functor_t>  binary_op_map_t;
19133       typedef std::map<operator_t,trinary_functor_t> trinary_op_map_t;
19134 
19135       typedef std::map<std::string,std::pair<trinary_functor_t   ,operator_t> > sf3_map_t;
19136       typedef std::map<std::string,std::pair<quaternary_functor_t,operator_t> > sf4_map_t;
19137 
19138       typedef std::map<binary_functor_t,operator_t> inv_binary_op_map_t;
19139       typedef std::multimap<std::string,details::base_operation_t,details::ilesscompare> base_ops_map_t;
19140       typedef std::set<std::string,details::ilesscompare> disabled_func_set_t;
19141 
19142       typedef details::T0oT1_define<T,  cref_t,  cref_t> vov_t;
19143       typedef details::T0oT1_define<T, const_t,  cref_t> cov_t;
19144       typedef details::T0oT1_define<T,  cref_t, const_t> voc_t;
19145 
19146       typedef details::T0oT1oT2_define<T,  cref_t,  cref_t,  cref_t> vovov_t;
19147       typedef details::T0oT1oT2_define<T,  cref_t,  cref_t, const_t> vovoc_t;
19148       typedef details::T0oT1oT2_define<T,  cref_t, const_t,  cref_t> vocov_t;
19149       typedef details::T0oT1oT2_define<T, const_t,  cref_t,  cref_t> covov_t;
19150       typedef details::T0oT1oT2_define<T, const_t,  cref_t, const_t> covoc_t;
19151       typedef details::T0oT1oT2_define<T, const_t, const_t,  cref_t> cocov_t;
19152       typedef details::T0oT1oT2_define<T,  cref_t, const_t, const_t> vococ_t;
19153 
19154       typedef details::T0oT1oT2oT3_define<T,  cref_t,  cref_t,  cref_t,  cref_t> vovovov_t;
19155       typedef details::T0oT1oT2oT3_define<T,  cref_t,  cref_t,  cref_t, const_t> vovovoc_t;
19156       typedef details::T0oT1oT2oT3_define<T,  cref_t,  cref_t, const_t,  cref_t> vovocov_t;
19157       typedef details::T0oT1oT2oT3_define<T,  cref_t, const_t,  cref_t,  cref_t> vocovov_t;
19158       typedef details::T0oT1oT2oT3_define<T, const_t,  cref_t,  cref_t,  cref_t> covovov_t;
19159 
19160       typedef details::T0oT1oT2oT3_define<T, const_t,  cref_t, const_t,  cref_t> covocov_t;
19161       typedef details::T0oT1oT2oT3_define<T,  cref_t, const_t,  cref_t, const_t> vocovoc_t;
19162       typedef details::T0oT1oT2oT3_define<T, const_t,  cref_t,  cref_t, const_t> covovoc_t;
19163       typedef details::T0oT1oT2oT3_define<T,  cref_t, const_t, const_t,  cref_t> vococov_t;
19164 
19165       typedef results_context<T> results_context_t;
19166 
19167       typedef parser_helper prsrhlpr_t;
19168 
19169       struct scope_element
19170       {
19171          enum element_type
19172          {
19173             e_none    ,
19174             e_variable,
19175             e_vector  ,
19176             e_vecelem ,
19177             e_string
19178          };
19179 
19180          typedef details::vector_holder<T> vector_holder_t;
19181          typedef variable_node_t*        variable_node_ptr;
19182          typedef vector_holder_t*        vector_holder_ptr;
19183          typedef expression_node_t*    expression_node_ptr;
19184          #ifndef exprtk_disable_string_capabilities
19185          typedef stringvar_node_t*      stringvar_node_ptr;
19186          #endif
19187 
scope_elementexprtk::parser::scope_element19188          scope_element()
19189          : name("???"),
19190            size (std::numeric_limits<std::size_t>::max()),
19191            index(std::numeric_limits<std::size_t>::max()),
19192            depth(std::numeric_limits<std::size_t>::max()),
19193            ref_count(0),
19194            ip_index (0),
19195            type (e_none),
19196            active(false),
19197            data    (0),
19198            var_node(0),
19199            vec_node(0)
19200            #ifndef exprtk_disable_string_capabilities
19201            ,str_node(0)
19202            #endif
19203          {}
19204 
operator <exprtk::parser::scope_element19205          bool operator < (const scope_element& se) const
19206          {
19207             if (ip_index < se.ip_index)
19208                return true;
19209             else if (ip_index > se.ip_index)
19210                return false;
19211             else if (depth < se.depth)
19212                return true;
19213             else if (depth > se.depth)
19214                return false;
19215             else if (index < se.index)
19216                return true;
19217             else if (index > se.index)
19218                return false;
19219             else
19220                return (name < se.name);
19221          }
19222 
clearexprtk::parser::scope_element19223          void clear()
19224          {
19225             name   = "???";
19226             size   = std::numeric_limits<std::size_t>::max();
19227             index  = std::numeric_limits<std::size_t>::max();
19228             depth  = std::numeric_limits<std::size_t>::max();
19229             type   = e_none;
19230             active = false;
19231             ref_count = 0;
19232             ip_index  = 0;
19233             data      = 0;
19234             var_node  = 0;
19235             vec_node  = 0;
19236             #ifndef exprtk_disable_string_capabilities
19237             str_node  = 0;
19238             #endif
19239          }
19240 
19241          std::string  name;
19242          std::size_t  size;
19243          std::size_t  index;
19244          std::size_t  depth;
19245          std::size_t  ref_count;
19246          std::size_t  ip_index;
19247          element_type type;
19248          bool         active;
19249          void*        data;
19250          expression_node_ptr var_node;
19251          vector_holder_ptr   vec_node;
19252          #ifndef exprtk_disable_string_capabilities
19253          stringvar_node_ptr str_node;
19254          #endif
19255       };
19256 
19257       class scope_element_manager
19258       {
19259       public:
19260 
19261          typedef expression_node_t* expression_node_ptr;
19262          typedef variable_node_t*     variable_node_ptr;
19263          typedef parser<T>                     parser_t;
19264 
scope_element_manager(parser<T> & p)19265          explicit scope_element_manager(parser<T>& p)
19266          : parser_(p),
19267            input_param_cnt_(0)
19268          {}
19269 
size() const19270          inline std::size_t size() const
19271          {
19272             return element_.size();
19273          }
19274 
empty() const19275          inline bool empty() const
19276          {
19277             return element_.empty();
19278          }
19279 
get_element(const std::size_t & index)19280          inline scope_element& get_element(const std::size_t& index)
19281          {
19282             if (index < element_.size())
19283                return element_[index];
19284             else
19285                return null_element_;
19286          }
19287 
get_element(const std::string & var_name,const std::size_t index=std::numeric_limits<std::size_t>::max ())19288          inline scope_element& get_element(const std::string& var_name,
19289                                            const std::size_t index = std::numeric_limits<std::size_t>::max())
19290          {
19291             const std::size_t current_depth = parser_.state_.scope_depth;
19292 
19293             for (std::size_t i = 0; i < element_.size(); ++i)
19294             {
19295                scope_element& se = element_[i];
19296 
19297                if (se.depth > current_depth)
19298                   continue;
19299                else if (
19300                          details::imatch(se.name, var_name) &&
19301                          (se.index == index)
19302                        )
19303                   return se;
19304             }
19305 
19306             return null_element_;
19307          }
19308 
get_active_element(const std::string & var_name,const std::size_t index=std::numeric_limits<std::size_t>::max ())19309          inline scope_element& get_active_element(const std::string& var_name,
19310                                                   const std::size_t index = std::numeric_limits<std::size_t>::max())
19311          {
19312             const std::size_t current_depth = parser_.state_.scope_depth;
19313 
19314             for (std::size_t i = 0; i < element_.size(); ++i)
19315             {
19316                scope_element& se = element_[i];
19317 
19318                if (se.depth > current_depth)
19319                   continue;
19320                else if (
19321                          details::imatch(se.name, var_name) &&
19322                          (se.index == index)                &&
19323                          (se.active)
19324                        )
19325                   return se;
19326             }
19327 
19328             return null_element_;
19329          }
19330 
add_element(const scope_element & se)19331          inline bool add_element(const scope_element& se)
19332          {
19333             for (std::size_t i = 0; i < element_.size(); ++i)
19334             {
19335                scope_element& cse = element_[i];
19336 
19337                if (
19338                     details::imatch(cse.name, se.name) &&
19339                     (cse.depth <= se.depth)            &&
19340                     (cse.index == se.index)            &&
19341                     (cse.size  == se.size )            &&
19342                     (cse.type  == se.type )            &&
19343                     (cse.active)
19344                   )
19345                   return false;
19346             }
19347 
19348             element_.push_back(se);
19349             std::sort(element_.begin(),element_.end());
19350 
19351             return true;
19352          }
19353 
deactivate(const std::size_t & scope_depth)19354          inline void deactivate(const std::size_t& scope_depth)
19355          {
19356             exprtk_debug(("deactivate() - Scope depth: %d\n",
19357                           static_cast<int>(parser_.state_.scope_depth)));
19358 
19359             for (std::size_t i = 0; i < element_.size(); ++i)
19360             {
19361                scope_element& se = element_[i];
19362 
19363                if (se.active && (se.depth >= scope_depth))
19364                {
19365                   exprtk_debug(("deactivate() - element[%02d] '%s'\n",
19366                                 static_cast<int>(i),
19367                                 se.name.c_str()));
19368 
19369                   se.active = false;
19370                }
19371             }
19372          }
19373 
free_element(scope_element & se)19374          inline void free_element(scope_element& se)
19375          {
19376             exprtk_debug(("free_element() - se[%s]\n", se.name.c_str()));
19377 
19378             switch (se.type)
19379             {
19380                case scope_element::e_variable   : delete reinterpret_cast<T*>(se.data);
19381                                                   delete se.var_node;
19382                                                   break;
19383 
19384                case scope_element::e_vector     : delete[] reinterpret_cast<T*>(se.data);
19385                                                   delete se.vec_node;
19386                                                   break;
19387 
19388                case scope_element::e_vecelem    : delete se.var_node;
19389                                                   break;
19390 
19391                #ifndef exprtk_disable_string_capabilities
19392                case scope_element::e_string     : delete reinterpret_cast<std::string*>(se.data);
19393                                                   delete se.str_node;
19394                                                   break;
19395                #endif
19396 
19397                default                          : return;
19398             }
19399 
19400             se.clear();
19401          }
19402 
cleanup()19403          inline void cleanup()
19404          {
19405             for (std::size_t i = 0; i < element_.size(); ++i)
19406             {
19407                free_element(element_[i]);
19408             }
19409 
19410             element_.clear();
19411 
19412             input_param_cnt_ = 0;
19413          }
19414 
next_ip_index()19415          inline std::size_t next_ip_index()
19416          {
19417             return ++input_param_cnt_;
19418          }
19419 
get_variable(const T & v)19420          inline expression_node_ptr get_variable(const T& v)
19421          {
19422             for (std::size_t i = 0; i < element_.size(); ++i)
19423             {
19424                scope_element& se = element_[i];
19425 
19426                if (
19427                     se.active   &&
19428                     se.var_node &&
19429                     details::is_variable_node(se.var_node)
19430                   )
19431                {
19432                   variable_node_ptr vn = reinterpret_cast<variable_node_ptr>(se.var_node);
19433 
19434                   if (&(vn->ref()) == (&v))
19435                   {
19436                      return se.var_node;
19437                   }
19438                }
19439             }
19440 
19441             return expression_node_ptr(0);
19442          }
19443 
19444       private:
19445 
19446          scope_element_manager& operator=(const scope_element_manager&);
19447 
19448          parser_t& parser_;
19449          std::vector<scope_element> element_;
19450          scope_element null_element_;
19451          std::size_t input_param_cnt_;
19452       };
19453 
19454       class scope_handler
19455       {
19456       public:
19457 
19458          typedef parser<T> parser_t;
19459 
scope_handler(parser<T> & p)19460          explicit scope_handler(parser<T>& p)
19461          : parser_(p)
19462          {
19463             parser_.state_.scope_depth++;
19464             #ifdef exprtk_enable_debugging
19465             const std::string depth(2 * parser_.state_.scope_depth,'-');
19466             exprtk_debug(("%s> Scope Depth: %02d\n",
19467                           depth.c_str(),
19468                           static_cast<int>(parser_.state_.scope_depth)));
19469             #endif
19470          }
19471 
~scope_handler()19472         ~scope_handler()
19473          {
19474             parser_.sem_.deactivate(parser_.state_.scope_depth);
19475             parser_.state_.scope_depth--;
19476             #ifdef exprtk_enable_debugging
19477             const std::string depth(2 * parser_.state_.scope_depth,'-');
19478             exprtk_debug(("<%s Scope Depth: %02d\n",
19479                           depth.c_str(),
19480                           static_cast<int>(parser_.state_.scope_depth)));
19481             #endif
19482          }
19483 
19484       private:
19485 
19486          scope_handler& operator=(const scope_handler&);
19487 
19488          parser_t& parser_;
19489       };
19490 
19491       class stack_limit_handler
19492       {
19493       public:
19494 
19495          typedef parser<T> parser_t;
19496 
stack_limit_handler(parser<T> & p)19497          explicit stack_limit_handler(parser<T>& p)
19498             : parser_(p),
19499               limit_exceeded_(false)
19500          {
19501             if (++parser_.state_.stack_depth > parser_.settings_.max_stack_depth_)
19502             {
19503                limit_exceeded_ = true;
19504                parser_.set_error(
19505                   make_error(parser_error::e_parser,
19506                      "ERR000 - Current stack depth " + details::to_str(parser_.state_.stack_depth) +
19507                      " exceeds maximum allowed stack depth of " + details::to_str(parser_.settings_.max_stack_depth_),
19508                      exprtk_error_location));
19509             }
19510          }
19511 
~stack_limit_handler()19512         ~stack_limit_handler()
19513          {
19514             parser_.state_.stack_depth--;
19515          }
19516 
operator !()19517          bool operator!()
19518          {
19519             return limit_exceeded_;
19520          }
19521 
19522       private:
19523 
19524          stack_limit_handler& operator=(const stack_limit_handler&);
19525 
19526          parser_t& parser_;
19527          bool limit_exceeded_;
19528       };
19529 
19530       struct symtab_store
19531       {
19532          symbol_table_list_t symtab_list_;
19533 
19534          typedef typename symbol_table_t::local_data_t   local_data_t;
19535          typedef typename symbol_table_t::variable_ptr   variable_ptr;
19536          typedef typename symbol_table_t::function_ptr   function_ptr;
19537          #ifndef exprtk_disable_string_capabilities
19538          typedef typename symbol_table_t::stringvar_ptr stringvar_ptr;
19539          #endif
19540          typedef typename symbol_table_t::vector_holder_ptr       vector_holder_ptr;
19541          typedef typename symbol_table_t::vararg_function_ptr   vararg_function_ptr;
19542          typedef typename symbol_table_t::generic_function_ptr generic_function_ptr;
19543 
emptyexprtk::parser::symtab_store19544          inline bool empty() const
19545          {
19546             return symtab_list_.empty();
19547          }
19548 
clearexprtk::parser::symtab_store19549          inline void clear()
19550          {
19551             symtab_list_.clear();
19552          }
19553 
validexprtk::parser::symtab_store19554          inline bool valid() const
19555          {
19556             if (!empty())
19557             {
19558                for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19559                {
19560                   if (symtab_list_[i].valid())
19561                      return true;
19562                }
19563             }
19564 
19565             return false;
19566          }
19567 
valid_symbolexprtk::parser::symtab_store19568          inline bool valid_symbol(const std::string& symbol) const
19569          {
19570             if (!symtab_list_.empty())
19571                return symtab_list_[0].valid_symbol(symbol);
19572             else
19573                return false;
19574          }
19575 
valid_function_nameexprtk::parser::symtab_store19576          inline bool valid_function_name(const std::string& symbol) const
19577          {
19578             if (!symtab_list_.empty())
19579                return symtab_list_[0].valid_function(symbol);
19580             else
19581                return false;
19582          }
19583 
get_variableexprtk::parser::symtab_store19584          inline variable_ptr get_variable(const std::string& variable_name) const
19585          {
19586             if (!valid_symbol(variable_name))
19587                return reinterpret_cast<variable_ptr>(0);
19588 
19589             variable_ptr result = reinterpret_cast<variable_ptr>(0);
19590 
19591             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19592             {
19593                if (!symtab_list_[i].valid())
19594                   continue;
19595                else
19596                   result = local_data(i)
19597                               .variable_store.get(variable_name);
19598 
19599                if (result) break;
19600             }
19601 
19602             return result;
19603          }
19604 
get_variableexprtk::parser::symtab_store19605          inline variable_ptr get_variable(const T& var_ref) const
19606          {
19607             variable_ptr result = reinterpret_cast<variable_ptr>(0);
19608 
19609             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19610             {
19611                if (!symtab_list_[i].valid())
19612                   continue;
19613                else
19614                   result = local_data(i).variable_store
19615                               .get_from_varptr(reinterpret_cast<const void*>(&var_ref));
19616 
19617                if (result) break;
19618             }
19619 
19620             return result;
19621          }
19622 
19623          #ifndef exprtk_disable_string_capabilities
get_stringvarexprtk::parser::symtab_store19624          inline stringvar_ptr get_stringvar(const std::string& string_name) const
19625          {
19626             if (!valid_symbol(string_name))
19627                return reinterpret_cast<stringvar_ptr>(0);
19628 
19629             stringvar_ptr result = reinterpret_cast<stringvar_ptr>(0);
19630 
19631             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19632             {
19633                if (!symtab_list_[i].valid())
19634                   continue;
19635                else
19636                   result = local_data(i)
19637                               .stringvar_store.get(string_name);
19638 
19639                if (result) break;
19640             }
19641 
19642             return result;
19643          }
19644          #endif
19645 
get_functionexprtk::parser::symtab_store19646          inline function_ptr get_function(const std::string& function_name) const
19647          {
19648             if (!valid_function_name(function_name))
19649                return reinterpret_cast<function_ptr>(0);
19650 
19651             function_ptr result = reinterpret_cast<function_ptr>(0);
19652 
19653             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19654             {
19655                if (!symtab_list_[i].valid())
19656                   continue;
19657                else
19658                   result = local_data(i)
19659                               .function_store.get(function_name);
19660 
19661                if (result) break;
19662             }
19663 
19664             return result;
19665          }
19666 
get_vararg_functionexprtk::parser::symtab_store19667          inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const
19668          {
19669             if (!valid_function_name(vararg_function_name))
19670                return reinterpret_cast<vararg_function_ptr>(0);
19671 
19672             vararg_function_ptr result = reinterpret_cast<vararg_function_ptr>(0);
19673 
19674             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19675             {
19676                if (!symtab_list_[i].valid())
19677                   continue;
19678                else
19679                   result = local_data(i)
19680                               .vararg_function_store.get(vararg_function_name);
19681 
19682                if (result) break;
19683             }
19684 
19685             return result;
19686          }
19687 
get_generic_functionexprtk::parser::symtab_store19688          inline generic_function_ptr get_generic_function(const std::string& function_name) const
19689          {
19690             if (!valid_function_name(function_name))
19691                return reinterpret_cast<generic_function_ptr>(0);
19692 
19693             generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0);
19694 
19695             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19696             {
19697                if (!symtab_list_[i].valid())
19698                   continue;
19699                else
19700                   result = local_data(i)
19701                               .generic_function_store.get(function_name);
19702 
19703                if (result) break;
19704             }
19705 
19706             return result;
19707          }
19708 
get_string_functionexprtk::parser::symtab_store19709          inline generic_function_ptr get_string_function(const std::string& function_name) const
19710          {
19711             if (!valid_function_name(function_name))
19712                return reinterpret_cast<generic_function_ptr>(0);
19713 
19714             generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0);
19715 
19716             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19717             {
19718                if (!symtab_list_[i].valid())
19719                   continue;
19720                else
19721                   result =
19722                      local_data(i).string_function_store.get(function_name);
19723 
19724                if (result) break;
19725             }
19726 
19727             return result;
19728          }
19729 
get_overload_functionexprtk::parser::symtab_store19730          inline generic_function_ptr get_overload_function(const std::string& function_name) const
19731          {
19732             if (!valid_function_name(function_name))
19733                return reinterpret_cast<generic_function_ptr>(0);
19734 
19735             generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0);
19736 
19737             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19738             {
19739                if (!symtab_list_[i].valid())
19740                   continue;
19741                else
19742                   result =
19743                      local_data(i).overload_function_store.get(function_name);
19744 
19745                if (result) break;
19746             }
19747 
19748             return result;
19749          }
19750 
get_vectorexprtk::parser::symtab_store19751          inline vector_holder_ptr get_vector(const std::string& vector_name) const
19752          {
19753             if (!valid_symbol(vector_name))
19754                return reinterpret_cast<vector_holder_ptr>(0);
19755 
19756             vector_holder_ptr result = reinterpret_cast<vector_holder_ptr>(0);
19757 
19758             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19759             {
19760                if (!symtab_list_[i].valid())
19761                   continue;
19762                else
19763                   result =
19764                      local_data(i).vector_store.get(vector_name);
19765 
19766                if (result) break;
19767             }
19768 
19769             return result;
19770          }
19771 
is_constant_nodeexprtk::parser::symtab_store19772          inline bool is_constant_node(const std::string& symbol_name) const
19773          {
19774             if (!valid_symbol(symbol_name))
19775                return false;
19776 
19777             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19778             {
19779                if (!symtab_list_[i].valid())
19780                   continue;
19781                else if (local_data(i).variable_store.is_constant(symbol_name))
19782                   return true;
19783             }
19784 
19785             return false;
19786          }
19787 
19788          #ifndef exprtk_disable_string_capabilities
is_constant_stringexprtk::parser::symtab_store19789          inline bool is_constant_string(const std::string& symbol_name) const
19790          {
19791             if (!valid_symbol(symbol_name))
19792                return false;
19793 
19794             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19795             {
19796                if (!symtab_list_[i].valid())
19797                   continue;
19798                else if (!local_data(i).stringvar_store.symbol_exists(symbol_name))
19799                   continue;
19800                else if ( local_data(i).stringvar_store.is_constant(symbol_name))
19801                   return true;
19802             }
19803 
19804             return false;
19805          }
19806          #endif
19807 
symbol_existsexprtk::parser::symtab_store19808          inline bool symbol_exists(const std::string& symbol) const
19809          {
19810             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19811             {
19812                if (!symtab_list_[i].valid())
19813                   continue;
19814                else if (symtab_list_[i].symbol_exists(symbol))
19815                   return true;
19816             }
19817 
19818             return false;
19819          }
19820 
is_variableexprtk::parser::symtab_store19821          inline bool is_variable(const std::string& variable_name) const
19822          {
19823             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19824             {
19825                if (!symtab_list_[i].valid())
19826                   continue;
19827                else if (
19828                          symtab_list_[i].local_data().variable_store
19829                            .symbol_exists(variable_name)
19830                        )
19831                   return true;
19832             }
19833 
19834             return false;
19835          }
19836 
19837          #ifndef exprtk_disable_string_capabilities
is_stringvarexprtk::parser::symtab_store19838          inline bool is_stringvar(const std::string& stringvar_name) const
19839          {
19840             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19841             {
19842                if (!symtab_list_[i].valid())
19843                   continue;
19844                else if (
19845                          symtab_list_[i].local_data().stringvar_store
19846                            .symbol_exists(stringvar_name)
19847                        )
19848                   return true;
19849             }
19850 
19851             return false;
19852          }
19853 
is_conststr_stringvarexprtk::parser::symtab_store19854          inline bool is_conststr_stringvar(const std::string& symbol_name) const
19855          {
19856             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19857             {
19858                if (!symtab_list_[i].valid())
19859                   continue;
19860                else if (
19861                          symtab_list_[i].local_data().stringvar_store
19862                            .symbol_exists(symbol_name)
19863                        )
19864                {
19865                   return (
19866                            local_data(i).stringvar_store.symbol_exists(symbol_name) ||
19867                            local_data(i).stringvar_store.is_constant  (symbol_name)
19868                          );
19869 
19870                }
19871             }
19872 
19873             return false;
19874          }
19875          #endif
19876 
is_functionexprtk::parser::symtab_store19877          inline bool is_function(const std::string& function_name) const
19878          {
19879             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19880             {
19881                if (!symtab_list_[i].valid())
19882                   continue;
19883                else if (
19884                          local_data(i).vararg_function_store
19885                            .symbol_exists(function_name)
19886                        )
19887                   return true;
19888             }
19889 
19890             return false;
19891          }
19892 
is_vararg_functionexprtk::parser::symtab_store19893          inline bool is_vararg_function(const std::string& vararg_function_name) const
19894          {
19895             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19896             {
19897                if (!symtab_list_[i].valid())
19898                   continue;
19899                else if (
19900                          local_data(i).vararg_function_store
19901                            .symbol_exists(vararg_function_name)
19902                        )
19903                   return true;
19904             }
19905 
19906             return false;
19907          }
19908 
is_vectorexprtk::parser::symtab_store19909          inline bool is_vector(const std::string& vector_name) const
19910          {
19911             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19912             {
19913                if (!symtab_list_[i].valid())
19914                   continue;
19915                else if (
19916                          local_data(i).vector_store
19917                            .symbol_exists(vector_name)
19918                        )
19919                   return true;
19920             }
19921 
19922             return false;
19923          }
19924 
get_variable_nameexprtk::parser::symtab_store19925          inline std::string get_variable_name(const expression_node_ptr& ptr) const
19926          {
19927             return local_data().variable_store.entity_name(ptr);
19928          }
19929 
get_vector_nameexprtk::parser::symtab_store19930          inline std::string get_vector_name(const vector_holder_ptr& ptr) const
19931          {
19932             return local_data().vector_store.entity_name(ptr);
19933          }
19934 
19935          #ifndef exprtk_disable_string_capabilities
get_stringvar_nameexprtk::parser::symtab_store19936          inline std::string get_stringvar_name(const expression_node_ptr& ptr) const
19937          {
19938             return local_data().stringvar_store.entity_name(ptr);
19939          }
19940 
get_conststr_stringvar_nameexprtk::parser::symtab_store19941          inline std::string get_conststr_stringvar_name(const expression_node_ptr& ptr) const
19942          {
19943             return local_data().stringvar_store.entity_name(ptr);
19944          }
19945          #endif
19946 
local_dataexprtk::parser::symtab_store19947          inline local_data_t& local_data(const std::size_t& index = 0)
19948          {
19949             return symtab_list_[index].local_data();
19950          }
19951 
local_dataexprtk::parser::symtab_store19952          inline const local_data_t& local_data(const std::size_t& index = 0) const
19953          {
19954             return symtab_list_[index].local_data();
19955          }
19956 
get_symbol_tableexprtk::parser::symtab_store19957          inline symbol_table_t& get_symbol_table(const std::size_t& index = 0)
19958          {
19959             return symtab_list_[index];
19960          }
19961       };
19962 
19963       struct parser_state
19964       {
parser_stateexprtk::parser::parser_state19965          parser_state()
19966          : type_check_enabled(true)
19967          {
19968             reset();
19969          }
19970 
resetexprtk::parser::parser_state19971          void reset()
19972          {
19973             parsing_return_stmt     = false;
19974             parsing_break_stmt      = false;
19975             return_stmt_present     = false;
19976             side_effect_present     = false;
19977             scope_depth             = 0;
19978             stack_depth             = 0;
19979             parsing_loop_stmt_count = 0;
19980          }
19981 
19982          #ifndef exprtk_enable_debugging
activate_side_effectexprtk::parser::parser_state19983          void activate_side_effect(const std::string&)
19984          #else
19985          void activate_side_effect(const std::string& source)
19986          #endif
19987          {
19988             if (!side_effect_present)
19989             {
19990                side_effect_present = true;
19991 
19992                exprtk_debug(("activate_side_effect() - caller: %s\n",source.c_str()));
19993             }
19994          }
19995 
19996          bool parsing_return_stmt;
19997          bool parsing_break_stmt;
19998          bool return_stmt_present;
19999          bool side_effect_present;
20000          bool type_check_enabled;
20001          std::size_t scope_depth;
20002          std::size_t stack_depth;
20003          std::size_t parsing_loop_stmt_count;
20004       };
20005 
20006    public:
20007 
20008       struct unknown_symbol_resolver
20009       {
20010 
20011          enum usr_symbol_type
20012          {
20013             e_usr_unknown_type  = 0,
20014             e_usr_variable_type = 1,
20015             e_usr_constant_type = 2
20016          };
20017 
20018          enum usr_mode
20019          {
20020             e_usrmode_default  = 0,
20021             e_usrmode_extended = 1
20022          };
20023 
20024          usr_mode mode;
20025 
unknown_symbol_resolverexprtk::parser::unknown_symbol_resolver20026          unknown_symbol_resolver(const usr_mode m = e_usrmode_default)
20027          : mode(m)
20028          {}
20029 
~unknown_symbol_resolverexprtk::parser::unknown_symbol_resolver20030          virtual ~unknown_symbol_resolver()
20031          {}
20032 
processexprtk::parser::unknown_symbol_resolver20033          virtual bool process(const std::string& /*unknown_symbol*/,
20034                               usr_symbol_type&   st,
20035                               T&                 default_value,
20036                               std::string&       error_message)
20037          {
20038             if (e_usrmode_default != mode)
20039                return false;
20040 
20041             st = e_usr_variable_type;
20042             default_value = T(0);
20043             error_message.clear();
20044 
20045             return true;
20046          }
20047 
processexprtk::parser::unknown_symbol_resolver20048          virtual bool process(const std::string& /* unknown_symbol */,
20049                               symbol_table_t&    /* symbol_table   */,
20050                               std::string&       /* error_message  */)
20051          {
20052             return false;
20053          }
20054       };
20055 
20056       enum collect_type
20057       {
20058          e_ct_none        = 0,
20059          e_ct_variables   = 1,
20060          e_ct_functions   = 2,
20061          e_ct_assignments = 4
20062       };
20063 
20064       enum symbol_type
20065       {
20066          e_st_unknown        = 0,
20067          e_st_variable       = 1,
20068          e_st_vector         = 2,
20069          e_st_vecelem        = 3,
20070          e_st_string         = 4,
20071          e_st_function       = 5,
20072          e_st_local_variable = 6,
20073          e_st_local_vector   = 7,
20074          e_st_local_string   = 8
20075       };
20076 
20077       class dependent_entity_collector
20078       {
20079       public:
20080 
20081          typedef std::pair<std::string,symbol_type> symbol_t;
20082          typedef std::vector<symbol_t> symbol_list_t;
20083 
dependent_entity_collector(const std::size_t options=e_ct_none)20084          dependent_entity_collector(const std::size_t options = e_ct_none)
20085          : options_(options),
20086            collect_variables_  ((options_ & e_ct_variables  ) == e_ct_variables  ),
20087            collect_functions_  ((options_ & e_ct_functions  ) == e_ct_functions  ),
20088            collect_assignments_((options_ & e_ct_assignments) == e_ct_assignments),
20089            return_present_   (false),
20090            final_stmt_return_(false)
20091          {}
20092 
20093          template <typename Allocator,
20094                    template <typename, typename> class Sequence>
symbols(Sequence<symbol_t,Allocator> & symbols_list)20095          inline std::size_t symbols(Sequence<symbol_t,Allocator>& symbols_list)
20096          {
20097             if (!collect_variables_ && !collect_functions_)
20098                return 0;
20099             else if (symbol_name_list_.empty())
20100                return 0;
20101 
20102             for (std::size_t i = 0; i < symbol_name_list_.size(); ++i)
20103             {
20104                details::case_normalise(symbol_name_list_[i].first);
20105             }
20106 
20107             std::sort(symbol_name_list_.begin(),symbol_name_list_.end());
20108 
20109             std::unique_copy(symbol_name_list_.begin(),
20110                              symbol_name_list_.end  (),
20111                              std::back_inserter(symbols_list));
20112 
20113             return symbols_list.size();
20114          }
20115 
20116          template <typename Allocator,
20117                    template <typename, typename> class Sequence>
assignment_symbols(Sequence<symbol_t,Allocator> & assignment_list)20118          inline std::size_t assignment_symbols(Sequence<symbol_t,Allocator>& assignment_list)
20119          {
20120             if (!collect_assignments_)
20121                return 0;
20122             else if (assignment_name_list_.empty())
20123                return 0;
20124 
20125             for (std::size_t i = 0; i < assignment_name_list_.size(); ++i)
20126             {
20127                details::case_normalise(assignment_name_list_[i].first);
20128             }
20129 
20130             std::sort(assignment_name_list_.begin(),assignment_name_list_.end());
20131 
20132             std::unique_copy(assignment_name_list_.begin(),
20133                              assignment_name_list_.end  (),
20134                              std::back_inserter(assignment_list));
20135 
20136             return assignment_list.size();
20137          }
20138 
clear()20139          void clear()
20140          {
20141             symbol_name_list_    .clear();
20142             assignment_name_list_.clear();
20143             retparam_list_       .clear();
20144             return_present_    = false;
20145             final_stmt_return_ = false;
20146          }
20147 
collect_variables()20148          bool& collect_variables()
20149          {
20150             return collect_variables_;
20151          }
20152 
collect_functions()20153          bool& collect_functions()
20154          {
20155             return collect_functions_;
20156          }
20157 
collect_assignments()20158          bool& collect_assignments()
20159          {
20160             return collect_assignments_;
20161          }
20162 
return_present() const20163          bool return_present() const
20164          {
20165             return return_present_;
20166          }
20167 
final_stmt_return() const20168          bool final_stmt_return() const
20169          {
20170             return final_stmt_return_;
20171          }
20172 
20173          typedef std::vector<std::string> retparam_list_t;
20174 
return_param_type_list() const20175          retparam_list_t return_param_type_list() const
20176          {
20177             return retparam_list_;
20178          }
20179 
20180       private:
20181 
add_symbol(const std::string & symbol,const symbol_type st)20182          inline void add_symbol(const std::string& symbol, const symbol_type st)
20183          {
20184             switch (st)
20185             {
20186                case e_st_variable       :
20187                case e_st_vector         :
20188                case e_st_string         :
20189                case e_st_local_variable :
20190                case e_st_local_vector   :
20191                case e_st_local_string   : if (collect_variables_)
20192                                              symbol_name_list_
20193                                                 .push_back(std::make_pair(symbol, st));
20194                                           break;
20195 
20196                case e_st_function       : if (collect_functions_)
20197                                              symbol_name_list_
20198                                                 .push_back(std::make_pair(symbol, st));
20199                                           break;
20200 
20201                default                  : return;
20202             }
20203          }
20204 
add_assignment(const std::string & symbol,const symbol_type st)20205          inline void add_assignment(const std::string& symbol, const symbol_type st)
20206          {
20207             switch (st)
20208             {
20209                case e_st_variable       :
20210                case e_st_vector         :
20211                case e_st_string         : if (collect_assignments_)
20212                                              assignment_name_list_
20213                                                 .push_back(std::make_pair(symbol, st));
20214                                           break;
20215 
20216                default                  : return;
20217             }
20218          }
20219 
20220          std::size_t options_;
20221          bool collect_variables_;
20222          bool collect_functions_;
20223          bool collect_assignments_;
20224          bool return_present_;
20225          bool final_stmt_return_;
20226          symbol_list_t symbol_name_list_;
20227          symbol_list_t assignment_name_list_;
20228          retparam_list_t retparam_list_;
20229 
20230          friend class parser<T>;
20231       };
20232 
20233       class settings_store
20234       {
20235       private:
20236 
20237          typedef std::set<std::string,details::ilesscompare> disabled_entity_set_t;
20238          typedef disabled_entity_set_t::iterator des_itr_t;
20239 
20240       public:
20241 
20242          enum settings_compilation_options
20243          {
20244             e_unknown              =    0,
20245             e_replacer             =    1,
20246             e_joiner               =    2,
20247             e_numeric_check        =    4,
20248             e_bracket_check        =    8,
20249             e_sequence_check       =   16,
20250             e_commutative_check    =   32,
20251             e_strength_reduction   =   64,
20252             e_disable_vardef       =  128,
20253             e_collect_vars         =  256,
20254             e_collect_funcs        =  512,
20255             e_collect_assings      = 1024,
20256             e_disable_usr_on_rsrvd = 2048,
20257             e_disable_zero_return  = 4096
20258          };
20259 
20260          enum settings_base_funcs
20261          {
20262             e_bf_unknown = 0,
20263             e_bf_abs       , e_bf_acos     , e_bf_acosh    , e_bf_asin   ,
20264             e_bf_asinh     , e_bf_atan     , e_bf_atan2    , e_bf_atanh  ,
20265             e_bf_avg       , e_bf_ceil     , e_bf_clamp    , e_bf_cos    ,
20266             e_bf_cosh      , e_bf_cot      , e_bf_csc      , e_bf_equal  ,
20267             e_bf_erf       , e_bf_erfc     , e_bf_exp      , e_bf_expm1  ,
20268             e_bf_floor     , e_bf_frac     , e_bf_hypot    , e_bf_iclamp ,
20269             e_bf_like      , e_bf_log      , e_bf_log10    , e_bf_log1p  ,
20270             e_bf_log2      , e_bf_logn     , e_bf_mand     , e_bf_max    ,
20271             e_bf_min       , e_bf_mod      , e_bf_mor      , e_bf_mul    ,
20272             e_bf_ncdf      , e_bf_pow      , e_bf_root     , e_bf_round  ,
20273             e_bf_roundn    , e_bf_sec      , e_bf_sgn      , e_bf_sin    ,
20274             e_bf_sinc      , e_bf_sinh     , e_bf_sqrt     , e_bf_sum    ,
20275             e_bf_swap      , e_bf_tan      , e_bf_tanh     , e_bf_trunc  ,
20276             e_bf_not_equal , e_bf_inrange  , e_bf_deg2grad , e_bf_deg2rad,
20277             e_bf_rad2deg   , e_bf_grad2deg
20278          };
20279 
20280          enum settings_control_structs
20281          {
20282             e_ctrl_unknown = 0,
20283             e_ctrl_ifelse,
20284             e_ctrl_switch,
20285             e_ctrl_for_loop,
20286             e_ctrl_while_loop,
20287             e_ctrl_repeat_loop,
20288             e_ctrl_return
20289          };
20290 
20291          enum settings_logic_opr
20292          {
20293             e_logic_unknown = 0,
20294             e_logic_and, e_logic_nand,  e_logic_nor,
20295             e_logic_not, e_logic_or,    e_logic_xnor,
20296             e_logic_xor, e_logic_scand, e_logic_scor
20297          };
20298 
20299          enum settings_arithmetic_opr
20300          {
20301             e_arith_unknown = 0,
20302             e_arith_add, e_arith_sub, e_arith_mul,
20303             e_arith_div, e_arith_mod, e_arith_pow
20304          };
20305 
20306          enum settings_assignment_opr
20307          {
20308             e_assign_unknown = 0,
20309             e_assign_assign, e_assign_addass, e_assign_subass,
20310             e_assign_mulass, e_assign_divass, e_assign_modass
20311          };
20312 
20313          enum settings_inequality_opr
20314          {
20315             e_ineq_unknown = 0,
20316             e_ineq_lt,    e_ineq_lte, e_ineq_eq,
20317             e_ineq_equal, e_ineq_ne,  e_ineq_nequal,
20318             e_ineq_gte,   e_ineq_gt
20319          };
20320 
20321          static const std::size_t compile_all_opts = e_replacer          +
20322                                                      e_joiner            +
20323                                                      e_numeric_check     +
20324                                                      e_bracket_check     +
20325                                                      e_sequence_check    +
20326                                                      e_commutative_check +
20327                                                      e_strength_reduction;
20328 
settings_store(const std::size_t compile_options=compile_all_opts)20329          settings_store(const std::size_t compile_options = compile_all_opts)
20330          : max_stack_depth_(400),
20331            max_node_depth_(10000)
20332          {
20333            load_compile_options(compile_options);
20334          }
20335 
enable_all_base_functions()20336          settings_store& enable_all_base_functions()
20337          {
20338             disabled_func_set_.clear();
20339             return (*this);
20340          }
20341 
enable_all_control_structures()20342          settings_store& enable_all_control_structures()
20343          {
20344             disabled_ctrl_set_.clear();
20345             return (*this);
20346          }
20347 
enable_all_logic_ops()20348          settings_store& enable_all_logic_ops()
20349          {
20350             disabled_logic_set_.clear();
20351             return (*this);
20352          }
20353 
enable_all_arithmetic_ops()20354          settings_store& enable_all_arithmetic_ops()
20355          {
20356             disabled_arithmetic_set_.clear();
20357             return (*this);
20358          }
20359 
enable_all_assignment_ops()20360          settings_store& enable_all_assignment_ops()
20361          {
20362             disabled_assignment_set_.clear();
20363             return (*this);
20364          }
20365 
enable_all_inequality_ops()20366          settings_store& enable_all_inequality_ops()
20367          {
20368             disabled_inequality_set_.clear();
20369             return (*this);
20370          }
20371 
enable_local_vardef()20372          settings_store& enable_local_vardef()
20373          {
20374             disable_vardef_ = false;
20375             return (*this);
20376          }
20377 
disable_all_base_functions()20378          settings_store& disable_all_base_functions()
20379          {
20380             std::copy(details::base_function_list,
20381                       details::base_function_list + details::base_function_list_size,
20382                       std::insert_iterator<disabled_entity_set_t>
20383                         (disabled_func_set_, disabled_func_set_.begin()));
20384             return (*this);
20385          }
20386 
disable_all_control_structures()20387          settings_store& disable_all_control_structures()
20388          {
20389             std::copy(details::cntrl_struct_list,
20390                       details::cntrl_struct_list + details::cntrl_struct_list_size,
20391                       std::insert_iterator<disabled_entity_set_t>
20392                         (disabled_ctrl_set_, disabled_ctrl_set_.begin()));
20393             return (*this);
20394          }
20395 
disable_all_logic_ops()20396          settings_store& disable_all_logic_ops()
20397          {
20398             std::copy(details::logic_ops_list,
20399                       details::logic_ops_list + details::logic_ops_list_size,
20400                       std::insert_iterator<disabled_entity_set_t>
20401                         (disabled_logic_set_, disabled_logic_set_.begin()));
20402             return (*this);
20403          }
20404 
disable_all_arithmetic_ops()20405          settings_store& disable_all_arithmetic_ops()
20406          {
20407             std::copy(details::arithmetic_ops_list,
20408                       details::arithmetic_ops_list + details::arithmetic_ops_list_size,
20409                       std::insert_iterator<disabled_entity_set_t>
20410                         (disabled_arithmetic_set_, disabled_arithmetic_set_.begin()));
20411             return (*this);
20412          }
20413 
disable_all_assignment_ops()20414          settings_store& disable_all_assignment_ops()
20415          {
20416             std::copy(details::assignment_ops_list,
20417                       details::assignment_ops_list + details::assignment_ops_list_size,
20418                       std::insert_iterator<disabled_entity_set_t>
20419                         (disabled_assignment_set_, disabled_assignment_set_.begin()));
20420             return (*this);
20421          }
20422 
disable_all_inequality_ops()20423          settings_store& disable_all_inequality_ops()
20424          {
20425             std::copy(details::inequality_ops_list,
20426                       details::inequality_ops_list + details::inequality_ops_list_size,
20427                       std::insert_iterator<disabled_entity_set_t>
20428                         (disabled_inequality_set_, disabled_inequality_set_.begin()));
20429             return (*this);
20430          }
20431 
disable_local_vardef()20432          settings_store& disable_local_vardef()
20433          {
20434             disable_vardef_ = true;
20435             return (*this);
20436          }
20437 
replacer_enabled() const20438          bool replacer_enabled           () const { return enable_replacer_;           }
commutative_check_enabled() const20439          bool commutative_check_enabled  () const { return enable_commutative_check_;  }
joiner_enabled() const20440          bool joiner_enabled             () const { return enable_joiner_;             }
numeric_check_enabled() const20441          bool numeric_check_enabled      () const { return enable_numeric_check_;      }
bracket_check_enabled() const20442          bool bracket_check_enabled      () const { return enable_bracket_check_;      }
sequence_check_enabled() const20443          bool sequence_check_enabled     () const { return enable_sequence_check_;     }
strength_reduction_enabled() const20444          bool strength_reduction_enabled () const { return enable_strength_reduction_; }
collect_variables_enabled() const20445          bool collect_variables_enabled  () const { return enable_collect_vars_;       }
collect_functions_enabled() const20446          bool collect_functions_enabled  () const { return enable_collect_funcs_;      }
collect_assignments_enabled() const20447          bool collect_assignments_enabled() const { return enable_collect_assings_;    }
vardef_disabled() const20448          bool vardef_disabled            () const { return disable_vardef_;            }
rsrvd_sym_usr_disabled() const20449          bool rsrvd_sym_usr_disabled     () const { return disable_rsrvd_sym_usr_;     }
zero_return_disabled() const20450          bool zero_return_disabled       () const { return disable_zero_return_;       }
20451 
function_enabled(const std::string & function_name) const20452          bool function_enabled(const std::string& function_name) const
20453          {
20454             if (disabled_func_set_.empty())
20455                return true;
20456             else
20457                return (disabled_func_set_.end() == disabled_func_set_.find(function_name));
20458          }
20459 
control_struct_enabled(const std::string & control_struct) const20460          bool control_struct_enabled(const std::string& control_struct) const
20461          {
20462             if (disabled_ctrl_set_.empty())
20463                return true;
20464             else
20465                return (disabled_ctrl_set_.end() == disabled_ctrl_set_.find(control_struct));
20466          }
20467 
logic_enabled(const std::string & logic_operation) const20468          bool logic_enabled(const std::string& logic_operation) const
20469          {
20470             if (disabled_logic_set_.empty())
20471                return true;
20472             else
20473                return (disabled_logic_set_.end() == disabled_logic_set_.find(logic_operation));
20474          }
20475 
arithmetic_enabled(const details::operator_type & arithmetic_operation) const20476          bool arithmetic_enabled(const details::operator_type& arithmetic_operation) const
20477          {
20478             if (disabled_logic_set_.empty())
20479                return true;
20480             else
20481                return disabled_arithmetic_set_.end() == disabled_arithmetic_set_
20482                                                             .find(arith_opr_to_string(arithmetic_operation));
20483          }
20484 
assignment_enabled(const details::operator_type & assignment) const20485          bool assignment_enabled(const details::operator_type& assignment) const
20486          {
20487             if (disabled_assignment_set_.empty())
20488                return true;
20489             else
20490                return disabled_assignment_set_.end() == disabled_assignment_set_
20491                                                            .find(assign_opr_to_string(assignment));
20492          }
20493 
inequality_enabled(const details::operator_type & inequality) const20494          bool inequality_enabled(const details::operator_type& inequality) const
20495          {
20496             if (disabled_inequality_set_.empty())
20497                return true;
20498             else
20499                return disabled_inequality_set_.end() == disabled_inequality_set_
20500                                                            .find(inequality_opr_to_string(inequality));
20501          }
20502 
function_disabled(const std::string & function_name) const20503          bool function_disabled(const std::string& function_name) const
20504          {
20505             if (disabled_func_set_.empty())
20506                return false;
20507             else
20508                return (disabled_func_set_.end() != disabled_func_set_.find(function_name));
20509          }
20510 
control_struct_disabled(const std::string & control_struct) const20511          bool control_struct_disabled(const std::string& control_struct) const
20512          {
20513             if (disabled_ctrl_set_.empty())
20514                return false;
20515             else
20516                return (disabled_ctrl_set_.end() != disabled_ctrl_set_.find(control_struct));
20517          }
20518 
logic_disabled(const std::string & logic_operation) const20519          bool logic_disabled(const std::string& logic_operation) const
20520          {
20521             if (disabled_logic_set_.empty())
20522                return false;
20523             else
20524                return (disabled_logic_set_.end() != disabled_logic_set_.find(logic_operation));
20525          }
20526 
assignment_disabled(const details::operator_type assignment_operation) const20527          bool assignment_disabled(const details::operator_type assignment_operation) const
20528          {
20529             if (disabled_assignment_set_.empty())
20530                return false;
20531             else
20532                return disabled_assignment_set_.end() != disabled_assignment_set_
20533                                                            .find(assign_opr_to_string(assignment_operation));
20534          }
20535 
logic_disabled(const details::operator_type logic_operation) const20536          bool logic_disabled(const details::operator_type logic_operation) const
20537          {
20538             if (disabled_logic_set_.empty())
20539                return false;
20540             else
20541                return disabled_logic_set_.end() != disabled_logic_set_
20542                                                            .find(logic_opr_to_string(logic_operation));
20543          }
20544 
arithmetic_disabled(const details::operator_type arithmetic_operation) const20545          bool arithmetic_disabled(const details::operator_type arithmetic_operation) const
20546          {
20547             if (disabled_arithmetic_set_.empty())
20548                return false;
20549             else
20550                return disabled_arithmetic_set_.end() != disabled_arithmetic_set_
20551                                                            .find(arith_opr_to_string(arithmetic_operation));
20552          }
20553 
inequality_disabled(const details::operator_type & inequality) const20554          bool inequality_disabled(const details::operator_type& inequality) const
20555          {
20556             if (disabled_inequality_set_.empty())
20557                return false;
20558             else
20559                return disabled_inequality_set_.end() != disabled_inequality_set_
20560                                                            .find(inequality_opr_to_string(inequality));
20561          }
20562 
disable_base_function(settings_base_funcs bf)20563          settings_store& disable_base_function(settings_base_funcs bf)
20564          {
20565             if (
20566                  (e_bf_unknown != bf) &&
20567                  (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1))
20568                )
20569             {
20570                disabled_func_set_.insert(details::base_function_list[bf - 1]);
20571             }
20572 
20573             return (*this);
20574          }
20575 
disable_control_structure(settings_control_structs ctrl_struct)20576          settings_store& disable_control_structure(settings_control_structs ctrl_struct)
20577          {
20578             if (
20579                  (e_ctrl_unknown != ctrl_struct) &&
20580                  (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1))
20581                )
20582             {
20583                disabled_ctrl_set_.insert(details::cntrl_struct_list[ctrl_struct - 1]);
20584             }
20585 
20586             return (*this);
20587          }
20588 
disable_logic_operation(settings_logic_opr logic)20589          settings_store& disable_logic_operation(settings_logic_opr logic)
20590          {
20591             if (
20592                  (e_logic_unknown != logic) &&
20593                  (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1))
20594                )
20595             {
20596                disabled_logic_set_.insert(details::logic_ops_list[logic - 1]);
20597             }
20598 
20599             return (*this);
20600          }
20601 
disable_arithmetic_operation(settings_arithmetic_opr arithmetic)20602          settings_store& disable_arithmetic_operation(settings_arithmetic_opr arithmetic)
20603          {
20604             if (
20605                  (e_arith_unknown != arithmetic) &&
20606                  (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1))
20607                )
20608             {
20609                disabled_arithmetic_set_.insert(details::arithmetic_ops_list[arithmetic - 1]);
20610             }
20611 
20612             return (*this);
20613          }
20614 
disable_assignment_operation(settings_assignment_opr assignment)20615          settings_store& disable_assignment_operation(settings_assignment_opr assignment)
20616          {
20617             if (
20618                  (e_assign_unknown != assignment) &&
20619                  (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1))
20620                )
20621             {
20622                disabled_assignment_set_.insert(details::assignment_ops_list[assignment - 1]);
20623             }
20624 
20625             return (*this);
20626          }
20627 
disable_inequality_operation(settings_inequality_opr inequality)20628          settings_store& disable_inequality_operation(settings_inequality_opr inequality)
20629          {
20630             if (
20631                  (e_ineq_unknown != inequality) &&
20632                  (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1))
20633                )
20634             {
20635                disabled_inequality_set_.insert(details::inequality_ops_list[inequality - 1]);
20636             }
20637 
20638             return (*this);
20639          }
20640 
enable_base_function(settings_base_funcs bf)20641          settings_store& enable_base_function(settings_base_funcs bf)
20642          {
20643             if (
20644                  (e_bf_unknown != bf) &&
20645                  (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1))
20646                )
20647             {
20648                const des_itr_t itr = disabled_func_set_.find(details::base_function_list[bf - 1]);
20649 
20650                if (disabled_func_set_.end() != itr)
20651                {
20652                   disabled_func_set_.erase(itr);
20653                }
20654             }
20655 
20656             return (*this);
20657          }
20658 
enable_control_structure(settings_control_structs ctrl_struct)20659          settings_store& enable_control_structure(settings_control_structs ctrl_struct)
20660          {
20661             if (
20662                  (e_ctrl_unknown != ctrl_struct) &&
20663                  (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1))
20664                )
20665             {
20666                const des_itr_t itr = disabled_ctrl_set_.find(details::cntrl_struct_list[ctrl_struct - 1]);
20667 
20668                if (disabled_ctrl_set_.end() != itr)
20669                {
20670                   disabled_ctrl_set_.erase(itr);
20671                }
20672             }
20673 
20674             return (*this);
20675          }
20676 
enable_logic_operation(settings_logic_opr logic)20677          settings_store& enable_logic_operation(settings_logic_opr logic)
20678          {
20679             if (
20680                  (e_logic_unknown != logic) &&
20681                  (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1))
20682                )
20683             {
20684                const des_itr_t itr = disabled_logic_set_.find(details::logic_ops_list[logic - 1]);
20685 
20686                if (disabled_logic_set_.end() != itr)
20687                {
20688                   disabled_logic_set_.erase(itr);
20689                }
20690             }
20691 
20692             return (*this);
20693          }
20694 
enable_arithmetic_operation(settings_arithmetic_opr arithmetic)20695          settings_store& enable_arithmetic_operation(settings_arithmetic_opr arithmetic)
20696          {
20697             if (
20698                  (e_arith_unknown != arithmetic) &&
20699                  (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1))
20700                )
20701             {
20702                const des_itr_t itr = disabled_arithmetic_set_.find(details::arithmetic_ops_list[arithmetic - 1]);
20703 
20704                if (disabled_arithmetic_set_.end() != itr)
20705                {
20706                   disabled_arithmetic_set_.erase(itr);
20707                }
20708             }
20709 
20710             return (*this);
20711          }
20712 
enable_assignment_operation(settings_assignment_opr assignment)20713          settings_store& enable_assignment_operation(settings_assignment_opr assignment)
20714          {
20715             if (
20716                  (e_assign_unknown != assignment) &&
20717                  (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1))
20718                )
20719             {
20720                const des_itr_t itr = disabled_assignment_set_.find(details::assignment_ops_list[assignment - 1]);
20721 
20722                if (disabled_assignment_set_.end() != itr)
20723                {
20724                   disabled_assignment_set_.erase(itr);
20725                }
20726             }
20727 
20728             return (*this);
20729          }
20730 
enable_inequality_operation(settings_inequality_opr inequality)20731          settings_store& enable_inequality_operation(settings_inequality_opr inequality)
20732          {
20733             if (
20734                  (e_ineq_unknown != inequality) &&
20735                  (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1))
20736                )
20737             {
20738                const des_itr_t itr = disabled_inequality_set_.find(details::inequality_ops_list[inequality - 1]);
20739 
20740                if (disabled_inequality_set_.end() != itr)
20741                {
20742                   disabled_inequality_set_.erase(itr);
20743                }
20744             }
20745 
20746             return (*this);
20747          }
20748 
set_max_stack_depth(const std::size_t mx_stack_depth)20749          void set_max_stack_depth(const std::size_t mx_stack_depth)
20750          {
20751             max_stack_depth_ = mx_stack_depth;
20752          }
20753 
set_max_node_depth(const std::size_t max_node_depth)20754          void set_max_node_depth(const std::size_t max_node_depth)
20755          {
20756             max_node_depth_ = max_node_depth;
20757          }
20758 
20759       private:
20760 
load_compile_options(const std::size_t compile_options)20761          void load_compile_options(const std::size_t compile_options)
20762          {
20763             enable_replacer_           = (compile_options & e_replacer            ) == e_replacer;
20764             enable_joiner_             = (compile_options & e_joiner              ) == e_joiner;
20765             enable_numeric_check_      = (compile_options & e_numeric_check       ) == e_numeric_check;
20766             enable_bracket_check_      = (compile_options & e_bracket_check       ) == e_bracket_check;
20767             enable_sequence_check_     = (compile_options & e_sequence_check      ) == e_sequence_check;
20768             enable_commutative_check_  = (compile_options & e_commutative_check   ) == e_commutative_check;
20769             enable_strength_reduction_ = (compile_options & e_strength_reduction  ) == e_strength_reduction;
20770             enable_collect_vars_       = (compile_options & e_collect_vars        ) == e_collect_vars;
20771             enable_collect_funcs_      = (compile_options & e_collect_funcs       ) == e_collect_funcs;
20772             enable_collect_assings_    = (compile_options & e_collect_assings     ) == e_collect_assings;
20773             disable_vardef_            = (compile_options & e_disable_vardef      ) == e_disable_vardef;
20774             disable_rsrvd_sym_usr_     = (compile_options & e_disable_usr_on_rsrvd) == e_disable_usr_on_rsrvd;
20775             disable_zero_return_       = (compile_options & e_disable_zero_return ) == e_disable_zero_return;
20776          }
20777 
assign_opr_to_string(details::operator_type opr) const20778          std::string assign_opr_to_string(details::operator_type opr) const
20779          {
20780             switch (opr)
20781             {
20782                case details::e_assign : return ":=";
20783                case details::e_addass : return "+=";
20784                case details::e_subass : return "-=";
20785                case details::e_mulass : return "*=";
20786                case details::e_divass : return "/=";
20787                case details::e_modass : return "%=";
20788                default                : return   "";
20789             }
20790          }
20791 
arith_opr_to_string(details::operator_type opr) const20792          std::string arith_opr_to_string(details::operator_type opr) const
20793          {
20794             switch (opr)
20795             {
20796                case details::e_add : return "+";
20797                case details::e_sub : return "-";
20798                case details::e_mul : return "*";
20799                case details::e_div : return "/";
20800                case details::e_mod : return "%";
20801                default             : return  "";
20802             }
20803          }
20804 
inequality_opr_to_string(details::operator_type opr) const20805          std::string inequality_opr_to_string(details::operator_type opr) const
20806          {
20807             switch (opr)
20808             {
20809                case details::e_lt    : return  "<";
20810                case details::e_lte   : return "<=";
20811                case details::e_eq    : return "==";
20812                case details::e_equal : return  "=";
20813                case details::e_ne    : return "!=";
20814                case details::e_nequal: return "<>";
20815                case details::e_gte   : return ">=";
20816                case details::e_gt    : return  ">";
20817                default               : return   "";
20818             }
20819          }
20820 
logic_opr_to_string(details::operator_type opr) const20821          std::string logic_opr_to_string(details::operator_type opr) const
20822          {
20823             switch (opr)
20824             {
20825                case details::e_and  : return "and" ;
20826                case details::e_or   : return "or"  ;
20827                case details::e_xor  : return "xor" ;
20828                case details::e_nand : return "nand";
20829                case details::e_nor  : return "nor" ;
20830                case details::e_xnor : return "xnor";
20831                case details::e_notl : return "not" ;
20832                default              : return ""    ;
20833             }
20834          }
20835 
20836          bool enable_replacer_;
20837          bool enable_joiner_;
20838          bool enable_numeric_check_;
20839          bool enable_bracket_check_;
20840          bool enable_sequence_check_;
20841          bool enable_commutative_check_;
20842          bool enable_strength_reduction_;
20843          bool enable_collect_vars_;
20844          bool enable_collect_funcs_;
20845          bool enable_collect_assings_;
20846          bool disable_vardef_;
20847          bool disable_rsrvd_sym_usr_;
20848          bool disable_zero_return_;
20849 
20850          disabled_entity_set_t disabled_func_set_ ;
20851          disabled_entity_set_t disabled_ctrl_set_ ;
20852          disabled_entity_set_t disabled_logic_set_;
20853          disabled_entity_set_t disabled_arithmetic_set_;
20854          disabled_entity_set_t disabled_assignment_set_;
20855          disabled_entity_set_t disabled_inequality_set_;
20856 
20857          std::size_t max_stack_depth_;
20858          std::size_t max_node_depth_;
20859 
20860          friend class parser<T>;
20861       };
20862 
20863       typedef settings_store settings_t;
20864 
parser(const settings_t & settings=settings_t ())20865       parser(const settings_t& settings = settings_t())
20866       : settings_(settings),
20867         resolve_unknown_symbol_(false),
20868         results_context_(0),
20869         unknown_symbol_resolver_(reinterpret_cast<unknown_symbol_resolver*>(0)),
20870         #ifdef _MSC_VER
20871         #pragma warning(push)
20872         #pragma warning (disable:4355)
20873         #endif
20874         sem_(*this),
20875         #ifdef _MSC_VER
20876         #pragma warning(pop)
20877         #endif
20878         operator_joiner_2_(2),
20879         operator_joiner_3_(3),
20880         loop_runtime_check_(0)
20881       {
20882          init_precompilation();
20883 
20884          load_operations_map           (base_ops_map_     );
20885          load_unary_operations_map     (unary_op_map_     );
20886          load_binary_operations_map    (binary_op_map_    );
20887          load_inv_binary_operations_map(inv_binary_op_map_);
20888          load_sf3_map                  (sf3_map_          );
20889          load_sf4_map                  (sf4_map_          );
20890 
20891          expression_generator_.init_synthesize_map();
20892          expression_generator_.set_parser(*this);
20893          expression_generator_.set_uom(unary_op_map_);
20894          expression_generator_.set_bom(binary_op_map_);
20895          expression_generator_.set_ibom(inv_binary_op_map_);
20896          expression_generator_.set_sf3m(sf3_map_);
20897          expression_generator_.set_sf4m(sf4_map_);
20898          expression_generator_.set_strength_reduction_state(settings_.strength_reduction_enabled());
20899       }
20900 
~parser()20901      ~parser()
20902       {}
20903 
init_precompilation()20904       inline void init_precompilation()
20905       {
20906          if (settings_.collect_variables_enabled())
20907             dec_.collect_variables() = true;
20908 
20909          if (settings_.collect_functions_enabled())
20910             dec_.collect_functions() = true;
20911 
20912          if (settings_.collect_assignments_enabled())
20913             dec_.collect_assignments() = true;
20914 
20915          if (settings_.replacer_enabled())
20916          {
20917             symbol_replacer_.clear();
20918             symbol_replacer_.add_replace("true" , "1", lexer::token::e_number);
20919             symbol_replacer_.add_replace("false", "0", lexer::token::e_number);
20920             helper_assembly_.token_modifier_list.clear();
20921             helper_assembly_.register_modifier(&symbol_replacer_);
20922          }
20923 
20924          if (settings_.commutative_check_enabled())
20925          {
20926             for (std::size_t i = 0; i < details::reserved_words_size; ++i)
20927             {
20928                commutative_inserter_.ignore_symbol(details::reserved_words[i]);
20929             }
20930 
20931             helper_assembly_.token_inserter_list.clear();
20932             helper_assembly_.register_inserter(&commutative_inserter_);
20933          }
20934 
20935          if (settings_.joiner_enabled())
20936          {
20937             helper_assembly_.token_joiner_list.clear();
20938             helper_assembly_.register_joiner(&operator_joiner_2_);
20939             helper_assembly_.register_joiner(&operator_joiner_3_);
20940          }
20941 
20942          if (
20943               settings_.numeric_check_enabled () ||
20944               settings_.bracket_check_enabled () ||
20945               settings_.sequence_check_enabled()
20946             )
20947          {
20948             helper_assembly_.token_scanner_list.clear();
20949 
20950             if (settings_.numeric_check_enabled())
20951             {
20952                helper_assembly_.register_scanner(&numeric_checker_);
20953             }
20954 
20955             if (settings_.bracket_check_enabled())
20956             {
20957                helper_assembly_.register_scanner(&bracket_checker_);
20958             }
20959 
20960             if (settings_.sequence_check_enabled())
20961             {
20962                helper_assembly_.register_scanner(&sequence_validator_      );
20963                helper_assembly_.register_scanner(&sequence_validator_3tkns_);
20964             }
20965          }
20966       }
20967 
compile(const std::string & expression_string,expression<T> & expr)20968       inline bool compile(const std::string& expression_string, expression<T>& expr)
20969       {
20970          state_          .reset();
20971          error_list_     .clear();
20972          brkcnt_list_    .clear();
20973          synthesis_error_.clear();
20974          sem_            .cleanup();
20975 
20976          return_cleanup();
20977 
20978          expression_generator_.set_allocator(node_allocator_);
20979 
20980          if (expression_string.empty())
20981          {
20982             set_error(
20983                make_error(parser_error::e_syntax,
20984                           "ERR001 - Empty expression!",
20985                           exprtk_error_location));
20986 
20987             return false;
20988          }
20989 
20990          if (!init(expression_string))
20991          {
20992             process_lexer_errors();
20993             return false;
20994          }
20995 
20996          if (lexer().empty())
20997          {
20998             set_error(
20999                make_error(parser_error::e_syntax,
21000                           "ERR002 - Empty expression!",
21001                           exprtk_error_location));
21002 
21003             return false;
21004          }
21005 
21006          if (!run_assemblies())
21007          {
21008             return false;
21009          }
21010 
21011          symtab_store_.symtab_list_ = expr.get_symbol_table_list();
21012          dec_.clear();
21013 
21014          lexer().begin();
21015 
21016          next_token();
21017 
21018          expression_node_ptr e = parse_corpus();
21019 
21020          if ((0 != e) && (token_t::e_eof == current_token().type))
21021          {
21022             bool* retinvk_ptr = 0;
21023 
21024             if (state_.return_stmt_present)
21025             {
21026                dec_.return_present_ = true;
21027 
21028                e = expression_generator_
21029                      .return_envelope(e, results_context_, retinvk_ptr);
21030             }
21031 
21032             expr.set_expression(e);
21033             expr.set_retinvk(retinvk_ptr);
21034 
21035             register_local_vars(expr);
21036             register_return_results(expr);
21037 
21038             return !(!expr);
21039          }
21040          else
21041          {
21042             if (error_list_.empty())
21043             {
21044                set_error(
21045                   make_error(parser_error::e_syntax,
21046                              current_token(),
21047                              "ERR003 - Invalid expression encountered",
21048                              exprtk_error_location));
21049             }
21050 
21051             if ((0 != e) && branch_deletable(e))
21052             {
21053                destroy_node(e);
21054             }
21055 
21056             dec_.clear    ();
21057             sem_.cleanup  ();
21058             return_cleanup();
21059 
21060             return false;
21061          }
21062       }
21063 
compile(const std::string & expression_string,symbol_table_t & symtab)21064       inline expression_t compile(const std::string& expression_string, symbol_table_t& symtab)
21065       {
21066          expression_t expression;
21067 
21068          expression.register_symbol_table(symtab);
21069 
21070          compile(expression_string,expression);
21071 
21072          return expression;
21073       }
21074 
process_lexer_errors()21075       void process_lexer_errors()
21076       {
21077          for (std::size_t i = 0; i < lexer().size(); ++i)
21078          {
21079             if (lexer()[i].is_error())
21080             {
21081                std::string diagnostic = "ERR004 - ";
21082 
21083                switch (lexer()[i].type)
21084                {
21085                   case lexer::token::e_error      : diagnostic += "General token error";
21086                                                     break;
21087 
21088                   case lexer::token::e_err_symbol : diagnostic += "Symbol error";
21089                                                     break;
21090 
21091                   case lexer::token::e_err_number : diagnostic += "Invalid numeric token";
21092                                                     break;
21093 
21094                   case lexer::token::e_err_string : diagnostic += "Invalid string token";
21095                                                     break;
21096 
21097                   case lexer::token::e_err_sfunc  : diagnostic += "Invalid special function token";
21098                                                     break;
21099 
21100                   default                         : diagnostic += "Unknown compiler error";
21101                }
21102 
21103                set_error(
21104                   make_error(parser_error::e_lexer,
21105                              lexer()[i],
21106                              diagnostic + ": " + lexer()[i].value,
21107                              exprtk_error_location));
21108             }
21109          }
21110       }
21111 
run_assemblies()21112       inline bool run_assemblies()
21113       {
21114          if (settings_.commutative_check_enabled())
21115          {
21116             helper_assembly_.run_inserters(lexer());
21117          }
21118 
21119          if (settings_.joiner_enabled())
21120          {
21121             helper_assembly_.run_joiners(lexer());
21122          }
21123 
21124          if (settings_.replacer_enabled())
21125          {
21126             helper_assembly_.run_modifiers(lexer());
21127          }
21128 
21129          if (
21130               settings_.numeric_check_enabled () ||
21131               settings_.bracket_check_enabled () ||
21132               settings_.sequence_check_enabled()
21133             )
21134          {
21135             if (!helper_assembly_.run_scanners(lexer()))
21136             {
21137                if (helper_assembly_.error_token_scanner)
21138                {
21139                   lexer::helper::bracket_checker*            bracket_checker_ptr     = 0;
21140                   lexer::helper::numeric_checker*            numeric_checker_ptr     = 0;
21141                   lexer::helper::sequence_validator*         sequence_validator_ptr  = 0;
21142                   lexer::helper::sequence_validator_3tokens* sequence_validator3_ptr = 0;
21143 
21144                   if (0 != (bracket_checker_ptr = dynamic_cast<lexer::helper::bracket_checker*>(helper_assembly_.error_token_scanner)))
21145                   {
21146                      set_error(
21147                         make_error(parser_error::e_token,
21148                                    bracket_checker_ptr->error_token(),
21149                                    "ERR005 - Mismatched brackets: '" + bracket_checker_ptr->error_token().value + "'",
21150                                    exprtk_error_location));
21151                   }
21152                   else if (0 != (numeric_checker_ptr = dynamic_cast<lexer::helper::numeric_checker*>(helper_assembly_.error_token_scanner)))
21153                   {
21154                      for (std::size_t i = 0; i < numeric_checker_ptr->error_count(); ++i)
21155                      {
21156                         lexer::token error_token = lexer()[numeric_checker_ptr->error_index(i)];
21157 
21158                         set_error(
21159                            make_error(parser_error::e_token,
21160                                       error_token,
21161                                       "ERR006 - Invalid numeric token: '" + error_token.value + "'",
21162                                       exprtk_error_location));
21163                      }
21164 
21165                      if (numeric_checker_ptr->error_count())
21166                      {
21167                         numeric_checker_ptr->clear_errors();
21168                      }
21169                   }
21170                   else if (0 != (sequence_validator_ptr = dynamic_cast<lexer::helper::sequence_validator*>(helper_assembly_.error_token_scanner)))
21171                   {
21172                      for (std::size_t i = 0; i < sequence_validator_ptr->error_count(); ++i)
21173                      {
21174                         std::pair<lexer::token,lexer::token> error_token = sequence_validator_ptr->error(i);
21175 
21176                         set_error(
21177                            make_error(parser_error::e_token,
21178                                       error_token.first,
21179                                       "ERR007 - Invalid token sequence: '" +
21180                                       error_token.first.value  + "' and '" +
21181                                       error_token.second.value + "'",
21182                                       exprtk_error_location));
21183                      }
21184 
21185                      if (sequence_validator_ptr->error_count())
21186                      {
21187                         sequence_validator_ptr->clear_errors();
21188                      }
21189                   }
21190                   else if (0 != (sequence_validator3_ptr = dynamic_cast<lexer::helper::sequence_validator_3tokens*>(helper_assembly_.error_token_scanner)))
21191                   {
21192                      for (std::size_t i = 0; i < sequence_validator3_ptr->error_count(); ++i)
21193                      {
21194                         std::pair<lexer::token,lexer::token> error_token = sequence_validator3_ptr->error(i);
21195 
21196                         set_error(
21197                            make_error(parser_error::e_token,
21198                                       error_token.first,
21199                                       "ERR008 - Invalid token sequence: '" +
21200                                       error_token.first.value  + "' and '" +
21201                                       error_token.second.value + "'",
21202                                       exprtk_error_location));
21203                      }
21204 
21205                      if (sequence_validator3_ptr->error_count())
21206                      {
21207                         sequence_validator3_ptr->clear_errors();
21208                      }
21209                   }
21210                }
21211 
21212                return false;
21213             }
21214          }
21215 
21216          return true;
21217       }
21218 
settings()21219       inline settings_store& settings()
21220       {
21221          return settings_;
21222       }
21223 
get_error(const std::size_t & index) const21224       inline parser_error::type get_error(const std::size_t& index) const
21225       {
21226          if (index < error_list_.size())
21227             return error_list_[index];
21228          else
21229             throw std::invalid_argument("parser::get_error() - Invalid error index specificed");
21230       }
21231 
error() const21232       inline std::string error() const
21233       {
21234          if (!error_list_.empty())
21235          {
21236             return error_list_[0].diagnostic;
21237          }
21238          else
21239             return std::string("No Error");
21240       }
21241 
error_count() const21242       inline std::size_t error_count() const
21243       {
21244          return error_list_.size();
21245       }
21246 
dec()21247       inline dependent_entity_collector& dec()
21248       {
21249          return dec_;
21250       }
21251 
replace_symbol(const std::string & old_symbol,const std::string & new_symbol)21252       inline bool replace_symbol(const std::string& old_symbol, const std::string& new_symbol)
21253       {
21254          if (!settings_.replacer_enabled())
21255             return false;
21256          else if (details::is_reserved_word(old_symbol))
21257             return false;
21258          else
21259             return symbol_replacer_.add_replace(old_symbol,new_symbol,lexer::token::e_symbol);
21260       }
21261 
remove_replace_symbol(const std::string & symbol)21262       inline bool remove_replace_symbol(const std::string& symbol)
21263       {
21264          if (!settings_.replacer_enabled())
21265             return false;
21266          else if (details::is_reserved_word(symbol))
21267             return false;
21268          else
21269             return symbol_replacer_.remove(symbol);
21270       }
21271 
enable_unknown_symbol_resolver(unknown_symbol_resolver * usr=reinterpret_cast<unknown_symbol_resolver * > (0))21272       inline void enable_unknown_symbol_resolver(unknown_symbol_resolver* usr = reinterpret_cast<unknown_symbol_resolver*>(0))
21273       {
21274          resolve_unknown_symbol_ = true;
21275 
21276          if (usr)
21277             unknown_symbol_resolver_ = usr;
21278          else
21279             unknown_symbol_resolver_ = &default_usr_;
21280       }
21281 
enable_unknown_symbol_resolver(unknown_symbol_resolver & usr)21282       inline void enable_unknown_symbol_resolver(unknown_symbol_resolver& usr)
21283       {
21284          enable_unknown_symbol_resolver(&usr);
21285       }
21286 
disable_unknown_symbol_resolver()21287       inline void disable_unknown_symbol_resolver()
21288       {
21289          resolve_unknown_symbol_  = false;
21290          unknown_symbol_resolver_ = &default_usr_;
21291       }
21292 
register_loop_runtime_check(loop_runtime_check & lrtchk)21293       inline void register_loop_runtime_check(loop_runtime_check& lrtchk)
21294       {
21295          loop_runtime_check_ = &lrtchk;
21296       }
21297 
clear_loop_runtime_check()21298       inline void clear_loop_runtime_check()
21299       {
21300          loop_runtime_check_ = loop_runtime_check_ptr(0);
21301       }
21302 
21303    private:
21304 
valid_base_operation(const std::string & symbol) const21305       inline bool valid_base_operation(const std::string& symbol) const
21306       {
21307          const std::size_t length = symbol.size();
21308 
21309          if (
21310               (length < 3) || // Shortest base op symbol length
21311               (length > 9)    // Longest base op symbol length
21312             )
21313             return false;
21314          else
21315             return settings_.function_enabled(symbol) &&
21316                    (base_ops_map_.end() != base_ops_map_.find(symbol));
21317       }
21318 
valid_vararg_operation(const std::string & symbol) const21319       inline bool valid_vararg_operation(const std::string& symbol) const
21320       {
21321          static const std::string s_sum     = "sum" ;
21322          static const std::string s_mul     = "mul" ;
21323          static const std::string s_avg     = "avg" ;
21324          static const std::string s_min     = "min" ;
21325          static const std::string s_max     = "max" ;
21326          static const std::string s_mand    = "mand";
21327          static const std::string s_mor     = "mor" ;
21328          static const std::string s_multi   = "~"   ;
21329          static const std::string s_mswitch = "[*]" ;
21330 
21331          return
21332                (
21333                   details::imatch(symbol,s_sum    ) ||
21334                   details::imatch(symbol,s_mul    ) ||
21335                   details::imatch(symbol,s_avg    ) ||
21336                   details::imatch(symbol,s_min    ) ||
21337                   details::imatch(symbol,s_max    ) ||
21338                   details::imatch(symbol,s_mand   ) ||
21339                   details::imatch(symbol,s_mor    ) ||
21340                   details::imatch(symbol,s_multi  ) ||
21341                   details::imatch(symbol,s_mswitch)
21342                ) &&
21343                settings_.function_enabled(symbol);
21344       }
21345 
is_invalid_logic_operation(const details::operator_type operation) const21346       bool is_invalid_logic_operation(const details::operator_type operation) const
21347       {
21348          return settings_.logic_disabled(operation);
21349       }
21350 
is_invalid_arithmetic_operation(const details::operator_type operation) const21351       bool is_invalid_arithmetic_operation(const details::operator_type operation) const
21352       {
21353          return settings_.arithmetic_disabled(operation);
21354       }
21355 
is_invalid_assignment_operation(const details::operator_type operation) const21356       bool is_invalid_assignment_operation(const details::operator_type operation) const
21357       {
21358          return settings_.assignment_disabled(operation);
21359       }
21360 
is_invalid_inequality_operation(const details::operator_type operation) const21361       bool is_invalid_inequality_operation(const details::operator_type operation) const
21362       {
21363          return settings_.inequality_disabled(operation);
21364       }
21365 
21366       #ifdef exprtk_enable_debugging
next_token()21367       inline void next_token()
21368       {
21369          const std::string ct_str = current_token().value;
21370          const std::size_t ct_pos = current_token().position;
21371          parser_helper::next_token();
21372          const std::string depth(2 * state_.scope_depth,' ');
21373          exprtk_debug(("%s"
21374                        "prev[%s | %04d] --> curr[%s | %04d]  stack_level: %3d\n",
21375                        depth.c_str(),
21376                        ct_str.c_str(),
21377                        static_cast<unsigned int>(ct_pos),
21378                        current_token().value.c_str(),
21379                        static_cast<unsigned int>(current_token().position),
21380                        static_cast<unsigned int>(state_.stack_depth)));
21381       }
21382       #endif
21383 
parse_corpus()21384       inline expression_node_ptr parse_corpus()
21385       {
21386          std::vector<expression_node_ptr> arg_list;
21387          std::vector<bool> side_effect_list;
21388 
21389          scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
21390 
21391          lexer::token begin_token;
21392          lexer::token   end_token;
21393 
21394          for ( ; ; )
21395          {
21396             state_.side_effect_present = false;
21397 
21398             begin_token = current_token();
21399 
21400             expression_node_ptr arg = parse_expression();
21401 
21402             if (0 == arg)
21403             {
21404                if (error_list_.empty())
21405                {
21406                   set_error(
21407                      make_error(parser_error::e_syntax,
21408                                 current_token(),
21409                                 "ERR009 - Invalid expression encountered",
21410                                 exprtk_error_location));
21411                }
21412 
21413                return error_node();
21414             }
21415             else
21416             {
21417                arg_list.push_back(arg);
21418 
21419                side_effect_list.push_back(state_.side_effect_present);
21420 
21421                end_token = current_token();
21422 
21423                const std::string sub_expr = construct_subexpr(begin_token, end_token);
21424 
21425                exprtk_debug(("parse_corpus(%02d) Subexpr: %s\n",
21426                              static_cast<int>(arg_list.size() - 1),
21427                              sub_expr.c_str()));
21428 
21429                exprtk_debug(("parse_corpus(%02d) - Side effect present: %s\n",
21430                              static_cast<int>(arg_list.size() - 1),
21431                              state_.side_effect_present ? "true" : "false"));
21432 
21433                exprtk_debug(("-------------------------------------------------\n"));
21434             }
21435 
21436             if (lexer().finished())
21437                break;
21438             else if (token_is(token_t::e_eof,prsrhlpr_t::e_hold))
21439             {
21440                if (lexer().finished())
21441                   break;
21442                else
21443                   next_token();
21444             }
21445          }
21446 
21447          if (
21448               !arg_list.empty() &&
21449               is_return_node(arg_list.back())
21450             )
21451          {
21452             dec_.final_stmt_return_ = true;
21453          }
21454 
21455          const expression_node_ptr result = simplify(arg_list,side_effect_list);
21456 
21457          sdd.delete_ptr = (0 == result);
21458 
21459          return result;
21460       }
21461 
construct_subexpr(lexer::token & begin_token,lexer::token & end_token)21462       std::string construct_subexpr(lexer::token& begin_token, lexer::token& end_token)
21463       {
21464          std::string result = lexer().substr(begin_token.position,end_token.position);
21465 
21466          for (std::size_t i = 0; i < result.size(); ++i)
21467          {
21468             if (details::is_whitespace(result[i])) result[i] = ' ';
21469          }
21470 
21471          return result;
21472       }
21473 
21474       static const precedence_level default_precedence = e_level00;
21475 
21476       struct state_t
21477       {
setexprtk::parser::state_t21478          inline void set(const precedence_level& l,
21479                          const precedence_level& r,
21480                          const details::operator_type& o)
21481          {
21482             left  = l;
21483             right = r;
21484             operation = o;
21485          }
21486 
resetexprtk::parser::state_t21487          inline void reset()
21488          {
21489             left      = e_level00;
21490             right     = e_level00;
21491             operation = details::e_default;
21492          }
21493 
21494          precedence_level left;
21495          precedence_level right;
21496          details::operator_type operation;
21497       };
21498 
parse_expression(precedence_level precedence=e_level00)21499       inline expression_node_ptr parse_expression(precedence_level precedence = e_level00)
21500       {
21501          stack_limit_handler slh(*this);
21502 
21503          if (!slh)
21504          {
21505             return error_node();
21506          }
21507 
21508          expression_node_ptr expression = parse_branch(precedence);
21509 
21510          if (0 == expression)
21511          {
21512             return error_node();
21513          }
21514 
21515          bool break_loop = false;
21516 
21517          state_t current_state;
21518 
21519          for ( ; ; )
21520          {
21521             current_state.reset();
21522 
21523             switch (current_token().type)
21524             {
21525                case token_t::e_assign : current_state.set(e_level00,e_level00, details::e_assign); break;
21526                case token_t::e_addass : current_state.set(e_level00,e_level00, details::e_addass); break;
21527                case token_t::e_subass : current_state.set(e_level00,e_level00, details::e_subass); break;
21528                case token_t::e_mulass : current_state.set(e_level00,e_level00, details::e_mulass); break;
21529                case token_t::e_divass : current_state.set(e_level00,e_level00, details::e_divass); break;
21530                case token_t::e_modass : current_state.set(e_level00,e_level00, details::e_modass); break;
21531                case token_t::e_swap   : current_state.set(e_level00,e_level00, details::e_swap  ); break;
21532                case token_t::e_lt     : current_state.set(e_level05,e_level06, details::    e_lt); break;
21533                case token_t::e_lte    : current_state.set(e_level05,e_level06, details::   e_lte); break;
21534                case token_t::e_eq     : current_state.set(e_level05,e_level06, details::    e_eq); break;
21535                case token_t::e_ne     : current_state.set(e_level05,e_level06, details::    e_ne); break;
21536                case token_t::e_gte    : current_state.set(e_level05,e_level06, details::   e_gte); break;
21537                case token_t::e_gt     : current_state.set(e_level05,e_level06, details::    e_gt); break;
21538                case token_t::e_add    : current_state.set(e_level07,e_level08, details::   e_add); break;
21539                case token_t::e_sub    : current_state.set(e_level07,e_level08, details::   e_sub); break;
21540                case token_t::e_div    : current_state.set(e_level10,e_level11, details::   e_div); break;
21541                case token_t::e_mul    : current_state.set(e_level10,e_level11, details::   e_mul); break;
21542                case token_t::e_mod    : current_state.set(e_level10,e_level11, details::   e_mod); break;
21543                case token_t::e_pow    : current_state.set(e_level12,e_level12, details::   e_pow); break;
21544                default                : if (token_t::e_symbol == current_token().type)
21545                                         {
21546                                            static const std::string s_and   =   "and";
21547                                            static const std::string s_nand  =  "nand";
21548                                            static const std::string s_or    =    "or";
21549                                            static const std::string s_nor   =   "nor";
21550                                            static const std::string s_xor   =   "xor";
21551                                            static const std::string s_xnor  =  "xnor";
21552                                            static const std::string s_in    =    "in";
21553                                            static const std::string s_like  =  "like";
21554                                            static const std::string s_ilike = "ilike";
21555                                            static const std::string s_and1  =     "&";
21556                                            static const std::string s_or1   =     "|";
21557                                            static const std::string s_not   =   "not";
21558 
21559                                            if (details::imatch(current_token().value,s_and))
21560                                            {
21561                                               current_state.set(e_level03, e_level04, details::e_and);
21562                                               break;
21563                                            }
21564                                            else if (details::imatch(current_token().value,s_and1))
21565                                            {
21566                                               #ifndef exprtk_disable_sc_andor
21567                                               current_state.set(e_level03, e_level04, details::e_scand);
21568                                               #else
21569                                               current_state.set(e_level03, e_level04, details::e_and);
21570                                               #endif
21571                                               break;
21572                                            }
21573                                            else if (details::imatch(current_token().value,s_nand))
21574                                            {
21575                                               current_state.set(e_level03, e_level04, details::e_nand);
21576                                               break;
21577                                            }
21578                                            else if (details::imatch(current_token().value,s_or))
21579                                            {
21580                                               current_state.set(e_level01, e_level02, details::e_or);
21581                                               break;
21582                                            }
21583                                            else if (details::imatch(current_token().value,s_or1))
21584                                            {
21585                                               #ifndef exprtk_disable_sc_andor
21586                                               current_state.set(e_level01, e_level02, details::e_scor);
21587                                               #else
21588                                               current_state.set(e_level01, e_level02, details::e_or);
21589                                               #endif
21590                                               break;
21591                                            }
21592                                            else if (details::imatch(current_token().value,s_nor))
21593                                            {
21594                                               current_state.set(e_level01, e_level02, details::e_nor);
21595                                               break;
21596                                            }
21597                                            else if (details::imatch(current_token().value,s_xor))
21598                                            {
21599                                               current_state.set(e_level01, e_level02, details::e_xor);
21600                                               break;
21601                                            }
21602                                            else if (details::imatch(current_token().value,s_xnor))
21603                                            {
21604                                               current_state.set(e_level01, e_level02, details::e_xnor);
21605                                               break;
21606                                            }
21607                                            else if (details::imatch(current_token().value,s_in))
21608                                            {
21609                                               current_state.set(e_level04, e_level04, details::e_in);
21610                                               break;
21611                                            }
21612                                            else if (details::imatch(current_token().value,s_like))
21613                                            {
21614                                               current_state.set(e_level04, e_level04, details::e_like);
21615                                               break;
21616                                            }
21617                                            else if (details::imatch(current_token().value,s_ilike))
21618                                            {
21619                                               current_state.set(e_level04, e_level04, details::e_ilike);
21620                                               break;
21621                                            }
21622                                            else if (details::imatch(current_token().value,s_not))
21623                                            {
21624                                               break;
21625                                            }
21626                                         }
21627 
21628                                         break_loop = true;
21629             }
21630 
21631             if (break_loop)
21632             {
21633                parse_pending_string_rangesize(expression);
21634                break;
21635             }
21636             else if (current_state.left < precedence)
21637                break;
21638 
21639             const lexer::token prev_token = current_token();
21640 
21641             next_token();
21642 
21643             expression_node_ptr right_branch   = error_node();
21644             expression_node_ptr new_expression = error_node();
21645 
21646             if (is_invalid_logic_operation(current_state.operation))
21647             {
21648                free_node(node_allocator_,expression);
21649 
21650                set_error(
21651                   make_error(parser_error::e_syntax,
21652                              prev_token,
21653                              "ERR010 - Invalid or disabled logic operation '" + details::to_str(current_state.operation) + "'",
21654                              exprtk_error_location));
21655 
21656                return error_node();
21657             }
21658             else if (is_invalid_arithmetic_operation(current_state.operation))
21659             {
21660                free_node(node_allocator_,expression);
21661 
21662                set_error(
21663                   make_error(parser_error::e_syntax,
21664                              prev_token,
21665                              "ERR011 - Invalid or disabled arithmetic operation '" + details::to_str(current_state.operation) + "'",
21666                              exprtk_error_location));
21667 
21668                return error_node();
21669             }
21670             else if (is_invalid_inequality_operation(current_state.operation))
21671             {
21672                free_node(node_allocator_,expression);
21673 
21674                set_error(
21675                   make_error(parser_error::e_syntax,
21676                              prev_token,
21677                              "ERR012 - Invalid inequality operation '" + details::to_str(current_state.operation) + "'",
21678                              exprtk_error_location));
21679 
21680                return error_node();
21681             }
21682             else if (is_invalid_assignment_operation(current_state.operation))
21683             {
21684                free_node(node_allocator_,expression);
21685 
21686                set_error(
21687                   make_error(parser_error::e_syntax,
21688                              prev_token,
21689                              "ERR013 - Invalid or disabled assignment operation '" + details::to_str(current_state.operation) + "'",
21690                              exprtk_error_location));
21691 
21692                return error_node();
21693             }
21694 
21695             if (0 != (right_branch = parse_expression(current_state.right)))
21696             {
21697                if (
21698                     details::is_return_node(  expression) ||
21699                     details::is_return_node(right_branch)
21700                   )
21701                {
21702                   free_node(node_allocator_,   expression);
21703                   free_node(node_allocator_, right_branch);
21704 
21705                   set_error(
21706                      make_error(parser_error::e_syntax,
21707                                 prev_token,
21708                                 "ERR014 - Return statements cannot be part of sub-expressions",
21709                                 exprtk_error_location));
21710 
21711                   return error_node();
21712                }
21713 
21714                new_expression = expression_generator_
21715                                   (
21716                                     current_state.operation,
21717                                     expression,
21718                                     right_branch
21719                                   );
21720             }
21721 
21722             if (0 == new_expression)
21723             {
21724                if (error_list_.empty())
21725                {
21726                   set_error(
21727                      make_error(parser_error::e_syntax,
21728                                 prev_token,
21729                                 !synthesis_error_.empty() ?
21730                                 synthesis_error_ :
21731                                 "ERR015 - General parsing error at token: '" + prev_token.value + "'",
21732                                 exprtk_error_location));
21733                }
21734 
21735                free_node(node_allocator_,   expression);
21736                free_node(node_allocator_, right_branch);
21737 
21738                return error_node();
21739             }
21740             else
21741             {
21742                if (
21743                     token_is(token_t::e_ternary,prsrhlpr_t::e_hold) &&
21744                     (precedence == e_level00)
21745                   )
21746                {
21747                   expression = parse_ternary_conditional_statement(new_expression);
21748                }
21749                else
21750                   expression = new_expression;
21751 
21752                parse_pending_string_rangesize(expression);
21753             }
21754          }
21755 
21756          if ((0 != expression) && (expression->node_depth() > settings_.max_node_depth_))
21757          {
21758             set_error(
21759                make_error(parser_error::e_syntax,
21760                   current_token(),
21761                   "ERR016 - Expression depth of " + details::to_str(static_cast<int>(expression->node_depth())) +
21762                   " exceeds maximum allowed expression depth of " + details::to_str(static_cast<int>(settings_.max_node_depth_)),
21763                   exprtk_error_location));
21764 
21765             free_node(node_allocator_,expression);
21766 
21767             return error_node();
21768          }
21769 
21770          return expression;
21771       }
21772 
simplify_unary_negation_branch(expression_node_ptr & node)21773       bool simplify_unary_negation_branch(expression_node_ptr& node)
21774       {
21775          {
21776             typedef details::unary_branch_node<T,details::neg_op<T> > ubn_t;
21777             ubn_t* n = dynamic_cast<ubn_t*>(node);
21778 
21779             if (n)
21780             {
21781                expression_node_ptr un_r = n->branch(0);
21782                n->release();
21783                free_node(node_allocator_,node);
21784                node = un_r;
21785 
21786                return true;
21787             }
21788          }
21789 
21790          {
21791             typedef details::unary_variable_node<T,details::neg_op<T> > uvn_t;
21792 
21793             uvn_t* n = dynamic_cast<uvn_t*>(node);
21794 
21795             if (n)
21796             {
21797                const T& v = n->v();
21798                expression_node_ptr return_node = error_node();
21799 
21800                if (
21801                     (0 != (return_node = symtab_store_.get_variable(v))) ||
21802                     (0 != (return_node = sem_         .get_variable(v)))
21803                   )
21804                {
21805                   free_node(node_allocator_,node);
21806                   node = return_node;
21807 
21808                   return true;
21809                }
21810                else
21811                {
21812                   set_error(
21813                      make_error(parser_error::e_syntax,
21814                                 current_token(),
21815                                 "ERR017 - Failed to find variable node in symbol table",
21816                                 exprtk_error_location));
21817 
21818                   free_node(node_allocator_,node);
21819 
21820                   return false;
21821                }
21822             }
21823          }
21824 
21825          return false;
21826       }
21827 
error_node()21828       static inline expression_node_ptr error_node()
21829       {
21830          return reinterpret_cast<expression_node_ptr>(0);
21831       }
21832 
21833       struct scoped_expression_delete
21834       {
scoped_expression_deleteexprtk::parser::scoped_expression_delete21835          scoped_expression_delete(parser<T>& pr, expression_node_ptr& expression)
21836          : delete_ptr(true),
21837            parser_(pr),
21838            expression_(expression)
21839          {}
21840 
~scoped_expression_deleteexprtk::parser::scoped_expression_delete21841         ~scoped_expression_delete()
21842          {
21843             if (delete_ptr)
21844             {
21845                free_node(parser_.node_allocator_, expression_);
21846             }
21847          }
21848 
21849          bool delete_ptr;
21850          parser<T>& parser_;
21851          expression_node_ptr& expression_;
21852 
21853       private:
21854 
21855          scoped_expression_delete& operator=(const scoped_expression_delete&);
21856       };
21857 
21858       template <typename Type, std::size_t N>
21859       struct scoped_delete
21860       {
21861          typedef Type* ptr_t;
21862 
scoped_deleteexprtk::parser::scoped_delete21863          scoped_delete(parser<T>& pr, ptr_t& p)
21864          : delete_ptr(true),
21865            parser_(pr),
21866            p_(&p)
21867          {}
21868 
scoped_deleteexprtk::parser::scoped_delete21869          scoped_delete(parser<T>& pr, ptr_t (&p)[N])
21870          : delete_ptr(true),
21871            parser_(pr),
21872            p_(&p[0])
21873          {}
21874 
~scoped_deleteexprtk::parser::scoped_delete21875         ~scoped_delete()
21876          {
21877             if (delete_ptr)
21878             {
21879                for (std::size_t i = 0; i < N; ++i)
21880                {
21881                   free_node(parser_.node_allocator_, p_[i]);
21882                }
21883             }
21884          }
21885 
21886          bool delete_ptr;
21887          parser<T>& parser_;
21888          ptr_t* p_;
21889 
21890       private:
21891 
21892          scoped_delete<Type,N>& operator=(const scoped_delete<Type,N>&);
21893       };
21894 
21895       template <typename Type>
21896       struct scoped_deq_delete
21897       {
21898          typedef Type* ptr_t;
21899 
scoped_deq_deleteexprtk::parser::scoped_deq_delete21900          scoped_deq_delete(parser<T>& pr, std::deque<ptr_t>& deq)
21901          : delete_ptr(true),
21902            parser_(pr),
21903            deq_(deq)
21904          {}
21905 
~scoped_deq_deleteexprtk::parser::scoped_deq_delete21906         ~scoped_deq_delete()
21907          {
21908             if (delete_ptr && !deq_.empty())
21909             {
21910                for (std::size_t i = 0; i < deq_.size(); ++i)
21911                {
21912                   free_node(parser_.node_allocator_,deq_[i]);
21913                }
21914 
21915                deq_.clear();
21916             }
21917          }
21918 
21919          bool delete_ptr;
21920          parser<T>& parser_;
21921          std::deque<ptr_t>& deq_;
21922 
21923       private:
21924 
21925          scoped_deq_delete<Type>& operator=(const scoped_deq_delete<Type>&);
21926       };
21927 
21928       template <typename Type>
21929       struct scoped_vec_delete
21930       {
21931          typedef Type* ptr_t;
21932 
scoped_vec_deleteexprtk::parser::scoped_vec_delete21933          scoped_vec_delete(parser<T>& pr, std::vector<ptr_t>& vec)
21934          : delete_ptr(true),
21935            parser_(pr),
21936            vec_(vec)
21937          {}
21938 
~scoped_vec_deleteexprtk::parser::scoped_vec_delete21939         ~scoped_vec_delete()
21940          {
21941             if (delete_ptr && !vec_.empty())
21942             {
21943                for (std::size_t i = 0; i < vec_.size(); ++i)
21944                {
21945                   free_node(parser_.node_allocator_,vec_[i]);
21946                }
21947 
21948                vec_.clear();
21949             }
21950          }
21951 
21952          bool delete_ptr;
21953          parser<T>& parser_;
21954          std::vector<ptr_t>& vec_;
21955 
21956       private:
21957 
21958          scoped_vec_delete<Type>& operator=(const scoped_vec_delete<Type>&);
21959       };
21960 
21961       struct scoped_bool_negator
21962       {
scoped_bool_negatorexprtk::parser::scoped_bool_negator21963          explicit scoped_bool_negator(bool& bb)
21964          : b(bb)
21965          { b = !b; }
21966 
~scoped_bool_negatorexprtk::parser::scoped_bool_negator21967         ~scoped_bool_negator()
21968          { b = !b; }
21969 
21970          bool& b;
21971       };
21972 
21973       struct scoped_bool_or_restorer
21974       {
scoped_bool_or_restorerexprtk::parser::scoped_bool_or_restorer21975          explicit scoped_bool_or_restorer(bool& bb)
21976          : b(bb),
21977            original_value_(bb)
21978          {}
21979 
~scoped_bool_or_restorerexprtk::parser::scoped_bool_or_restorer21980         ~scoped_bool_or_restorer()
21981          {
21982             b = b || original_value_;
21983          }
21984 
21985          bool& b;
21986          bool original_value_;
21987       };
21988 
21989       struct scoped_inc_dec
21990       {
scoped_inc_decexprtk::parser::scoped_inc_dec21991          explicit scoped_inc_dec(std::size_t& v)
21992          : v_(v)
21993          { ++v_; }
21994 
~scoped_inc_decexprtk::parser::scoped_inc_dec21995         ~scoped_inc_dec()
21996          {
21997            assert(v_ > 0);
21998            --v_;
21999          }
22000 
22001          std::size_t& v_;
22002       };
22003 
parse_function_invocation(ifunction<T> * function,const std::string & function_name)22004       inline expression_node_ptr parse_function_invocation(ifunction<T>* function, const std::string& function_name)
22005       {
22006          expression_node_ptr func_node = reinterpret_cast<expression_node_ptr>(0);
22007 
22008          switch (function->param_count)
22009          {
22010             case  0 : func_node = parse_function_call_0  (function,function_name); break;
22011             case  1 : func_node = parse_function_call< 1>(function,function_name); break;
22012             case  2 : func_node = parse_function_call< 2>(function,function_name); break;
22013             case  3 : func_node = parse_function_call< 3>(function,function_name); break;
22014             case  4 : func_node = parse_function_call< 4>(function,function_name); break;
22015             case  5 : func_node = parse_function_call< 5>(function,function_name); break;
22016             case  6 : func_node = parse_function_call< 6>(function,function_name); break;
22017             case  7 : func_node = parse_function_call< 7>(function,function_name); break;
22018             case  8 : func_node = parse_function_call< 8>(function,function_name); break;
22019             case  9 : func_node = parse_function_call< 9>(function,function_name); break;
22020             case 10 : func_node = parse_function_call<10>(function,function_name); break;
22021             case 11 : func_node = parse_function_call<11>(function,function_name); break;
22022             case 12 : func_node = parse_function_call<12>(function,function_name); break;
22023             case 13 : func_node = parse_function_call<13>(function,function_name); break;
22024             case 14 : func_node = parse_function_call<14>(function,function_name); break;
22025             case 15 : func_node = parse_function_call<15>(function,function_name); break;
22026             case 16 : func_node = parse_function_call<16>(function,function_name); break;
22027             case 17 : func_node = parse_function_call<17>(function,function_name); break;
22028             case 18 : func_node = parse_function_call<18>(function,function_name); break;
22029             case 19 : func_node = parse_function_call<19>(function,function_name); break;
22030             case 20 : func_node = parse_function_call<20>(function,function_name); break;
22031             default : {
22032                          set_error(
22033                             make_error(parser_error::e_syntax,
22034                                        current_token(),
22035                                        "ERR018 - Invalid number of parameters for function: '" + function_name + "'",
22036                                        exprtk_error_location));
22037 
22038                          return error_node();
22039                       }
22040          }
22041 
22042          if (func_node)
22043             return func_node;
22044          else
22045          {
22046             set_error(
22047                make_error(parser_error::e_syntax,
22048                           current_token(),
22049                           "ERR019 - Failed to generate call to function: '" + function_name + "'",
22050                           exprtk_error_location));
22051 
22052             return error_node();
22053          }
22054       }
22055 
22056       template <std::size_t NumberofParameters>
parse_function_call(ifunction<T> * function,const std::string & function_name)22057       inline expression_node_ptr parse_function_call(ifunction<T>* function, const std::string& function_name)
22058       {
22059          #ifdef _MSC_VER
22060             #pragma warning(push)
22061             #pragma warning(disable: 4127)
22062          #endif
22063          if (0 == NumberofParameters)
22064          {
22065             set_error(
22066                make_error(parser_error::e_syntax,
22067                           current_token(),
22068                           "ERR020 - Expecting ifunction '" + function_name + "' to have non-zero parameter count",
22069                           exprtk_error_location));
22070 
22071             return error_node();
22072          }
22073          #ifdef _MSC_VER
22074             #pragma warning(pop)
22075          #endif
22076 
22077          expression_node_ptr branch[NumberofParameters];
22078          expression_node_ptr result  = error_node();
22079 
22080          std::fill_n(branch, NumberofParameters, reinterpret_cast<expression_node_ptr>(0));
22081 
22082          scoped_delete<expression_node_t,NumberofParameters> sd((*this),branch);
22083 
22084          next_token();
22085 
22086          if (!token_is(token_t::e_lbracket))
22087          {
22088             set_error(
22089                make_error(parser_error::e_syntax,
22090                           current_token(),
22091                           "ERR021 - Expecting argument list for function: '" + function_name + "'",
22092                           exprtk_error_location));
22093 
22094             return error_node();
22095          }
22096 
22097          for (int i = 0; i < static_cast<int>(NumberofParameters); ++i)
22098          {
22099             branch[i] = parse_expression();
22100 
22101             if (0 == branch[i])
22102             {
22103                set_error(
22104                   make_error(parser_error::e_syntax,
22105                              current_token(),
22106                              "ERR022 - Failed to parse argument " + details::to_str(i) + " for function: '" + function_name + "'",
22107                              exprtk_error_location));
22108 
22109                return error_node();
22110             }
22111             else if (i < static_cast<int>(NumberofParameters - 1))
22112             {
22113                if (!token_is(token_t::e_comma))
22114                {
22115                   set_error(
22116                      make_error(parser_error::e_syntax,
22117                                 current_token(),
22118                                 "ERR023 - Invalid number of arguments for function: '" + function_name + "'",
22119                                 exprtk_error_location));
22120 
22121                   return error_node();
22122                }
22123             }
22124          }
22125 
22126          if (!token_is(token_t::e_rbracket))
22127          {
22128             set_error(
22129                make_error(parser_error::e_syntax,
22130                           current_token(),
22131                           "ERR024 - Invalid number of arguments for function: '" + function_name + "'",
22132                           exprtk_error_location));
22133 
22134             return error_node();
22135          }
22136          else
22137             result = expression_generator_.function(function,branch);
22138 
22139          sd.delete_ptr = (0 == result);
22140 
22141          return result;
22142       }
22143 
parse_function_call_0(ifunction<T> * function,const std::string & function_name)22144       inline expression_node_ptr parse_function_call_0(ifunction<T>* function, const std::string& function_name)
22145       {
22146          expression_node_ptr result = expression_generator_.function(function);
22147 
22148          state_.side_effect_present = function->has_side_effects();
22149 
22150          next_token();
22151 
22152          if (
22153                token_is(token_t::e_lbracket) &&
22154               !token_is(token_t::e_rbracket)
22155             )
22156          {
22157             set_error(
22158                make_error(parser_error::e_syntax,
22159                           current_token(),
22160                           "ERR025 - Expecting '()' to proceed call to function: '" + function_name + "'",
22161                           exprtk_error_location));
22162 
22163             free_node(node_allocator_,result);
22164 
22165             return error_node();
22166          }
22167          else
22168             return result;
22169       }
22170 
22171       template <std::size_t MaxNumberofParameters>
parse_base_function_call(expression_node_ptr (& param_list)[MaxNumberofParameters],const std::string & function_name="")22172       inline std::size_t parse_base_function_call(expression_node_ptr (&param_list)[MaxNumberofParameters], const std::string& function_name = "")
22173       {
22174          std::fill_n(param_list, MaxNumberofParameters, reinterpret_cast<expression_node_ptr>(0));
22175 
22176          scoped_delete<expression_node_t,MaxNumberofParameters> sd((*this),param_list);
22177 
22178          next_token();
22179 
22180          if (!token_is(token_t::e_lbracket))
22181          {
22182             set_error(
22183                make_error(parser_error::e_syntax,
22184                           current_token(),
22185                           "ERR026 - Expected a '(' at start of function call to '" + function_name  +
22186                           "', instead got: '" + current_token().value + "'",
22187                           exprtk_error_location));
22188 
22189             return 0;
22190          }
22191 
22192          if (token_is(token_t::e_rbracket, e_hold))
22193          {
22194             set_error(
22195                make_error(parser_error::e_syntax,
22196                           current_token(),
22197                           "ERR027 - Expected at least one input parameter for function call '" + function_name + "'",
22198                           exprtk_error_location));
22199 
22200             return 0;
22201          }
22202 
22203          std::size_t param_index = 0;
22204 
22205          for (; param_index < MaxNumberofParameters; ++param_index)
22206          {
22207             param_list[param_index] = parse_expression();
22208 
22209             if (0 == param_list[param_index])
22210                return 0;
22211             else if (token_is(token_t::e_rbracket))
22212             {
22213                sd.delete_ptr = false;
22214                break;
22215             }
22216             else if (token_is(token_t::e_comma))
22217                continue;
22218             else
22219             {
22220                set_error(
22221                   make_error(parser_error::e_syntax,
22222                              current_token(),
22223                              "ERR028 - Expected a ',' between function input parameters, instead got: '" + current_token().value + "'",
22224                              exprtk_error_location));
22225 
22226                return 0;
22227             }
22228          }
22229 
22230          if (sd.delete_ptr)
22231          {
22232             set_error(
22233                make_error(parser_error::e_syntax,
22234                           current_token(),
22235                           "ERR029 - Invalid number of input parameters passed to function '" + function_name  + "'",
22236                           exprtk_error_location));
22237 
22238             return 0;
22239          }
22240 
22241          return (param_index + 1);
22242       }
22243 
parse_base_operation()22244       inline expression_node_ptr parse_base_operation()
22245       {
22246          typedef std::pair<base_ops_map_t::iterator,base_ops_map_t::iterator> map_range_t;
22247 
22248          const std::string operation_name   = current_token().value;
22249          const token_t     diagnostic_token = current_token();
22250 
22251          map_range_t itr_range = base_ops_map_.equal_range(operation_name);
22252 
22253          if (0 == std::distance(itr_range.first,itr_range.second))
22254          {
22255             set_error(
22256                make_error(parser_error::e_syntax,
22257                           diagnostic_token,
22258                           "ERR030 - No entry found for base operation: " + operation_name,
22259                           exprtk_error_location));
22260 
22261             return error_node();
22262          }
22263 
22264          static const std::size_t MaxNumberofParameters = 4;
22265          expression_node_ptr param_list[MaxNumberofParameters] = {0};
22266 
22267          const std::size_t parameter_count = parse_base_function_call(param_list, operation_name);
22268 
22269          if ((parameter_count > 0) && (parameter_count <= MaxNumberofParameters))
22270          {
22271             for (base_ops_map_t::iterator itr = itr_range.first; itr != itr_range.second; ++itr)
22272             {
22273                const details::base_operation_t& operation = itr->second;
22274 
22275                if (operation.num_params == parameter_count)
22276                {
22277                   switch (parameter_count)
22278                   {
22279                      #define base_opr_case(N)                                         \
22280                      case N : {                                                       \
22281                                  expression_node_ptr pl##N[N] = {0};                  \
22282                                  std::copy(param_list, param_list + N, pl##N);        \
22283                                  lodge_symbol(operation_name, e_st_function);         \
22284                                  return expression_generator_(operation.type, pl##N); \
22285                               }                                                       \
22286 
22287                      base_opr_case(1)
22288                      base_opr_case(2)
22289                      base_opr_case(3)
22290                      base_opr_case(4)
22291                      #undef base_opr_case
22292                   }
22293                }
22294             }
22295          }
22296 
22297          for (std::size_t i = 0; i < MaxNumberofParameters; ++i)
22298          {
22299             free_node(node_allocator_, param_list[i]);
22300          }
22301 
22302          set_error(
22303             make_error(parser_error::e_syntax,
22304                        diagnostic_token,
22305                        "ERR031 - Invalid number of input parameters for call to function: '" + operation_name + "'",
22306                        exprtk_error_location));
22307 
22308          return error_node();
22309       }
22310 
parse_conditional_statement_01(expression_node_ptr condition)22311       inline expression_node_ptr parse_conditional_statement_01(expression_node_ptr condition)
22312       {
22313          // Parse: [if][(][condition][,][consequent][,][alternative][)]
22314 
22315          expression_node_ptr consequent  = error_node();
22316          expression_node_ptr alternative = error_node();
22317 
22318          bool result = true;
22319 
22320          if (!token_is(token_t::e_comma))
22321          {
22322             set_error(
22323                make_error(parser_error::e_syntax,
22324                           current_token(),
22325                           "ERR032 - Expected ',' between if-statement condition and consequent",
22326                           exprtk_error_location));
22327             result = false;
22328          }
22329          else if (0 == (consequent = parse_expression()))
22330          {
22331             set_error(
22332                make_error(parser_error::e_syntax,
22333                           current_token(),
22334                           "ERR033 - Failed to parse consequent for if-statement",
22335                           exprtk_error_location));
22336             result = false;
22337          }
22338          else if (!token_is(token_t::e_comma))
22339          {
22340             set_error(
22341                make_error(parser_error::e_syntax,
22342                           current_token(),
22343                           "ERR034 - Expected ',' between if-statement consequent and alternative",
22344                           exprtk_error_location));
22345             result = false;
22346          }
22347          else if (0 == (alternative = parse_expression()))
22348          {
22349             set_error(
22350                make_error(parser_error::e_syntax,
22351                           current_token(),
22352                           "ERR035 - Failed to parse alternative for if-statement",
22353                           exprtk_error_location));
22354             result = false;
22355          }
22356          else if (!token_is(token_t::e_rbracket))
22357          {
22358             set_error(
22359                make_error(parser_error::e_syntax,
22360                           current_token(),
22361                           "ERR036 - Expected ')' at the end of if-statement",
22362                           exprtk_error_location));
22363             result = false;
22364          }
22365 
22366          #ifndef exprtk_disable_string_capabilities
22367          if (result)
22368          {
22369             const bool consq_is_str = is_generally_string_node( consequent);
22370             const bool alter_is_str = is_generally_string_node(alternative);
22371 
22372             if (consq_is_str || alter_is_str)
22373             {
22374                if (consq_is_str && alter_is_str)
22375                {
22376                   return expression_generator_
22377                            .conditional_string(condition, consequent, alternative);
22378                }
22379 
22380                set_error(
22381                   make_error(parser_error::e_syntax,
22382                              current_token(),
22383                              "ERR037 - Return types of ternary if-statement differ",
22384                              exprtk_error_location));
22385 
22386                result = false;
22387             }
22388          }
22389          #endif
22390 
22391          if (!result)
22392          {
22393             free_node(node_allocator_, condition  );
22394             free_node(node_allocator_, consequent );
22395             free_node(node_allocator_, alternative);
22396 
22397             return error_node();
22398          }
22399          else
22400             return expression_generator_
22401                       .conditional(condition, consequent, alternative);
22402       }
22403 
parse_conditional_statement_02(expression_node_ptr condition)22404       inline expression_node_ptr parse_conditional_statement_02(expression_node_ptr condition)
22405       {
22406          expression_node_ptr consequent  = error_node();
22407          expression_node_ptr alternative = error_node();
22408 
22409          bool result = true;
22410 
22411          if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
22412          {
22413             if (0 == (consequent = parse_multi_sequence("if-statement-01")))
22414             {
22415                set_error(
22416                   make_error(parser_error::e_syntax,
22417                              current_token(),
22418                              "ERR038 - Failed to parse body of consequent for if-statement",
22419                              exprtk_error_location));
22420 
22421                result = false;
22422             }
22423          }
22424          else
22425          {
22426             if (
22427                  settings_.commutative_check_enabled() &&
22428                  token_is(token_t::e_mul,prsrhlpr_t::e_hold)
22429                )
22430             {
22431                next_token();
22432             }
22433 
22434             if (0 != (consequent = parse_expression()))
22435             {
22436                if (!token_is(token_t::e_eof))
22437                {
22438                   set_error(
22439                      make_error(parser_error::e_syntax,
22440                                 current_token(),
22441                                 "ERR039 - Expected ';' at the end of the consequent for if-statement",
22442                                 exprtk_error_location));
22443 
22444                   result = false;
22445                }
22446             }
22447             else
22448             {
22449                set_error(
22450                   make_error(parser_error::e_syntax,
22451                              current_token(),
22452                              "ERR040 - Failed to parse body of consequent for if-statement",
22453                              exprtk_error_location));
22454 
22455                result = false;
22456             }
22457          }
22458 
22459          if (result)
22460          {
22461             if (details::imatch(current_token().value,"else"))
22462             {
22463                next_token();
22464 
22465                if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
22466                {
22467                   if (0 == (alternative = parse_multi_sequence("else-statement-01")))
22468                   {
22469                      set_error(
22470                         make_error(parser_error::e_syntax,
22471                                    current_token(),
22472                                    "ERR041 - Failed to parse body of the 'else' for if-statement",
22473                                    exprtk_error_location));
22474 
22475                      result = false;
22476                   }
22477                }
22478                else if (details::imatch(current_token().value,"if"))
22479                {
22480                   if (0 == (alternative = parse_conditional_statement()))
22481                   {
22482                      set_error(
22483                         make_error(parser_error::e_syntax,
22484                                    current_token(),
22485                                    "ERR042 - Failed to parse body of if-else statement",
22486                                    exprtk_error_location));
22487 
22488                      result = false;
22489                   }
22490                }
22491                else if (0 != (alternative = parse_expression()))
22492                {
22493                   if (!token_is(token_t::e_eof))
22494                   {
22495                      set_error(
22496                         make_error(parser_error::e_syntax,
22497                                    current_token(),
22498                                    "ERR043 - Expected ';' at the end of the 'else-if' for the if-statement",
22499                                    exprtk_error_location));
22500 
22501                      result = false;
22502                   }
22503                }
22504                else
22505                {
22506                   set_error(
22507                      make_error(parser_error::e_syntax,
22508                                 current_token(),
22509                                 "ERR044 - Failed to parse body of the 'else' for if-statement",
22510                                 exprtk_error_location));
22511 
22512                   result = false;
22513                }
22514             }
22515          }
22516 
22517          #ifndef exprtk_disable_string_capabilities
22518          if (result)
22519          {
22520             const bool consq_is_str = is_generally_string_node( consequent);
22521             const bool alter_is_str = is_generally_string_node(alternative);
22522 
22523             if (consq_is_str || alter_is_str)
22524             {
22525                if (consq_is_str && alter_is_str)
22526                {
22527                   return expression_generator_
22528                            .conditional_string(condition, consequent, alternative);
22529                }
22530 
22531                set_error(
22532                   make_error(parser_error::e_syntax,
22533                              current_token(),
22534                              "ERR045 - Return types of ternary if-statement differ",
22535                              exprtk_error_location));
22536 
22537                result = false;
22538             }
22539          }
22540          #endif
22541 
22542          if (!result)
22543          {
22544             free_node(node_allocator_,   condition);
22545             free_node(node_allocator_,  consequent);
22546             free_node(node_allocator_, alternative);
22547 
22548             return error_node();
22549          }
22550          else
22551             return expression_generator_
22552                       .conditional(condition, consequent, alternative);
22553       }
22554 
parse_conditional_statement()22555       inline expression_node_ptr parse_conditional_statement()
22556       {
22557          expression_node_ptr condition = error_node();
22558 
22559          next_token();
22560 
22561          if (!token_is(token_t::e_lbracket))
22562          {
22563             set_error(
22564                make_error(parser_error::e_syntax,
22565                           current_token(),
22566                           "ERR046 - Expected '(' at start of if-statement, instead got: '" + current_token().value + "'",
22567                           exprtk_error_location));
22568 
22569             return error_node();
22570          }
22571          else if (0 == (condition = parse_expression()))
22572          {
22573             set_error(
22574                make_error(parser_error::e_syntax,
22575                           current_token(),
22576                           "ERR047 - Failed to parse condition for if-statement",
22577                           exprtk_error_location));
22578 
22579             return error_node();
22580          }
22581          else if (token_is(token_t::e_comma,prsrhlpr_t::e_hold))
22582          {
22583             // if (x,y,z)
22584             return parse_conditional_statement_01(condition);
22585          }
22586          else if (token_is(token_t::e_rbracket))
22587          {
22588             // 00. if (x) y;
22589             // 01. if (x) y; else z;
22590             // 02. if (x) y; else {z0; ... zn;}
22591             // 03. if (x) y; else if (z) w;
22592             // 04. if (x) y; else if (z) w; else u;
22593             // 05. if (x) y; else if (z) w; else {u0; ... un;}
22594             // 06. if (x) y; else if (z) {w0; ... wn;}
22595             // 07. if (x) {y0; ... yn;}
22596             // 08. if (x) {y0; ... yn;} else z;
22597             // 09. if (x) {y0; ... yn;} else {z0; ... zn;};
22598             // 10. if (x) {y0; ... yn;} else if (z) w;
22599             // 11. if (x) {y0; ... yn;} else if (z) w; else u;
22600             // 12. if (x) {y0; ... nex;} else if (z) w; else {u0 ... un;}
22601             // 13. if (x) {y0; ... yn;} else if (z) {w0; ... wn;}
22602             return parse_conditional_statement_02(condition);
22603          }
22604 
22605          set_error(
22606             make_error(parser_error::e_syntax,
22607                        current_token(),
22608                        "ERR048 - Invalid if-statement",
22609                        exprtk_error_location));
22610 
22611          free_node(node_allocator_,condition);
22612 
22613          return error_node();
22614       }
22615 
parse_ternary_conditional_statement(expression_node_ptr condition)22616       inline expression_node_ptr parse_ternary_conditional_statement(expression_node_ptr condition)
22617       {
22618          // Parse: [condition][?][consequent][:][alternative]
22619          expression_node_ptr consequent  = error_node();
22620          expression_node_ptr alternative = error_node();
22621 
22622          bool result = true;
22623 
22624          if (0 == condition)
22625          {
22626             set_error(
22627                make_error(parser_error::e_syntax,
22628                           current_token(),
22629                           "ERR049 - Encountered invalid condition branch for ternary if-statement",
22630                           exprtk_error_location));
22631 
22632             return error_node();
22633          }
22634          else if (!token_is(token_t::e_ternary))
22635          {
22636             set_error(
22637                make_error(parser_error::e_syntax,
22638                           current_token(),
22639                           "ERR050 - Expected '?' after condition of ternary if-statement",
22640                           exprtk_error_location));
22641 
22642             result = false;
22643          }
22644          else if (0 == (consequent = parse_expression()))
22645          {
22646             set_error(
22647                make_error(parser_error::e_syntax,
22648                           current_token(),
22649                           "ERR051 - Failed to parse consequent for ternary if-statement",
22650                           exprtk_error_location));
22651 
22652             result = false;
22653          }
22654          else if (!token_is(token_t::e_colon))
22655          {
22656             set_error(
22657                make_error(parser_error::e_syntax,
22658                           current_token(),
22659                           "ERR052 - Expected ':' between ternary if-statement consequent and alternative",
22660                           exprtk_error_location));
22661 
22662             result = false;
22663          }
22664          else if (0 == (alternative = parse_expression()))
22665          {
22666             set_error(
22667                make_error(parser_error::e_syntax,
22668                           current_token(),
22669                           "ERR053 - Failed to parse alternative for ternary if-statement",
22670                           exprtk_error_location));
22671 
22672             result = false;
22673          }
22674 
22675          #ifndef exprtk_disable_string_capabilities
22676          if (result)
22677          {
22678             const bool consq_is_str = is_generally_string_node( consequent);
22679             const bool alter_is_str = is_generally_string_node(alternative);
22680 
22681             if (consq_is_str || alter_is_str)
22682             {
22683                if (consq_is_str && alter_is_str)
22684                {
22685                   return expression_generator_
22686                            .conditional_string(condition, consequent, alternative);
22687                }
22688 
22689                set_error(
22690                   make_error(parser_error::e_syntax,
22691                              current_token(),
22692                              "ERR054 - Return types of ternary if-statement differ",
22693                              exprtk_error_location));
22694 
22695                result = false;
22696             }
22697          }
22698          #endif
22699 
22700          if (!result)
22701          {
22702             free_node(node_allocator_,   condition);
22703             free_node(node_allocator_,  consequent);
22704             free_node(node_allocator_, alternative);
22705 
22706             return error_node();
22707          }
22708          else
22709             return expression_generator_
22710                       .conditional(condition, consequent, alternative);
22711       }
22712 
parse_not_statement()22713       inline expression_node_ptr parse_not_statement()
22714       {
22715          if (settings_.logic_disabled("not"))
22716          {
22717             set_error(
22718                make_error(parser_error::e_syntax,
22719                           current_token(),
22720                           "ERR055 - Invalid or disabled logic operation 'not'",
22721                           exprtk_error_location));
22722 
22723             return error_node();
22724          }
22725 
22726          return parse_base_operation();
22727       }
22728 
parse_while_loop()22729       inline expression_node_ptr parse_while_loop()
22730       {
22731          // Parse: [while][(][test expr][)][{][expression][}]
22732          expression_node_ptr condition   = error_node();
22733          expression_node_ptr branch      = error_node();
22734          expression_node_ptr result_node = error_node();
22735 
22736          bool result = true;
22737 
22738          next_token();
22739 
22740          if (!token_is(token_t::e_lbracket))
22741          {
22742             set_error(
22743                make_error(parser_error::e_syntax,
22744                           current_token(),
22745                           "ERR056 - Expected '(' at start of while-loop condition statement",
22746                           exprtk_error_location));
22747 
22748             return error_node();
22749          }
22750          else if (0 == (condition = parse_expression()))
22751          {
22752             set_error(
22753                make_error(parser_error::e_syntax,
22754                           current_token(),
22755                           "ERR057 - Failed to parse condition for while-loop",
22756                           exprtk_error_location));
22757 
22758             return error_node();
22759          }
22760          else if (!token_is(token_t::e_rbracket))
22761          {
22762             set_error(
22763                make_error(parser_error::e_syntax,
22764                           current_token(),
22765                           "ERR058 - Expected ')' at end of while-loop condition statement",
22766                           exprtk_error_location));
22767 
22768             result = false;
22769          }
22770 
22771          brkcnt_list_.push_front(false);
22772 
22773          if (result)
22774          {
22775             scoped_inc_dec sid(state_.parsing_loop_stmt_count);
22776 
22777             if (0 == (branch = parse_multi_sequence("while-loop")))
22778             {
22779                set_error(
22780                   make_error(parser_error::e_syntax,
22781                              current_token(),
22782                              "ERR059 - Failed to parse body of while-loop"));
22783                result = false;
22784             }
22785             else if (0 == (result_node = expression_generator_.while_loop(condition,
22786                                                                           branch,
22787                                                                           brkcnt_list_.front())))
22788             {
22789                set_error(
22790                   make_error(parser_error::e_syntax,
22791                              current_token(),
22792                              "ERR060 - Failed to synthesize while-loop",
22793                              exprtk_error_location));
22794 
22795                result = false;
22796             }
22797          }
22798 
22799          if (!result)
22800          {
22801             free_node(node_allocator_,      branch);
22802             free_node(node_allocator_,   condition);
22803             free_node(node_allocator_, result_node);
22804 
22805             brkcnt_list_.pop_front();
22806 
22807             return error_node();
22808          }
22809          else
22810             return result_node;
22811       }
22812 
parse_repeat_until_loop()22813       inline expression_node_ptr parse_repeat_until_loop()
22814       {
22815          // Parse: [repeat][{][expression][}][until][(][test expr][)]
22816          expression_node_ptr condition = error_node();
22817          expression_node_ptr branch    = error_node();
22818          next_token();
22819 
22820          std::vector<expression_node_ptr> arg_list;
22821          std::vector<bool> side_effect_list;
22822 
22823          scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
22824 
22825          brkcnt_list_.push_front(false);
22826 
22827          if (details::imatch(current_token().value,"until"))
22828          {
22829             next_token();
22830             branch = node_allocator_.allocate<details::null_node<T> >();
22831          }
22832          else
22833          {
22834             const token_t::token_type seperator = token_t::e_eof;
22835 
22836             scope_handler sh(*this);
22837 
22838             scoped_bool_or_restorer sbr(state_.side_effect_present);
22839 
22840             scoped_inc_dec sid(state_.parsing_loop_stmt_count);
22841 
22842             for ( ; ; )
22843             {
22844                state_.side_effect_present = false;
22845 
22846                expression_node_ptr arg = parse_expression();
22847 
22848                if (0 == arg)
22849                   return error_node();
22850                else
22851                {
22852                   arg_list.push_back(arg);
22853                   side_effect_list.push_back(state_.side_effect_present);
22854                }
22855 
22856                if (details::imatch(current_token().value,"until"))
22857                {
22858                   next_token();
22859                   break;
22860                }
22861 
22862                const bool is_next_until = peek_token_is(token_t::e_symbol) &&
22863                                           peek_token_is("until");
22864 
22865                if (!token_is(seperator) && is_next_until)
22866                {
22867                   set_error(
22868                      make_error(parser_error::e_syntax,
22869                                 current_token(),
22870                                 "ERR061 - Expected '" + token_t::to_str(seperator) + "' in body of repeat until loop",
22871                                 exprtk_error_location));
22872 
22873                   return error_node();
22874                }
22875 
22876                if (details::imatch(current_token().value,"until"))
22877                {
22878                   next_token();
22879                   break;
22880                }
22881             }
22882 
22883             branch = simplify(arg_list,side_effect_list);
22884 
22885             sdd.delete_ptr = (0 == branch);
22886 
22887             if (sdd.delete_ptr)
22888             {
22889                brkcnt_list_.pop_front();
22890 
22891                set_error(
22892                   make_error(parser_error::e_syntax,
22893                              current_token(),
22894                              "ERR062 - Failed to parse body of repeat until loop",
22895                              exprtk_error_location));
22896 
22897                return error_node();
22898             }
22899          }
22900 
22901          if (!token_is(token_t::e_lbracket))
22902          {
22903             brkcnt_list_.pop_front();
22904 
22905             set_error(
22906                make_error(parser_error::e_syntax,
22907                           current_token(),
22908                           "ERR063 - Expected '(' before condition statement of repeat until loop",
22909                           exprtk_error_location));
22910 
22911             free_node(node_allocator_,branch);
22912 
22913             return error_node();
22914          }
22915          else if (0 == (condition = parse_expression()))
22916          {
22917             brkcnt_list_.pop_front();
22918 
22919             set_error(
22920                make_error(parser_error::e_syntax,
22921                           current_token(),
22922                           "ERR064 - Failed to parse condition for repeat until loop",
22923                           exprtk_error_location));
22924 
22925             free_node(node_allocator_,branch);
22926 
22927             return error_node();
22928          }
22929          else if (!token_is(token_t::e_rbracket))
22930          {
22931             set_error(
22932                make_error(parser_error::e_syntax,
22933                           current_token(),
22934                           "ERR065 - Expected ')' after condition of repeat until loop",
22935                           exprtk_error_location));
22936 
22937             free_node(node_allocator_,    branch);
22938             free_node(node_allocator_, condition);
22939 
22940             brkcnt_list_.pop_front();
22941 
22942             return error_node();
22943          }
22944 
22945          expression_node_ptr result;
22946 
22947          result = expression_generator_
22948                      .repeat_until_loop(condition, branch, brkcnt_list_.front());
22949 
22950          if (0 == result)
22951          {
22952             set_error(
22953                make_error(parser_error::e_syntax,
22954                           current_token(),
22955                           "ERR066 - Failed to synthesize repeat until loop",
22956                           exprtk_error_location));
22957 
22958             free_node(node_allocator_,condition);
22959 
22960             brkcnt_list_.pop_front();
22961 
22962             return error_node();
22963          }
22964          else
22965          {
22966             brkcnt_list_.pop_front();
22967             return result;
22968          }
22969       }
22970 
parse_for_loop()22971       inline expression_node_ptr parse_for_loop()
22972       {
22973          expression_node_ptr initialiser = error_node();
22974          expression_node_ptr condition   = error_node();
22975          expression_node_ptr incrementor = error_node();
22976          expression_node_ptr loop_body   = error_node();
22977 
22978          scope_element* se = 0;
22979          bool result       = true;
22980 
22981          next_token();
22982 
22983          scope_handler sh(*this);
22984 
22985          if (!token_is(token_t::e_lbracket))
22986          {
22987             set_error(
22988                make_error(parser_error::e_syntax,
22989                           current_token(),
22990                           "ERR067 - Expected '(' at start of for-loop",
22991                           exprtk_error_location));
22992 
22993             return error_node();
22994          }
22995 
22996          if (!token_is(token_t::e_eof))
22997          {
22998             if (
22999                  !token_is(token_t::e_symbol,prsrhlpr_t::e_hold) &&
23000                  details::imatch(current_token().value,"var")
23001                )
23002             {
23003                next_token();
23004 
23005                if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold))
23006                {
23007                   set_error(
23008                      make_error(parser_error::e_syntax,
23009                                 current_token(),
23010                                 "ERR068 - Expected a variable at the start of initialiser section of for-loop",
23011                                 exprtk_error_location));
23012 
23013                   return error_node();
23014                }
23015                else if (!peek_token_is(token_t::e_assign))
23016                {
23017                   set_error(
23018                      make_error(parser_error::e_syntax,
23019                                 current_token(),
23020                                 "ERR069 - Expected variable assignment of initialiser section of for-loop",
23021                                 exprtk_error_location));
23022 
23023                   return error_node();
23024                }
23025 
23026                const std::string loop_counter_symbol = current_token().value;
23027 
23028                se = &sem_.get_element(loop_counter_symbol);
23029 
23030                if ((se->name == loop_counter_symbol) && se->active)
23031                {
23032                   set_error(
23033                      make_error(parser_error::e_syntax,
23034                                 current_token(),
23035                                 "ERR070 - For-loop variable '" + loop_counter_symbol+ "' is being shadowed by a previous declaration",
23036                                 exprtk_error_location));
23037 
23038                   return error_node();
23039                }
23040                else if (!symtab_store_.is_variable(loop_counter_symbol))
23041                {
23042                   if (
23043                        !se->active &&
23044                        (se->name == loop_counter_symbol) &&
23045                        (se->type ==  scope_element::e_variable)
23046                      )
23047                   {
23048                      se->active = true;
23049                      se->ref_count++;
23050                   }
23051                   else
23052                   {
23053                      scope_element nse;
23054                      nse.name      = loop_counter_symbol;
23055                      nse.active    = true;
23056                      nse.ref_count = 1;
23057                      nse.type      = scope_element::e_variable;
23058                      nse.depth     = state_.scope_depth;
23059                      nse.data      = new T(T(0));
23060                      nse.var_node  = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data));
23061 
23062                      if (!sem_.add_element(nse))
23063                      {
23064                         set_error(
23065                            make_error(parser_error::e_syntax,
23066                                       current_token(),
23067                                       "ERR071 - Failed to add new local variable '" + loop_counter_symbol + "' to SEM",
23068                                       exprtk_error_location));
23069 
23070                         sem_.free_element(nse);
23071 
23072                         result = false;
23073                      }
23074                      else
23075                      {
23076                         exprtk_debug(("parse_for_loop() - INFO - Added new local variable: %s\n",nse.name.c_str()));
23077 
23078                         state_.activate_side_effect("parse_for_loop()");
23079                      }
23080                   }
23081                }
23082             }
23083 
23084             if (0 == (initialiser = parse_expression()))
23085             {
23086                set_error(
23087                   make_error(parser_error::e_syntax,
23088                              current_token(),
23089                              "ERR072 - Failed to parse initialiser of for-loop",
23090                              exprtk_error_location));
23091 
23092                result = false;
23093             }
23094             else if (!token_is(token_t::e_eof))
23095             {
23096                set_error(
23097                   make_error(parser_error::e_syntax,
23098                              current_token(),
23099                              "ERR073 - Expected ';' after initialiser of for-loop",
23100                              exprtk_error_location));
23101 
23102                result = false;
23103             }
23104          }
23105 
23106          if (!token_is(token_t::e_eof))
23107          {
23108             if (0 == (condition = parse_expression()))
23109             {
23110                set_error(
23111                   make_error(parser_error::e_syntax,
23112                              current_token(),
23113                              "ERR074 - Failed to parse condition of for-loop",
23114                              exprtk_error_location));
23115 
23116                result = false;
23117             }
23118             else if (!token_is(token_t::e_eof))
23119             {
23120                set_error(
23121                   make_error(parser_error::e_syntax,
23122                              current_token(),
23123                              "ERR075 - Expected ';' after condition section of for-loop",
23124                              exprtk_error_location));
23125 
23126                result = false;
23127             }
23128          }
23129 
23130          if (!token_is(token_t::e_rbracket))
23131          {
23132             if (0 == (incrementor = parse_expression()))
23133             {
23134                set_error(
23135                   make_error(parser_error::e_syntax,
23136                              current_token(),
23137                              "ERR076 - Failed to parse incrementor of for-loop",
23138                              exprtk_error_location));
23139 
23140                result = false;
23141             }
23142             else if (!token_is(token_t::e_rbracket))
23143             {
23144                set_error(
23145                   make_error(parser_error::e_syntax,
23146                              current_token(),
23147                              "ERR077 - Expected ')' after incrementor section of for-loop",
23148                              exprtk_error_location));
23149 
23150                result = false;
23151             }
23152          }
23153 
23154          if (result)
23155          {
23156             brkcnt_list_.push_front(false);
23157 
23158             scoped_inc_dec sid(state_.parsing_loop_stmt_count);
23159 
23160             if (0 == (loop_body = parse_multi_sequence("for-loop")))
23161             {
23162                set_error(
23163                   make_error(parser_error::e_syntax,
23164                              current_token(),
23165                              "ERR078 - Failed to parse body of for-loop",
23166                              exprtk_error_location));
23167 
23168                result = false;
23169             }
23170          }
23171 
23172          if (!result)
23173          {
23174             if (se)
23175             {
23176                se->ref_count--;
23177             }
23178 
23179             free_node(node_allocator_, initialiser);
23180             free_node(node_allocator_,   condition);
23181             free_node(node_allocator_, incrementor);
23182             free_node(node_allocator_,   loop_body);
23183 
23184             if (!brkcnt_list_.empty())
23185             {
23186                brkcnt_list_.pop_front();
23187             }
23188 
23189             return error_node();
23190          }
23191          else
23192          {
23193             expression_node_ptr result_node =
23194                expression_generator_.for_loop(initialiser,
23195                                               condition,
23196                                               incrementor,
23197                                               loop_body,
23198                                               brkcnt_list_.front());
23199             brkcnt_list_.pop_front();
23200 
23201             return result_node;
23202          }
23203       }
23204 
parse_switch_statement()23205       inline expression_node_ptr parse_switch_statement()
23206       {
23207          std::vector<expression_node_ptr> arg_list;
23208          expression_node_ptr result = error_node();
23209 
23210          if (!details::imatch(current_token().value,"switch"))
23211          {
23212             set_error(
23213                make_error(parser_error::e_syntax,
23214                           current_token(),
23215                           "ERR079 - Expected keyword 'switch'",
23216                           exprtk_error_location));
23217 
23218             return error_node();
23219          }
23220 
23221          scoped_vec_delete<expression_node_t> svd((*this),arg_list);
23222 
23223          next_token();
23224 
23225          if (!token_is(token_t::e_lcrlbracket))
23226          {
23227             set_error(
23228                make_error(parser_error::e_syntax,
23229                           current_token(),
23230                           "ERR080 - Expected '{' for call to switch statement",
23231                           exprtk_error_location));
23232 
23233             return error_node();
23234          }
23235 
23236          expression_node_ptr default_statement = error_node();
23237 
23238          scoped_expression_delete defstmt_delete((*this), default_statement);
23239 
23240          for ( ; ; )
23241          {
23242             if (details::imatch("case",current_token().value))
23243             {
23244                next_token();
23245 
23246                expression_node_ptr condition = parse_expression();
23247 
23248                if (0 == condition)
23249                   return error_node();
23250                else if (!token_is(token_t::e_colon))
23251                {
23252                   set_error(
23253                      make_error(parser_error::e_syntax,
23254                                 current_token(),
23255                                 "ERR081 - Expected ':' for case of switch statement",
23256                                 exprtk_error_location));
23257 
23258                   free_node(node_allocator_, condition);
23259 
23260                   return error_node();
23261                }
23262 
23263                expression_node_ptr consequent = parse_expression();
23264 
23265                if (0 == consequent)
23266                {
23267                   free_node(node_allocator_, condition);
23268 
23269                   return error_node();
23270                }
23271                else if (!token_is(token_t::e_eof))
23272                {
23273                   set_error(
23274                      make_error(parser_error::e_syntax,
23275                                 current_token(),
23276                                 "ERR082 - Expected ';' at end of case for switch statement",
23277                                 exprtk_error_location));
23278 
23279                   free_node(node_allocator_,  condition);
23280                   free_node(node_allocator_, consequent);
23281 
23282                   return error_node();
23283                }
23284 
23285                // Can we optimise away the case statement?
23286                if (is_constant_node(condition) && is_false(condition))
23287                {
23288                   free_node(node_allocator_,  condition);
23289                   free_node(node_allocator_, consequent);
23290                }
23291                else
23292                {
23293                   arg_list.push_back( condition);
23294                   arg_list.push_back(consequent);
23295                }
23296 
23297             }
23298             else if (details::imatch("default",current_token().value))
23299             {
23300                if (0 != default_statement)
23301                {
23302                   set_error(
23303                      make_error(parser_error::e_syntax,
23304                                 current_token(),
23305                                 "ERR083 - Multiple default cases for switch statement",
23306                                 exprtk_error_location));
23307 
23308                   return error_node();
23309                }
23310 
23311                next_token();
23312 
23313                if (!token_is(token_t::e_colon))
23314                {
23315                   set_error(
23316                      make_error(parser_error::e_syntax,
23317                                 current_token(),
23318                                 "ERR084 - Expected ':' for default of switch statement",
23319                                 exprtk_error_location));
23320 
23321                   return error_node();
23322                }
23323 
23324                if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
23325                   default_statement = parse_multi_sequence("switch-default");
23326                else
23327                   default_statement = parse_expression();
23328 
23329                if (0 == default_statement)
23330                   return error_node();
23331                else if (!token_is(token_t::e_eof))
23332                {
23333                   set_error(
23334                      make_error(parser_error::e_syntax,
23335                                 current_token(),
23336                                 "ERR085 - Expected ';' at end of default for switch statement",
23337                                 exprtk_error_location));
23338 
23339                   return error_node();
23340                }
23341             }
23342             else if (token_is(token_t::e_rcrlbracket))
23343                break;
23344             else
23345             {
23346                set_error(
23347                   make_error(parser_error::e_syntax,
23348                              current_token(),
23349                              "ERR086 - Expected '}' at end of switch statement",
23350                              exprtk_error_location));
23351 
23352                return error_node();
23353             }
23354          }
23355 
23356          const bool default_statement_present = (0 != default_statement);
23357 
23358          if (default_statement_present)
23359          {
23360             arg_list.push_back(default_statement);
23361          }
23362 
23363          result = expression_generator_.switch_statement(arg_list, (0 != default_statement));
23364 
23365          svd.delete_ptr = (0 == result);
23366          defstmt_delete.delete_ptr = (0 == result);
23367 
23368          return result;
23369       }
23370 
parse_multi_switch_statement()23371       inline expression_node_ptr parse_multi_switch_statement()
23372       {
23373          std::vector<expression_node_ptr> arg_list;
23374 
23375          if (!details::imatch(current_token().value,"[*]"))
23376          {
23377             set_error(
23378                make_error(parser_error::e_syntax,
23379                           current_token(),
23380                           "ERR087 - Expected token '[*]'",
23381                           exprtk_error_location));
23382 
23383             return error_node();
23384          }
23385 
23386          scoped_vec_delete<expression_node_t> svd((*this),arg_list);
23387 
23388          next_token();
23389 
23390          if (!token_is(token_t::e_lcrlbracket))
23391          {
23392             set_error(
23393                make_error(parser_error::e_syntax,
23394                           current_token(),
23395                           "ERR088 - Expected '{' for call to [*] statement",
23396                           exprtk_error_location));
23397 
23398             return error_node();
23399          }
23400 
23401          for ( ; ; )
23402          {
23403             if (!details::imatch("case",current_token().value))
23404             {
23405                set_error(
23406                   make_error(parser_error::e_syntax,
23407                              current_token(),
23408                              "ERR089 - Expected a 'case' statement for multi-switch",
23409                              exprtk_error_location));
23410 
23411                return error_node();
23412             }
23413 
23414             next_token();
23415 
23416             expression_node_ptr condition = parse_expression();
23417 
23418             if (0 == condition)
23419                return error_node();
23420 
23421             if (!token_is(token_t::e_colon))
23422             {
23423                set_error(
23424                   make_error(parser_error::e_syntax,
23425                              current_token(),
23426                              "ERR090 - Expected ':' for case of [*] statement",
23427                              exprtk_error_location));
23428 
23429                return error_node();
23430             }
23431 
23432             expression_node_ptr consequent = parse_expression();
23433 
23434             if (0 == consequent)
23435                return error_node();
23436 
23437             if (!token_is(token_t::e_eof))
23438             {
23439                set_error(
23440                   make_error(parser_error::e_syntax,
23441                              current_token(),
23442                              "ERR091 - Expected ';' at end of case for [*] statement",
23443                              exprtk_error_location));
23444 
23445                return error_node();
23446             }
23447 
23448             // Can we optimise away the case statement?
23449             if (is_constant_node(condition) && is_false(condition))
23450             {
23451                free_node(node_allocator_,  condition);
23452                free_node(node_allocator_, consequent);
23453             }
23454             else
23455             {
23456                arg_list.push_back( condition);
23457                arg_list.push_back(consequent);
23458             }
23459 
23460             if (token_is(token_t::e_rcrlbracket,prsrhlpr_t::e_hold))
23461             {
23462                break;
23463             }
23464          }
23465 
23466          if (!token_is(token_t::e_rcrlbracket))
23467          {
23468             set_error(
23469                make_error(parser_error::e_syntax,
23470                           current_token(),
23471                           "ERR092 - Expected '}' at end of [*] statement",
23472                           exprtk_error_location));
23473 
23474             return error_node();
23475          }
23476 
23477          const expression_node_ptr result = expression_generator_.multi_switch_statement(arg_list);
23478 
23479          svd.delete_ptr = (0 == result);
23480 
23481          return result;
23482       }
23483 
parse_vararg_function()23484       inline expression_node_ptr parse_vararg_function()
23485       {
23486          std::vector<expression_node_ptr> arg_list;
23487 
23488          details::operator_type opt_type = details::e_default;
23489          const std::string symbol = current_token().value;
23490 
23491          if (details::imatch(symbol,"~"))
23492          {
23493             next_token();
23494             return parse_multi_sequence();
23495          }
23496          else if (details::imatch(symbol,"[*]"))
23497          {
23498             return parse_multi_switch_statement();
23499          }
23500          else if (details::imatch(symbol, "avg" )) opt_type = details::e_avg ;
23501          else if (details::imatch(symbol, "mand")) opt_type = details::e_mand;
23502          else if (details::imatch(symbol, "max" )) opt_type = details::e_max ;
23503          else if (details::imatch(symbol, "min" )) opt_type = details::e_min ;
23504          else if (details::imatch(symbol, "mor" )) opt_type = details::e_mor ;
23505          else if (details::imatch(symbol, "mul" )) opt_type = details::e_prod;
23506          else if (details::imatch(symbol, "sum" )) opt_type = details::e_sum ;
23507          else
23508          {
23509             set_error(
23510                make_error(parser_error::e_syntax,
23511                           current_token(),
23512                           "ERR093 - Unsupported vararg function: " + symbol,
23513                           exprtk_error_location));
23514 
23515             return error_node();
23516          }
23517 
23518          scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
23519 
23520          lodge_symbol(symbol, e_st_function);
23521 
23522          next_token();
23523 
23524          if (!token_is(token_t::e_lbracket))
23525          {
23526             set_error(
23527                make_error(parser_error::e_syntax,
23528                           current_token(),
23529                           "ERR094 - Expected '(' for call to vararg function: " + symbol,
23530                           exprtk_error_location));
23531 
23532             return error_node();
23533          }
23534 
23535          for ( ; ; )
23536          {
23537             expression_node_ptr arg = parse_expression();
23538 
23539             if (0 == arg)
23540                return error_node();
23541             else
23542                arg_list.push_back(arg);
23543 
23544             if (token_is(token_t::e_rbracket))
23545                break;
23546             else if (!token_is(token_t::e_comma))
23547             {
23548                set_error(
23549                   make_error(parser_error::e_syntax,
23550                              current_token(),
23551                              "ERR095 - Expected ',' for call to vararg function: " + symbol,
23552                              exprtk_error_location));
23553 
23554                return error_node();
23555             }
23556          }
23557 
23558          const expression_node_ptr result = expression_generator_.vararg_function(opt_type,arg_list);
23559 
23560          sdd.delete_ptr = (0 == result);
23561          return result;
23562       }
23563 
23564       #ifndef exprtk_disable_string_capabilities
parse_string_range_statement(expression_node_ptr & expression)23565       inline expression_node_ptr parse_string_range_statement(expression_node_ptr& expression)
23566       {
23567          if (!token_is(token_t::e_lsqrbracket))
23568          {
23569             set_error(
23570                make_error(parser_error::e_syntax,
23571                           current_token(),
23572                           "ERR096 - Expected '[' as start of string range definition",
23573                           exprtk_error_location));
23574 
23575             free_node(node_allocator_,expression);
23576 
23577             return error_node();
23578          }
23579          else if (token_is(token_t::e_rsqrbracket))
23580          {
23581             return node_allocator_.allocate<details::string_size_node<T> >(expression);
23582          }
23583 
23584          range_t rp;
23585 
23586          if (!parse_range(rp,true))
23587          {
23588             free_node(node_allocator_,expression);
23589 
23590             return error_node();
23591          }
23592 
23593          expression_node_ptr result = expression_generator_(expression,rp);
23594 
23595          if (0 == result)
23596          {
23597             set_error(
23598                make_error(parser_error::e_syntax,
23599                           current_token(),
23600                           "ERR097 - Failed to generate string range node",
23601                           exprtk_error_location));
23602 
23603             free_node(node_allocator_,expression);
23604             rp.free();
23605          }
23606 
23607          rp.clear();
23608 
23609          return result;
23610       }
23611       #else
parse_string_range_statement(expression_node_ptr &)23612       inline expression_node_ptr parse_string_range_statement(expression_node_ptr&)
23613       {
23614          return error_node();
23615       }
23616       #endif
23617 
parse_pending_string_rangesize(expression_node_ptr & expression)23618       inline void parse_pending_string_rangesize(expression_node_ptr& expression)
23619       {
23620          // Allow no more than 100 range calls, eg: s[][][]...[][]
23621          const std::size_t max_rangesize_parses = 100;
23622 
23623          std::size_t i = 0;
23624 
23625          while
23626             (
23627               (0 != expression)                     &&
23628               (i++ < max_rangesize_parses)          &&
23629               error_list_.empty()                   &&
23630               is_generally_string_node(expression)  &&
23631               token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold)
23632             )
23633          {
23634             expression = parse_string_range_statement(expression);
23635          }
23636       }
23637 
23638       template <typename Allocator1,
23639                 typename Allocator2,
23640                 template <typename, typename> class Sequence>
simplify(Sequence<expression_node_ptr,Allocator1> & expression_list,Sequence<bool,Allocator2> & side_effect_list,const bool specialise_on_final_type=false)23641       inline expression_node_ptr simplify(Sequence<expression_node_ptr,Allocator1>& expression_list,
23642                                           Sequence<bool,Allocator2>& side_effect_list,
23643                                           const bool specialise_on_final_type = false)
23644       {
23645          if (expression_list.empty())
23646             return error_node();
23647          else if (1 == expression_list.size())
23648             return expression_list[0];
23649 
23650          Sequence<expression_node_ptr,Allocator1> tmp_expression_list;
23651 
23652          bool return_node_present = false;
23653 
23654          for (std::size_t i = 0; i < (expression_list.size() - 1); ++i)
23655          {
23656             if (is_variable_node(expression_list[i]))
23657                continue;
23658             else if (
23659                       is_return_node  (expression_list[i]) ||
23660                       is_break_node   (expression_list[i]) ||
23661                       is_continue_node(expression_list[i])
23662                     )
23663             {
23664                tmp_expression_list.push_back(expression_list[i]);
23665 
23666                // Remove all subexpressions after first short-circuit
23667                // node has been encountered.
23668 
23669                for (std::size_t j = i + 1; j < expression_list.size(); ++j)
23670                {
23671                   free_node(node_allocator_,expression_list[j]);
23672                }
23673 
23674                return_node_present = true;
23675 
23676                break;
23677             }
23678             else if (
23679                       is_constant_node(expression_list[i]) ||
23680                       is_null_node    (expression_list[i]) ||
23681                       !side_effect_list[i]
23682                     )
23683             {
23684                free_node(node_allocator_,expression_list[i]);
23685                continue;
23686             }
23687             else
23688                tmp_expression_list.push_back(expression_list[i]);
23689          }
23690 
23691          if (!return_node_present)
23692          {
23693             tmp_expression_list.push_back(expression_list.back());
23694          }
23695 
23696          expression_list.swap(tmp_expression_list);
23697 
23698          if (tmp_expression_list.size() > expression_list.size())
23699          {
23700             exprtk_debug(("simplify() - Reduced subexpressions from %d to %d\n",
23701                           static_cast<int>(tmp_expression_list.size()),
23702                           static_cast<int>(expression_list    .size())));
23703          }
23704 
23705          if (
23706               return_node_present          ||
23707               side_effect_list.back()      ||
23708               (expression_list.size() > 1)
23709             )
23710             state_.activate_side_effect("simplify()");
23711 
23712          if (1 == expression_list.size())
23713             return expression_list[0];
23714          else if (specialise_on_final_type && is_generally_string_node(expression_list.back()))
23715             return expression_generator_.vararg_function(details::e_smulti,expression_list);
23716          else
23717             return expression_generator_.vararg_function(details::e_multi,expression_list);
23718       }
23719 
parse_multi_sequence(const std::string & source="")23720       inline expression_node_ptr parse_multi_sequence(const std::string& source = "")
23721       {
23722          token_t::token_type close_bracket = token_t::e_rcrlbracket;
23723          token_t::token_type seperator     = token_t::e_eof;
23724 
23725          if (!token_is(token_t::e_lcrlbracket))
23726          {
23727             if (token_is(token_t::e_lbracket))
23728             {
23729                close_bracket = token_t::e_rbracket;
23730                seperator     = token_t::e_comma;
23731             }
23732             else
23733             {
23734                set_error(
23735                   make_error(parser_error::e_syntax,
23736                              current_token(),
23737                              "ERR098 - Expected '" + token_t::to_str(close_bracket) + "' for call to multi-sequence" +
23738                              ((!source.empty()) ? std::string(" section of " + source): ""),
23739                              exprtk_error_location));
23740 
23741                return error_node();
23742             }
23743          }
23744          else if (token_is(token_t::e_rcrlbracket))
23745          {
23746             return node_allocator_.allocate<details::null_node<T> >();
23747          }
23748 
23749          std::vector<expression_node_ptr> arg_list;
23750          std::vector<bool> side_effect_list;
23751 
23752          expression_node_ptr result = error_node();
23753 
23754          scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
23755 
23756          scope_handler sh(*this);
23757 
23758          scoped_bool_or_restorer sbr(state_.side_effect_present);
23759 
23760          for ( ; ; )
23761          {
23762             state_.side_effect_present = false;
23763 
23764             expression_node_ptr arg = parse_expression();
23765 
23766             if (0 == arg)
23767                return error_node();
23768             else
23769             {
23770                arg_list.push_back(arg);
23771                side_effect_list.push_back(state_.side_effect_present);
23772             }
23773 
23774             if (token_is(close_bracket))
23775                break;
23776 
23777             const bool is_next_close = peek_token_is(close_bracket);
23778 
23779             if (!token_is(seperator) && is_next_close)
23780             {
23781                set_error(
23782                   make_error(parser_error::e_syntax,
23783                              current_token(),
23784                              "ERR099 - Expected '" + details::to_str(seperator) + "' for call to multi-sequence section of " + source,
23785                              exprtk_error_location));
23786 
23787                return error_node();
23788             }
23789 
23790             if (token_is(close_bracket))
23791                break;
23792          }
23793 
23794          result = simplify(arg_list,side_effect_list,source.empty());
23795 
23796          sdd.delete_ptr = (0 == result);
23797          return result;
23798       }
23799 
parse_range(range_t & rp,const bool skip_lsqr=false)23800       inline bool parse_range(range_t& rp, const bool skip_lsqr = false)
23801       {
23802          // Examples of valid ranges:
23803          // 1. [1:5]     -> 1..5
23804          // 2. [ :5]     -> 0..5
23805          // 3. [1: ]     -> 1..end
23806          // 4. [x:y]     -> x..y where x <= y
23807          // 5. [x+1:y/2] -> x+1..y/2 where x+1 <= y/2
23808          // 6. [ :y]     -> 0..y where 0 <= y
23809          // 7. [x: ]     -> x..end where x <= end
23810 
23811          rp.clear();
23812 
23813          if (!skip_lsqr && !token_is(token_t::e_lsqrbracket))
23814          {
23815             set_error(
23816                make_error(parser_error::e_syntax,
23817                           current_token(),
23818                           "ERR100 - Expected '[' for start of range",
23819                           exprtk_error_location));
23820 
23821             return false;
23822          }
23823 
23824          if (token_is(token_t::e_colon))
23825          {
23826             rp.n0_c.first  = true;
23827             rp.n0_c.second = 0;
23828             rp.cache.first = 0;
23829          }
23830          else
23831          {
23832             expression_node_ptr r0 = parse_expression();
23833 
23834             if (0 == r0)
23835             {
23836                set_error(
23837                   make_error(parser_error::e_syntax,
23838                              current_token(),
23839                              "ERR101 - Failed parse begin section of range",
23840                              exprtk_error_location));
23841 
23842                return false;
23843             }
23844             else if (is_constant_node(r0))
23845             {
23846                const T r0_value = r0->value();
23847 
23848                if (r0_value >= T(0))
23849                {
23850                   rp.n0_c.first  = true;
23851                   rp.n0_c.second = static_cast<std::size_t>(details::numeric::to_int64(r0_value));
23852                   rp.cache.first = rp.n0_c.second;
23853                }
23854 
23855                free_node(node_allocator_,r0);
23856 
23857                if (r0_value < T(0))
23858                {
23859                   set_error(
23860                      make_error(parser_error::e_syntax,
23861                                 current_token(),
23862                                 "ERR102 - Range lower bound less than zero! Constraint: r0 >= 0",
23863                                 exprtk_error_location));
23864 
23865                   return false;
23866                }
23867             }
23868             else
23869             {
23870                rp.n0_e.first  = true;
23871                rp.n0_e.second = r0;
23872             }
23873 
23874             if (!token_is(token_t::e_colon))
23875             {
23876                set_error(
23877                   make_error(parser_error::e_syntax,
23878                              current_token(),
23879                              "ERR103 - Expected ':' for break  in range",
23880                              exprtk_error_location));
23881 
23882                rp.free();
23883 
23884                return false;
23885             }
23886          }
23887 
23888          if (token_is(token_t::e_rsqrbracket))
23889          {
23890             rp.n1_c.first  = true;
23891             rp.n1_c.second = std::numeric_limits<std::size_t>::max();
23892          }
23893          else
23894          {
23895             expression_node_ptr r1 = parse_expression();
23896 
23897             if (0 == r1)
23898             {
23899                set_error(
23900                   make_error(parser_error::e_syntax,
23901                              current_token(),
23902                              "ERR104 - Failed parse end section of range",
23903                              exprtk_error_location));
23904 
23905                rp.free();
23906 
23907                return false;
23908             }
23909             else if (is_constant_node(r1))
23910             {
23911                const T r1_value = r1->value();
23912 
23913                if (r1_value >= T(0))
23914                {
23915                   rp.n1_c.first   = true;
23916                   rp.n1_c.second  = static_cast<std::size_t>(details::numeric::to_int64(r1_value));
23917                   rp.cache.second = rp.n1_c.second;
23918                }
23919 
23920                free_node(node_allocator_,r1);
23921 
23922                if (r1_value < T(0))
23923                {
23924                   set_error(
23925                      make_error(parser_error::e_syntax,
23926                                 current_token(),
23927                                 "ERR105 - Range upper bound less than zero! Constraint: r1 >= 0",
23928                                 exprtk_error_location));
23929 
23930                   rp.free();
23931 
23932                   return false;
23933                }
23934             }
23935             else
23936             {
23937                rp.n1_e.first  = true;
23938                rp.n1_e.second = r1;
23939             }
23940 
23941             if (!token_is(token_t::e_rsqrbracket))
23942             {
23943                set_error(
23944                   make_error(parser_error::e_syntax,
23945                              current_token(),
23946                              "ERR106 - Expected ']' for start of range",
23947                              exprtk_error_location));
23948 
23949                rp.free();
23950 
23951                return false;
23952             }
23953          }
23954 
23955          if (rp.const_range())
23956          {
23957             std::size_t r0 = 0;
23958             std::size_t r1 = 0;
23959 
23960             bool rp_result = false;
23961 
23962             try
23963             {
23964                rp_result = rp(r0, r1);
23965             }
23966             catch (std::runtime_error&)
23967             {}
23968 
23969             if (!rp_result || (r0 > r1))
23970             {
23971                set_error(
23972                   make_error(parser_error::e_syntax,
23973                              current_token(),
23974                              "ERR107 - Invalid range, Constraint: r0 <= r1",
23975                              exprtk_error_location));
23976 
23977                return false;
23978             }
23979          }
23980 
23981          return true;
23982       }
23983 
lodge_symbol(const std::string & symbol,const symbol_type st)23984       inline void lodge_symbol(const std::string& symbol,
23985                                const symbol_type st)
23986       {
23987          dec_.add_symbol(symbol,st);
23988       }
23989 
23990       #ifndef exprtk_disable_string_capabilities
parse_string()23991       inline expression_node_ptr parse_string()
23992       {
23993          const std::string symbol = current_token().value;
23994 
23995          typedef details::stringvar_node<T>* strvar_node_t;
23996 
23997          expression_node_ptr result   = error_node();
23998          strvar_node_t const_str_node = static_cast<strvar_node_t>(0);
23999 
24000          scope_element& se = sem_.get_active_element(symbol);
24001 
24002          if (scope_element::e_string == se.type)
24003          {
24004             se.active = true;
24005             result    = se.str_node;
24006             lodge_symbol(symbol, e_st_local_string);
24007          }
24008          else
24009          {
24010             if (!symtab_store_.is_conststr_stringvar(symbol))
24011             {
24012                set_error(
24013                   make_error(parser_error::e_syntax,
24014                              current_token(),
24015                              "ERR108 - Unknown string symbol",
24016                              exprtk_error_location));
24017 
24018                return error_node();
24019             }
24020 
24021             result = symtab_store_.get_stringvar(symbol);
24022 
24023             if (symtab_store_.is_constant_string(symbol))
24024             {
24025                const_str_node = static_cast<strvar_node_t>(result);
24026                result = expression_generator_(const_str_node->str());
24027             }
24028 
24029             lodge_symbol(symbol, e_st_string);
24030          }
24031 
24032          if (peek_token_is(token_t::e_lsqrbracket))
24033          {
24034             next_token();
24035 
24036             if (peek_token_is(token_t::e_rsqrbracket))
24037             {
24038                next_token();
24039                next_token();
24040 
24041                if (const_str_node)
24042                {
24043                   free_node(node_allocator_,result);
24044 
24045                   return expression_generator_(T(const_str_node->size()));
24046                }
24047                else
24048                   return node_allocator_.allocate<details::stringvar_size_node<T> >
24049                             (static_cast<details::stringvar_node<T>*>(result)->ref());
24050             }
24051 
24052             range_t rp;
24053 
24054             if (!parse_range(rp))
24055             {
24056                free_node(node_allocator_,result);
24057 
24058                return error_node();
24059             }
24060             else if (const_str_node)
24061             {
24062                free_node(node_allocator_,result);
24063                result = expression_generator_(const_str_node->ref(),rp);
24064             }
24065             else
24066                result = expression_generator_(static_cast<details::stringvar_node<T>*>
24067                            (result)->ref(), rp);
24068 
24069             if (result)
24070                rp.clear();
24071          }
24072          else
24073             next_token();
24074 
24075          return result;
24076       }
24077       #else
parse_string()24078       inline expression_node_ptr parse_string()
24079       {
24080          return error_node();
24081       }
24082       #endif
24083 
24084       #ifndef exprtk_disable_string_capabilities
parse_const_string()24085       inline expression_node_ptr parse_const_string()
24086       {
24087          const std::string   const_str = current_token().value;
24088          expression_node_ptr result    = expression_generator_(const_str);
24089 
24090          if (peek_token_is(token_t::e_lsqrbracket))
24091          {
24092             next_token();
24093 
24094             if (peek_token_is(token_t::e_rsqrbracket))
24095             {
24096                next_token();
24097                next_token();
24098 
24099                free_node(node_allocator_,result);
24100 
24101                return expression_generator_(T(const_str.size()));
24102             }
24103 
24104             range_t rp;
24105 
24106             if (!parse_range(rp))
24107             {
24108                free_node(node_allocator_,result);
24109                rp.free();
24110 
24111                return error_node();
24112             }
24113 
24114             free_node(node_allocator_,result);
24115 
24116             if (rp.n1_c.first && (rp.n1_c.second == std::numeric_limits<std::size_t>::max()))
24117             {
24118                rp.n1_c.second  = const_str.size() - 1;
24119                rp.cache.second = rp.n1_c.second;
24120             }
24121 
24122             if (
24123                  (rp.n0_c.first && (rp.n0_c.second >= const_str.size())) ||
24124                  (rp.n1_c.first && (rp.n1_c.second >= const_str.size()))
24125                )
24126             {
24127                set_error(
24128                   make_error(parser_error::e_syntax,
24129                              current_token(),
24130                              "ERR109 - Overflow in range for string: '" + const_str + "'[" +
24131                              (rp.n0_c.first ? details::to_str(static_cast<int>(rp.n0_c.second)) : "?") + ":" +
24132                              (rp.n1_c.first ? details::to_str(static_cast<int>(rp.n1_c.second)) : "?") + "]",
24133                              exprtk_error_location));
24134 
24135                rp.free();
24136 
24137                return error_node();
24138             }
24139 
24140             result = expression_generator_(const_str,rp);
24141 
24142             if (result)
24143                rp.clear();
24144          }
24145          else
24146             next_token();
24147 
24148          return result;
24149       }
24150       #else
parse_const_string()24151       inline expression_node_ptr parse_const_string()
24152       {
24153          return error_node();
24154       }
24155       #endif
24156 
parse_vector()24157       inline expression_node_ptr parse_vector()
24158       {
24159          const std::string symbol = current_token().value;
24160 
24161          vector_holder_ptr vec = vector_holder_ptr(0);
24162 
24163          const scope_element& se = sem_.get_active_element(symbol);
24164 
24165          if (
24166               !details::imatch(se.name, symbol) ||
24167               (se.depth > state_.scope_depth)   ||
24168               (scope_element::e_vector != se.type)
24169             )
24170          {
24171             if (0 == (vec = symtab_store_.get_vector(symbol)))
24172             {
24173                set_error(
24174                   make_error(parser_error::e_syntax,
24175                              current_token(),
24176                              "ERR110 - Symbol '" + symbol+ " not a vector",
24177                              exprtk_error_location));
24178 
24179                return error_node();
24180             }
24181          }
24182          else
24183             vec = se.vec_node;
24184 
24185          expression_node_ptr index_expr = error_node();
24186 
24187          next_token();
24188 
24189          if (!token_is(token_t::e_lsqrbracket))
24190          {
24191             return node_allocator_.allocate<vector_node_t>(vec);
24192          }
24193          else if (token_is(token_t::e_rsqrbracket))
24194          {
24195             return expression_generator_(T(vec->size()));
24196          }
24197          else if (0 == (index_expr = parse_expression()))
24198          {
24199             set_error(
24200                make_error(parser_error::e_syntax,
24201                           current_token(),
24202                           "ERR111 - Failed to parse index for vector: '" + symbol + "'",
24203                           exprtk_error_location));
24204 
24205             return error_node();
24206          }
24207          else if (!token_is(token_t::e_rsqrbracket))
24208          {
24209             set_error(
24210                make_error(parser_error::e_syntax,
24211                           current_token(),
24212                           "ERR112 - Expected ']' for index of vector: '" + symbol + "'",
24213                           exprtk_error_location));
24214 
24215             free_node(node_allocator_,index_expr);
24216 
24217             return error_node();
24218          }
24219 
24220          // Perform compile-time range check
24221          if (details::is_constant_node(index_expr))
24222          {
24223             const std::size_t index    = static_cast<std::size_t>(details::numeric::to_int32(index_expr->value()));
24224             const std::size_t vec_size = vec->size();
24225 
24226             if (index >= vec_size)
24227             {
24228                set_error(
24229                   make_error(parser_error::e_syntax,
24230                              current_token(),
24231                              "ERR113 - Index of " + details::to_str(index) + " out of range for "
24232                              "vector '" + symbol + "' of size " + details::to_str(vec_size),
24233                              exprtk_error_location));
24234 
24235                free_node(node_allocator_,index_expr);
24236 
24237                return error_node();
24238             }
24239          }
24240 
24241          return expression_generator_.vector_element(symbol, vec, index_expr);
24242       }
24243 
parse_vararg_function_call(ivararg_function<T> * vararg_function,const std::string & vararg_function_name)24244       inline expression_node_ptr parse_vararg_function_call(ivararg_function<T>* vararg_function, const std::string& vararg_function_name)
24245       {
24246          std::vector<expression_node_ptr> arg_list;
24247 
24248          expression_node_ptr result = error_node();
24249 
24250          scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
24251 
24252          next_token();
24253 
24254          if (token_is(token_t::e_lbracket))
24255          {
24256             if (token_is(token_t::e_rbracket))
24257             {
24258                if (!vararg_function->allow_zero_parameters())
24259                {
24260                   set_error(
24261                      make_error(parser_error::e_syntax,
24262                                 current_token(),
24263                                 "ERR114 - Zero parameter call to vararg function: "
24264                                 + vararg_function_name + " not allowed",
24265                                 exprtk_error_location));
24266 
24267                   return error_node();
24268                }
24269             }
24270             else
24271             {
24272                for ( ; ; )
24273                {
24274                   expression_node_ptr arg = parse_expression();
24275 
24276                   if (0 == arg)
24277                      return error_node();
24278                   else
24279                      arg_list.push_back(arg);
24280 
24281                   if (token_is(token_t::e_rbracket))
24282                      break;
24283                   else if (!token_is(token_t::e_comma))
24284                   {
24285                      set_error(
24286                         make_error(parser_error::e_syntax,
24287                                    current_token(),
24288                                    "ERR115 - Expected ',' for call to vararg function: "
24289                                    + vararg_function_name,
24290                                    exprtk_error_location));
24291 
24292                      return error_node();
24293                   }
24294                }
24295             }
24296          }
24297          else if (!vararg_function->allow_zero_parameters())
24298          {
24299             set_error(
24300                make_error(parser_error::e_syntax,
24301                           current_token(),
24302                           "ERR116 - Zero parameter call to vararg function: "
24303                           + vararg_function_name + " not allowed",
24304                           exprtk_error_location));
24305 
24306             return error_node();
24307          }
24308 
24309          if (arg_list.size() < vararg_function->min_num_args())
24310          {
24311             set_error(
24312                make_error(parser_error::e_syntax,
24313                           current_token(),
24314                           "ERR117 - Invalid number of parameters to call to vararg function: "
24315                           + vararg_function_name + ", require at least "
24316                           + details::to_str(static_cast<int>(vararg_function->min_num_args())) + " parameters",
24317                           exprtk_error_location));
24318 
24319             return error_node();
24320          }
24321          else if (arg_list.size() > vararg_function->max_num_args())
24322          {
24323             set_error(
24324                make_error(parser_error::e_syntax,
24325                           current_token(),
24326                           "ERR118 - Invalid number of parameters to call to vararg function: "
24327                           + vararg_function_name + ", require no more than "
24328                           + details::to_str(static_cast<int>(vararg_function->max_num_args())) + " parameters",
24329                           exprtk_error_location));
24330 
24331             return error_node();
24332          }
24333 
24334          result = expression_generator_.vararg_function_call(vararg_function,arg_list);
24335 
24336          sdd.delete_ptr = (0 == result);
24337 
24338          return result;
24339       }
24340 
24341       class type_checker
24342       {
24343       public:
24344 
24345          enum return_type_t
24346          {
24347             e_overload = ' ',
24348             e_numeric  = 'T',
24349             e_string   = 'S'
24350          };
24351 
24352          struct function_prototype_t
24353          {
24354              return_type_t return_type;
24355              std::string   param_seq;
24356          };
24357 
24358          typedef parser<T> parser_t;
24359          typedef std::vector<function_prototype_t> function_definition_list_t;
24360 
type_checker(parser_t & p,const std::string & func_name,const std::string & func_prototypes,const return_type_t default_return_type)24361          type_checker(parser_t& p,
24362                       const std::string& func_name,
24363                       const std::string& func_prototypes,
24364                       const return_type_t default_return_type)
24365          : invalid_state_(true),
24366            parser_(p),
24367            function_name_(func_name),
24368            default_return_type_(default_return_type)
24369          {
24370             parse_function_prototypes(func_prototypes);
24371          }
24372 
verify(const std::string & param_seq,std::size_t & pseq_index)24373          bool verify(const std::string& param_seq, std::size_t& pseq_index)
24374          {
24375             if (function_definition_list_.empty())
24376                return true;
24377 
24378             std::vector<std::pair<std::size_t,char> > error_list;
24379 
24380             for (std::size_t i = 0; i < function_definition_list_.size(); ++i)
24381             {
24382                details::char_t diff_value = 0;
24383                std::size_t     diff_index = 0;
24384 
24385                const bool result = details::sequence_match(function_definition_list_[i].param_seq,
24386                                                            param_seq,
24387                                                            diff_index, diff_value);
24388 
24389               if (result)
24390               {
24391                  pseq_index = i;
24392                  return true;
24393               }
24394               else
24395                  error_list.push_back(std::make_pair(diff_index, diff_value));
24396             }
24397 
24398             if (1 == error_list.size())
24399             {
24400                parser_.
24401                   set_error(
24402                      make_error(parser_error::e_syntax,
24403                                 parser_.current_token(),
24404                                 "ERR119 - Failed parameter type check for function '" + function_name_ + "', "
24405                                 "Expected '" + function_definition_list_[0].param_seq +
24406                                 "'  call set: '" + param_seq + "'",
24407                                 exprtk_error_location));
24408             }
24409             else
24410             {
24411                // find first with largest diff_index;
24412                std::size_t max_diff_index = 0;
24413 
24414                for (std::size_t i = 1; i < error_list.size(); ++i)
24415                {
24416                   if (error_list[i].first > error_list[max_diff_index].first)
24417                   {
24418                      max_diff_index = i;
24419                   }
24420                }
24421 
24422                parser_.
24423                   set_error(
24424                      make_error(parser_error::e_syntax,
24425                                 parser_.current_token(),
24426                                 "ERR120 - Failed parameter type check for function '" + function_name_ + "', "
24427                                 "Best match: '" + function_definition_list_[max_diff_index].param_seq +
24428                                 "'  call set: '" + param_seq + "'",
24429                                 exprtk_error_location));
24430             }
24431 
24432             return false;
24433          }
24434 
paramseq_count() const24435          std::size_t paramseq_count() const
24436          {
24437             return function_definition_list_.size();
24438          }
24439 
paramseq(const std::size_t & index) const24440          std::string paramseq(const std::size_t& index) const
24441          {
24442             return function_definition_list_[index].param_seq;
24443          }
24444 
return_type(const std::size_t & index) const24445          return_type_t return_type(const std::size_t& index) const
24446          {
24447             return function_definition_list_[index].return_type;
24448          }
24449 
invalid() const24450          bool invalid() const
24451          {
24452             return !invalid_state_;
24453          }
24454 
allow_zero_parameters() const24455          bool allow_zero_parameters() const
24456          {
24457 
24458             for (std::size_t i = 0; i < function_definition_list_.size(); ++i)
24459             {
24460                if (std::string::npos != function_definition_list_[i].param_seq.find("Z"))
24461                {
24462                   return true;
24463                }
24464             }
24465 
24466             return false;
24467          }
24468 
24469       private:
24470 
split_param_seq(const std::string & param_seq,const details::char_t delimiter='|') const24471          std::vector<std::string> split_param_seq(const std::string& param_seq, const details::char_t delimiter = '|') const
24472          {
24473              std::string::const_iterator current_begin = param_seq.begin();
24474              std::string::const_iterator iter          = param_seq.begin();
24475 
24476              std::vector<std::string> result;
24477 
24478              while (iter != param_seq.end())
24479              {
24480                  if (*iter == delimiter)
24481                  {
24482                      result.push_back(std::string(current_begin, iter));
24483                      current_begin = ++iter;
24484                  }
24485                  else
24486                      ++iter;
24487              }
24488 
24489              if (current_begin != iter)
24490              {
24491                  result.push_back(std::string(current_begin, iter));
24492              }
24493 
24494              return result;
24495          }
24496 
is_valid_token(std::string param_seq,function_prototype_t & funcproto) const24497          inline bool is_valid_token(std::string param_seq,
24498                                     function_prototype_t& funcproto) const
24499          {
24500             // Determine return type
24501             funcproto.return_type = default_return_type_;
24502 
24503             if (param_seq.size() > 2)
24504             {
24505                if (':' == param_seq[1])
24506                {
24507                   // Note: Only overloaded igeneric functions can have return
24508                   // type definitions.
24509                   if (type_checker::e_overload != default_return_type_)
24510                      return false;
24511 
24512                   switch (param_seq[0])
24513                   {
24514                      case 'T' : funcproto.return_type = type_checker::e_numeric;
24515                                 break;
24516 
24517                      case 'S' : funcproto.return_type = type_checker::e_string;
24518                                 break;
24519 
24520                      default  : return false;
24521                   }
24522 
24523                   param_seq.erase(0,2);
24524                }
24525             }
24526 
24527             if (
24528                  (std::string::npos != param_seq.find("?*")) ||
24529                  (std::string::npos != param_seq.find("**"))
24530                )
24531             {
24532                return false;
24533             }
24534             else if (
24535                       (std::string::npos == param_seq.find_first_not_of("STV*?|")) ||
24536                       ("Z" == param_seq)
24537                     )
24538             {
24539                funcproto.param_seq = param_seq;
24540                return true;
24541             }
24542 
24543             return false;
24544          }
24545 
parse_function_prototypes(const std::string & func_prototypes)24546          void parse_function_prototypes(const std::string& func_prototypes)
24547          {
24548             if (func_prototypes.empty())
24549                return;
24550 
24551             std::vector<std::string> param_seq_list = split_param_seq(func_prototypes);
24552 
24553             typedef std::map<std::string,std::size_t> param_seq_map_t;
24554             param_seq_map_t param_seq_map;
24555 
24556             for (std::size_t i = 0; i < param_seq_list.size(); ++i)
24557             {
24558                function_prototype_t func_proto;
24559 
24560                if (!is_valid_token(param_seq_list[i], func_proto))
24561                {
24562                   invalid_state_ = false;
24563 
24564                   parser_.
24565                      set_error(
24566                         make_error(parser_error::e_syntax,
24567                                    parser_.current_token(),
24568                                    "ERR121 - Invalid parameter sequence of '" + param_seq_list[i] +
24569                                    "' for function: " + function_name_,
24570                                    exprtk_error_location));
24571                   return;
24572                }
24573 
24574                param_seq_map_t::const_iterator seq_itr = param_seq_map.find(param_seq_list[i]);
24575 
24576                if (param_seq_map.end() != seq_itr)
24577                {
24578                   invalid_state_ = false;
24579 
24580                   parser_.
24581                      set_error(
24582                         make_error(parser_error::e_syntax,
24583                                    parser_.current_token(),
24584                                    "ERR122 - Function '" + function_name_ + "' has a parameter sequence conflict between " +
24585                                    "pseq_idx[" + details::to_str(seq_itr->second) + "] and" +
24586                                    "pseq_idx[" + details::to_str(i) + "] " +
24587                                    "param seq: " + param_seq_list[i],
24588                                    exprtk_error_location));
24589                   return;
24590                }
24591 
24592                function_definition_list_.push_back(func_proto);
24593             }
24594          }
24595 
24596          type_checker(const type_checker&);
24597          type_checker& operator=(const type_checker&);
24598 
24599          bool invalid_state_;
24600          parser_t& parser_;
24601          std::string function_name_;
24602          const return_type_t default_return_type_;
24603          function_definition_list_t function_definition_list_;
24604       };
24605 
parse_generic_function_call(igeneric_function<T> * function,const std::string & function_name)24606       inline expression_node_ptr parse_generic_function_call(igeneric_function<T>* function, const std::string& function_name)
24607       {
24608          std::vector<expression_node_ptr> arg_list;
24609 
24610          scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
24611 
24612          next_token();
24613 
24614          std::string param_type_list;
24615 
24616          type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_string);
24617 
24618          if (tc.invalid())
24619          {
24620             set_error(
24621                make_error(parser_error::e_syntax,
24622                           current_token(),
24623                           "ERR123 - Type checker instantiation failure for generic function: " + function_name,
24624                           exprtk_error_location));
24625 
24626             return error_node();
24627          }
24628 
24629          if (token_is(token_t::e_lbracket))
24630          {
24631             if (token_is(token_t::e_rbracket))
24632             {
24633                if (
24634                     !function->allow_zero_parameters() &&
24635                     !tc       .allow_zero_parameters()
24636                   )
24637                {
24638                   set_error(
24639                      make_error(parser_error::e_syntax,
24640                                 current_token(),
24641                                 "ERR124 - Zero parameter call to generic function: "
24642                                 + function_name + " not allowed",
24643                                 exprtk_error_location));
24644 
24645                   return error_node();
24646                }
24647             }
24648             else
24649             {
24650                for ( ; ; )
24651                {
24652                   expression_node_ptr arg = parse_expression();
24653 
24654                   if (0 == arg)
24655                      return error_node();
24656 
24657                   if (is_ivector_node(arg))
24658                      param_type_list += 'V';
24659                   else if (is_generally_string_node(arg))
24660                      param_type_list += 'S';
24661                   else // Everything else is assumed to be a scalar returning expression
24662                      param_type_list += 'T';
24663 
24664                   arg_list.push_back(arg);
24665 
24666                   if (token_is(token_t::e_rbracket))
24667                      break;
24668                   else if (!token_is(token_t::e_comma))
24669                   {
24670                      set_error(
24671                         make_error(parser_error::e_syntax,
24672                                    current_token(),
24673                                    "ERR125 - Expected ',' for call to generic function: " + function_name,
24674                                    exprtk_error_location));
24675 
24676                      return error_node();
24677                   }
24678                }
24679             }
24680          }
24681          else if (
24682                    !function->parameter_sequence.empty() &&
24683                    function->allow_zero_parameters    () &&
24684                    !tc      .allow_zero_parameters    ()
24685                  )
24686          {
24687             set_error(
24688                make_error(parser_error::e_syntax,
24689                           current_token(),
24690                           "ERR126 - Zero parameter call to generic function: "
24691                           + function_name + " not allowed",
24692                           exprtk_error_location));
24693 
24694             return error_node();
24695          }
24696 
24697          std::size_t param_seq_index = 0;
24698 
24699          if (
24700               state_.type_check_enabled &&
24701               !tc.verify(param_type_list, param_seq_index)
24702             )
24703          {
24704             set_error(
24705                make_error(parser_error::e_syntax,
24706                           current_token(),
24707                           "ERR127 - Invalid input parameter sequence for call to generic function: " + function_name,
24708                           exprtk_error_location));
24709 
24710             return error_node();
24711          }
24712 
24713          expression_node_ptr result = error_node();
24714 
24715          if (tc.paramseq_count() <= 1)
24716             result = expression_generator_
24717                        .generic_function_call(function, arg_list);
24718          else
24719             result = expression_generator_
24720                        .generic_function_call(function, arg_list, param_seq_index);
24721 
24722          sdd.delete_ptr = (0 == result);
24723 
24724          return result;
24725       }
24726 
parse_igeneric_function_params(std::string & param_type_list,std::vector<expression_node_ptr> & arg_list,const std::string & function_name,igeneric_function<T> * function,const type_checker & tc)24727       inline bool parse_igeneric_function_params(std::string& param_type_list,
24728                                                  std::vector<expression_node_ptr>& arg_list,
24729                                                  const std::string& function_name,
24730                                                  igeneric_function<T>* function,
24731                                                  const type_checker& tc)
24732       {
24733          if (token_is(token_t::e_lbracket))
24734          {
24735             if (token_is(token_t::e_rbracket))
24736             {
24737                if (
24738                     !function->allow_zero_parameters() &&
24739                     !tc       .allow_zero_parameters()
24740                   )
24741                {
24742                   set_error(
24743                      make_error(parser_error::e_syntax,
24744                                 current_token(),
24745                                 "ERR128 - Zero parameter call to generic function: "
24746                                 + function_name + " not allowed",
24747                                 exprtk_error_location));
24748 
24749                   return false;
24750                }
24751             }
24752             else
24753             {
24754                for ( ; ; )
24755                {
24756                   expression_node_ptr arg = parse_expression();
24757 
24758                   if (0 == arg)
24759                      return false;
24760 
24761                   if (is_ivector_node(arg))
24762                      param_type_list += 'V';
24763                   else if (is_generally_string_node(arg))
24764                      param_type_list += 'S';
24765                   else // Everything else is a scalar returning expression
24766                      param_type_list += 'T';
24767 
24768                   arg_list.push_back(arg);
24769 
24770                   if (token_is(token_t::e_rbracket))
24771                      break;
24772                   else if (!token_is(token_t::e_comma))
24773                   {
24774                      set_error(
24775                         make_error(parser_error::e_syntax,
24776                                    current_token(),
24777                                    "ERR129 - Expected ',' for call to string function: " + function_name,
24778                                    exprtk_error_location));
24779 
24780                      return false;
24781                   }
24782                }
24783             }
24784 
24785             return true;
24786          }
24787          else
24788             return false;
24789       }
24790 
24791       #ifndef exprtk_disable_string_capabilities
parse_string_function_call(igeneric_function<T> * function,const std::string & function_name)24792       inline expression_node_ptr parse_string_function_call(igeneric_function<T>* function, const std::string& function_name)
24793       {
24794          // Move pass the function name
24795          next_token();
24796 
24797          std::string param_type_list;
24798 
24799          type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_string);
24800 
24801          if (
24802               (!function->parameter_sequence.empty()) &&
24803               (0 == tc.paramseq_count())
24804             )
24805          {
24806             return error_node();
24807          }
24808 
24809          std::vector<expression_node_ptr> arg_list;
24810          scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
24811 
24812          if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc))
24813          {
24814             return error_node();
24815          }
24816 
24817          std::size_t param_seq_index = 0;
24818 
24819          if (!tc.verify(param_type_list, param_seq_index))
24820          {
24821             set_error(
24822                make_error(parser_error::e_syntax,
24823                           current_token(),
24824                           "ERR130 - Invalid input parameter sequence for call to string function: " + function_name,
24825                           exprtk_error_location));
24826 
24827             return error_node();
24828          }
24829 
24830          expression_node_ptr result = error_node();
24831 
24832          if (tc.paramseq_count() <= 1)
24833             result = expression_generator_
24834                        .string_function_call(function, arg_list);
24835          else
24836             result = expression_generator_
24837                        .string_function_call(function, arg_list, param_seq_index);
24838 
24839          sdd.delete_ptr = (0 == result);
24840 
24841          return result;
24842       }
24843 
parse_overload_function_call(igeneric_function<T> * function,const std::string & function_name)24844       inline expression_node_ptr parse_overload_function_call(igeneric_function<T>* function, const std::string& function_name)
24845       {
24846          // Move pass the function name
24847          next_token();
24848 
24849          std::string param_type_list;
24850 
24851          type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_overload);
24852 
24853          if (
24854               (!function->parameter_sequence.empty()) &&
24855               (0 == tc.paramseq_count())
24856             )
24857          {
24858             return error_node();
24859          }
24860 
24861          std::vector<expression_node_ptr> arg_list;
24862          scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
24863 
24864          if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc))
24865          {
24866             return error_node();
24867          }
24868 
24869          std::size_t param_seq_index = 0;
24870 
24871          if (!tc.verify(param_type_list, param_seq_index))
24872          {
24873             set_error(
24874                make_error(parser_error::e_syntax,
24875                           current_token(),
24876                           "ERR131 - Invalid input parameter sequence for call to overloaded function: " + function_name,
24877                           exprtk_error_location));
24878 
24879             return error_node();
24880          }
24881 
24882          expression_node_ptr result = error_node();
24883 
24884          if (type_checker::e_numeric == tc.return_type(param_seq_index))
24885          {
24886             if (tc.paramseq_count() <= 1)
24887                result = expression_generator_
24888                           .generic_function_call(function, arg_list);
24889             else
24890                result = expression_generator_
24891                           .generic_function_call(function, arg_list, param_seq_index);
24892          }
24893          else if (type_checker::e_string == tc.return_type(param_seq_index))
24894          {
24895             if (tc.paramseq_count() <= 1)
24896                result = expression_generator_
24897                           .string_function_call(function, arg_list);
24898             else
24899                result = expression_generator_
24900                           .string_function_call(function, arg_list, param_seq_index);
24901          }
24902          else
24903          {
24904             set_error(
24905                make_error(parser_error::e_syntax,
24906                           current_token(),
24907                           "ERR132 - Invalid return type for call to overloaded function: " + function_name,
24908                           exprtk_error_location));
24909          }
24910 
24911          sdd.delete_ptr = (0 == result);
24912          return result;
24913       }
24914       #endif
24915 
24916       template <typename Type, std::size_t NumberOfParameters>
24917       struct parse_special_function_impl
24918       {
processexprtk::parser::parse_special_function_impl24919          static inline expression_node_ptr process(parser<Type>& p, const details::operator_type opt_type, const std::string& sf_name)
24920          {
24921             expression_node_ptr branch[NumberOfParameters];
24922             expression_node_ptr result = error_node();
24923 
24924             std::fill_n(branch, NumberOfParameters, reinterpret_cast<expression_node_ptr>(0));
24925 
24926             scoped_delete<expression_node_t,NumberOfParameters> sd(p,branch);
24927 
24928             p.next_token();
24929 
24930             if (!p.token_is(token_t::e_lbracket))
24931             {
24932                p.set_error(
24933                     make_error(parser_error::e_syntax,
24934                                p.current_token(),
24935                                "ERR133 - Expected '(' for special function '" + sf_name + "'",
24936                                exprtk_error_location));
24937 
24938                return error_node();
24939             }
24940 
24941             for (std::size_t i = 0; i < NumberOfParameters; ++i)
24942             {
24943                branch[i] = p.parse_expression();
24944 
24945                if (0 == branch[i])
24946                {
24947                   return p.error_node();
24948                }
24949                else if (i < (NumberOfParameters - 1))
24950                {
24951                   if (!p.token_is(token_t::e_comma))
24952                   {
24953                      p.set_error(
24954                           make_error(parser_error::e_syntax,
24955                                      p.current_token(),
24956                                      "ERR134 - Expected ',' before next parameter of special function '" + sf_name + "'",
24957                                      exprtk_error_location));
24958 
24959                      return p.error_node();
24960                   }
24961                }
24962             }
24963 
24964             if (!p.token_is(token_t::e_rbracket))
24965             {
24966                p.set_error(
24967                     make_error(parser_error::e_syntax,
24968                                p.current_token(),
24969                                "ERR135 - Invalid number of parameters for special function '" + sf_name + "'",
24970                                exprtk_error_location));
24971 
24972                return p.error_node();
24973             }
24974             else
24975                result = p.expression_generator_.special_function(opt_type,branch);
24976 
24977             sd.delete_ptr = (0 == result);
24978 
24979             return result;
24980          }
24981       };
24982 
parse_special_function()24983       inline expression_node_ptr parse_special_function()
24984       {
24985          const std::string sf_name = current_token().value;
24986 
24987          // Expect: $fDD(expr0,expr1,expr2) or $fDD(expr0,expr1,expr2,expr3)
24988          if (
24989               !details::is_digit(sf_name[2]) ||
24990               !details::is_digit(sf_name[3])
24991             )
24992          {
24993             set_error(
24994                make_error(parser_error::e_token,
24995                           current_token(),
24996                           "ERR136 - Invalid special function[1]: " + sf_name,
24997                           exprtk_error_location));
24998 
24999             return error_node();
25000          }
25001 
25002          const int id = (sf_name[2] - '0') * 10 +
25003                         (sf_name[3] - '0');
25004 
25005          if (id >= details::e_sffinal)
25006          {
25007             set_error(
25008                make_error(parser_error::e_token,
25009                           current_token(),
25010                           "ERR137 - Invalid special function[2]: " + sf_name,
25011                           exprtk_error_location));
25012 
25013             return error_node();
25014          }
25015 
25016          const int sf_3_to_4                   = details::e_sf48;
25017          const details::operator_type opt_type = details::operator_type(id + 1000);
25018          const std::size_t NumberOfParameters  = (id < (sf_3_to_4 - 1000)) ? 3U : 4U;
25019 
25020          switch (NumberOfParameters)
25021          {
25022             case 3  : return parse_special_function_impl<T,3>::process((*this), opt_type, sf_name);
25023             case 4  : return parse_special_function_impl<T,4>::process((*this), opt_type, sf_name);
25024             default : return error_node();
25025          }
25026       }
25027 
parse_null_statement()25028       inline expression_node_ptr parse_null_statement()
25029       {
25030          next_token();
25031          return node_allocator_.allocate<details::null_node<T> >();
25032       }
25033 
25034       #ifndef exprtk_disable_break_continue
parse_break_statement()25035       inline expression_node_ptr parse_break_statement()
25036       {
25037          if (state_.parsing_break_stmt)
25038          {
25039             set_error(
25040                make_error(parser_error::e_syntax,
25041                           current_token(),
25042                           "ERR138 - Invoking 'break' within a break call is not allowed",
25043                           exprtk_error_location));
25044 
25045             return error_node();
25046          }
25047          else if (0 == state_.parsing_loop_stmt_count)
25048          {
25049             set_error(
25050                make_error(parser_error::e_syntax,
25051                           current_token(),
25052                           "ERR139 - Invalid use of 'break', allowed only in the scope of a loop",
25053                           exprtk_error_location));
25054 
25055             return error_node();
25056          }
25057 
25058          scoped_bool_negator sbn(state_.parsing_break_stmt);
25059 
25060          if (!brkcnt_list_.empty())
25061          {
25062             next_token();
25063 
25064             brkcnt_list_.front() = true;
25065 
25066             expression_node_ptr return_expr = error_node();
25067 
25068             if (token_is(token_t::e_lsqrbracket))
25069             {
25070                if (0 == (return_expr = parse_expression()))
25071                {
25072                   set_error(
25073                      make_error(parser_error::e_syntax,
25074                                 current_token(),
25075                                 "ERR140 - Failed to parse return expression for 'break' statement",
25076                                 exprtk_error_location));
25077 
25078                   return error_node();
25079                }
25080                else if (!token_is(token_t::e_rsqrbracket))
25081                {
25082                   set_error(
25083                      make_error(parser_error::e_syntax,
25084                                 current_token(),
25085                                 "ERR141 - Expected ']' at the completion of break's return expression",
25086                                 exprtk_error_location));
25087 
25088                   free_node(node_allocator_,return_expr);
25089 
25090                   return error_node();
25091                }
25092             }
25093 
25094             state_.activate_side_effect("parse_break_statement()");
25095 
25096             return node_allocator_.allocate<details::break_node<T> >(return_expr);
25097          }
25098          else
25099          {
25100             set_error(
25101                make_error(parser_error::e_syntax,
25102                           current_token(),
25103                           "ERR142 - Invalid use of 'break', allowed only in the scope of a loop",
25104                           exprtk_error_location));
25105          }
25106 
25107          return error_node();
25108       }
25109 
parse_continue_statement()25110       inline expression_node_ptr parse_continue_statement()
25111       {
25112          if (0 == state_.parsing_loop_stmt_count)
25113          {
25114             set_error(
25115                make_error(parser_error::e_syntax,
25116                           current_token(),
25117                           "ERR143 - Invalid use of 'continue', allowed only in the scope of a loop",
25118                           exprtk_error_location));
25119 
25120             return error_node();
25121          }
25122          else
25123          {
25124             next_token();
25125 
25126             brkcnt_list_.front() = true;
25127             state_.activate_side_effect("parse_continue_statement()");
25128 
25129             return node_allocator_.allocate<details::continue_node<T> >();
25130          }
25131       }
25132       #endif
25133 
parse_define_vector_statement(const std::string & vec_name)25134       inline expression_node_ptr parse_define_vector_statement(const std::string& vec_name)
25135       {
25136          expression_node_ptr size_expr = error_node();
25137 
25138          if (!token_is(token_t::e_lsqrbracket))
25139          {
25140             set_error(
25141                make_error(parser_error::e_syntax,
25142                           current_token(),
25143                           "ERR144 - Expected '[' as part of vector size definition",
25144                           exprtk_error_location));
25145 
25146             return error_node();
25147          }
25148          else if (0 == (size_expr = parse_expression()))
25149          {
25150             set_error(
25151                make_error(parser_error::e_syntax,
25152                           current_token(),
25153                           "ERR145 - Failed to determine size of vector '" + vec_name + "'",
25154                           exprtk_error_location));
25155 
25156             return error_node();
25157          }
25158          else if (!is_constant_node(size_expr))
25159          {
25160             free_node(node_allocator_,size_expr);
25161 
25162             set_error(
25163                make_error(parser_error::e_syntax,
25164                           current_token(),
25165                           "ERR146 - Expected a literal number as size of vector '" + vec_name + "'",
25166                           exprtk_error_location));
25167 
25168             return error_node();
25169          }
25170 
25171          const T vector_size = size_expr->value();
25172 
25173          free_node(node_allocator_,size_expr);
25174 
25175          const T max_vector_size = T(2000000000.0);
25176 
25177          if (
25178               (vector_size <= T(0)) ||
25179               std::not_equal_to<T>()
25180               (T(0),vector_size - details::numeric::trunc(vector_size)) ||
25181               (vector_size > max_vector_size)
25182             )
25183          {
25184             set_error(
25185                make_error(parser_error::e_syntax,
25186                           current_token(),
25187                           "ERR147 - Invalid vector size. Must be an integer in the range [0,2e9], size: " +
25188                           details::to_str(details::numeric::to_int32(vector_size)),
25189                           exprtk_error_location));
25190 
25191             return error_node();
25192          }
25193 
25194          std::vector<expression_node_ptr> vec_initilizer_list;
25195 
25196          scoped_vec_delete<expression_node_t> svd((*this),vec_initilizer_list);
25197 
25198          bool single_value_initialiser = false;
25199          bool vec_to_vec_initialiser   = false;
25200          bool null_initialisation      = false;
25201 
25202          if (!token_is(token_t::e_rsqrbracket))
25203          {
25204             set_error(
25205                make_error(parser_error::e_syntax,
25206                           current_token(),
25207                           "ERR148 - Expected ']' as part of vector size definition",
25208                           exprtk_error_location));
25209 
25210             return error_node();
25211          }
25212          else if (!token_is(token_t::e_eof))
25213          {
25214             if (!token_is(token_t::e_assign))
25215             {
25216                set_error(
25217                   make_error(parser_error::e_syntax,
25218                              current_token(),
25219                              "ERR149 - Expected ':=' as part of vector definition",
25220                              exprtk_error_location));
25221 
25222                return error_node();
25223             }
25224             else if (token_is(token_t::e_lsqrbracket))
25225             {
25226                expression_node_ptr initialiser = parse_expression();
25227 
25228                if (0 == initialiser)
25229                {
25230                   set_error(
25231                      make_error(parser_error::e_syntax,
25232                                 current_token(),
25233                                 "ERR150 - Failed to parse single vector initialiser",
25234                                 exprtk_error_location));
25235 
25236                   return error_node();
25237                }
25238 
25239                vec_initilizer_list.push_back(initialiser);
25240 
25241                if (!token_is(token_t::e_rsqrbracket))
25242                {
25243                   set_error(
25244                      make_error(parser_error::e_syntax,
25245                                 current_token(),
25246                                 "ERR151 - Expected ']' to close single value vector initialiser",
25247                                 exprtk_error_location));
25248 
25249                   return error_node();
25250                }
25251 
25252                single_value_initialiser = true;
25253             }
25254             else if (!token_is(token_t::e_lcrlbracket))
25255             {
25256                expression_node_ptr initialiser = error_node();
25257 
25258                // Is this a vector to vector assignment and initialisation?
25259                if (token_t::e_symbol == current_token().type)
25260                {
25261                   // Is it a locally defined vector?
25262                   const scope_element& se = sem_.get_active_element(current_token().value);
25263 
25264                   if (scope_element::e_vector == se.type)
25265                   {
25266                      if (0 != (initialiser = parse_expression()))
25267                         vec_initilizer_list.push_back(initialiser);
25268                      else
25269                         return error_node();
25270                   }
25271                   // Are we dealing with a user defined vector?
25272                   else if (symtab_store_.is_vector(current_token().value))
25273                   {
25274                      lodge_symbol(current_token().value, e_st_vector);
25275 
25276                      if (0 != (initialiser = parse_expression()))
25277                         vec_initilizer_list.push_back(initialiser);
25278                      else
25279                         return error_node();
25280                   }
25281                   // Are we dealing with a null initialisation vector definition?
25282                   else if (token_is(token_t::e_symbol,"null"))
25283                      null_initialisation = true;
25284                }
25285 
25286                if (!null_initialisation)
25287                {
25288                   if (0 == initialiser)
25289                   {
25290                      set_error(
25291                         make_error(parser_error::e_syntax,
25292                                    current_token(),
25293                                    "ERR152 - Expected '{' as part of vector initialiser list",
25294                                    exprtk_error_location));
25295 
25296                      return error_node();
25297                   }
25298                   else
25299                      vec_to_vec_initialiser = true;
25300                }
25301             }
25302             else if (!token_is(token_t::e_rcrlbracket))
25303             {
25304                for ( ; ; )
25305                {
25306                   expression_node_ptr initialiser = parse_expression();
25307 
25308                   if (0 == initialiser)
25309                   {
25310                      set_error(
25311                         make_error(parser_error::e_syntax,
25312                                    current_token(),
25313                                    "ERR153 - Expected '{' as part of vector initialiser list",
25314                                    exprtk_error_location));
25315 
25316                      return error_node();
25317                   }
25318                   else
25319                      vec_initilizer_list.push_back(initialiser);
25320 
25321                   if (token_is(token_t::e_rcrlbracket))
25322                      break;
25323 
25324                   const bool is_next_close = peek_token_is(token_t::e_rcrlbracket);
25325 
25326                   if (!token_is(token_t::e_comma) && is_next_close)
25327                   {
25328                      set_error(
25329                         make_error(parser_error::e_syntax,
25330                                    current_token(),
25331                                    "ERR154 - Expected ',' between vector initialisers",
25332                                    exprtk_error_location));
25333 
25334                      return error_node();
25335                   }
25336 
25337                   if (token_is(token_t::e_rcrlbracket))
25338                      break;
25339                }
25340             }
25341 
25342             if (
25343                  !token_is(token_t::e_rbracket   , prsrhlpr_t::e_hold) &&
25344                  !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) &&
25345                  !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold)
25346                )
25347             {
25348                if (!token_is(token_t::e_eof))
25349                {
25350                   set_error(
25351                      make_error(parser_error::e_syntax,
25352                                 current_token(),
25353                                 "ERR155 - Expected ';' at end of vector definition",
25354                                 exprtk_error_location));
25355 
25356                   return error_node();
25357                }
25358             }
25359 
25360             if (vec_initilizer_list.size() > vector_size)
25361             {
25362                set_error(
25363                   make_error(parser_error::e_syntax,
25364                              current_token(),
25365                              "ERR156 - Initialiser list larger than the number of elements in the vector: '" + vec_name + "'",
25366                              exprtk_error_location));
25367 
25368                return error_node();
25369             }
25370          }
25371 
25372          typename symbol_table_t::vector_holder_ptr vec_holder = typename symbol_table_t::vector_holder_ptr(0);
25373 
25374          const std::size_t vec_size = static_cast<std::size_t>(details::numeric::to_int32(vector_size));
25375 
25376          scope_element& se = sem_.get_element(vec_name);
25377 
25378          if (se.name == vec_name)
25379          {
25380             if (se.active)
25381             {
25382                set_error(
25383                   make_error(parser_error::e_syntax,
25384                              current_token(),
25385                              "ERR157 - Illegal redefinition of local vector: '" + vec_name + "'",
25386                              exprtk_error_location));
25387 
25388                return error_node();
25389             }
25390             else if (
25391                       (se.size == vec_size) &&
25392                       (scope_element::e_vector == se.type)
25393                     )
25394             {
25395                vec_holder = se.vec_node;
25396                se.active  = true;
25397                se.depth   = state_.scope_depth;
25398                se.ref_count++;
25399             }
25400          }
25401 
25402          if (0 == vec_holder)
25403          {
25404             scope_element nse;
25405             nse.name      = vec_name;
25406             nse.active    = true;
25407             nse.ref_count = 1;
25408             nse.type      = scope_element::e_vector;
25409             nse.depth     = state_.scope_depth;
25410             nse.size      = vec_size;
25411             nse.data      = new T[vec_size];
25412             nse.vec_node  = new typename scope_element::vector_holder_t(reinterpret_cast<T*>(nse.data),nse.size);
25413 
25414             if (!sem_.add_element(nse))
25415             {
25416                set_error(
25417                   make_error(parser_error::e_syntax,
25418                              current_token(),
25419                              "ERR158 - Failed to add new local vector '" + vec_name + "' to SEM",
25420                              exprtk_error_location));
25421 
25422                sem_.free_element(nse);
25423 
25424                return error_node();
25425             }
25426 
25427             vec_holder = nse.vec_node;
25428 
25429             exprtk_debug(("parse_define_vector_statement() - INFO - Added new local vector: %s[%d]\n",
25430                           nse.name.c_str(),
25431                           static_cast<int>(nse.size)));
25432          }
25433 
25434          state_.activate_side_effect("parse_define_vector_statement()");
25435 
25436          lodge_symbol(vec_name, e_st_local_vector);
25437 
25438          expression_node_ptr result = error_node();
25439 
25440          if (null_initialisation)
25441             result = expression_generator_(T(0.0));
25442          else if (vec_to_vec_initialiser)
25443          {
25444             expression_node_ptr vec_node = node_allocator_.allocate<vector_node_t>(vec_holder);
25445 
25446             result = expression_generator_(
25447                         details::e_assign,
25448                         vec_node,
25449                         vec_initilizer_list[0]);
25450          }
25451          else
25452             result = node_allocator_
25453                         .allocate<details::vector_assignment_node<T> >(
25454                            (*vec_holder)[0],
25455                            vec_size,
25456                            vec_initilizer_list,
25457                            single_value_initialiser);
25458 
25459          svd.delete_ptr = (0 == result);
25460 
25461          return result;
25462       }
25463 
25464       #ifndef exprtk_disable_string_capabilities
parse_define_string_statement(const std::string & str_name,expression_node_ptr initialisation_expression)25465       inline expression_node_ptr parse_define_string_statement(const std::string& str_name, expression_node_ptr initialisation_expression)
25466       {
25467          stringvar_node_t* str_node = reinterpret_cast<stringvar_node_t*>(0);
25468 
25469          scope_element& se = sem_.get_element(str_name);
25470 
25471          if (se.name == str_name)
25472          {
25473             if (se.active)
25474             {
25475                set_error(
25476                   make_error(parser_error::e_syntax,
25477                              current_token(),
25478                              "ERR159 - Illegal redefinition of local variable: '" + str_name + "'",
25479                              exprtk_error_location));
25480 
25481                free_node(node_allocator_,initialisation_expression);
25482 
25483                return error_node();
25484             }
25485             else if (scope_element::e_string == se.type)
25486             {
25487                str_node  = se.str_node;
25488                se.active = true;
25489                se.depth  = state_.scope_depth;
25490                se.ref_count++;
25491             }
25492          }
25493 
25494          if (0 == str_node)
25495          {
25496             scope_element nse;
25497             nse.name      = str_name;
25498             nse.active    = true;
25499             nse.ref_count = 1;
25500             nse.type      = scope_element::e_string;
25501             nse.depth     = state_.scope_depth;
25502             nse.data      = new std::string;
25503             nse.str_node  = new stringvar_node_t(*reinterpret_cast<std::string*>(nse.data));
25504 
25505             if (!sem_.add_element(nse))
25506             {
25507                set_error(
25508                   make_error(parser_error::e_syntax,
25509                              current_token(),
25510                              "ERR160 - Failed to add new local string variable '" + str_name + "' to SEM",
25511                              exprtk_error_location));
25512 
25513                free_node(node_allocator_,initialisation_expression);
25514 
25515                sem_.free_element(nse);
25516 
25517                return error_node();
25518             }
25519 
25520             str_node = nse.str_node;
25521 
25522             exprtk_debug(("parse_define_string_statement() - INFO - Added new local string variable: %s\n",nse.name.c_str()));
25523          }
25524 
25525          lodge_symbol(str_name, e_st_local_string);
25526 
25527          state_.activate_side_effect("parse_define_string_statement()");
25528 
25529          expression_node_ptr branch[2] = {0};
25530 
25531          branch[0] = str_node;
25532          branch[1] = initialisation_expression;
25533 
25534          return expression_generator_(details::e_assign,branch);
25535       }
25536       #else
parse_define_string_statement(const std::string &,expression_node_ptr)25537       inline expression_node_ptr parse_define_string_statement(const std::string&, expression_node_ptr)
25538       {
25539          return error_node();
25540       }
25541       #endif
25542 
local_variable_is_shadowed(const std::string & symbol)25543       inline bool local_variable_is_shadowed(const std::string& symbol)
25544       {
25545          const scope_element& se = sem_.get_element(symbol);
25546          return (se.name == symbol) && se.active;
25547       }
25548 
parse_define_var_statement()25549       inline expression_node_ptr parse_define_var_statement()
25550       {
25551          if (settings_.vardef_disabled())
25552          {
25553             set_error(
25554                make_error(parser_error::e_syntax,
25555                           current_token(),
25556                           "ERR161 - Illegal variable definition",
25557                           exprtk_error_location));
25558 
25559             return error_node();
25560          }
25561          else if (!details::imatch(current_token().value,"var"))
25562          {
25563             return error_node();
25564          }
25565          else
25566             next_token();
25567 
25568          const std::string var_name = current_token().value;
25569 
25570          expression_node_ptr initialisation_expression = error_node();
25571 
25572          if (!token_is(token_t::e_symbol))
25573          {
25574             set_error(
25575                make_error(parser_error::e_syntax,
25576                           current_token(),
25577                           "ERR162 - Expected a symbol for variable definition",
25578                           exprtk_error_location));
25579 
25580             return error_node();
25581          }
25582          else if (details::is_reserved_symbol(var_name))
25583          {
25584             set_error(
25585                make_error(parser_error::e_syntax,
25586                           current_token(),
25587                           "ERR163 - Illegal redefinition of reserved keyword: '" + var_name + "'",
25588                           exprtk_error_location));
25589 
25590             return error_node();
25591          }
25592          else if (symtab_store_.symbol_exists(var_name))
25593          {
25594             set_error(
25595                make_error(parser_error::e_syntax,
25596                           current_token(),
25597                           "ERR164 - Illegal redefinition of variable '" + var_name + "'",
25598                           exprtk_error_location));
25599 
25600             return error_node();
25601          }
25602          else if (local_variable_is_shadowed(var_name))
25603          {
25604             set_error(
25605                make_error(parser_error::e_syntax,
25606                           current_token(),
25607                           "ERR165 - Illegal redefinition of local variable: '" + var_name + "'",
25608                           exprtk_error_location));
25609 
25610             return error_node();
25611          }
25612          else if (token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold))
25613          {
25614             return parse_define_vector_statement(var_name);
25615          }
25616          else if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
25617          {
25618             return parse_uninitialised_var_statement(var_name);
25619          }
25620          else if (token_is(token_t::e_assign))
25621          {
25622             if (0 == (initialisation_expression = parse_expression()))
25623             {
25624                set_error(
25625                   make_error(parser_error::e_syntax,
25626                              current_token(),
25627                              "ERR166 - Failed to parse initialisation expression",
25628                              exprtk_error_location));
25629 
25630                return error_node();
25631             }
25632          }
25633 
25634          if (
25635               !token_is(token_t::e_rbracket   , prsrhlpr_t::e_hold) &&
25636               !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) &&
25637               !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold)
25638             )
25639          {
25640             if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold))
25641             {
25642                set_error(
25643                   make_error(parser_error::e_syntax,
25644                              current_token(),
25645                              "ERR167 - Expected ';' after variable definition",
25646                              exprtk_error_location));
25647 
25648                free_node(node_allocator_,initialisation_expression);
25649 
25650                return error_node();
25651             }
25652          }
25653 
25654          if (
25655               (0 != initialisation_expression) &&
25656               details::is_generally_string_node(initialisation_expression)
25657             )
25658          {
25659             return parse_define_string_statement(var_name,initialisation_expression);
25660          }
25661 
25662          expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0);
25663 
25664          scope_element& se = sem_.get_element(var_name);
25665 
25666          if (se.name == var_name)
25667          {
25668             if (se.active)
25669             {
25670                set_error(
25671                   make_error(parser_error::e_syntax,
25672                              current_token(),
25673                              "ERR168 - Illegal redefinition of local variable: '" + var_name + "'",
25674                              exprtk_error_location));
25675 
25676                free_node(node_allocator_, initialisation_expression);
25677 
25678                return error_node();
25679             }
25680             else if (scope_element::e_variable == se.type)
25681             {
25682                var_node  = se.var_node;
25683                se.active = true;
25684                se.depth  = state_.scope_depth;
25685                se.ref_count++;
25686             }
25687          }
25688 
25689          if (0 == var_node)
25690          {
25691             scope_element nse;
25692             nse.name      = var_name;
25693             nse.active    = true;
25694             nse.ref_count = 1;
25695             nse.type      = scope_element::e_variable;
25696             nse.depth     = state_.scope_depth;
25697             nse.data      = new T(T(0));
25698             nse.var_node  = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data));
25699 
25700             if (!sem_.add_element(nse))
25701             {
25702                set_error(
25703                   make_error(parser_error::e_syntax,
25704                              current_token(),
25705                              "ERR169 - Failed to add new local variable '" + var_name + "' to SEM",
25706                              exprtk_error_location));
25707 
25708                free_node(node_allocator_, initialisation_expression);
25709 
25710                sem_.free_element(nse);
25711 
25712                return error_node();
25713             }
25714 
25715             var_node = nse.var_node;
25716 
25717             exprtk_debug(("parse_define_var_statement() - INFO - Added new local variable: %s\n",nse.name.c_str()));
25718          }
25719 
25720          state_.activate_side_effect("parse_define_var_statement()");
25721 
25722          lodge_symbol(var_name, e_st_local_variable);
25723 
25724          expression_node_ptr branch[2] = {0};
25725 
25726          branch[0] = var_node;
25727          branch[1] = initialisation_expression ? initialisation_expression : expression_generator_(T(0));
25728 
25729          return expression_generator_(details::e_assign,branch);
25730       }
25731 
parse_uninitialised_var_statement(const std::string & var_name)25732       inline expression_node_ptr parse_uninitialised_var_statement(const std::string& var_name)
25733       {
25734          if (
25735               !token_is(token_t::e_lcrlbracket) ||
25736               !token_is(token_t::e_rcrlbracket)
25737             )
25738          {
25739             set_error(
25740                make_error(parser_error::e_syntax,
25741                           current_token(),
25742                           "ERR170 - Expected a '{}' for uninitialised var definition",
25743                           exprtk_error_location));
25744 
25745             return error_node();
25746          }
25747          else if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold))
25748          {
25749             set_error(
25750                make_error(parser_error::e_syntax,
25751                           current_token(),
25752                           "ERR171 - Expected ';' after uninitialised variable definition",
25753                           exprtk_error_location));
25754 
25755             return error_node();
25756          }
25757 
25758          expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0);
25759 
25760          scope_element& se = sem_.get_element(var_name);
25761 
25762          if (se.name == var_name)
25763          {
25764             if (se.active)
25765             {
25766                set_error(
25767                   make_error(parser_error::e_syntax,
25768                              current_token(),
25769                              "ERR172 - Illegal redefinition of local variable: '" + var_name + "'",
25770                              exprtk_error_location));
25771 
25772                return error_node();
25773             }
25774             else if (scope_element::e_variable == se.type)
25775             {
25776                var_node  = se.var_node;
25777                se.active = true;
25778                se.ref_count++;
25779             }
25780          }
25781 
25782          if (0 == var_node)
25783          {
25784             scope_element nse;
25785             nse.name      = var_name;
25786             nse.active    = true;
25787             nse.ref_count = 1;
25788             nse.type      = scope_element::e_variable;
25789             nse.depth     = state_.scope_depth;
25790             nse.ip_index  = sem_.next_ip_index();
25791             nse.data      = new T(T(0));
25792             nse.var_node  = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data));
25793 
25794             if (!sem_.add_element(nse))
25795             {
25796                set_error(
25797                   make_error(parser_error::e_syntax,
25798                              current_token(),
25799                              "ERR173 - Failed to add new local variable '" + var_name + "' to SEM",
25800                              exprtk_error_location));
25801 
25802                sem_.free_element(nse);
25803 
25804                return error_node();
25805             }
25806 
25807             exprtk_debug(("parse_uninitialised_var_statement() - INFO - Added new local variable: %s\n",
25808                           nse.name.c_str()));
25809          }
25810 
25811          lodge_symbol(var_name, e_st_local_variable);
25812 
25813          state_.activate_side_effect("parse_uninitialised_var_statement()");
25814 
25815          return expression_generator_(T(0));
25816       }
25817 
parse_swap_statement()25818       inline expression_node_ptr parse_swap_statement()
25819       {
25820          if (!details::imatch(current_token().value,"swap"))
25821          {
25822             return error_node();
25823          }
25824          else
25825             next_token();
25826 
25827          if (!token_is(token_t::e_lbracket))
25828          {
25829             set_error(
25830                make_error(parser_error::e_syntax,
25831                           current_token(),
25832                           "ERR174 - Expected '(' at start of swap statement",
25833                           exprtk_error_location));
25834 
25835             return error_node();
25836          }
25837 
25838          expression_node_ptr variable0 = error_node();
25839          expression_node_ptr variable1 = error_node();
25840 
25841          bool variable0_generated = false;
25842          bool variable1_generated = false;
25843 
25844          const std::string var0_name = current_token().value;
25845 
25846          if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold))
25847          {
25848             set_error(
25849                make_error(parser_error::e_syntax,
25850                           current_token(),
25851                           "ERR175 - Expected a symbol for variable or vector element definition",
25852                           exprtk_error_location));
25853 
25854             return error_node();
25855          }
25856          else if (peek_token_is(token_t::e_lsqrbracket))
25857          {
25858             if (0 == (variable0 = parse_vector()))
25859             {
25860                set_error(
25861                   make_error(parser_error::e_syntax,
25862                              current_token(),
25863                              "ERR176 - First parameter to swap is an invalid vector element: '" + var0_name + "'",
25864                              exprtk_error_location));
25865 
25866                return error_node();
25867             }
25868 
25869             variable0_generated = true;
25870          }
25871          else
25872          {
25873             if (symtab_store_.is_variable(var0_name))
25874             {
25875                variable0 = symtab_store_.get_variable(var0_name);
25876             }
25877 
25878             const scope_element& se = sem_.get_element(var0_name);
25879 
25880             if (
25881                  (se.active)            &&
25882                  (se.name == var0_name) &&
25883                  (scope_element::e_variable == se.type)
25884                )
25885             {
25886                variable0 = se.var_node;
25887             }
25888 
25889             lodge_symbol(var0_name, e_st_variable);
25890 
25891             if (0 == variable0)
25892             {
25893                set_error(
25894                   make_error(parser_error::e_syntax,
25895                              current_token(),
25896                              "ERR177 - First parameter to swap is an invalid variable: '" + var0_name + "'",
25897                              exprtk_error_location));
25898 
25899                return error_node();
25900             }
25901             else
25902                next_token();
25903          }
25904 
25905          if (!token_is(token_t::e_comma))
25906          {
25907             set_error(
25908                 make_error(parser_error::e_syntax,
25909                            current_token(),
25910                            "ERR178 - Expected ',' between parameters to swap",
25911                            exprtk_error_location));
25912 
25913             if (variable0_generated)
25914             {
25915                free_node(node_allocator_,variable0);
25916             }
25917 
25918             return error_node();
25919          }
25920 
25921          const std::string var1_name = current_token().value;
25922 
25923          if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold))
25924          {
25925             set_error(
25926                make_error(parser_error::e_syntax,
25927                           current_token(),
25928                           "ERR179 - Expected a symbol for variable or vector element definition",
25929                           exprtk_error_location));
25930 
25931             if (variable0_generated)
25932             {
25933                free_node(node_allocator_,variable0);
25934             }
25935 
25936             return error_node();
25937          }
25938          else if (peek_token_is(token_t::e_lsqrbracket))
25939          {
25940             if (0 == (variable1 = parse_vector()))
25941             {
25942                set_error(
25943                   make_error(parser_error::e_syntax,
25944                              current_token(),
25945                              "ERR180 - Second parameter to swap is an invalid vector element: '" + var1_name + "'",
25946                              exprtk_error_location));
25947 
25948                if (variable0_generated)
25949                {
25950                   free_node(node_allocator_,variable0);
25951                }
25952 
25953                return error_node();
25954             }
25955 
25956             variable1_generated = true;
25957          }
25958          else
25959          {
25960             if (symtab_store_.is_variable(var1_name))
25961             {
25962                variable1 = symtab_store_.get_variable(var1_name);
25963             }
25964 
25965             const scope_element& se = sem_.get_element(var1_name);
25966 
25967             if (
25968                  (se.active) &&
25969                  (se.name == var1_name) &&
25970                  (scope_element::e_variable == se.type)
25971                )
25972             {
25973                variable1 = se.var_node;
25974             }
25975 
25976             lodge_symbol(var1_name, e_st_variable);
25977 
25978             if (0 == variable1)
25979             {
25980                set_error(
25981                   make_error(parser_error::e_syntax,
25982                              current_token(),
25983                              "ERR181 - Second parameter to swap is an invalid variable: '" + var1_name + "'",
25984                              exprtk_error_location));
25985 
25986                if (variable0_generated)
25987                {
25988                   free_node(node_allocator_,variable0);
25989                }
25990 
25991                return error_node();
25992             }
25993             else
25994                next_token();
25995          }
25996 
25997          if (!token_is(token_t::e_rbracket))
25998          {
25999             set_error(
26000                make_error(parser_error::e_syntax,
26001                           current_token(),
26002                           "ERR182 - Expected ')' at end of swap statement",
26003                           exprtk_error_location));
26004 
26005             if (variable0_generated)
26006             {
26007                free_node(node_allocator_,variable0);
26008             }
26009 
26010             if (variable1_generated)
26011             {
26012                free_node(node_allocator_,variable1);
26013             }
26014 
26015             return error_node();
26016          }
26017 
26018          typedef details::variable_node<T>* variable_node_ptr;
26019 
26020          variable_node_ptr v0 = variable_node_ptr(0);
26021          variable_node_ptr v1 = variable_node_ptr(0);
26022 
26023          expression_node_ptr result = error_node();
26024 
26025          if (
26026               (0 != (v0 = dynamic_cast<variable_node_ptr>(variable0))) &&
26027               (0 != (v1 = dynamic_cast<variable_node_ptr>(variable1)))
26028             )
26029          {
26030             result = node_allocator_.allocate<details::swap_node<T> >(v0, v1);
26031 
26032             if (variable0_generated)
26033             {
26034                free_node(node_allocator_,variable0);
26035             }
26036 
26037             if (variable1_generated)
26038             {
26039                free_node(node_allocator_,variable1);
26040             }
26041          }
26042          else
26043             result = node_allocator_.allocate<details::swap_generic_node<T> >
26044                         (variable0, variable1);
26045 
26046          state_.activate_side_effect("parse_swap_statement()");
26047 
26048          return result;
26049       }
26050 
26051       #ifndef exprtk_disable_return_statement
parse_return_statement()26052       inline expression_node_ptr parse_return_statement()
26053       {
26054          if (state_.parsing_return_stmt)
26055          {
26056             set_error(
26057                make_error(parser_error::e_syntax,
26058                           current_token(),
26059                           "ERR183 - Return call within a return call is not allowed",
26060                           exprtk_error_location));
26061 
26062             return error_node();
26063          }
26064 
26065          scoped_bool_negator sbn(state_.parsing_return_stmt);
26066 
26067          std::vector<expression_node_ptr> arg_list;
26068 
26069          scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
26070 
26071          if (!details::imatch(current_token().value,"return"))
26072          {
26073             return error_node();
26074          }
26075          else
26076             next_token();
26077 
26078          if (!token_is(token_t::e_lsqrbracket))
26079          {
26080             set_error(
26081                make_error(parser_error::e_syntax,
26082                           current_token(),
26083                           "ERR184 - Expected '[' at start of return statement",
26084                           exprtk_error_location));
26085 
26086             return error_node();
26087          }
26088          else if (!token_is(token_t::e_rsqrbracket))
26089          {
26090             for ( ; ; )
26091             {
26092                expression_node_ptr arg = parse_expression();
26093 
26094                if (0 == arg)
26095                   return error_node();
26096 
26097                arg_list.push_back(arg);
26098 
26099                if (token_is(token_t::e_rsqrbracket))
26100                   break;
26101                else if (!token_is(token_t::e_comma))
26102                {
26103                   set_error(
26104                      make_error(parser_error::e_syntax,
26105                                 current_token(),
26106                                 "ERR185 - Expected ',' between values during call to return",
26107                                 exprtk_error_location));
26108 
26109                   return error_node();
26110                }
26111             }
26112          }
26113          else if (settings_.zero_return_disabled())
26114          {
26115             set_error(
26116                make_error(parser_error::e_syntax,
26117                           current_token(),
26118                           "ERR186 - Zero parameter return statement not allowed",
26119                           exprtk_error_location));
26120 
26121             return error_node();
26122          }
26123 
26124          const lexer::token prev_token = current_token();
26125 
26126          if (token_is(token_t::e_rsqrbracket))
26127          {
26128             if (!arg_list.empty())
26129             {
26130                set_error(
26131                   make_error(parser_error::e_syntax,
26132                              prev_token,
26133                              "ERR187 - Invalid ']' found during return call",
26134                              exprtk_error_location));
26135 
26136                return error_node();
26137             }
26138          }
26139 
26140          std::string ret_param_type_list;
26141 
26142          for (std::size_t i = 0; i < arg_list.size(); ++i)
26143          {
26144             if (0 == arg_list[i])
26145                return error_node();
26146             else if (is_ivector_node(arg_list[i]))
26147                ret_param_type_list += 'V';
26148             else if (is_generally_string_node(arg_list[i]))
26149                ret_param_type_list += 'S';
26150             else
26151                ret_param_type_list += 'T';
26152          }
26153 
26154          dec_.retparam_list_.push_back(ret_param_type_list);
26155 
26156          expression_node_ptr result = expression_generator_.return_call(arg_list);
26157 
26158          sdd.delete_ptr = (0 == result);
26159 
26160          state_.return_stmt_present = true;
26161 
26162          state_.activate_side_effect("parse_return_statement()");
26163 
26164          return result;
26165       }
26166       #else
parse_return_statement()26167       inline expression_node_ptr parse_return_statement()
26168       {
26169          return error_node();
26170       }
26171       #endif
26172 
post_variable_process(const std::string & symbol)26173       inline bool post_variable_process(const std::string& symbol)
26174       {
26175          if (
26176               peek_token_is(token_t::e_lbracket   ) ||
26177               peek_token_is(token_t::e_lcrlbracket) ||
26178               peek_token_is(token_t::e_lsqrbracket)
26179             )
26180          {
26181             if (!settings_.commutative_check_enabled())
26182             {
26183                set_error(
26184                   make_error(parser_error::e_syntax,
26185                              current_token(),
26186                              "ERR188 - Invalid sequence of variable '"+ symbol + "' and bracket",
26187                              exprtk_error_location));
26188 
26189                return false;
26190             }
26191 
26192             lexer().insert_front(token_t::e_mul);
26193          }
26194 
26195          return true;
26196       }
26197 
post_bracket_process(const typename token_t::token_type & token,expression_node_ptr & branch)26198       inline bool post_bracket_process(const typename token_t::token_type& token, expression_node_ptr& branch)
26199       {
26200          bool implied_mul = false;
26201 
26202          if (is_generally_string_node(branch))
26203             return true;
26204 
26205          const lexer::parser_helper::token_advance_mode hold = prsrhlpr_t::e_hold;
26206 
26207          switch (token)
26208          {
26209             case token_t::e_lcrlbracket : implied_mul = token_is(token_t::e_lbracket   ,hold) ||
26210                                                         token_is(token_t::e_lcrlbracket,hold) ||
26211                                                         token_is(token_t::e_lsqrbracket,hold) ;
26212                                           break;
26213 
26214             case token_t::e_lbracket    : implied_mul = token_is(token_t::e_lbracket   ,hold) ||
26215                                                         token_is(token_t::e_lcrlbracket,hold) ||
26216                                                         token_is(token_t::e_lsqrbracket,hold) ;
26217                                           break;
26218 
26219             case token_t::e_lsqrbracket : implied_mul = token_is(token_t::e_lbracket   ,hold) ||
26220                                                         token_is(token_t::e_lcrlbracket,hold) ||
26221                                                         token_is(token_t::e_lsqrbracket,hold) ;
26222                                           break;
26223 
26224             default                     : return true;
26225          }
26226 
26227          if (implied_mul)
26228          {
26229             if (!settings_.commutative_check_enabled())
26230             {
26231                set_error(
26232                   make_error(parser_error::e_syntax,
26233                              current_token(),
26234                              "ERR189 - Invalid sequence of brackets",
26235                              exprtk_error_location));
26236 
26237                return false;
26238             }
26239             else if (token_t::e_eof != current_token().type)
26240             {
26241                lexer().insert_front(current_token().type);
26242                lexer().insert_front(token_t::e_mul);
26243                next_token();
26244             }
26245          }
26246 
26247          return true;
26248       }
26249 
parse_symtab_symbol()26250       inline expression_node_ptr parse_symtab_symbol()
26251       {
26252          const std::string symbol = current_token().value;
26253 
26254          // Are we dealing with a variable or a special constant?
26255          expression_node_ptr variable = symtab_store_.get_variable(symbol);
26256 
26257          if (variable)
26258          {
26259             if (symtab_store_.is_constant_node(symbol))
26260             {
26261                variable = expression_generator_(variable->value());
26262             }
26263 
26264             if (!post_variable_process(symbol))
26265                return error_node();
26266 
26267             lodge_symbol(symbol, e_st_variable);
26268             next_token();
26269 
26270             return variable;
26271          }
26272 
26273          // Are we dealing with a locally defined variable, vector or string?
26274          if (!sem_.empty())
26275          {
26276             scope_element& se = sem_.get_active_element(symbol);
26277 
26278             if (se.active && details::imatch(se.name, symbol))
26279             {
26280                if (scope_element::e_variable == se.type)
26281                {
26282                   se.active = true;
26283                   lodge_symbol(symbol, e_st_local_variable);
26284 
26285                   if (!post_variable_process(symbol))
26286                      return error_node();
26287 
26288                   next_token();
26289 
26290                   return se.var_node;
26291                }
26292                else if (scope_element::e_vector == se.type)
26293                {
26294                   return parse_vector();
26295                }
26296                #ifndef exprtk_disable_string_capabilities
26297                else if (scope_element::e_string == se.type)
26298                {
26299                   return parse_string();
26300                }
26301                #endif
26302             }
26303          }
26304 
26305          #ifndef exprtk_disable_string_capabilities
26306          // Are we dealing with a string variable?
26307          if (symtab_store_.is_stringvar(symbol))
26308          {
26309             return parse_string();
26310          }
26311          #endif
26312 
26313          {
26314             // Are we dealing with a function?
26315             ifunction<T>* function = symtab_store_.get_function(symbol);
26316 
26317             if (function)
26318             {
26319                lodge_symbol(symbol, e_st_function);
26320 
26321                expression_node_ptr func_node =
26322                                       parse_function_invocation(function,symbol);
26323 
26324                if (func_node)
26325                   return func_node;
26326                else
26327                {
26328                   set_error(
26329                      make_error(parser_error::e_syntax,
26330                                 current_token(),
26331                                 "ERR190 - Failed to generate node for function: '" + symbol + "'",
26332                                 exprtk_error_location));
26333 
26334                   return error_node();
26335                }
26336             }
26337          }
26338 
26339          {
26340             // Are we dealing with a vararg function?
26341             ivararg_function<T>* vararg_function = symtab_store_.get_vararg_function(symbol);
26342 
26343             if (vararg_function)
26344             {
26345                lodge_symbol(symbol, e_st_function);
26346 
26347                expression_node_ptr vararg_func_node =
26348                                       parse_vararg_function_call(vararg_function, symbol);
26349 
26350                if (vararg_func_node)
26351                   return vararg_func_node;
26352                else
26353                {
26354                   set_error(
26355                      make_error(parser_error::e_syntax,
26356                                 current_token(),
26357                                 "ERR191 - Failed to generate node for vararg function: '" + symbol + "'",
26358                                 exprtk_error_location));
26359 
26360                   return error_node();
26361                }
26362             }
26363          }
26364 
26365          {
26366             // Are we dealing with a vararg generic function?
26367             igeneric_function<T>* generic_function = symtab_store_.get_generic_function(symbol);
26368 
26369             if (generic_function)
26370             {
26371                lodge_symbol(symbol, e_st_function);
26372 
26373                expression_node_ptr genericfunc_node =
26374                                       parse_generic_function_call(generic_function, symbol);
26375 
26376                if (genericfunc_node)
26377                   return genericfunc_node;
26378                else
26379                {
26380                   set_error(
26381                      make_error(parser_error::e_syntax,
26382                                 current_token(),
26383                                 "ERR192 - Failed to generate node for generic function: '" + symbol + "'",
26384                                 exprtk_error_location));
26385 
26386                   return error_node();
26387                }
26388             }
26389          }
26390 
26391          #ifndef exprtk_disable_string_capabilities
26392          {
26393             // Are we dealing with a vararg string returning function?
26394             igeneric_function<T>* string_function = symtab_store_.get_string_function(symbol);
26395 
26396             if (string_function)
26397             {
26398                lodge_symbol(symbol, e_st_function);
26399 
26400                expression_node_ptr stringfunc_node =
26401                                       parse_string_function_call(string_function, symbol);
26402 
26403                if (stringfunc_node)
26404                   return stringfunc_node;
26405                else
26406                {
26407                   set_error(
26408                      make_error(parser_error::e_syntax,
26409                                 current_token(),
26410                                 "ERR193 - Failed to generate node for string function: '" + symbol + "'",
26411                                 exprtk_error_location));
26412 
26413                   return error_node();
26414                }
26415             }
26416          }
26417 
26418          {
26419             // Are we dealing with a vararg overloaded scalar/string returning function?
26420             igeneric_function<T>* overload_function = symtab_store_.get_overload_function(symbol);
26421 
26422             if (overload_function)
26423             {
26424                lodge_symbol(symbol, e_st_function);
26425 
26426                expression_node_ptr overloadfunc_node =
26427                                       parse_overload_function_call(overload_function, symbol);
26428 
26429                if (overloadfunc_node)
26430                   return overloadfunc_node;
26431                else
26432                {
26433                   set_error(
26434                      make_error(parser_error::e_syntax,
26435                                 current_token(),
26436                                 "ERR194 - Failed to generate node for overload function: '" + symbol + "'",
26437                                 exprtk_error_location));
26438 
26439                   return error_node();
26440                }
26441             }
26442          }
26443          #endif
26444 
26445          // Are we dealing with a vector?
26446          if (symtab_store_.is_vector(symbol))
26447          {
26448             lodge_symbol(symbol, e_st_vector);
26449             return parse_vector();
26450          }
26451 
26452          if (details::is_reserved_symbol(symbol))
26453          {
26454                if (
26455                     settings_.function_enabled(symbol) ||
26456                     !details::is_base_function(symbol)
26457                   )
26458                {
26459                   set_error(
26460                      make_error(parser_error::e_syntax,
26461                                 current_token(),
26462                                 "ERR195 - Invalid use of reserved symbol '" + symbol + "'",
26463                                 exprtk_error_location));
26464 
26465                   return error_node();
26466                }
26467          }
26468 
26469          // Should we handle unknown symbols?
26470          if (resolve_unknown_symbol_ && unknown_symbol_resolver_)
26471          {
26472             if (!(settings_.rsrvd_sym_usr_disabled() && details::is_reserved_symbol(symbol)))
26473             {
26474                symbol_table_t& symtab = symtab_store_.get_symbol_table();
26475 
26476                std::string error_message;
26477 
26478                if (unknown_symbol_resolver::e_usrmode_default == unknown_symbol_resolver_->mode)
26479                {
26480                   T default_value = T(0);
26481 
26482                   typename unknown_symbol_resolver::usr_symbol_type usr_symbol_type = unknown_symbol_resolver::e_usr_unknown_type;
26483 
26484                   if (unknown_symbol_resolver_->process(symbol, usr_symbol_type, default_value, error_message))
26485                   {
26486                      bool create_result = false;
26487 
26488                      switch (usr_symbol_type)
26489                      {
26490                         case unknown_symbol_resolver::e_usr_variable_type : create_result = symtab.create_variable(symbol, default_value);
26491                                                                             break;
26492 
26493                         case unknown_symbol_resolver::e_usr_constant_type : create_result = symtab.add_constant(symbol, default_value);
26494                                                                             break;
26495 
26496                         default                                           : create_result = false;
26497                      }
26498 
26499                      if (create_result)
26500                      {
26501                         expression_node_ptr var = symtab_store_.get_variable(symbol);
26502 
26503                         if (var)
26504                         {
26505                            if (symtab_store_.is_constant_node(symbol))
26506                            {
26507                               var = expression_generator_(var->value());
26508                            }
26509 
26510                            lodge_symbol(symbol, e_st_variable);
26511 
26512                            if (!post_variable_process(symbol))
26513                               return error_node();
26514 
26515                            next_token();
26516 
26517                            return var;
26518                         }
26519                      }
26520                   }
26521 
26522                   set_error(
26523                      make_error(parser_error::e_symtab,
26524                                 current_token(),
26525                                 "ERR196 - Failed to create variable: '" + symbol + "'" +
26526                                 (error_message.empty() ? "" : " - " + error_message),
26527                                 exprtk_error_location));
26528 
26529                }
26530                else if (unknown_symbol_resolver::e_usrmode_extended == unknown_symbol_resolver_->mode)
26531                {
26532                   if (unknown_symbol_resolver_->process(symbol, symtab, error_message))
26533                   {
26534                      expression_node_ptr result = parse_symtab_symbol();
26535 
26536                      if (result)
26537                      {
26538                         return result;
26539                      }
26540                   }
26541 
26542                   set_error(
26543                      make_error(parser_error::e_symtab,
26544                                 current_token(),
26545                                 "ERR197 - Failed to resolve symbol: '" + symbol + "'" +
26546                                 (error_message.empty() ? "" : " - " + error_message),
26547                                 exprtk_error_location));
26548                }
26549 
26550                return error_node();
26551             }
26552          }
26553 
26554          set_error(
26555             make_error(parser_error::e_syntax,
26556                        current_token(),
26557                        "ERR198 - Undefined symbol: '" + symbol + "'",
26558                        exprtk_error_location));
26559 
26560          return error_node();
26561       }
26562 
parse_symbol()26563       inline expression_node_ptr parse_symbol()
26564       {
26565          static const std::string symbol_if       = "if"      ;
26566          static const std::string symbol_while    = "while"   ;
26567          static const std::string symbol_repeat   = "repeat"  ;
26568          static const std::string symbol_for      = "for"     ;
26569          static const std::string symbol_switch   = "switch"  ;
26570          static const std::string symbol_null     = "null"    ;
26571          static const std::string symbol_break    = "break"   ;
26572          static const std::string symbol_continue = "continue";
26573          static const std::string symbol_var      = "var"     ;
26574          static const std::string symbol_swap     = "swap"    ;
26575          static const std::string symbol_return   = "return"  ;
26576          static const std::string symbol_not      = "not"     ;
26577 
26578          if (valid_vararg_operation(current_token().value))
26579          {
26580             return parse_vararg_function();
26581          }
26582          else if (details::imatch(current_token().value, symbol_not))
26583          {
26584             return parse_not_statement();
26585          }
26586          else if (valid_base_operation(current_token().value))
26587          {
26588             return parse_base_operation();
26589          }
26590          else if (
26591                    details::imatch(current_token().value, symbol_if) &&
26592                    settings_.control_struct_enabled(current_token().value)
26593                  )
26594          {
26595             return parse_conditional_statement();
26596          }
26597          else if (
26598                    details::imatch(current_token().value, symbol_while) &&
26599                    settings_.control_struct_enabled(current_token().value)
26600                  )
26601          {
26602             return parse_while_loop();
26603          }
26604          else if (
26605                    details::imatch(current_token().value, symbol_repeat) &&
26606                    settings_.control_struct_enabled(current_token().value)
26607                  )
26608          {
26609             return parse_repeat_until_loop();
26610          }
26611          else if (
26612                    details::imatch(current_token().value, symbol_for) &&
26613                    settings_.control_struct_enabled(current_token().value)
26614                  )
26615          {
26616             return parse_for_loop();
26617          }
26618          else if (
26619                    details::imatch(current_token().value, symbol_switch) &&
26620                    settings_.control_struct_enabled(current_token().value)
26621                  )
26622          {
26623             return parse_switch_statement();
26624          }
26625          else if (details::is_valid_sf_symbol(current_token().value))
26626          {
26627             return parse_special_function();
26628          }
26629          else if (details::imatch(current_token().value, symbol_null))
26630          {
26631             return parse_null_statement();
26632          }
26633          #ifndef exprtk_disable_break_continue
26634          else if (details::imatch(current_token().value, symbol_break))
26635          {
26636             return parse_break_statement();
26637          }
26638          else if (details::imatch(current_token().value, symbol_continue))
26639          {
26640             return parse_continue_statement();
26641          }
26642          #endif
26643          else if (details::imatch(current_token().value, symbol_var))
26644          {
26645             return parse_define_var_statement();
26646          }
26647          else if (details::imatch(current_token().value, symbol_swap))
26648          {
26649             return parse_swap_statement();
26650          }
26651          #ifndef exprtk_disable_return_statement
26652          else if (
26653                    details::imatch(current_token().value, symbol_return) &&
26654                    settings_.control_struct_enabled(current_token().value)
26655                  )
26656          {
26657             return parse_return_statement();
26658          }
26659          #endif
26660          else if (symtab_store_.valid() || !sem_.empty())
26661          {
26662             return parse_symtab_symbol();
26663          }
26664          else
26665          {
26666             set_error(
26667                make_error(parser_error::e_symtab,
26668                           current_token(),
26669                           "ERR199 - Variable or function detected, yet symbol-table is invalid, Symbol: " + current_token().value,
26670                           exprtk_error_location));
26671 
26672             return error_node();
26673          }
26674       }
26675 
parse_branch(precedence_level precedence=e_level00)26676       inline expression_node_ptr parse_branch(precedence_level precedence = e_level00)
26677       {
26678          stack_limit_handler slh(*this);
26679 
26680          if (!slh)
26681          {
26682             return error_node();
26683          }
26684 
26685          expression_node_ptr branch = error_node();
26686 
26687          if (token_t::e_number == current_token().type)
26688          {
26689             T numeric_value = T(0);
26690 
26691             if (details::string_to_real(current_token().value, numeric_value))
26692             {
26693                expression_node_ptr literal_exp = expression_generator_(numeric_value);
26694 
26695                if (0 == literal_exp)
26696                {
26697                   set_error(
26698                      make_error(parser_error::e_numeric,
26699                                 current_token(),
26700                                 "ERR200 - Failed generate node for scalar: '" + current_token().value + "'",
26701                                 exprtk_error_location));
26702 
26703                   return error_node();
26704                }
26705 
26706                next_token();
26707                branch = literal_exp;
26708             }
26709             else
26710             {
26711                set_error(
26712                   make_error(parser_error::e_numeric,
26713                              current_token(),
26714                              "ERR201 - Failed to convert '" + current_token().value + "' to a number",
26715                              exprtk_error_location));
26716 
26717                return error_node();
26718             }
26719          }
26720          else if (token_t::e_symbol == current_token().type)
26721          {
26722             branch = parse_symbol();
26723          }
26724          #ifndef exprtk_disable_string_capabilities
26725          else if (token_t::e_string == current_token().type)
26726          {
26727             branch = parse_const_string();
26728          }
26729          #endif
26730          else if (token_t::e_lbracket == current_token().type)
26731          {
26732             next_token();
26733 
26734             if (0 == (branch = parse_expression()))
26735                return error_node();
26736             else if (!token_is(token_t::e_rbracket))
26737             {
26738                set_error(
26739                   make_error(parser_error::e_syntax,
26740                              current_token(),
26741                              "ERR202 - Expected ')' instead of: '" + current_token().value + "'",
26742                              exprtk_error_location));
26743 
26744                free_node(node_allocator_,branch);
26745 
26746                return error_node();
26747             }
26748             else if (!post_bracket_process(token_t::e_lbracket,branch))
26749             {
26750                free_node(node_allocator_,branch);
26751 
26752                return error_node();
26753             }
26754          }
26755          else if (token_t::e_lsqrbracket == current_token().type)
26756          {
26757             next_token();
26758 
26759             if (0 == (branch = parse_expression()))
26760                return error_node();
26761             else if (!token_is(token_t::e_rsqrbracket))
26762             {
26763                set_error(
26764                   make_error(parser_error::e_syntax,
26765                              current_token(),
26766                              "ERR203 - Expected ']' instead of: '" + current_token().value + "'",
26767                              exprtk_error_location));
26768 
26769                free_node(node_allocator_,branch);
26770 
26771                return error_node();
26772             }
26773             else if (!post_bracket_process(token_t::e_lsqrbracket,branch))
26774             {
26775                free_node(node_allocator_,branch);
26776 
26777                return error_node();
26778             }
26779          }
26780          else if (token_t::e_lcrlbracket == current_token().type)
26781          {
26782             next_token();
26783 
26784             if (0 == (branch = parse_expression()))
26785                return error_node();
26786             else if (!token_is(token_t::e_rcrlbracket))
26787             {
26788                set_error(
26789                   make_error(parser_error::e_syntax,
26790                              current_token(),
26791                              "ERR204 - Expected '}' instead of: '" + current_token().value + "'",
26792                              exprtk_error_location));
26793 
26794                free_node(node_allocator_,branch);
26795 
26796                return error_node();
26797             }
26798             else if (!post_bracket_process(token_t::e_lcrlbracket,branch))
26799             {
26800                free_node(node_allocator_,branch);
26801 
26802                return error_node();
26803             }
26804          }
26805          else if (token_t::e_sub == current_token().type)
26806          {
26807             next_token();
26808             branch = parse_expression(e_level11);
26809 
26810             if (
26811                  branch &&
26812                  !(
26813                     details::is_neg_unary_node    (branch) &&
26814                     simplify_unary_negation_branch(branch)
26815                   )
26816                )
26817             {
26818                expression_node_ptr result = expression_generator_(details::e_neg,branch);
26819 
26820                if (0 == result)
26821                {
26822                   free_node(node_allocator_,branch);
26823 
26824                   return error_node();
26825                }
26826                else
26827                   branch = result;
26828             }
26829          }
26830          else if (token_t::e_add == current_token().type)
26831          {
26832             next_token();
26833             branch = parse_expression(e_level13);
26834          }
26835          else if (token_t::e_eof == current_token().type)
26836          {
26837             set_error(
26838                make_error(parser_error::e_syntax,
26839                           current_token(),
26840                           "ERR205 - Premature end of expression[1]",
26841                           exprtk_error_location));
26842 
26843             return error_node();
26844          }
26845          else
26846          {
26847             set_error(
26848                make_error(parser_error::e_syntax,
26849                           current_token(),
26850                           "ERR206 - Premature end of expression[2]",
26851                           exprtk_error_location));
26852 
26853             return error_node();
26854          }
26855 
26856          if (
26857               branch                    &&
26858               (e_level00 == precedence) &&
26859               token_is(token_t::e_ternary,prsrhlpr_t::e_hold)
26860             )
26861          {
26862             branch = parse_ternary_conditional_statement(branch);
26863          }
26864 
26865          parse_pending_string_rangesize(branch);
26866 
26867          return branch;
26868       }
26869 
26870       template <typename Type>
26871       class expression_generator
26872       {
26873       public:
26874 
26875          typedef details::expression_node<Type>* expression_node_ptr;
26876          typedef expression_node_ptr (*synthesize_functor_t)(expression_generator<T>&, const details::operator_type& operation, expression_node_ptr (&branch)[2]);
26877          typedef std::map<std::string,synthesize_functor_t> synthesize_map_t;
26878          typedef typename exprtk::parser<Type> parser_t;
26879          typedef const Type& vtype;
26880          typedef const Type  ctype;
26881 
init_synthesize_map()26882          inline void init_synthesize_map()
26883          {
26884             #ifndef exprtk_disable_enhanced_features
26885             synthesize_map_["(v)o(v)"] = synthesize_vov_expression::process;
26886             synthesize_map_["(c)o(v)"] = synthesize_cov_expression::process;
26887             synthesize_map_["(v)o(c)"] = synthesize_voc_expression::process;
26888 
26889             #define register_synthezier(S)                      \
26890             synthesize_map_[S ::node_type::id()] = S ::process; \
26891 
26892             register_synthezier(synthesize_vovov_expression0)
26893             register_synthezier(synthesize_vovov_expression1)
26894             register_synthezier(synthesize_vovoc_expression0)
26895             register_synthezier(synthesize_vovoc_expression1)
26896             register_synthezier(synthesize_vocov_expression0)
26897             register_synthezier(synthesize_vocov_expression1)
26898             register_synthezier(synthesize_covov_expression0)
26899             register_synthezier(synthesize_covov_expression1)
26900             register_synthezier(synthesize_covoc_expression0)
26901             register_synthezier(synthesize_covoc_expression1)
26902             register_synthezier(synthesize_cocov_expression1)
26903             register_synthezier(synthesize_vococ_expression0)
26904 
26905             register_synthezier(synthesize_vovovov_expression0)
26906             register_synthezier(synthesize_vovovoc_expression0)
26907             register_synthezier(synthesize_vovocov_expression0)
26908             register_synthezier(synthesize_vocovov_expression0)
26909             register_synthezier(synthesize_covovov_expression0)
26910             register_synthezier(synthesize_covocov_expression0)
26911             register_synthezier(synthesize_vocovoc_expression0)
26912             register_synthezier(synthesize_covovoc_expression0)
26913             register_synthezier(synthesize_vococov_expression0)
26914 
26915             register_synthezier(synthesize_vovovov_expression1)
26916             register_synthezier(synthesize_vovovoc_expression1)
26917             register_synthezier(synthesize_vovocov_expression1)
26918             register_synthezier(synthesize_vocovov_expression1)
26919             register_synthezier(synthesize_covovov_expression1)
26920             register_synthezier(synthesize_covocov_expression1)
26921             register_synthezier(synthesize_vocovoc_expression1)
26922             register_synthezier(synthesize_covovoc_expression1)
26923             register_synthezier(synthesize_vococov_expression1)
26924 
26925             register_synthezier(synthesize_vovovov_expression2)
26926             register_synthezier(synthesize_vovovoc_expression2)
26927             register_synthezier(synthesize_vovocov_expression2)
26928             register_synthezier(synthesize_vocovov_expression2)
26929             register_synthezier(synthesize_covovov_expression2)
26930             register_synthezier(synthesize_covocov_expression2)
26931             register_synthezier(synthesize_vocovoc_expression2)
26932             register_synthezier(synthesize_covovoc_expression2)
26933 
26934             register_synthezier(synthesize_vovovov_expression3)
26935             register_synthezier(synthesize_vovovoc_expression3)
26936             register_synthezier(synthesize_vovocov_expression3)
26937             register_synthezier(synthesize_vocovov_expression3)
26938             register_synthezier(synthesize_covovov_expression3)
26939             register_synthezier(synthesize_covocov_expression3)
26940             register_synthezier(synthesize_vocovoc_expression3)
26941             register_synthezier(synthesize_covovoc_expression3)
26942             register_synthezier(synthesize_vococov_expression3)
26943 
26944             register_synthezier(synthesize_vovovov_expression4)
26945             register_synthezier(synthesize_vovovoc_expression4)
26946             register_synthezier(synthesize_vovocov_expression4)
26947             register_synthezier(synthesize_vocovov_expression4)
26948             register_synthezier(synthesize_covovov_expression4)
26949             register_synthezier(synthesize_covocov_expression4)
26950             register_synthezier(synthesize_vocovoc_expression4)
26951             register_synthezier(synthesize_covovoc_expression4)
26952             #endif
26953          }
26954 
set_parser(parser_t & p)26955          inline void set_parser(parser_t& p)
26956          {
26957             parser_ = &p;
26958          }
26959 
set_uom(unary_op_map_t & unary_op_map)26960          inline void set_uom(unary_op_map_t& unary_op_map)
26961          {
26962             unary_op_map_ = &unary_op_map;
26963          }
26964 
set_bom(binary_op_map_t & binary_op_map)26965          inline void set_bom(binary_op_map_t& binary_op_map)
26966          {
26967             binary_op_map_ = &binary_op_map;
26968          }
26969 
set_ibom(inv_binary_op_map_t & inv_binary_op_map)26970          inline void set_ibom(inv_binary_op_map_t& inv_binary_op_map)
26971          {
26972             inv_binary_op_map_ = &inv_binary_op_map;
26973          }
26974 
set_sf3m(sf3_map_t & sf3_map)26975          inline void set_sf3m(sf3_map_t& sf3_map)
26976          {
26977             sf3_map_ = &sf3_map;
26978          }
26979 
set_sf4m(sf4_map_t & sf4_map)26980          inline void set_sf4m(sf4_map_t& sf4_map)
26981          {
26982             sf4_map_ = &sf4_map;
26983          }
26984 
set_allocator(details::node_allocator & na)26985          inline void set_allocator(details::node_allocator& na)
26986          {
26987             node_allocator_ = &na;
26988          }
26989 
set_strength_reduction_state(const bool enabled)26990          inline void set_strength_reduction_state(const bool enabled)
26991          {
26992             strength_reduction_enabled_ = enabled;
26993          }
26994 
strength_reduction_enabled() const26995          inline bool strength_reduction_enabled() const
26996          {
26997             return strength_reduction_enabled_;
26998          }
26999 
valid_operator(const details::operator_type & operation,binary_functor_t & bop)27000          inline bool valid_operator(const details::operator_type& operation, binary_functor_t& bop)
27001          {
27002             typename binary_op_map_t::iterator bop_itr = binary_op_map_->find(operation);
27003 
27004             if ((*binary_op_map_).end() == bop_itr)
27005                return false;
27006 
27007             bop = bop_itr->second;
27008 
27009             return true;
27010          }
27011 
valid_operator(const details::operator_type & operation,unary_functor_t & uop)27012          inline bool valid_operator(const details::operator_type& operation, unary_functor_t& uop)
27013          {
27014             typename unary_op_map_t::iterator uop_itr = unary_op_map_->find(operation);
27015 
27016             if ((*unary_op_map_).end() == uop_itr)
27017                return false;
27018 
27019             uop = uop_itr->second;
27020 
27021             return true;
27022          }
27023 
get_operator(const binary_functor_t & bop) const27024          inline details::operator_type get_operator(const binary_functor_t& bop) const
27025          {
27026             return (*inv_binary_op_map_).find(bop)->second;
27027          }
27028 
operator ()(const Type & v) const27029          inline expression_node_ptr operator() (const Type& v) const
27030          {
27031             return node_allocator_->allocate<literal_node_t>(v);
27032          }
27033 
27034          #ifndef exprtk_disable_string_capabilities
operator ()(const std::string & s) const27035          inline expression_node_ptr operator() (const std::string& s) const
27036          {
27037             return node_allocator_->allocate<string_literal_node_t>(s);
27038          }
27039 
operator ()(std::string & s,range_t & rp) const27040          inline expression_node_ptr operator() (std::string& s, range_t& rp) const
27041          {
27042             return node_allocator_->allocate_rr<string_range_node_t>(s,rp);
27043          }
27044 
operator ()(const std::string & s,range_t & rp) const27045          inline expression_node_ptr operator() (const std::string& s, range_t& rp) const
27046          {
27047             return node_allocator_->allocate_tt<const_string_range_node_t>(s,rp);
27048          }
27049 
operator ()(expression_node_ptr branch,range_t & rp) const27050          inline expression_node_ptr operator() (expression_node_ptr branch, range_t& rp) const
27051          {
27052             if (is_generally_string_node(branch))
27053                return node_allocator_->allocate_tt<generic_string_range_node_t>(branch,rp);
27054             else
27055                return error_node();
27056          }
27057          #endif
27058 
unary_optimisable(const details::operator_type & operation) const27059          inline bool unary_optimisable(const details::operator_type& operation) const
27060          {
27061             return (details::e_abs   == operation) || (details::e_acos  == operation) ||
27062                    (details::e_acosh == operation) || (details::e_asin  == operation) ||
27063                    (details::e_asinh == operation) || (details::e_atan  == operation) ||
27064                    (details::e_atanh == operation) || (details::e_ceil  == operation) ||
27065                    (details::e_cos   == operation) || (details::e_cosh  == operation) ||
27066                    (details::e_exp   == operation) || (details::e_expm1 == operation) ||
27067                    (details::e_floor == operation) || (details::e_log   == operation) ||
27068                    (details::e_log10 == operation) || (details::e_log2  == operation) ||
27069                    (details::e_log1p == operation) || (details::e_neg   == operation) ||
27070                    (details::e_pos   == operation) || (details::e_round == operation) ||
27071                    (details::e_sin   == operation) || (details::e_sinc  == operation) ||
27072                    (details::e_sinh  == operation) || (details::e_sqrt  == operation) ||
27073                    (details::e_tan   == operation) || (details::e_tanh  == operation) ||
27074                    (details::e_cot   == operation) || (details::e_sec   == operation) ||
27075                    (details::e_csc   == operation) || (details::e_r2d   == operation) ||
27076                    (details::e_d2r   == operation) || (details::e_d2g   == operation) ||
27077                    (details::e_g2d   == operation) || (details::e_notl  == operation) ||
27078                    (details::e_sgn   == operation) || (details::e_erf   == operation) ||
27079                    (details::e_erfc  == operation) || (details::e_ncdf  == operation) ||
27080                    (details::e_frac  == operation) || (details::e_trunc == operation) ;
27081          }
27082 
sf3_optimisable(const std::string & sf3id,trinary_functor_t & tfunc) const27083          inline bool sf3_optimisable(const std::string& sf3id, trinary_functor_t& tfunc) const
27084          {
27085             typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id);
27086 
27087             if (sf3_map_->end() == itr)
27088                return false;
27089             else
27090                tfunc = itr->second.first;
27091 
27092             return true;
27093          }
27094 
sf4_optimisable(const std::string & sf4id,quaternary_functor_t & qfunc) const27095          inline bool sf4_optimisable(const std::string& sf4id, quaternary_functor_t& qfunc) const
27096          {
27097             typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id);
27098 
27099             if (sf4_map_->end() == itr)
27100                return false;
27101             else
27102                qfunc = itr->second.first;
27103 
27104             return true;
27105          }
27106 
sf3_optimisable(const std::string & sf3id,details::operator_type & operation) const27107          inline bool sf3_optimisable(const std::string& sf3id, details::operator_type& operation) const
27108          {
27109             typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id);
27110 
27111             if (sf3_map_->end() == itr)
27112                return false;
27113             else
27114                operation = itr->second.second;
27115 
27116             return true;
27117          }
27118 
sf4_optimisable(const std::string & sf4id,details::operator_type & operation) const27119          inline bool sf4_optimisable(const std::string& sf4id, details::operator_type& operation) const
27120          {
27121             typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id);
27122 
27123             if (sf4_map_->end() == itr)
27124                return false;
27125             else
27126                operation = itr->second.second;
27127 
27128             return true;
27129          }
27130 
operator ()(const details::operator_type & operation,expression_node_ptr (& branch)[1])27131          inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[1])
27132          {
27133             if (0 == branch[0])
27134             {
27135                return error_node();
27136             }
27137             else if (details::is_null_node(branch[0]))
27138             {
27139                return branch[0];
27140             }
27141             else if (details::is_break_node(branch[0]))
27142             {
27143                return error_node();
27144             }
27145             else if (details::is_continue_node(branch[0]))
27146             {
27147                return error_node();
27148             }
27149             else if (details::is_constant_node(branch[0]))
27150             {
27151                return synthesize_expression<unary_node_t,1>(operation,branch);
27152             }
27153             else if (unary_optimisable(operation) && details::is_variable_node(branch[0]))
27154             {
27155                return synthesize_uv_expression(operation,branch);
27156             }
27157             else if (unary_optimisable(operation) && details::is_ivector_node(branch[0]))
27158             {
27159                return synthesize_uvec_expression(operation,branch);
27160             }
27161             else
27162                return synthesize_unary_expression(operation,branch);
27163          }
27164 
is_assignment_operation(const details::operator_type & operation) const27165          inline bool is_assignment_operation(const details::operator_type& operation) const
27166          {
27167             return (
27168                      (details::e_addass == operation) ||
27169                      (details::e_subass == operation) ||
27170                      (details::e_mulass == operation) ||
27171                      (details::e_divass == operation) ||
27172                      (details::e_modass == operation)
27173                    ) &&
27174                    parser_->settings_.assignment_enabled(operation);
27175          }
27176 
27177          #ifndef exprtk_disable_string_capabilities
valid_string_operation(const details::operator_type & operation) const27178          inline bool valid_string_operation(const details::operator_type& operation) const
27179          {
27180             return (details::e_add    == operation) ||
27181                    (details::e_lt     == operation) ||
27182                    (details::e_lte    == operation) ||
27183                    (details::e_gt     == operation) ||
27184                    (details::e_gte    == operation) ||
27185                    (details::e_eq     == operation) ||
27186                    (details::e_ne     == operation) ||
27187                    (details::e_in     == operation) ||
27188                    (details::e_like   == operation) ||
27189                    (details::e_ilike  == operation) ||
27190                    (details::e_assign == operation) ||
27191                    (details::e_addass == operation) ||
27192                    (details::e_swap   == operation) ;
27193          }
27194          #else
valid_string_operation(const details::operator_type &) const27195          inline bool valid_string_operation(const details::operator_type&) const
27196          {
27197             return false;
27198          }
27199          #endif
27200 
to_str(const details::operator_type & operation) const27201          inline std::string to_str(const details::operator_type& operation) const
27202          {
27203             switch (operation)
27204             {
27205                case details::e_add  : return "+"      ;
27206                case details::e_sub  : return "-"      ;
27207                case details::e_mul  : return "*"      ;
27208                case details::e_div  : return "/"      ;
27209                case details::e_mod  : return "%"      ;
27210                case details::e_pow  : return "^"      ;
27211                case details::e_lt   : return "<"      ;
27212                case details::e_lte  : return "<="     ;
27213                case details::e_gt   : return ">"      ;
27214                case details::e_gte  : return ">="     ;
27215                case details::e_eq   : return "=="     ;
27216                case details::e_ne   : return "!="     ;
27217                case details::e_and  : return "and"    ;
27218                case details::e_nand : return "nand"   ;
27219                case details::e_or   : return "or"     ;
27220                case details::e_nor  : return "nor"    ;
27221                case details::e_xor  : return "xor"    ;
27222                case details::e_xnor : return "xnor"   ;
27223                default              : return "UNKNOWN";
27224             }
27225          }
27226 
operation_optimisable(const details::operator_type & operation) const27227          inline bool operation_optimisable(const details::operator_type& operation) const
27228          {
27229             return (details::e_add  == operation) ||
27230                    (details::e_sub  == operation) ||
27231                    (details::e_mul  == operation) ||
27232                    (details::e_div  == operation) ||
27233                    (details::e_mod  == operation) ||
27234                    (details::e_pow  == operation) ||
27235                    (details::e_lt   == operation) ||
27236                    (details::e_lte  == operation) ||
27237                    (details::e_gt   == operation) ||
27238                    (details::e_gte  == operation) ||
27239                    (details::e_eq   == operation) ||
27240                    (details::e_ne   == operation) ||
27241                    (details::e_and  == operation) ||
27242                    (details::e_nand == operation) ||
27243                    (details::e_or   == operation) ||
27244                    (details::e_nor  == operation) ||
27245                    (details::e_xor  == operation) ||
27246                    (details::e_xnor == operation) ;
27247          }
27248 
branch_to_id(expression_node_ptr branch) const27249          inline std::string branch_to_id(expression_node_ptr branch) const
27250          {
27251             static const std::string null_str   ("(null)" );
27252             static const std::string const_str  ("(c)"    );
27253             static const std::string var_str    ("(v)"    );
27254             static const std::string vov_str    ("(vov)"  );
27255             static const std::string cov_str    ("(cov)"  );
27256             static const std::string voc_str    ("(voc)"  );
27257             static const std::string str_str    ("(s)"    );
27258             static const std::string strrng_str ("(rngs)" );
27259             static const std::string cs_str     ("(cs)"   );
27260             static const std::string cstrrng_str("(crngs)");
27261 
27262             if (details::is_null_node(branch))
27263                return null_str;
27264             else if (details::is_constant_node(branch))
27265                return const_str;
27266             else if (details::is_variable_node(branch))
27267                return var_str;
27268             else if (details::is_vov_node(branch))
27269                return vov_str;
27270             else if (details::is_cov_node(branch))
27271                return cov_str;
27272             else if (details::is_voc_node(branch))
27273                return voc_str;
27274             else if (details::is_string_node(branch))
27275                return str_str;
27276             else if (details::is_const_string_node(branch))
27277                return cs_str;
27278             else if (details::is_string_range_node(branch))
27279                return strrng_str;
27280             else if (details::is_const_string_range_node(branch))
27281                return cstrrng_str;
27282             else if (details::is_t0ot1ot2_node(branch))
27283                return "(" + dynamic_cast<details::T0oT1oT2_base_node<T>*>(branch)->type_id() + ")";
27284             else if (details::is_t0ot1ot2ot3_node(branch))
27285                return "(" + dynamic_cast<details::T0oT1oT2oT3_base_node<T>*>(branch)->type_id() + ")";
27286             else
27287                return "ERROR";
27288          }
27289 
branch_to_id(expression_node_ptr (& branch)[2]) const27290          inline std::string branch_to_id(expression_node_ptr (&branch)[2]) const
27291          {
27292             return branch_to_id(branch[0]) + std::string("o") + branch_to_id(branch[1]);
27293          }
27294 
cov_optimisable(const details::operator_type & operation,expression_node_ptr (& branch)[2]) const27295          inline bool cov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
27296          {
27297             if (!operation_optimisable(operation))
27298                return false;
27299             else
27300                return details::is_constant_node(branch[0]) &&
27301                       details::is_variable_node(branch[1]) ;
27302          }
27303 
voc_optimisable(const details::operator_type & operation,expression_node_ptr (& branch)[2]) const27304          inline bool voc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
27305          {
27306             if (!operation_optimisable(operation))
27307                return false;
27308             else
27309                return details::is_variable_node(branch[0]) &&
27310                       details::is_constant_node(branch[1]) ;
27311          }
27312 
vov_optimisable(const details::operator_type & operation,expression_node_ptr (& branch)[2]) const27313          inline bool vov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
27314          {
27315             if (!operation_optimisable(operation))
27316                return false;
27317             else
27318                return details::is_variable_node(branch[0]) &&
27319                       details::is_variable_node(branch[1]) ;
27320          }
27321 
cob_optimisable(const details::operator_type & operation,expression_node_ptr (& branch)[2]) const27322          inline bool cob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
27323          {
27324             if (!operation_optimisable(operation))
27325                return false;
27326             else
27327                return details::is_constant_node(branch[0]) &&
27328                      !details::is_constant_node(branch[1]) ;
27329          }
27330 
boc_optimisable(const details::operator_type & operation,expression_node_ptr (& branch)[2]) const27331          inline bool boc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
27332          {
27333             if (!operation_optimisable(operation))
27334                return false;
27335             else
27336                return !details::is_constant_node(branch[0]) &&
27337                        details::is_constant_node(branch[1]) ;
27338          }
27339 
cocob_optimisable(const details::operator_type & operation,expression_node_ptr (& branch)[2]) const27340          inline bool cocob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
27341          {
27342             if (
27343                  (details::e_add == operation) ||
27344                  (details::e_sub == operation) ||
27345                  (details::e_mul == operation) ||
27346                  (details::e_div == operation)
27347                )
27348             {
27349                return (details::is_constant_node(branch[0]) && details::is_cob_node(branch[1])) ||
27350                       (details::is_constant_node(branch[1]) && details::is_cob_node(branch[0])) ;
27351             }
27352             else
27353                return false;
27354          }
27355 
coboc_optimisable(const details::operator_type & operation,expression_node_ptr (& branch)[2]) const27356          inline bool coboc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
27357          {
27358             if (
27359                  (details::e_add == operation) ||
27360                  (details::e_sub == operation) ||
27361                  (details::e_mul == operation) ||
27362                  (details::e_div == operation)
27363                )
27364             {
27365                return (details::is_constant_node(branch[0]) && details::is_boc_node(branch[1])) ||
27366                       (details::is_constant_node(branch[1]) && details::is_boc_node(branch[0])) ;
27367             }
27368             else
27369                return false;
27370          }
27371 
uvouv_optimisable(const details::operator_type & operation,expression_node_ptr (& branch)[2]) const27372          inline bool uvouv_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
27373          {
27374             if (!operation_optimisable(operation))
27375                return false;
27376             else
27377                return details::is_uv_node(branch[0]) &&
27378                       details::is_uv_node(branch[1]) ;
27379          }
27380 
vob_optimisable(const details::operator_type & operation,expression_node_ptr (& branch)[2]) const27381          inline bool vob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
27382          {
27383             if (!operation_optimisable(operation))
27384                return false;
27385             else
27386                return details::is_variable_node(branch[0]) &&
27387                      !details::is_variable_node(branch[1]) ;
27388          }
27389 
bov_optimisable(const details::operator_type & operation,expression_node_ptr (& branch)[2]) const27390          inline bool bov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
27391          {
27392             if (!operation_optimisable(operation))
27393                return false;
27394             else
27395                return !details::is_variable_node(branch[0]) &&
27396                        details::is_variable_node(branch[1]) ;
27397          }
27398 
binext_optimisable(const details::operator_type & operation,expression_node_ptr (& branch)[2]) const27399          inline bool binext_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
27400          {
27401             if (!operation_optimisable(operation))
27402                return false;
27403             else
27404                return !details::is_constant_node(branch[0]) ||
27405                       !details::is_constant_node(branch[1]) ;
27406          }
27407 
is_invalid_assignment_op(const details::operator_type & operation,expression_node_ptr (& branch)[2]) const27408          inline bool is_invalid_assignment_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
27409          {
27410             if (is_assignment_operation(operation))
27411             {
27412                const bool b1_is_genstring = details::is_generally_string_node(branch[1]);
27413 
27414                if (details::is_string_node(branch[0]))
27415                   return !b1_is_genstring;
27416                else
27417                   return (
27418                            !details::is_variable_node          (branch[0]) &&
27419                            !details::is_vector_elem_node       (branch[0]) &&
27420                            !details::is_rebasevector_elem_node (branch[0]) &&
27421                            !details::is_rebasevector_celem_node(branch[0]) &&
27422                            !details::is_vector_node            (branch[0])
27423                          )
27424                          || b1_is_genstring;
27425             }
27426             else
27427                return false;
27428          }
27429 
is_constpow_operation(const details::operator_type & operation,expression_node_ptr (& branch)[2]) const27430          inline bool is_constpow_operation(const details::operator_type& operation, expression_node_ptr(&branch)[2]) const
27431          {
27432             if (
27433                  !details::is_constant_node(branch[1]) ||
27434                   details::is_constant_node(branch[0]) ||
27435                   details::is_variable_node(branch[0]) ||
27436                   details::is_vector_node  (branch[0]) ||
27437                   details::is_generally_string_node(branch[0])
27438                )
27439                return false;
27440 
27441             const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
27442 
27443             return cardinal_pow_optimisable(operation, c);
27444          }
27445 
is_invalid_break_continue_op(expression_node_ptr (& branch)[2]) const27446          inline bool is_invalid_break_continue_op(expression_node_ptr (&branch)[2]) const
27447          {
27448             return (
27449                      details::is_break_node   (branch[0]) ||
27450                      details::is_break_node   (branch[1]) ||
27451                      details::is_continue_node(branch[0]) ||
27452                      details::is_continue_node(branch[1])
27453                    );
27454          }
27455 
is_invalid_string_op(const details::operator_type & operation,expression_node_ptr (& branch)[2]) const27456          inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
27457          {
27458             const bool b0_string = is_generally_string_node(branch[0]);
27459             const bool b1_string = is_generally_string_node(branch[1]);
27460 
27461             bool result = false;
27462 
27463             if (b0_string != b1_string)
27464                result = true;
27465             else if (!valid_string_operation(operation) && b0_string && b1_string)
27466                result = true;
27467 
27468             if (result)
27469             {
27470                parser_->set_synthesis_error("Invalid string operation");
27471             }
27472 
27473             return result;
27474          }
27475 
is_invalid_string_op(const details::operator_type & operation,expression_node_ptr (& branch)[3]) const27476          inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[3]) const
27477          {
27478             const bool b0_string = is_generally_string_node(branch[0]);
27479             const bool b1_string = is_generally_string_node(branch[1]);
27480             const bool b2_string = is_generally_string_node(branch[2]);
27481 
27482             bool result = false;
27483 
27484             if ((b0_string != b1_string) || (b1_string != b2_string))
27485                result = true;
27486             else if ((details::e_inrange != operation) && b0_string && b1_string && b2_string)
27487                result = true;
27488 
27489             if (result)
27490             {
27491                parser_->set_synthesis_error("Invalid string operation");
27492             }
27493 
27494             return result;
27495          }
27496 
is_string_operation(const details::operator_type & operation,expression_node_ptr (& branch)[2]) const27497          inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
27498          {
27499             const bool b0_string = is_generally_string_node(branch[0]);
27500             const bool b1_string = is_generally_string_node(branch[1]);
27501 
27502             return (b0_string && b1_string && valid_string_operation(operation));
27503          }
27504 
is_string_operation(const details::operator_type & operation,expression_node_ptr (& branch)[3]) const27505          inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[3]) const
27506          {
27507             const bool b0_string = is_generally_string_node(branch[0]);
27508             const bool b1_string = is_generally_string_node(branch[1]);
27509             const bool b2_string = is_generally_string_node(branch[2]);
27510 
27511             return (b0_string && b1_string && b2_string && (details::e_inrange == operation));
27512          }
27513 
27514          #ifndef exprtk_disable_sc_andor
is_shortcircuit_expression(const details::operator_type & operation) const27515          inline bool is_shortcircuit_expression(const details::operator_type& operation) const
27516          {
27517             return (
27518                      (details::e_scand == operation) ||
27519                      (details::e_scor  == operation)
27520                    );
27521          }
27522          #else
is_shortcircuit_expression(const details::operator_type &) const27523          inline bool is_shortcircuit_expression(const details::operator_type&) const
27524          {
27525             return false;
27526          }
27527          #endif
27528 
is_null_present(expression_node_ptr (& branch)[2]) const27529          inline bool is_null_present(expression_node_ptr (&branch)[2]) const
27530          {
27531             return (
27532                      details::is_null_node(branch[0]) ||
27533                      details::is_null_node(branch[1])
27534                    );
27535          }
27536 
is_vector_eqineq_logic_operation(const details::operator_type & operation,expression_node_ptr (& branch)[2]) const27537          inline bool is_vector_eqineq_logic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
27538          {
27539             if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1]))
27540                return false;
27541             else
27542                return (
27543                         (details::e_lt    == operation) ||
27544                         (details::e_lte   == operation) ||
27545                         (details::e_gt    == operation) ||
27546                         (details::e_gte   == operation) ||
27547                         (details::e_eq    == operation) ||
27548                         (details::e_ne    == operation) ||
27549                         (details::e_equal == operation) ||
27550                         (details::e_and   == operation) ||
27551                         (details::e_nand  == operation) ||
27552                         (details::  e_or  == operation) ||
27553                         (details:: e_nor  == operation) ||
27554                         (details:: e_xor  == operation) ||
27555                         (details::e_xnor  == operation)
27556                       );
27557          }
27558 
is_vector_arithmetic_operation(const details::operator_type & operation,expression_node_ptr (& branch)[2]) const27559          inline bool is_vector_arithmetic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
27560          {
27561             if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1]))
27562                return false;
27563             else
27564                return (
27565                         (details::e_add == operation) ||
27566                         (details::e_sub == operation) ||
27567                         (details::e_mul == operation) ||
27568                         (details::e_div == operation) ||
27569                         (details::e_pow == operation)
27570                       );
27571          }
27572 
operator ()(const details::operator_type & operation,expression_node_ptr (& branch)[2])27573          inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[2])
27574          {
27575             if ((0 == branch[0]) || (0 == branch[1]))
27576             {
27577                return error_node();
27578             }
27579             else if (is_invalid_string_op(operation,branch))
27580             {
27581                return error_node();
27582             }
27583             else if (is_invalid_assignment_op(operation,branch))
27584             {
27585                return error_node();
27586             }
27587             else if (is_invalid_break_continue_op(branch))
27588             {
27589                return error_node();
27590             }
27591             else if (details::e_assign == operation)
27592             {
27593                return synthesize_assignment_expression(operation, branch);
27594             }
27595             else if (details::e_swap == operation)
27596             {
27597                return synthesize_swap_expression(branch);
27598             }
27599             else if (is_assignment_operation(operation))
27600             {
27601                return synthesize_assignment_operation_expression(operation, branch);
27602             }
27603             else if (is_vector_eqineq_logic_operation(operation, branch))
27604             {
27605                return synthesize_veceqineqlogic_operation_expression(operation, branch);
27606             }
27607             else if (is_vector_arithmetic_operation(operation, branch))
27608             {
27609                return synthesize_vecarithmetic_operation_expression(operation, branch);
27610             }
27611             else if (is_shortcircuit_expression(operation))
27612             {
27613                return synthesize_shortcircuit_expression(operation, branch);
27614             }
27615             else if (is_string_operation(operation, branch))
27616             {
27617                return synthesize_string_expression(operation, branch);
27618             }
27619             else if (is_null_present(branch))
27620             {
27621                return synthesize_null_expression(operation, branch);
27622             }
27623             #ifndef exprtk_disable_cardinal_pow_optimisation
27624             else if (is_constpow_operation(operation, branch))
27625             {
27626                return cardinal_pow_optimisation(branch);
27627             }
27628             #endif
27629 
27630             expression_node_ptr result = error_node();
27631 
27632             #ifndef exprtk_disable_enhanced_features
27633             if (synthesize_expression(operation, branch, result))
27634             {
27635                return result;
27636             }
27637             else
27638             #endif
27639 
27640             {
27641                /*
27642                   Possible reductions:
27643                   1. c o cob -> cob
27644                   2. cob o c -> cob
27645                   3. c o boc -> boc
27646                   4. boc o c -> boc
27647                */
27648                result = error_node();
27649 
27650                if (cocob_optimisable(operation, branch))
27651                {
27652                   result = synthesize_cocob_expression::process((*this), operation, branch);
27653                }
27654                else if (coboc_optimisable(operation, branch) && (0 == result))
27655                {
27656                   result = synthesize_coboc_expression::process((*this), operation, branch);
27657                }
27658 
27659                if (result)
27660                   return result;
27661             }
27662 
27663             if (uvouv_optimisable(operation, branch))
27664             {
27665                return synthesize_uvouv_expression(operation, branch);
27666             }
27667             else if (vob_optimisable(operation, branch))
27668             {
27669                return synthesize_vob_expression::process((*this), operation, branch);
27670             }
27671             else if (bov_optimisable(operation, branch))
27672             {
27673                return synthesize_bov_expression::process((*this), operation, branch);
27674             }
27675             else if (cob_optimisable(operation, branch))
27676             {
27677                return synthesize_cob_expression::process((*this), operation, branch);
27678             }
27679             else if (boc_optimisable(operation, branch))
27680             {
27681                return synthesize_boc_expression::process((*this), operation, branch);
27682             }
27683             #ifndef exprtk_disable_enhanced_features
27684             else if (cov_optimisable(operation, branch))
27685             {
27686                return synthesize_cov_expression::process((*this), operation, branch);
27687             }
27688             #endif
27689             else if (binext_optimisable(operation, branch))
27690             {
27691                return synthesize_binary_ext_expression::process((*this), operation, branch);
27692             }
27693             else
27694                return synthesize_expression<binary_node_t,2>(operation, branch);
27695          }
27696 
operator ()(const details::operator_type & operation,expression_node_ptr (& branch)[3])27697          inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[3])
27698          {
27699             if (
27700                  (0 == branch[0]) ||
27701                  (0 == branch[1]) ||
27702                  (0 == branch[2])
27703                )
27704             {
27705                details::free_all_nodes(*node_allocator_,branch);
27706 
27707                return error_node();
27708             }
27709             else if (is_invalid_string_op(operation, branch))
27710             {
27711                return error_node();
27712             }
27713             else if (is_string_operation(operation, branch))
27714             {
27715                return synthesize_string_expression(operation, branch);
27716             }
27717             else
27718                return synthesize_expression<trinary_node_t,3>(operation, branch);
27719          }
27720 
operator ()(const details::operator_type & operation,expression_node_ptr (& branch)[4])27721          inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[4])
27722          {
27723             return synthesize_expression<quaternary_node_t,4>(operation,branch);
27724          }
27725 
operator ()(const details::operator_type & operation,expression_node_ptr b0)27726          inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr b0)
27727          {
27728             expression_node_ptr branch[1] = { b0 };
27729             return (*this)(operation,branch);
27730          }
27731 
operator ()(const details::operator_type & operation,expression_node_ptr & b0,expression_node_ptr & b1)27732          inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr& b0, expression_node_ptr& b1)
27733          {
27734             expression_node_ptr result = error_node();
27735 
27736             if ((0 != b0) && (0 != b1))
27737             {
27738                expression_node_ptr branch[2] = { b0, b1 };
27739                result = expression_generator<Type>::operator()(operation, branch);
27740                b0 = branch[0];
27741                b1 = branch[1];
27742             }
27743 
27744             return result;
27745          }
27746 
conditional(expression_node_ptr condition,expression_node_ptr consequent,expression_node_ptr alternative) const27747          inline expression_node_ptr conditional(expression_node_ptr condition,
27748                                                 expression_node_ptr consequent,
27749                                                 expression_node_ptr alternative) const
27750          {
27751             if ((0 == condition) || (0 == consequent))
27752             {
27753                free_node(*node_allocator_,   condition);
27754                free_node(*node_allocator_,  consequent);
27755                free_node(*node_allocator_, alternative);
27756 
27757                return error_node();
27758             }
27759             // Can the condition be immediately evaluated? if so optimise.
27760             else if (details::is_constant_node(condition))
27761             {
27762                // True branch
27763                if (details::is_true(condition))
27764                {
27765                   free_node(*node_allocator_,   condition);
27766                   free_node(*node_allocator_, alternative);
27767 
27768                   return consequent;
27769                }
27770                // False branch
27771                else
27772                {
27773                   free_node(*node_allocator_,  condition);
27774                   free_node(*node_allocator_, consequent);
27775 
27776                   if (alternative)
27777                      return alternative;
27778                   else
27779                      return node_allocator_->allocate<details::null_node<T> >();
27780                }
27781             }
27782             else if ((0 != consequent) && (0 != alternative))
27783             {
27784                return node_allocator_->
27785                         allocate<conditional_node_t>(condition, consequent, alternative);
27786             }
27787             else
27788                return node_allocator_->
27789                         allocate<cons_conditional_node_t>(condition, consequent);
27790          }
27791 
27792          #ifndef exprtk_disable_string_capabilities
conditional_string(expression_node_ptr condition,expression_node_ptr consequent,expression_node_ptr alternative) const27793          inline expression_node_ptr conditional_string(expression_node_ptr condition,
27794                                                        expression_node_ptr consequent,
27795                                                        expression_node_ptr alternative) const
27796          {
27797             if ((0 == condition) || (0 == consequent))
27798             {
27799                free_node(*node_allocator_,   condition);
27800                free_node(*node_allocator_,  consequent);
27801                free_node(*node_allocator_, alternative);
27802 
27803                return error_node();
27804             }
27805             // Can the condition be immediately evaluated? if so optimise.
27806             else if (details::is_constant_node(condition))
27807             {
27808                // True branch
27809                if (details::is_true(condition))
27810                {
27811                   free_node(*node_allocator_,   condition);
27812                   free_node(*node_allocator_, alternative);
27813 
27814                   return consequent;
27815                }
27816                // False branch
27817                else
27818                {
27819                   free_node(*node_allocator_,  condition);
27820                   free_node(*node_allocator_, consequent);
27821 
27822                   if (alternative)
27823                      return alternative;
27824                   else
27825                      return node_allocator_->
27826                               allocate_c<details::string_literal_node<Type> >("");
27827                }
27828             }
27829             else if ((0 != consequent) && (0 != alternative))
27830                return node_allocator_->
27831                         allocate<conditional_string_node_t>(condition, consequent, alternative);
27832             else
27833                return error_node();
27834          }
27835          #else
conditional_string(expression_node_ptr,expression_node_ptr,expression_node_ptr) const27836          inline expression_node_ptr conditional_string(expression_node_ptr,
27837                                                        expression_node_ptr,
27838                                                        expression_node_ptr) const
27839          {
27840             return error_node();
27841          }
27842          #endif
27843 
get_loop_runtime_check(const loop_runtime_check::loop_types loop_type) const27844          inline loop_runtime_check_ptr get_loop_runtime_check(const loop_runtime_check::loop_types loop_type) const
27845          {
27846             if (
27847                  parser_->loop_runtime_check_ &&
27848                  (loop_type == (parser_->loop_runtime_check_->loop_set & loop_type))
27849                )
27850             {
27851                return parser_->loop_runtime_check_;
27852             }
27853 
27854             return loop_runtime_check_ptr(0);
27855          }
27856 
while_loop(expression_node_ptr & condition,expression_node_ptr & branch,const bool brkcont=false) const27857          inline expression_node_ptr while_loop(expression_node_ptr& condition,
27858                                                expression_node_ptr& branch,
27859                                                const bool brkcont = false) const
27860          {
27861             if (!brkcont && details::is_constant_node(condition))
27862             {
27863                expression_node_ptr result = error_node();
27864                if (details::is_true(condition))
27865                   // Infinite loops are not allowed.
27866                   result = error_node();
27867                else
27868                   result = node_allocator_->allocate<details::null_node<Type> >();
27869 
27870                free_node(*node_allocator_, condition);
27871                free_node(*node_allocator_,    branch);
27872 
27873                return result;
27874             }
27875             else if (details::is_null_node(condition))
27876             {
27877                free_node(*node_allocator_,condition);
27878 
27879                return branch;
27880             }
27881             else if (!brkcont)
27882                return node_allocator_->allocate<while_loop_node_t>
27883                         (
27884                           condition,
27885                           branch,
27886                           get_loop_runtime_check(loop_runtime_check::e_while_loop)
27887                         );
27888             #ifndef exprtk_disable_break_continue
27889             else
27890                return node_allocator_->allocate<while_loop_bc_node_t>
27891                         (
27892                           condition,
27893                           branch,
27894                           get_loop_runtime_check(loop_runtime_check::e_while_loop)
27895                         );
27896             #else
27897                return error_node();
27898             #endif
27899          }
27900 
repeat_until_loop(expression_node_ptr & condition,expression_node_ptr & branch,const bool brkcont=false) const27901          inline expression_node_ptr repeat_until_loop(expression_node_ptr& condition,
27902                                                       expression_node_ptr& branch,
27903                                                       const bool brkcont = false) const
27904          {
27905             if (!brkcont && details::is_constant_node(condition))
27906             {
27907                if (
27908                     details::is_true(condition) &&
27909                     details::is_constant_node(branch)
27910                   )
27911                {
27912                   free_node(*node_allocator_,condition);
27913 
27914                   return branch;
27915                }
27916 
27917                free_node(*node_allocator_, condition);
27918                free_node(*node_allocator_,    branch);
27919 
27920                return error_node();
27921             }
27922             else if (details::is_null_node(condition))
27923             {
27924                free_node(*node_allocator_,condition);
27925 
27926                return branch;
27927             }
27928             else if (!brkcont)
27929                return node_allocator_->allocate<repeat_until_loop_node_t>
27930                         (
27931                           condition,
27932                           branch,
27933                           get_loop_runtime_check(loop_runtime_check::e_repeat_until_loop)
27934                         );
27935             #ifndef exprtk_disable_break_continue
27936             else
27937                return node_allocator_->allocate<repeat_until_loop_bc_node_t>
27938                         (
27939                           condition,
27940                           branch,
27941                           get_loop_runtime_check(loop_runtime_check::e_repeat_until_loop)
27942                         );
27943             #else
27944                return error_node();
27945             #endif
27946          }
27947 
for_loop(expression_node_ptr & initialiser,expression_node_ptr & condition,expression_node_ptr & incrementor,expression_node_ptr & loop_body,bool brkcont=false) const27948          inline expression_node_ptr for_loop(expression_node_ptr& initialiser,
27949                                              expression_node_ptr& condition,
27950                                              expression_node_ptr& incrementor,
27951                                              expression_node_ptr& loop_body,
27952                                              bool brkcont = false) const
27953          {
27954             if (!brkcont && details::is_constant_node(condition))
27955             {
27956                expression_node_ptr result = error_node();
27957 
27958                if (details::is_true(condition))
27959                   // Infinite loops are not allowed.
27960                   result = error_node();
27961                else
27962                   result = node_allocator_->allocate<details::null_node<Type> >();
27963 
27964                free_node(*node_allocator_, initialiser);
27965                free_node(*node_allocator_,   condition);
27966                free_node(*node_allocator_, incrementor);
27967                free_node(*node_allocator_,   loop_body);
27968 
27969                return result;
27970             }
27971             else if (details::is_null_node(condition) || (0 == condition))
27972             {
27973                free_node(*node_allocator_, initialiser);
27974                free_node(*node_allocator_,   condition);
27975                free_node(*node_allocator_, incrementor);
27976 
27977                return loop_body;
27978             }
27979             else if (!brkcont)
27980                return node_allocator_->allocate<for_loop_node_t>
27981                                        (
27982                                          initialiser,
27983                                          condition,
27984                                          incrementor,
27985                                          loop_body,
27986                                          get_loop_runtime_check(loop_runtime_check::e_for_loop)
27987                                        );
27988 
27989             #ifndef exprtk_disable_break_continue
27990             else
27991                return node_allocator_->allocate<for_loop_bc_node_t>
27992                                        (
27993                                          initialiser,
27994                                          condition,
27995                                          incrementor,
27996                                          loop_body,
27997                                          get_loop_runtime_check(loop_runtime_check::e_for_loop)
27998                                        );
27999             #else
28000             return error_node();
28001             #endif
28002          }
28003 
28004          template <typename Allocator,
28005                    template <typename, typename> class Sequence>
const_optimise_switch(Sequence<expression_node_ptr,Allocator> & arg_list)28006          inline expression_node_ptr const_optimise_switch(Sequence<expression_node_ptr,Allocator>& arg_list)
28007          {
28008             expression_node_ptr result = error_node();
28009 
28010             for (std::size_t i = 0; i < (arg_list.size() / 2); ++i)
28011             {
28012                expression_node_ptr condition  = arg_list[(2 * i)    ];
28013                expression_node_ptr consequent = arg_list[(2 * i) + 1];
28014 
28015                if ((0 == result) && details::is_true(condition))
28016                {
28017                   result = consequent;
28018                   break;
28019                }
28020             }
28021 
28022             if (0 == result)
28023             {
28024                result = arg_list.back();
28025             }
28026 
28027             for (std::size_t i = 0; i < arg_list.size(); ++i)
28028             {
28029                expression_node_ptr current_expr = arg_list[i];
28030 
28031                if (current_expr && (current_expr != result))
28032                {
28033                   free_node(*node_allocator_,current_expr);
28034                }
28035             }
28036 
28037             return result;
28038          }
28039 
28040          template <typename Allocator,
28041                    template <typename, typename> class Sequence>
const_optimise_mswitch(Sequence<expression_node_ptr,Allocator> & arg_list)28042          inline expression_node_ptr const_optimise_mswitch(Sequence<expression_node_ptr,Allocator>& arg_list)
28043          {
28044             expression_node_ptr result = error_node();
28045 
28046             for (std::size_t i = 0; i < (arg_list.size() / 2); ++i)
28047             {
28048                expression_node_ptr condition  = arg_list[(2 * i)    ];
28049                expression_node_ptr consequent = arg_list[(2 * i) + 1];
28050 
28051                if (details::is_true(condition))
28052                {
28053                   result = consequent;
28054                }
28055             }
28056 
28057             if (0 == result)
28058             {
28059                T zero = T(0);
28060                result = node_allocator_->allocate<literal_node_t>(zero);
28061             }
28062 
28063             for (std::size_t i = 0; i < arg_list.size(); ++i)
28064             {
28065                expression_node_ptr& current_expr = arg_list[i];
28066 
28067                if (current_expr && (current_expr != result))
28068                {
28069                   free_node(*node_allocator_,current_expr);
28070                }
28071             }
28072 
28073             return result;
28074          }
28075 
28076          struct switch_nodes
28077          {
28078             typedef std::vector<std::pair<expression_node_ptr,bool> > arg_list_t;
28079 
28080             #define case_stmt(N)                                                         \
28081             if (is_true(arg[(2 * N)].first)) { return arg[(2 * N) + 1].first->value(); } \
28082 
28083             struct switch_1
28084             {
processexprtk::parser::expression_generator::switch_nodes::switch_128085                static inline T process(const arg_list_t& arg)
28086                {
28087                   case_stmt(0)
28088 
28089                   return arg.back().first->value();
28090                }
28091             };
28092 
28093             struct switch_2
28094             {
processexprtk::parser::expression_generator::switch_nodes::switch_228095                static inline T process(const arg_list_t& arg)
28096                {
28097                   case_stmt(0) case_stmt(1)
28098 
28099                   return arg.back().first->value();
28100                }
28101             };
28102 
28103             struct switch_3
28104             {
processexprtk::parser::expression_generator::switch_nodes::switch_328105                static inline T process(const arg_list_t& arg)
28106                {
28107                   case_stmt(0) case_stmt(1)
28108                   case_stmt(2)
28109 
28110                   return arg.back().first->value();
28111                }
28112             };
28113 
28114             struct switch_4
28115             {
processexprtk::parser::expression_generator::switch_nodes::switch_428116                static inline T process(const arg_list_t& arg)
28117                {
28118                   case_stmt(0) case_stmt(1)
28119                   case_stmt(2) case_stmt(3)
28120 
28121                   return arg.back().first->value();
28122                }
28123             };
28124 
28125             struct switch_5
28126             {
processexprtk::parser::expression_generator::switch_nodes::switch_528127                static inline T process(const arg_list_t& arg)
28128                {
28129                   case_stmt(0) case_stmt(1)
28130                   case_stmt(2) case_stmt(3)
28131                   case_stmt(4)
28132 
28133                   return arg.back().first->value();
28134                }
28135             };
28136 
28137             struct switch_6
28138             {
processexprtk::parser::expression_generator::switch_nodes::switch_628139                static inline T process(const arg_list_t& arg)
28140                {
28141                   case_stmt(0) case_stmt(1)
28142                   case_stmt(2) case_stmt(3)
28143                   case_stmt(4) case_stmt(5)
28144 
28145                   return arg.back().first->value();
28146                }
28147             };
28148 
28149             struct switch_7
28150             {
processexprtk::parser::expression_generator::switch_nodes::switch_728151                static inline T process(const arg_list_t& arg)
28152                {
28153                   case_stmt(0) case_stmt(1)
28154                   case_stmt(2) case_stmt(3)
28155                   case_stmt(4) case_stmt(5)
28156                   case_stmt(6)
28157 
28158                   return arg.back().first->value();
28159                }
28160             };
28161 
28162             #undef case_stmt
28163          };
28164 
28165          template <typename Allocator,
28166                    template <typename, typename> class Sequence>
switch_statement(Sequence<expression_node_ptr,Allocator> & arg_list,const bool default_statement_present)28167          inline expression_node_ptr switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list, const bool default_statement_present)
28168          {
28169             if (arg_list.empty())
28170                return error_node();
28171             else if (
28172                       !all_nodes_valid(arg_list) ||
28173                       (!default_statement_present && (arg_list.size() < 2))
28174                     )
28175             {
28176                details::free_all_nodes(*node_allocator_,arg_list);
28177 
28178                return error_node();
28179             }
28180             else if (is_constant_foldable(arg_list))
28181                return const_optimise_switch(arg_list);
28182 
28183             switch ((arg_list.size() - 1) / 2)
28184             {
28185                #define case_stmt(N)                                                 \
28186                case N :                                                             \
28187                   return node_allocator_->                                          \
28188                             allocate<details::switch_n_node                         \
28189                               <Type,typename switch_nodes::switch_##N> >(arg_list); \
28190 
28191                case_stmt(1)
28192                case_stmt(2)
28193                case_stmt(3)
28194                case_stmt(4)
28195                case_stmt(5)
28196                case_stmt(6)
28197                case_stmt(7)
28198                #undef case_stmt
28199 
28200                default : return node_allocator_->allocate<details::switch_node<Type> >(arg_list);
28201             }
28202          }
28203 
28204          template <typename Allocator,
28205                    template <typename, typename> class Sequence>
multi_switch_statement(Sequence<expression_node_ptr,Allocator> & arg_list)28206          inline expression_node_ptr multi_switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list)
28207          {
28208             if (!all_nodes_valid(arg_list))
28209             {
28210                details::free_all_nodes(*node_allocator_,arg_list);
28211 
28212                return error_node();
28213             }
28214             else if (is_constant_foldable(arg_list))
28215                return const_optimise_mswitch(arg_list);
28216             else
28217                return node_allocator_->allocate<details::multi_switch_node<Type> >(arg_list);
28218          }
28219 
28220          #define unary_opr_switch_statements            \
28221          case_stmt(details::  e_abs, details::  abs_op) \
28222          case_stmt(details:: e_acos, details:: acos_op) \
28223          case_stmt(details::e_acosh, details::acosh_op) \
28224          case_stmt(details:: e_asin, details:: asin_op) \
28225          case_stmt(details::e_asinh, details::asinh_op) \
28226          case_stmt(details:: e_atan, details:: atan_op) \
28227          case_stmt(details::e_atanh, details::atanh_op) \
28228          case_stmt(details:: e_ceil, details:: ceil_op) \
28229          case_stmt(details::  e_cos, details::  cos_op) \
28230          case_stmt(details:: e_cosh, details:: cosh_op) \
28231          case_stmt(details::  e_exp, details::  exp_op) \
28232          case_stmt(details::e_expm1, details::expm1_op) \
28233          case_stmt(details::e_floor, details::floor_op) \
28234          case_stmt(details::  e_log, details::  log_op) \
28235          case_stmt(details::e_log10, details::log10_op) \
28236          case_stmt(details:: e_log2, details:: log2_op) \
28237          case_stmt(details::e_log1p, details::log1p_op) \
28238          case_stmt(details::  e_neg, details::  neg_op) \
28239          case_stmt(details::  e_pos, details::  pos_op) \
28240          case_stmt(details::e_round, details::round_op) \
28241          case_stmt(details::  e_sin, details::  sin_op) \
28242          case_stmt(details:: e_sinc, details:: sinc_op) \
28243          case_stmt(details:: e_sinh, details:: sinh_op) \
28244          case_stmt(details:: e_sqrt, details:: sqrt_op) \
28245          case_stmt(details::  e_tan, details::  tan_op) \
28246          case_stmt(details:: e_tanh, details:: tanh_op) \
28247          case_stmt(details::  e_cot, details::  cot_op) \
28248          case_stmt(details::  e_sec, details::  sec_op) \
28249          case_stmt(details::  e_csc, details::  csc_op) \
28250          case_stmt(details::  e_r2d, details::  r2d_op) \
28251          case_stmt(details::  e_d2r, details::  d2r_op) \
28252          case_stmt(details::  e_d2g, details::  d2g_op) \
28253          case_stmt(details::  e_g2d, details::  g2d_op) \
28254          case_stmt(details:: e_notl, details:: notl_op) \
28255          case_stmt(details::  e_sgn, details::  sgn_op) \
28256          case_stmt(details::  e_erf, details::  erf_op) \
28257          case_stmt(details:: e_erfc, details:: erfc_op) \
28258          case_stmt(details:: e_ncdf, details:: ncdf_op) \
28259          case_stmt(details:: e_frac, details:: frac_op) \
28260          case_stmt(details::e_trunc, details::trunc_op) \
28261 
synthesize_uv_expression(const details::operator_type & operation,expression_node_ptr (& branch)[1])28262          inline expression_node_ptr synthesize_uv_expression(const details::operator_type& operation,
28263                                                              expression_node_ptr (&branch)[1])
28264          {
28265             T& v = static_cast<details::variable_node<T>*>(branch[0])->ref();
28266 
28267             switch (operation)
28268             {
28269                #define case_stmt(op0,op1)                                                          \
28270                case op0 : return node_allocator_->                                                 \
28271                              allocate<typename details::unary_variable_node<Type,op1<Type> > >(v); \
28272 
28273                unary_opr_switch_statements
28274                #undef case_stmt
28275                default : return error_node();
28276             }
28277          }
28278 
synthesize_uvec_expression(const details::operator_type & operation,expression_node_ptr (& branch)[1])28279          inline expression_node_ptr synthesize_uvec_expression(const details::operator_type& operation,
28280                                                                expression_node_ptr (&branch)[1])
28281          {
28282             switch (operation)
28283             {
28284                #define case_stmt(op0,op1)                                                    \
28285                case op0 : return node_allocator_->                                           \
28286                              allocate<typename details::unary_vector_node<Type,op1<Type> > > \
28287                                 (operation, branch[0]);                                      \
28288 
28289                unary_opr_switch_statements
28290                #undef case_stmt
28291                default : return error_node();
28292             }
28293          }
28294 
synthesize_unary_expression(const details::operator_type & operation,expression_node_ptr (& branch)[1])28295          inline expression_node_ptr synthesize_unary_expression(const details::operator_type& operation,
28296                                                                 expression_node_ptr (&branch)[1])
28297          {
28298             switch (operation)
28299             {
28300                #define case_stmt(op0,op1)                                                                \
28301                case op0 : return node_allocator_->                                                       \
28302                              allocate<typename details::unary_branch_node<Type,op1<Type> > >(branch[0]); \
28303 
28304                unary_opr_switch_statements
28305                #undef case_stmt
28306                default : return error_node();
28307             }
28308          }
28309 
const_optimise_sf3(const details::operator_type & operation,expression_node_ptr (& branch)[3])28310          inline expression_node_ptr const_optimise_sf3(const details::operator_type& operation,
28311                                                        expression_node_ptr (&branch)[3])
28312          {
28313             expression_node_ptr temp_node = error_node();
28314 
28315             switch (operation)
28316             {
28317                #define case_stmt(op)                                                        \
28318                case details::e_sf##op : temp_node = node_allocator_->                       \
28319                              allocate<details::sf3_node<Type,details::sf##op##_op<Type> > > \
28320                                 (operation, branch);                                        \
28321                              break;                                                         \
28322 
28323                case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
28324                case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
28325                case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
28326                case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
28327                case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
28328                case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
28329                case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
28330                case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31)
28331                case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35)
28332                case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39)
28333                case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43)
28334                case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47)
28335                #undef case_stmt
28336                default : return error_node();
28337             }
28338 
28339             const T v = temp_node->value();
28340 
28341             details::free_node(*node_allocator_,temp_node);
28342 
28343             return node_allocator_->allocate<literal_node_t>(v);
28344          }
28345 
varnode_optimise_sf3(const details::operator_type & operation,expression_node_ptr (& branch)[3])28346          inline expression_node_ptr varnode_optimise_sf3(const details::operator_type& operation, expression_node_ptr (&branch)[3])
28347          {
28348             typedef details::variable_node<Type>* variable_ptr;
28349 
28350             const Type& v0 = static_cast<variable_ptr>(branch[0])->ref();
28351             const Type& v1 = static_cast<variable_ptr>(branch[1])->ref();
28352             const Type& v2 = static_cast<variable_ptr>(branch[2])->ref();
28353 
28354             switch (operation)
28355             {
28356                #define case_stmt(op)                                                                \
28357                case details::e_sf##op : return node_allocator_->                                    \
28358                              allocate_rrr<details::sf3_var_node<Type,details::sf##op##_op<Type> > > \
28359                                 (v0, v1, v2);                                                       \
28360 
28361                case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
28362                case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
28363                case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
28364                case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
28365                case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
28366                case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
28367                case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
28368                case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31)
28369                case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35)
28370                case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39)
28371                case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43)
28372                case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47)
28373                #undef case_stmt
28374                default : return error_node();
28375             }
28376          }
28377 
special_function(const details::operator_type & operation,expression_node_ptr (& branch)[3])28378          inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[3])
28379          {
28380             if (!all_nodes_valid(branch))
28381                return error_node();
28382             else if (is_constant_foldable(branch))
28383                return const_optimise_sf3(operation,branch);
28384             else if (all_nodes_variables(branch))
28385                return varnode_optimise_sf3(operation,branch);
28386             else
28387             {
28388                switch (operation)
28389                {
28390                   #define case_stmt(op)                                                        \
28391                   case details::e_sf##op : return node_allocator_->                            \
28392                                 allocate<details::sf3_node<Type,details::sf##op##_op<Type> > > \
28393                                    (operation, branch);                                        \
28394 
28395                   case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
28396                   case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
28397                   case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
28398                   case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
28399                   case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
28400                   case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
28401                   case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
28402                   case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31)
28403                   case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35)
28404                   case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39)
28405                   case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43)
28406                   case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47)
28407                   #undef case_stmt
28408                   default : return error_node();
28409                }
28410             }
28411          }
28412 
const_optimise_sf4(const details::operator_type & operation,expression_node_ptr (& branch)[4])28413          inline expression_node_ptr const_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4])
28414          {
28415             expression_node_ptr temp_node = error_node();
28416 
28417             switch (operation)
28418             {
28419                #define case_stmt(op)                                                                    \
28420                case details::e_sf##op : temp_node = node_allocator_->                                   \
28421                                          allocate<details::sf4_node<Type,details::sf##op##_op<Type> > > \
28422                                             (operation, branch);                                        \
28423                                         break;                                                          \
28424 
28425                case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51)
28426                case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55)
28427                case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59)
28428                case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63)
28429                case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67)
28430                case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71)
28431                case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75)
28432                case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79)
28433                case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83)
28434                case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87)
28435                case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91)
28436                case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95)
28437                case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99)
28438                #undef case_stmt
28439                default : return error_node();
28440             }
28441 
28442             const T v = temp_node->value();
28443 
28444             details::free_node(*node_allocator_,temp_node);
28445 
28446             return node_allocator_->allocate<literal_node_t>(v);
28447          }
28448 
varnode_optimise_sf4(const details::operator_type & operation,expression_node_ptr (& branch)[4])28449          inline expression_node_ptr varnode_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4])
28450          {
28451             typedef details::variable_node<Type>* variable_ptr;
28452 
28453             const Type& v0 = static_cast<variable_ptr>(branch[0])->ref();
28454             const Type& v1 = static_cast<variable_ptr>(branch[1])->ref();
28455             const Type& v2 = static_cast<variable_ptr>(branch[2])->ref();
28456             const Type& v3 = static_cast<variable_ptr>(branch[3])->ref();
28457 
28458             switch (operation)
28459             {
28460                #define case_stmt(op)                                                                 \
28461                case details::e_sf##op : return node_allocator_->                                     \
28462                              allocate_rrrr<details::sf4_var_node<Type,details::sf##op##_op<Type> > > \
28463                                 (v0, v1, v2, v3);                                                    \
28464 
28465                case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51)
28466                case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55)
28467                case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59)
28468                case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63)
28469                case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67)
28470                case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71)
28471                case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75)
28472                case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79)
28473                case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83)
28474                case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87)
28475                case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91)
28476                case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95)
28477                case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99)
28478                #undef case_stmt
28479                default : return error_node();
28480             }
28481          }
28482 
special_function(const details::operator_type & operation,expression_node_ptr (& branch)[4])28483          inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[4])
28484          {
28485             if (!all_nodes_valid(branch))
28486                return error_node();
28487             else if (is_constant_foldable(branch))
28488                return const_optimise_sf4(operation,branch);
28489             else if (all_nodes_variables(branch))
28490                return varnode_optimise_sf4(operation,branch);
28491             switch (operation)
28492             {
28493                #define case_stmt(op)                                                        \
28494                case details::e_sf##op : return node_allocator_->                            \
28495                              allocate<details::sf4_node<Type,details::sf##op##_op<Type> > > \
28496                                 (operation, branch);                                        \
28497 
28498                case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51)
28499                case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55)
28500                case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59)
28501                case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63)
28502                case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67)
28503                case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71)
28504                case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75)
28505                case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79)
28506                case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83)
28507                case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87)
28508                case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91)
28509                case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95)
28510                case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99)
28511                #undef case_stmt
28512                default : return error_node();
28513             }
28514          }
28515 
28516          template <typename Allocator,
28517                    template <typename, typename> class Sequence>
const_optimise_varargfunc(const details::operator_type & operation,Sequence<expression_node_ptr,Allocator> & arg_list)28518          inline expression_node_ptr const_optimise_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
28519          {
28520             expression_node_ptr temp_node = error_node();
28521 
28522             switch (operation)
28523             {
28524                #define case_stmt(op0,op1)                                                 \
28525                case op0 : temp_node = node_allocator_->                                   \
28526                                          allocate<details::vararg_node<Type,op1<Type> > > \
28527                                             (arg_list);                                   \
28528                           break;                                                          \
28529 
28530                case_stmt(details::e_sum   , details::vararg_add_op  )
28531                case_stmt(details::e_prod  , details::vararg_mul_op  )
28532                case_stmt(details::e_avg   , details::vararg_avg_op  )
28533                case_stmt(details::e_min   , details::vararg_min_op  )
28534                case_stmt(details::e_max   , details::vararg_max_op  )
28535                case_stmt(details::e_mand  , details::vararg_mand_op )
28536                case_stmt(details::e_mor   , details::vararg_mor_op  )
28537                case_stmt(details::e_multi , details::vararg_multi_op)
28538                #undef case_stmt
28539                default : return error_node();
28540             }
28541 
28542             const T v = temp_node->value();
28543 
28544             details::free_node(*node_allocator_,temp_node);
28545 
28546             return node_allocator_->allocate<literal_node_t>(v);
28547          }
28548 
special_one_parameter_vararg(const details::operator_type & operation) const28549          inline bool special_one_parameter_vararg(const details::operator_type& operation) const
28550          {
28551             return (
28552                      (details::e_sum  == operation) ||
28553                      (details::e_prod == operation) ||
28554                      (details::e_avg  == operation) ||
28555                      (details::e_min  == operation) ||
28556                      (details::e_max  == operation)
28557                    );
28558          }
28559 
28560          template <typename Allocator,
28561                    template <typename, typename> class Sequence>
varnode_optimise_varargfunc(const details::operator_type & operation,Sequence<expression_node_ptr,Allocator> & arg_list)28562          inline expression_node_ptr varnode_optimise_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
28563          {
28564             switch (operation)
28565             {
28566                #define case_stmt(op0,op1)                                                   \
28567                case op0 : return node_allocator_->                                          \
28568                              allocate<details::vararg_varnode<Type,op1<Type> > >(arg_list); \
28569 
28570                case_stmt(details::e_sum   , details::vararg_add_op  )
28571                case_stmt(details::e_prod  , details::vararg_mul_op  )
28572                case_stmt(details::e_avg   , details::vararg_avg_op  )
28573                case_stmt(details::e_min   , details::vararg_min_op  )
28574                case_stmt(details::e_max   , details::vararg_max_op  )
28575                case_stmt(details::e_mand  , details::vararg_mand_op )
28576                case_stmt(details::e_mor   , details::vararg_mor_op  )
28577                case_stmt(details::e_multi , details::vararg_multi_op)
28578                #undef case_stmt
28579                default : return error_node();
28580             }
28581          }
28582 
28583          template <typename Allocator,
28584                    template <typename, typename> class Sequence>
vectorize_func(const details::operator_type & operation,Sequence<expression_node_ptr,Allocator> & arg_list)28585          inline expression_node_ptr vectorize_func(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
28586          {
28587             if (1 == arg_list.size())
28588             {
28589                switch (operation)
28590                {
28591                   #define case_stmt(op0,op1)                                                      \
28592                   case op0 : return node_allocator_->                                             \
28593                                 allocate<details::vectorize_node<Type,op1<Type> > >(arg_list[0]); \
28594 
28595                   case_stmt(details::e_sum  , details::vec_add_op)
28596                   case_stmt(details::e_prod , details::vec_mul_op)
28597                   case_stmt(details::e_avg  , details::vec_avg_op)
28598                   case_stmt(details::e_min  , details::vec_min_op)
28599                   case_stmt(details::e_max  , details::vec_max_op)
28600                   #undef case_stmt
28601                   default : return error_node();
28602                }
28603             }
28604             else
28605                return error_node();
28606          }
28607 
28608          template <typename Allocator,
28609                    template <typename, typename> class Sequence>
vararg_function(const details::operator_type & operation,Sequence<expression_node_ptr,Allocator> & arg_list)28610          inline expression_node_ptr vararg_function(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
28611          {
28612             if (!all_nodes_valid(arg_list))
28613             {
28614                details::free_all_nodes(*node_allocator_,arg_list);
28615 
28616                return error_node();
28617             }
28618             else if (is_constant_foldable(arg_list))
28619                return const_optimise_varargfunc(operation,arg_list);
28620             else if ((arg_list.size() == 1) && details::is_ivector_node(arg_list[0]))
28621                return vectorize_func(operation,arg_list);
28622             else if ((arg_list.size() == 1) && special_one_parameter_vararg(operation))
28623                return arg_list[0];
28624             else if (all_nodes_variables(arg_list))
28625                return varnode_optimise_varargfunc(operation,arg_list);
28626 
28627             #ifndef exprtk_disable_string_capabilities
28628             if (details::e_smulti == operation)
28629             {
28630                return node_allocator_->
28631                  allocate<details::str_vararg_node<Type,details::vararg_multi_op<Type> > >(arg_list);
28632             }
28633             else
28634             #endif
28635             {
28636                switch (operation)
28637                {
28638                   #define case_stmt(op0,op1)                                                \
28639                   case op0 : return node_allocator_->                                       \
28640                                 allocate<details::vararg_node<Type,op1<Type> > >(arg_list); \
28641 
28642                   case_stmt(details::e_sum   , details::vararg_add_op  )
28643                   case_stmt(details::e_prod  , details::vararg_mul_op  )
28644                   case_stmt(details::e_avg   , details::vararg_avg_op  )
28645                   case_stmt(details::e_min   , details::vararg_min_op  )
28646                   case_stmt(details::e_max   , details::vararg_max_op  )
28647                   case_stmt(details::e_mand  , details::vararg_mand_op )
28648                   case_stmt(details::e_mor   , details::vararg_mor_op  )
28649                   case_stmt(details::e_multi , details::vararg_multi_op)
28650                   #undef case_stmt
28651                   default : return error_node();
28652                }
28653             }
28654          }
28655 
28656          template <std::size_t N>
function(ifunction_t * f,expression_node_ptr (& b)[N])28657          inline expression_node_ptr function(ifunction_t* f, expression_node_ptr (&b)[N])
28658          {
28659             typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t;
28660             expression_node_ptr result = synthesize_expression<function_N_node_t,N>(f,b);
28661 
28662             if (0 == result)
28663                return error_node();
28664             else
28665             {
28666                // Can the function call be completely optimised?
28667                if (details::is_constant_node(result))
28668                   return result;
28669                else if (!all_nodes_valid(b))
28670                {
28671                   details::free_node(*node_allocator_,result);
28672                   std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0));
28673 
28674                   return error_node();
28675                }
28676                else if (N != f->param_count)
28677                {
28678                   details::free_node(*node_allocator_,result);
28679                   std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0));
28680 
28681                   return error_node();
28682                }
28683 
28684                function_N_node_t* func_node_ptr = reinterpret_cast<function_N_node_t*>(result);
28685 
28686                if (!func_node_ptr->init_branches(b))
28687                {
28688                   details::free_node(*node_allocator_,result);
28689                   std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0));
28690 
28691                   return error_node();
28692                }
28693 
28694                return result;
28695             }
28696          }
28697 
function(ifunction_t * f)28698          inline expression_node_ptr function(ifunction_t* f)
28699          {
28700             typedef typename details::function_N_node<Type,ifunction_t,0> function_N_node_t;
28701             return node_allocator_->allocate<function_N_node_t>(f);
28702          }
28703 
vararg_function_call(ivararg_function_t * vaf,std::vector<expression_node_ptr> & arg_list)28704          inline expression_node_ptr vararg_function_call(ivararg_function_t* vaf,
28705                                                          std::vector<expression_node_ptr>& arg_list)
28706          {
28707             if (!all_nodes_valid(arg_list))
28708             {
28709                details::free_all_nodes(*node_allocator_,arg_list);
28710 
28711                return error_node();
28712             }
28713 
28714             typedef details::vararg_function_node<Type,ivararg_function_t> alloc_type;
28715 
28716             expression_node_ptr result = node_allocator_->allocate<alloc_type>(vaf,arg_list);
28717 
28718             if (
28719                  !arg_list.empty()        &&
28720                  !vaf->has_side_effects() &&
28721                  is_constant_foldable(arg_list)
28722                )
28723             {
28724                const Type v = result->value();
28725                details::free_node(*node_allocator_,result);
28726                result = node_allocator_->allocate<literal_node_t>(v);
28727             }
28728 
28729             parser_->state_.activate_side_effect("vararg_function_call()");
28730 
28731             return result;
28732          }
28733 
generic_function_call(igeneric_function_t * gf,std::vector<expression_node_ptr> & arg_list,const std::size_t & param_seq_index=std::numeric_limits<std::size_t>::max ())28734          inline expression_node_ptr generic_function_call(igeneric_function_t* gf,
28735                                                           std::vector<expression_node_ptr>& arg_list,
28736                                                           const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max())
28737          {
28738             if (!all_nodes_valid(arg_list))
28739             {
28740                details::free_all_nodes(*node_allocator_,arg_list);
28741                return error_node();
28742             }
28743 
28744             typedef details::generic_function_node     <Type,igeneric_function_t> alloc_type1;
28745             typedef details::multimode_genfunction_node<Type,igeneric_function_t> alloc_type2;
28746 
28747             const std::size_t no_psi = std::numeric_limits<std::size_t>::max();
28748 
28749             expression_node_ptr result = error_node();
28750 
28751             if (no_psi == param_seq_index)
28752                result = node_allocator_->allocate<alloc_type1>(arg_list,gf);
28753             else
28754                result = node_allocator_->allocate<alloc_type2>(gf, param_seq_index, arg_list);
28755 
28756             alloc_type1* genfunc_node_ptr = static_cast<alloc_type1*>(result);
28757 
28758             if (
28759                  !arg_list.empty()                  &&
28760                  !gf->has_side_effects()            &&
28761                  parser_->state_.type_check_enabled &&
28762                  is_constant_foldable(arg_list)
28763                )
28764             {
28765                genfunc_node_ptr->init_branches();
28766 
28767                const Type v = result->value();
28768 
28769                details::free_node(*node_allocator_,result);
28770 
28771                return node_allocator_->allocate<literal_node_t>(v);
28772             }
28773             else if (genfunc_node_ptr->init_branches())
28774             {
28775                parser_->state_.activate_side_effect("generic_function_call()");
28776 
28777                return result;
28778             }
28779             else
28780             {
28781                details::free_node(*node_allocator_, result);
28782                details::free_all_nodes(*node_allocator_, arg_list);
28783 
28784                return error_node();
28785             }
28786          }
28787 
28788          #ifndef exprtk_disable_string_capabilities
string_function_call(igeneric_function_t * gf,std::vector<expression_node_ptr> & arg_list,const std::size_t & param_seq_index=std::numeric_limits<std::size_t>::max ())28789          inline expression_node_ptr string_function_call(igeneric_function_t* gf,
28790                                                          std::vector<expression_node_ptr>& arg_list,
28791                                                          const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max())
28792          {
28793             if (!all_nodes_valid(arg_list))
28794             {
28795                details::free_all_nodes(*node_allocator_,arg_list);
28796                return error_node();
28797             }
28798 
28799             typedef details::string_function_node      <Type,igeneric_function_t> alloc_type1;
28800             typedef details::multimode_strfunction_node<Type,igeneric_function_t> alloc_type2;
28801 
28802             const std::size_t no_psi = std::numeric_limits<std::size_t>::max();
28803 
28804             expression_node_ptr result = error_node();
28805 
28806             if (no_psi == param_seq_index)
28807                result = node_allocator_->allocate<alloc_type1>(gf,arg_list);
28808             else
28809                result = node_allocator_->allocate<alloc_type2>(gf, param_seq_index, arg_list);
28810 
28811             alloc_type1* strfunc_node_ptr = static_cast<alloc_type1*>(result);
28812 
28813             if (
28814                  !arg_list.empty()       &&
28815                  !gf->has_side_effects() &&
28816                  is_constant_foldable(arg_list)
28817                )
28818             {
28819                strfunc_node_ptr->init_branches();
28820 
28821                const Type v = result->value();
28822 
28823                details::free_node(*node_allocator_,result);
28824 
28825                return node_allocator_->allocate<literal_node_t>(v);
28826             }
28827             else if (strfunc_node_ptr->init_branches())
28828             {
28829                parser_->state_.activate_side_effect("string_function_call()");
28830 
28831                return result;
28832             }
28833             else
28834             {
28835                details::free_node     (*node_allocator_,result  );
28836                details::free_all_nodes(*node_allocator_,arg_list);
28837 
28838                return error_node();
28839             }
28840          }
28841          #endif
28842 
28843          #ifndef exprtk_disable_return_statement
return_call(std::vector<expression_node_ptr> & arg_list)28844          inline expression_node_ptr return_call(std::vector<expression_node_ptr>& arg_list)
28845          {
28846             if (!all_nodes_valid(arg_list))
28847             {
28848                details::free_all_nodes(*node_allocator_,arg_list);
28849                return error_node();
28850             }
28851 
28852             typedef details::return_node<Type> alloc_type;
28853 
28854             expression_node_ptr result = node_allocator_->
28855                                             allocate_rr<alloc_type>(arg_list,parser_->results_ctx());
28856 
28857             alloc_type* return_node_ptr = static_cast<alloc_type*>(result);
28858 
28859             if (return_node_ptr->init_branches())
28860             {
28861                parser_->state_.activate_side_effect("return_call()");
28862 
28863                return result;
28864             }
28865             else
28866             {
28867                details::free_node     (*node_allocator_,result  );
28868                details::free_all_nodes(*node_allocator_,arg_list);
28869 
28870                return error_node();
28871             }
28872          }
28873 
return_envelope(expression_node_ptr body,results_context_t * rc,bool * & return_invoked)28874          inline expression_node_ptr return_envelope(expression_node_ptr body,
28875                                                     results_context_t* rc,
28876                                                     bool*& return_invoked)
28877          {
28878             typedef details::return_envelope_node<Type> alloc_type;
28879 
28880             expression_node_ptr result = node_allocator_->
28881                                             allocate_cr<alloc_type>(body,(*rc));
28882 
28883             return_invoked = static_cast<alloc_type*>(result)->retinvk_ptr();
28884 
28885             return result;
28886          }
28887          #else
return_call(std::vector<expression_node_ptr> &)28888          inline expression_node_ptr return_call(std::vector<expression_node_ptr>&)
28889          {
28890             return error_node();
28891          }
28892 
return_envelope(expression_node_ptr,results_context_t *,bool * &)28893          inline expression_node_ptr return_envelope(expression_node_ptr,
28894                                                     results_context_t*,
28895                                                     bool*&)
28896          {
28897             return error_node();
28898          }
28899          #endif
28900 
vector_element(const std::string & symbol,vector_holder_ptr vector_base,expression_node_ptr index)28901          inline expression_node_ptr vector_element(const std::string& symbol,
28902                                                    vector_holder_ptr vector_base,
28903                                                    expression_node_ptr index)
28904          {
28905             expression_node_ptr result = error_node();
28906 
28907             if (details::is_constant_node(index))
28908             {
28909                std::size_t i = static_cast<std::size_t>(details::numeric::to_int64(index->value()));
28910 
28911                details::free_node(*node_allocator_,index);
28912 
28913                if (vector_base->rebaseable())
28914                {
28915                   return node_allocator_->allocate<rebasevector_celem_node_t>(i,vector_base);
28916                }
28917 
28918                const scope_element& se = parser_->sem_.get_element(symbol,i);
28919 
28920                if (se.index == i)
28921                {
28922                   result = se.var_node;
28923                }
28924                else
28925                {
28926                   scope_element nse;
28927                   nse.name      = symbol;
28928                   nse.active    = true;
28929                   nse.ref_count = 1;
28930                   nse.type      = scope_element::e_vecelem;
28931                   nse.index     = i;
28932                   nse.depth     = parser_->state_.scope_depth;
28933                   nse.data      = 0;
28934                   nse.var_node  = node_allocator_->allocate<variable_node_t>((*(*vector_base)[i]));
28935 
28936                   if (!parser_->sem_.add_element(nse))
28937                   {
28938                      parser_->set_synthesis_error("Failed to add new local vector element to SEM [1]");
28939 
28940                      parser_->sem_.free_element(nse);
28941 
28942                      result = error_node();
28943                   }
28944 
28945                   exprtk_debug(("vector_element() - INFO - Added new local vector element: %s\n",nse.name.c_str()));
28946 
28947                   parser_->state_.activate_side_effect("vector_element()");
28948 
28949                   result = nse.var_node;
28950                }
28951             }
28952             else if (vector_base->rebaseable())
28953                result = node_allocator_->allocate<rebasevector_elem_node_t>(index,vector_base);
28954             else
28955                result = node_allocator_->allocate<vector_elem_node_t>(index,vector_base);
28956 
28957             return result;
28958          }
28959 
28960       private:
28961 
28962          template <std::size_t N, typename NodePtr>
is_constant_foldable(NodePtr (& b)[N]) const28963          inline bool is_constant_foldable(NodePtr (&b)[N]) const
28964          {
28965             for (std::size_t i = 0; i < N; ++i)
28966             {
28967                if (0 == b[i])
28968                   return false;
28969                else if (!details::is_constant_node(b[i]))
28970                   return false;
28971             }
28972 
28973             return true;
28974          }
28975 
28976          template <typename NodePtr,
28977                    typename Allocator,
28978                    template <typename, typename> class Sequence>
is_constant_foldable(const Sequence<NodePtr,Allocator> & b) const28979          inline bool is_constant_foldable(const Sequence<NodePtr,Allocator>& b) const
28980          {
28981             for (std::size_t i = 0; i < b.size(); ++i)
28982             {
28983                if (0 == b[i])
28984                   return false;
28985                else if (!details::is_constant_node(b[i]))
28986                   return false;
28987             }
28988 
28989             return true;
28990          }
28991 
lodge_assignment(symbol_type cst,expression_node_ptr node)28992          void lodge_assignment(symbol_type cst, expression_node_ptr node)
28993          {
28994             parser_->state_.activate_side_effect("lodge_assignment()");
28995 
28996             if (!parser_->dec_.collect_assignments())
28997                return;
28998 
28999             std::string symbol_name;
29000 
29001             switch (cst)
29002             {
29003                case e_st_variable : symbol_name = parser_->symtab_store_
29004                                                      .get_variable_name(node);
29005                                     break;
29006 
29007                #ifndef exprtk_disable_string_capabilities
29008                case e_st_string   : symbol_name = parser_->symtab_store_
29009                                                      .get_stringvar_name(node);
29010                                     break;
29011                #endif
29012 
29013                case e_st_vector   : {
29014                                        typedef details::vector_holder<T> vector_holder_t;
29015 
29016                                        vector_holder_t& vh = static_cast<vector_node_t*>(node)->vec_holder();
29017 
29018                                        symbol_name = parser_->symtab_store_.get_vector_name(&vh);
29019                                     }
29020                                     break;
29021 
29022                case e_st_vecelem  : {
29023                                        typedef details::vector_holder<T> vector_holder_t;
29024 
29025                                        vector_holder_t& vh = static_cast<vector_elem_node_t*>(node)->vec_holder();
29026 
29027                                        symbol_name = parser_->symtab_store_.get_vector_name(&vh);
29028 
29029                                        cst = e_st_vector;
29030                                     }
29031                                     break;
29032 
29033                default            : return;
29034             }
29035 
29036             if (!symbol_name.empty())
29037             {
29038                parser_->dec_.add_assignment(symbol_name,cst);
29039             }
29040          }
29041 
synthesize_assignment_expression(const details::operator_type & operation,expression_node_ptr (& branch)[2])29042          inline expression_node_ptr synthesize_assignment_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
29043          {
29044             if (details::is_variable_node(branch[0]))
29045             {
29046                lodge_assignment(e_st_variable,branch[0]);
29047 
29048                return synthesize_expression<assignment_node_t,2>(operation,branch);
29049             }
29050             else if (details::is_vector_elem_node(branch[0]))
29051             {
29052                lodge_assignment(e_st_vecelem,branch[0]);
29053 
29054                return synthesize_expression<assignment_vec_elem_node_t, 2>(operation, branch);
29055             }
29056             else if (details::is_rebasevector_elem_node(branch[0]))
29057             {
29058                lodge_assignment(e_st_vecelem,branch[0]);
29059 
29060                return synthesize_expression<assignment_rebasevec_elem_node_t, 2>(operation, branch);
29061             }
29062             else if (details::is_rebasevector_celem_node(branch[0]))
29063             {
29064                lodge_assignment(e_st_vecelem,branch[0]);
29065 
29066                return synthesize_expression<assignment_rebasevec_celem_node_t, 2>(operation, branch);
29067             }
29068             #ifndef exprtk_disable_string_capabilities
29069             else if (details::is_string_node(branch[0]))
29070             {
29071                lodge_assignment(e_st_string,branch[0]);
29072 
29073                return synthesize_expression<assignment_string_node_t,2>(operation, branch);
29074             }
29075             else if (details::is_string_range_node(branch[0]))
29076             {
29077                lodge_assignment(e_st_string,branch[0]);
29078 
29079                return synthesize_expression<assignment_string_range_node_t,2>(operation, branch);
29080             }
29081             #endif
29082             else if (details::is_vector_node(branch[0]))
29083             {
29084                lodge_assignment(e_st_vector,branch[0]);
29085 
29086                if (details::is_ivector_node(branch[1]))
29087                   return synthesize_expression<assignment_vecvec_node_t,2>(operation, branch);
29088               else
29089                   return synthesize_expression<assignment_vec_node_t,2>(operation, branch);
29090             }
29091             else
29092             {
29093                parser_->set_synthesis_error("Invalid assignment operation.[1]");
29094 
29095                return error_node();
29096             }
29097          }
29098 
synthesize_assignment_operation_expression(const details::operator_type & operation,expression_node_ptr (& branch)[2])29099          inline expression_node_ptr synthesize_assignment_operation_expression(const details::operator_type& operation,
29100                                                                                expression_node_ptr (&branch)[2])
29101          {
29102             if (details::is_variable_node(branch[0]))
29103             {
29104                lodge_assignment(e_st_variable,branch[0]);
29105 
29106                switch (operation)
29107                {
29108                   #define case_stmt(op0,op1)                                                                  \
29109                   case op0 : return node_allocator_->                                                         \
29110                                 template allocate_rrr<typename details::assignment_op_node<Type,op1<Type> > > \
29111                                    (operation, branch[0], branch[1]);                                         \
29112 
29113                   case_stmt(details::e_addass,details::add_op)
29114                   case_stmt(details::e_subass,details::sub_op)
29115                   case_stmt(details::e_mulass,details::mul_op)
29116                   case_stmt(details::e_divass,details::div_op)
29117                   case_stmt(details::e_modass,details::mod_op)
29118                   #undef case_stmt
29119                   default : return error_node();
29120                }
29121             }
29122             else if (details::is_vector_elem_node(branch[0]))
29123             {
29124                lodge_assignment(e_st_vecelem,branch[0]);
29125 
29126                switch (operation)
29127                {
29128                   #define case_stmt(op0,op1)                                                                            \
29129                   case op0 : return node_allocator_->                                                                   \
29130                                  template allocate_rrr<typename details::assignment_vec_elem_op_node<Type,op1<Type> > > \
29131                                     (operation, branch[0], branch[1]);                                                  \
29132 
29133                   case_stmt(details::e_addass,details::add_op)
29134                   case_stmt(details::e_subass,details::sub_op)
29135                   case_stmt(details::e_mulass,details::mul_op)
29136                   case_stmt(details::e_divass,details::div_op)
29137                   case_stmt(details::e_modass,details::mod_op)
29138                   #undef case_stmt
29139                   default : return error_node();
29140                }
29141             }
29142             else if (details::is_rebasevector_elem_node(branch[0]))
29143             {
29144                lodge_assignment(e_st_vecelem,branch[0]);
29145 
29146                switch (operation)
29147                {
29148                   #define case_stmt(op0,op1)                                                                                  \
29149                   case op0 : return node_allocator_->                                                                         \
29150                                  template allocate_rrr<typename details::assignment_rebasevec_elem_op_node<Type,op1<Type> > > \
29151                                     (operation, branch[0], branch[1]);                                                        \
29152 
29153                   case_stmt(details::e_addass,details::add_op)
29154                   case_stmt(details::e_subass,details::sub_op)
29155                   case_stmt(details::e_mulass,details::mul_op)
29156                   case_stmt(details::e_divass,details::div_op)
29157                   case_stmt(details::e_modass,details::mod_op)
29158                   #undef case_stmt
29159                   default : return error_node();
29160                }
29161             }
29162             else if (details::is_rebasevector_celem_node(branch[0]))
29163             {
29164                lodge_assignment(e_st_vecelem,branch[0]);
29165 
29166                switch (operation)
29167                {
29168                   #define case_stmt(op0,op1)                                                                                   \
29169                   case op0 : return node_allocator_->                                                                          \
29170                                  template allocate_rrr<typename details::assignment_rebasevec_celem_op_node<Type,op1<Type> > > \
29171                                     (operation, branch[0], branch[1]);                                                         \
29172 
29173                   case_stmt(details::e_addass,details::add_op)
29174                   case_stmt(details::e_subass,details::sub_op)
29175                   case_stmt(details::e_mulass,details::mul_op)
29176                   case_stmt(details::e_divass,details::div_op)
29177                   case_stmt(details::e_modass,details::mod_op)
29178                   #undef case_stmt
29179                   default : return error_node();
29180                }
29181             }
29182             else if (details::is_vector_node(branch[0]))
29183             {
29184                lodge_assignment(e_st_vector,branch[0]);
29185 
29186                if (details::is_ivector_node(branch[1]))
29187                {
29188                   switch (operation)
29189                   {
29190                      #define case_stmt(op0,op1)                                                                         \
29191                      case op0 : return node_allocator_->                                                                \
29192                                    template allocate_rrr<typename details::assignment_vecvec_op_node<Type,op1<Type> > > \
29193                                       (operation, branch[0], branch[1]);                                                \
29194 
29195                      case_stmt(details::e_addass,details::add_op)
29196                      case_stmt(details::e_subass,details::sub_op)
29197                      case_stmt(details::e_mulass,details::mul_op)
29198                      case_stmt(details::e_divass,details::div_op)
29199                      case_stmt(details::e_modass,details::mod_op)
29200                      #undef case_stmt
29201                      default : return error_node();
29202                   }
29203                }
29204                else
29205                {
29206                   switch (operation)
29207                   {
29208                      #define case_stmt(op0,op1)                                                                      \
29209                      case op0 : return node_allocator_->                                                             \
29210                                    template allocate_rrr<typename details::assignment_vec_op_node<Type,op1<Type> > > \
29211                                       (operation, branch[0], branch[1]);                                             \
29212 
29213                      case_stmt(details::e_addass,details::add_op)
29214                      case_stmt(details::e_subass,details::sub_op)
29215                      case_stmt(details::e_mulass,details::mul_op)
29216                      case_stmt(details::e_divass,details::div_op)
29217                      case_stmt(details::e_modass,details::mod_op)
29218                      #undef case_stmt
29219                      default : return error_node();
29220                   }
29221                }
29222             }
29223             #ifndef exprtk_disable_string_capabilities
29224             else if (
29225                       (details::e_addass == operation) &&
29226                       details::is_string_node(branch[0])
29227                     )
29228             {
29229                typedef details::assignment_string_node<T,details::asn_addassignment> addass_t;
29230 
29231                lodge_assignment(e_st_string,branch[0]);
29232 
29233                return synthesize_expression<addass_t,2>(operation,branch);
29234             }
29235             #endif
29236             else
29237             {
29238                parser_->set_synthesis_error("Invalid assignment operation[2]");
29239 
29240                return error_node();
29241             }
29242          }
29243 
synthesize_veceqineqlogic_operation_expression(const details::operator_type & operation,expression_node_ptr (& branch)[2])29244          inline expression_node_ptr synthesize_veceqineqlogic_operation_expression(const details::operator_type& operation,
29245                                                                                    expression_node_ptr (&branch)[2])
29246          {
29247             const bool is_b0_ivec = details::is_ivector_node(branch[0]);
29248             const bool is_b1_ivec = details::is_ivector_node(branch[1]);
29249 
29250             #define batch_eqineq_logic_case                \
29251             case_stmt(details::   e_lt, details::   lt_op) \
29252             case_stmt(details::  e_lte, details::  lte_op) \
29253             case_stmt(details::   e_gt, details::   gt_op) \
29254             case_stmt(details::  e_gte, details::  gte_op) \
29255             case_stmt(details::   e_eq, details::   eq_op) \
29256             case_stmt(details::   e_ne, details::   ne_op) \
29257             case_stmt(details::e_equal, details::equal_op) \
29258             case_stmt(details::  e_and, details::  and_op) \
29259             case_stmt(details:: e_nand, details:: nand_op) \
29260             case_stmt(details::   e_or, details::   or_op) \
29261             case_stmt(details::  e_nor, details::  nor_op) \
29262             case_stmt(details::  e_xor, details::  xor_op) \
29263             case_stmt(details:: e_xnor, details:: xnor_op) \
29264 
29265             if (is_b0_ivec && is_b1_ivec)
29266             {
29267                switch (operation)
29268                {
29269                   #define case_stmt(op0,op1)                                                                     \
29270                   case op0 : return node_allocator_->                                                            \
29271                                 template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \
29272                                    (operation, branch[0], branch[1]);                                            \
29273 
29274                   batch_eqineq_logic_case
29275                   #undef case_stmt
29276                   default : return error_node();
29277                }
29278             }
29279             else if (is_b0_ivec && !is_b1_ivec)
29280             {
29281                switch (operation)
29282                {
29283                   #define case_stmt(op0,op1)                                                                     \
29284                   case op0 : return node_allocator_->                                                            \
29285                                 template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \
29286                                    (operation, branch[0], branch[1]);                                            \
29287 
29288                   batch_eqineq_logic_case
29289                   #undef case_stmt
29290                   default : return error_node();
29291                }
29292             }
29293             else if (!is_b0_ivec && is_b1_ivec)
29294             {
29295                switch (operation)
29296                {
29297                   #define case_stmt(op0,op1)                                                                     \
29298                   case op0 : return node_allocator_->                                                            \
29299                                 template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \
29300                                    (operation, branch[0], branch[1]);                                            \
29301 
29302                   batch_eqineq_logic_case
29303                   #undef case_stmt
29304                   default : return error_node();
29305                }
29306             }
29307             else
29308                return error_node();
29309 
29310             #undef batch_eqineq_logic_case
29311          }
29312 
synthesize_vecarithmetic_operation_expression(const details::operator_type & operation,expression_node_ptr (& branch)[2])29313          inline expression_node_ptr synthesize_vecarithmetic_operation_expression(const details::operator_type& operation,
29314                                                                                   expression_node_ptr (&branch)[2])
29315          {
29316             const bool is_b0_ivec = details::is_ivector_node(branch[0]);
29317             const bool is_b1_ivec = details::is_ivector_node(branch[1]);
29318 
29319             #define vector_ops                        \
29320             case_stmt(details::e_add,details::add_op) \
29321             case_stmt(details::e_sub,details::sub_op) \
29322             case_stmt(details::e_mul,details::mul_op) \
29323             case_stmt(details::e_div,details::div_op) \
29324             case_stmt(details::e_mod,details::mod_op) \
29325 
29326             if (is_b0_ivec && is_b1_ivec)
29327             {
29328                switch (operation)
29329                {
29330                   #define case_stmt(op0,op1)                                                                     \
29331                   case op0 : return node_allocator_->                                                            \
29332                                 template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \
29333                                    (operation, branch[0], branch[1]);                                            \
29334 
29335                   vector_ops
29336                   case_stmt(details::e_pow,details:: pow_op)
29337                   #undef case_stmt
29338                   default : return error_node();
29339                }
29340             }
29341             else if (is_b0_ivec && !is_b1_ivec)
29342             {
29343                switch (operation)
29344                {
29345                   #define case_stmt(op0,op1)                                                                     \
29346                   case op0 : return node_allocator_->                                                            \
29347                                 template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \
29348                                    (operation, branch[0], branch[1]);                                            \
29349 
29350                   vector_ops
29351                   case_stmt(details::e_pow,details:: pow_op)
29352                   #undef case_stmt
29353                   default : return error_node();
29354                }
29355             }
29356             else if (!is_b0_ivec && is_b1_ivec)
29357             {
29358                switch (operation)
29359                {
29360                   #define case_stmt(op0,op1)                                                                     \
29361                   case op0 : return node_allocator_->                                                            \
29362                                 template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \
29363                                    (operation, branch[0], branch[1]);                                            \
29364 
29365                   vector_ops
29366                   #undef case_stmt
29367                   default : return error_node();
29368                }
29369             }
29370             else
29371                return error_node();
29372 
29373             #undef vector_ops
29374          }
29375 
synthesize_swap_expression(expression_node_ptr (& branch)[2])29376          inline expression_node_ptr synthesize_swap_expression(expression_node_ptr (&branch)[2])
29377          {
29378             const bool v0_is_ivar = details::is_ivariable_node(branch[0]);
29379             const bool v1_is_ivar = details::is_ivariable_node(branch[1]);
29380 
29381             const bool v0_is_ivec = details::is_ivector_node  (branch[0]);
29382             const bool v1_is_ivec = details::is_ivector_node  (branch[1]);
29383 
29384             #ifndef exprtk_disable_string_capabilities
29385             const bool v0_is_str = details::is_generally_string_node(branch[0]);
29386             const bool v1_is_str = details::is_generally_string_node(branch[1]);
29387             #endif
29388 
29389             expression_node_ptr result = error_node();
29390 
29391             if (v0_is_ivar && v1_is_ivar)
29392             {
29393                typedef details::variable_node<T>* variable_node_ptr;
29394 
29395                variable_node_ptr v0 = variable_node_ptr(0);
29396                variable_node_ptr v1 = variable_node_ptr(0);
29397 
29398                if (
29399                     (0 != (v0 = dynamic_cast<variable_node_ptr>(branch[0]))) &&
29400                     (0 != (v1 = dynamic_cast<variable_node_ptr>(branch[1])))
29401                   )
29402                {
29403                   result = node_allocator_->allocate<details::swap_node<T> >(v0,v1);
29404                }
29405                else
29406                   result = node_allocator_->allocate<details::swap_generic_node<T> >(branch[0],branch[1]);
29407             }
29408             else if (v0_is_ivec && v1_is_ivec)
29409             {
29410                result = node_allocator_->allocate<details::swap_vecvec_node<T> >(branch[0],branch[1]);
29411             }
29412             #ifndef exprtk_disable_string_capabilities
29413             else if (v0_is_str && v1_is_str)
29414             {
29415                if (is_string_node(branch[0]) && is_string_node(branch[1]))
29416                   result = node_allocator_->allocate<details::swap_string_node<T> >
29417                                                (branch[0], branch[1]);
29418                else
29419                   result = node_allocator_->allocate<details::swap_genstrings_node<T> >
29420                                                (branch[0], branch[1]);
29421             }
29422             #endif
29423             else
29424             {
29425                parser_->set_synthesis_error("Only variables, strings, vectors or vector elements can be swapped");
29426 
29427                return error_node();
29428             }
29429 
29430             parser_->state_.activate_side_effect("synthesize_swap_expression()");
29431 
29432             return result;
29433          }
29434 
29435          #ifndef exprtk_disable_sc_andor
synthesize_shortcircuit_expression(const details::operator_type & operation,expression_node_ptr (& branch)[2])29436          inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
29437          {
29438             expression_node_ptr result = error_node();
29439 
29440             if (details::is_constant_node(branch[0]))
29441             {
29442                if (
29443                     (details::e_scand == operation) &&
29444                     std::equal_to<T>()(T(0),branch[0]->value())
29445                   )
29446                   result = node_allocator_->allocate_c<literal_node_t>(T(0));
29447                else if (
29448                          (details::e_scor == operation) &&
29449                          std::not_equal_to<T>()(T(0),branch[0]->value())
29450                        )
29451                   result = node_allocator_->allocate_c<literal_node_t>(T(1));
29452             }
29453 
29454             if (details::is_constant_node(branch[1]) && (0 == result))
29455             {
29456                if (
29457                     (details::e_scand == operation) &&
29458                     std::equal_to<T>()(T(0),branch[1]->value())
29459                   )
29460                   result = node_allocator_->allocate_c<literal_node_t>(T(0));
29461                else if (
29462                          (details::e_scor == operation) &&
29463                          std::not_equal_to<T>()(T(0),branch[1]->value())
29464                        )
29465                   result = node_allocator_->allocate_c<literal_node_t>(T(1));
29466             }
29467 
29468             if (result)
29469             {
29470                free_node(*node_allocator_, branch[0]);
29471                free_node(*node_allocator_, branch[1]);
29472 
29473                return result;
29474             }
29475             else if (details::e_scand == operation)
29476             {
29477                return synthesize_expression<scand_node_t,2>(operation, branch);
29478             }
29479             else if (details::e_scor == operation)
29480             {
29481                return synthesize_expression<scor_node_t,2>(operation, branch);
29482             }
29483             else
29484                return error_node();
29485          }
29486          #else
synthesize_shortcircuit_expression(const details::operator_type &,expression_node_ptr (&)[2])29487          inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type&, expression_node_ptr (&)[2])
29488          {
29489             return error_node();
29490          }
29491          #endif
29492 
29493          #define basic_opr_switch_statements        \
29494          case_stmt(details::e_add, details::add_op) \
29495          case_stmt(details::e_sub, details::sub_op) \
29496          case_stmt(details::e_mul, details::mul_op) \
29497          case_stmt(details::e_div, details::div_op) \
29498          case_stmt(details::e_mod, details::mod_op) \
29499          case_stmt(details::e_pow, details::pow_op) \
29500 
29501          #define extended_opr_switch_statements       \
29502          case_stmt(details::  e_lt, details::  lt_op) \
29503          case_stmt(details:: e_lte, details:: lte_op) \
29504          case_stmt(details::  e_gt, details::  gt_op) \
29505          case_stmt(details:: e_gte, details:: gte_op) \
29506          case_stmt(details::  e_eq, details::  eq_op) \
29507          case_stmt(details::  e_ne, details::  ne_op) \
29508          case_stmt(details:: e_and, details:: and_op) \
29509          case_stmt(details::e_nand, details::nand_op) \
29510          case_stmt(details::  e_or, details::  or_op) \
29511          case_stmt(details:: e_nor, details:: nor_op) \
29512          case_stmt(details:: e_xor, details:: xor_op) \
29513          case_stmt(details::e_xnor, details::xnor_op) \
29514 
29515          #ifndef exprtk_disable_cardinal_pow_optimisation
29516          template <typename TType, template <typename, typename> class IPowNode>
cardinal_pow_optimisation_impl(const TType & v,const unsigned int & p)29517          inline expression_node_ptr cardinal_pow_optimisation_impl(const TType& v, const unsigned int& p)
29518          {
29519             switch (p)
29520             {
29521                #define case_stmt(cp)                                                     \
29522                case cp : return node_allocator_->                                        \
29523                             allocate<IPowNode<T,details::numeric::fast_exp<T,cp> > >(v); \
29524 
29525                case_stmt( 1) case_stmt( 2) case_stmt( 3) case_stmt( 4)
29526                case_stmt( 5) case_stmt( 6) case_stmt( 7) case_stmt( 8)
29527                case_stmt( 9) case_stmt(10) case_stmt(11) case_stmt(12)
29528                case_stmt(13) case_stmt(14) case_stmt(15) case_stmt(16)
29529                case_stmt(17) case_stmt(18) case_stmt(19) case_stmt(20)
29530                case_stmt(21) case_stmt(22) case_stmt(23) case_stmt(24)
29531                case_stmt(25) case_stmt(26) case_stmt(27) case_stmt(28)
29532                case_stmt(29) case_stmt(30) case_stmt(31) case_stmt(32)
29533                case_stmt(33) case_stmt(34) case_stmt(35) case_stmt(36)
29534                case_stmt(37) case_stmt(38) case_stmt(39) case_stmt(40)
29535                case_stmt(41) case_stmt(42) case_stmt(43) case_stmt(44)
29536                case_stmt(45) case_stmt(46) case_stmt(47) case_stmt(48)
29537                case_stmt(49) case_stmt(50) case_stmt(51) case_stmt(52)
29538                case_stmt(53) case_stmt(54) case_stmt(55) case_stmt(56)
29539                case_stmt(57) case_stmt(58) case_stmt(59) case_stmt(60)
29540                #undef case_stmt
29541                default : return error_node();
29542             }
29543          }
29544 
cardinal_pow_optimisation(const T & v,const T & c)29545          inline expression_node_ptr cardinal_pow_optimisation(const T& v, const T& c)
29546          {
29547             const bool not_recipricol = (c >= T(0));
29548             const unsigned int p = static_cast<unsigned int>(details::numeric::to_int32(details::numeric::abs(c)));
29549 
29550             if (0 == p)
29551                return node_allocator_->allocate_c<literal_node_t>(T(1));
29552             else if (std::equal_to<T>()(T(2),c))
29553             {
29554                return node_allocator_->
29555                   template allocate_rr<typename details::vov_node<Type,details::mul_op<Type> > >(v,v);
29556             }
29557             else
29558             {
29559                if (not_recipricol)
29560                   return cardinal_pow_optimisation_impl<T,details::ipow_node>(v,p);
29561                else
29562                   return cardinal_pow_optimisation_impl<T,details::ipowinv_node>(v,p);
29563             }
29564          }
29565 
cardinal_pow_optimisable(const details::operator_type & operation,const T & c) const29566          inline bool cardinal_pow_optimisable(const details::operator_type& operation, const T& c) const
29567          {
29568             return (details::e_pow == operation) && (details::numeric::abs(c) <= T(60)) && details::numeric::is_integer(c);
29569          }
29570 
cardinal_pow_optimisation(expression_node_ptr (& branch)[2])29571          inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr (&branch)[2])
29572          {
29573             const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
29574             const bool not_recipricol = (c >= T(0));
29575             const unsigned int p = static_cast<unsigned int>(details::numeric::to_int32(details::numeric::abs(c)));
29576 
29577             node_allocator_->free(branch[1]);
29578 
29579             if (0 == p)
29580             {
29581                details::free_all_nodes(*node_allocator_, branch);
29582 
29583                return node_allocator_->allocate_c<literal_node_t>(T(1));
29584             }
29585             else if (not_recipricol)
29586                return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipow_node>(branch[0],p);
29587             else
29588                return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipowninv_node>(branch[0],p);
29589          }
29590          #else
cardinal_pow_optimisation(T &,const T &)29591          inline expression_node_ptr cardinal_pow_optimisation(T&, const T&)
29592          {
29593             return error_node();
29594          }
29595 
cardinal_pow_optimisable(const details::operator_type &,const T &)29596          inline bool cardinal_pow_optimisable(const details::operator_type&, const T&)
29597          {
29598             return false;
29599          }
29600 
cardinal_pow_optimisation(expression_node_ptr (&)[2])29601          inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr(&)[2])
29602          {
29603             return error_node();
29604          }
29605          #endif
29606 
29607          struct synthesize_binary_ext_expression
29608          {
processexprtk::parser::expression_generator::synthesize_binary_ext_expression29609             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
29610                                                       const details::operator_type& operation,
29611                                                       expression_node_ptr (&branch)[2])
29612             {
29613                const bool left_neg  = is_neg_unary_node(branch[0]);
29614                const bool right_neg = is_neg_unary_node(branch[1]);
29615 
29616                if (left_neg && right_neg)
29617                {
29618                   if (
29619                        (details::e_add == operation) ||
29620                        (details::e_sub == operation) ||
29621                        (details::e_mul == operation) ||
29622                        (details::e_div == operation)
29623                      )
29624                   {
29625                      if (
29626                           !expr_gen.parser_->simplify_unary_negation_branch(branch[0]) ||
29627                           !expr_gen.parser_->simplify_unary_negation_branch(branch[1])
29628                         )
29629                      {
29630                         details::free_all_nodes(*expr_gen.node_allocator_,branch);
29631 
29632                         return error_node();
29633                      }
29634                   }
29635 
29636                   switch (operation)
29637                   {
29638                                            // -f(x + 1) + -g(y + 1) --> -(f(x + 1) + g(y + 1))
29639                      case details::e_add : return expr_gen(details::e_neg,
29640                                               expr_gen.node_allocator_->
29641                                                  template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >
29642                                                     (branch[0],branch[1]));
29643 
29644                                            // -f(x + 1) - -g(y + 1) --> g(y + 1) - f(x + 1)
29645                      case details::e_sub : return expr_gen.node_allocator_->
29646                                               template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >
29647                                                  (branch[1],branch[0]);
29648 
29649                      default             : break;
29650                   }
29651                }
29652                else if (left_neg && !right_neg)
29653                {
29654                   if (
29655                        (details::e_add == operation) ||
29656                        (details::e_sub == operation) ||
29657                        (details::e_mul == operation) ||
29658                        (details::e_div == operation)
29659                      )
29660                   {
29661                      if (!expr_gen.parser_->simplify_unary_negation_branch(branch[0]))
29662                      {
29663                         details::free_all_nodes(*expr_gen.node_allocator_,branch);
29664 
29665                         return error_node();
29666                      }
29667 
29668                      switch (operation)
29669                      {
29670                                               // -f(x + 1) + g(y + 1) --> g(y + 1) - f(x + 1)
29671                         case details::e_add : return expr_gen.node_allocator_->
29672                                                  template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >
29673                                                    (branch[1], branch[0]);
29674 
29675                                               // -f(x + 1) - g(y + 1) --> -(f(x + 1) + g(y + 1))
29676                         case details::e_sub : return expr_gen(details::e_neg,
29677                                                  expr_gen.node_allocator_->
29678                                                     template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >
29679                                                        (branch[0], branch[1]));
29680 
29681                                               // -f(x + 1) * g(y + 1) --> -(f(x + 1) * g(y + 1))
29682                         case details::e_mul : return expr_gen(details::e_neg,
29683                                                  expr_gen.node_allocator_->
29684                                                     template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > >
29685                                                        (branch[0], branch[1]));
29686 
29687                                               // -f(x + 1) / g(y + 1) --> -(f(x + 1) / g(y + 1))
29688                         case details::e_div : return expr_gen(details::e_neg,
29689                                                  expr_gen.node_allocator_->
29690                                                     template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > >
29691                                                        (branch[0], branch[1]));
29692 
29693                         default             : return error_node();
29694                      }
29695                   }
29696                }
29697                else if (!left_neg && right_neg)
29698                {
29699                   if (
29700                        (details::e_add == operation) ||
29701                        (details::e_sub == operation) ||
29702                        (details::e_mul == operation) ||
29703                        (details::e_div == operation)
29704                      )
29705                   {
29706                      if (!expr_gen.parser_->simplify_unary_negation_branch(branch[1]))
29707                      {
29708                         details::free_all_nodes(*expr_gen.node_allocator_,branch);
29709 
29710                         return error_node();
29711                      }
29712 
29713                      switch (operation)
29714                      {
29715                                               // f(x + 1) + -g(y + 1) --> f(x + 1) - g(y + 1)
29716                         case details::e_add : return expr_gen.node_allocator_->
29717                                                  template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >
29718                                                    (branch[0], branch[1]);
29719 
29720                                               // f(x + 1) - - g(y + 1) --> f(x + 1) + g(y + 1)
29721                         case details::e_sub : return expr_gen.node_allocator_->
29722                                                  template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >
29723                                                    (branch[0], branch[1]);
29724 
29725                                               // f(x + 1) * -g(y + 1) --> -(f(x + 1) * g(y + 1))
29726                         case details::e_mul : return expr_gen(details::e_neg,
29727                                                  expr_gen.node_allocator_->
29728                                                     template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > >
29729                                                        (branch[0], branch[1]));
29730 
29731                                               // f(x + 1) / -g(y + 1) --> -(f(x + 1) / g(y + 1))
29732                         case details::e_div : return expr_gen(details::e_neg,
29733                                                  expr_gen.node_allocator_->
29734                                                     template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > >
29735                                                        (branch[0], branch[1]));
29736 
29737                         default             : return error_node();
29738                      }
29739                   }
29740                }
29741 
29742                switch (operation)
29743                {
29744                   #define case_stmt(op0,op1)                                                           \
29745                   case op0 : return expr_gen.node_allocator_->                                         \
29746                                 template allocate<typename details::binary_ext_node<Type,op1<Type> > > \
29747                                    (branch[0], branch[1]);                                             \
29748 
29749                   basic_opr_switch_statements
29750                   extended_opr_switch_statements
29751                   #undef case_stmt
29752                   default : return error_node();
29753                }
29754             }
29755          };
29756 
29757          struct synthesize_vob_expression
29758          {
processexprtk::parser::expression_generator::synthesize_vob_expression29759             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
29760                                                       const details::operator_type& operation,
29761                                                       expression_node_ptr (&branch)[2])
29762             {
29763                const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref();
29764 
29765                #ifndef exprtk_disable_enhanced_features
29766                if (details::is_sf3ext_node(branch[1]))
29767                {
29768                   expression_node_ptr result = error_node();
29769 
29770                   const bool synthesis_result =
29771                      synthesize_sf4ext_expression::template compile_right<vtype>
29772                         (expr_gen, v, operation, branch[1], result);
29773 
29774                   if (synthesis_result)
29775                   {
29776                      free_node(*expr_gen.node_allocator_,branch[1]);
29777                      return result;
29778                   }
29779                }
29780                #endif
29781 
29782                if (
29783                     (details::e_mul == operation) ||
29784                     (details::e_div == operation)
29785                   )
29786                {
29787                   if (details::is_uv_node(branch[1]))
29788                   {
29789                      typedef details::uv_base_node<Type>* uvbn_ptr_t;
29790 
29791                      details::operator_type o = static_cast<uvbn_ptr_t>(branch[1])->operation();
29792 
29793                      if (details::e_neg == o)
29794                      {
29795                         const Type& v1 = static_cast<uvbn_ptr_t>(branch[1])->v();
29796 
29797                         free_node(*expr_gen.node_allocator_,branch[1]);
29798 
29799                         switch (operation)
29800                         {
29801                            case details::e_mul : return expr_gen(details::e_neg,
29802                                                     expr_gen.node_allocator_->
29803                                                        template allocate_rr<typename details::
29804                                                           vov_node<Type,details::mul_op<Type> > >(v,v1));
29805 
29806                            case details::e_div : return expr_gen(details::e_neg,
29807                                                     expr_gen.node_allocator_->
29808                                                        template allocate_rr<typename details::
29809                                                           vov_node<Type,details::div_op<Type> > >(v,v1));
29810 
29811                            default             : break;
29812                         }
29813                      }
29814                   }
29815                }
29816 
29817                switch (operation)
29818                {
29819                   #define case_stmt(op0,op1)                                                       \
29820                   case op0 : return expr_gen.node_allocator_->                                     \
29821                                 template allocate_rc<typename details::vob_node<Type,op1<Type> > > \
29822                                    (v, branch[1]);                                                 \
29823 
29824                   basic_opr_switch_statements
29825                   extended_opr_switch_statements
29826                   #undef case_stmt
29827                   default : return error_node();
29828                }
29829             }
29830          };
29831 
29832          struct synthesize_bov_expression
29833          {
processexprtk::parser::expression_generator::synthesize_bov_expression29834             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
29835                                                       const details::operator_type& operation,
29836                                                       expression_node_ptr (&branch)[2])
29837             {
29838                const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref();
29839 
29840                #ifndef exprtk_disable_enhanced_features
29841                if (details::is_sf3ext_node(branch[0]))
29842                {
29843                   expression_node_ptr result = error_node();
29844 
29845                   const bool synthesis_result =
29846                      synthesize_sf4ext_expression::template compile_left<vtype>
29847                         (expr_gen, v, operation, branch[0], result);
29848 
29849                   if (synthesis_result)
29850                   {
29851                      free_node(*expr_gen.node_allocator_, branch[0]);
29852 
29853                      return result;
29854                   }
29855                }
29856                #endif
29857 
29858                if (
29859                     (details::e_add == operation) ||
29860                     (details::e_sub == operation) ||
29861                     (details::e_mul == operation) ||
29862                     (details::e_div == operation)
29863                   )
29864                {
29865                   if (details::is_uv_node(branch[0]))
29866                   {
29867                      typedef details::uv_base_node<Type>* uvbn_ptr_t;
29868 
29869                      details::operator_type o = static_cast<uvbn_ptr_t>(branch[0])->operation();
29870 
29871                      if (details::e_neg == o)
29872                      {
29873                         const Type& v0 = static_cast<uvbn_ptr_t>(branch[0])->v();
29874 
29875                         free_node(*expr_gen.node_allocator_,branch[0]);
29876 
29877                         switch (operation)
29878                         {
29879                            case details::e_add : return expr_gen.node_allocator_->
29880                                                     template allocate_rr<typename details::
29881                                                        vov_node<Type,details::sub_op<Type> > >(v,v0);
29882 
29883                            case details::e_sub : return expr_gen(details::e_neg,
29884                                                     expr_gen.node_allocator_->
29885                                                        template allocate_rr<typename details::
29886                                                           vov_node<Type,details::add_op<Type> > >(v0,v));
29887 
29888                            case details::e_mul : return expr_gen(details::e_neg,
29889                                                     expr_gen.node_allocator_->
29890                                                        template allocate_rr<typename details::
29891                                                           vov_node<Type,details::mul_op<Type> > >(v0,v));
29892 
29893                            case details::e_div : return expr_gen(details::e_neg,
29894                                                     expr_gen.node_allocator_->
29895                                                        template allocate_rr<typename details::
29896                                                           vov_node<Type,details::div_op<Type> > >(v0,v));
29897                            default : break;
29898                         }
29899                      }
29900                   }
29901                }
29902 
29903                switch (operation)
29904                {
29905                   #define case_stmt(op0,op1)                                                       \
29906                   case op0 : return expr_gen.node_allocator_->                                     \
29907                                 template allocate_cr<typename details::bov_node<Type,op1<Type> > > \
29908                                    (branch[0], v);                                                 \
29909 
29910                   basic_opr_switch_statements
29911                   extended_opr_switch_statements
29912                   #undef case_stmt
29913                   default : return error_node();
29914                }
29915             }
29916          };
29917 
29918          struct synthesize_cob_expression
29919          {
processexprtk::parser::expression_generator::synthesize_cob_expression29920             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
29921                                                       const details::operator_type& operation,
29922                                                       expression_node_ptr (&branch)[2])
29923             {
29924                const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
29925 
29926                free_node(*expr_gen.node_allocator_,branch[0]);
29927 
29928                if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
29929                {
29930                   free_node(*expr_gen.node_allocator_,branch[1]);
29931 
29932                   return expr_gen(T(0));
29933                }
29934                else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
29935                {
29936                   free_node(*expr_gen.node_allocator_, branch[1]);
29937 
29938                   return expr_gen(T(0));
29939                }
29940                else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
29941                   return branch[1];
29942                else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
29943                   return branch[1];
29944 
29945                if (details::is_cob_node(branch[1]))
29946                {
29947                   // Simplify expressions of the form:
29948                   // 1. (1 * (2 * (3 * (4 * (5 * (6 * (7 * (8 * (9 + x))))))))) --> 40320 * (9 + x)
29949                   // 2. (1 + (2 + (3 + (4 + (5 + (6 + (7 + (8 + (9 + x))))))))) --> 45 + x
29950                   if (
29951                        (operation == details::e_mul) ||
29952                        (operation == details::e_add)
29953                      )
29954                   {
29955                      details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
29956 
29957                      if (operation == cobnode->operation())
29958                      {
29959                         switch (operation)
29960                         {
29961                            case details::e_add : cobnode->set_c(c + cobnode->c()); break;
29962                            case details::e_mul : cobnode->set_c(c * cobnode->c()); break;
29963                            default             : return error_node();
29964                         }
29965 
29966                         return cobnode;
29967                      }
29968                   }
29969 
29970                   if (operation == details::e_mul)
29971                   {
29972                      details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
29973                      details::operator_type cob_opr = cobnode->operation();
29974 
29975                      if (
29976                           (details::e_div == cob_opr) ||
29977                           (details::e_mul == cob_opr)
29978                         )
29979                      {
29980                         switch (cob_opr)
29981                         {
29982                            case details::e_div : cobnode->set_c(c * cobnode->c()); break;
29983                            case details::e_mul : cobnode->set_c(cobnode->c() / c); break;
29984                            default             : return error_node();
29985                         }
29986 
29987                         return cobnode;
29988                      }
29989                   }
29990                   else if (operation == details::e_div)
29991                   {
29992                      details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
29993                      details::operator_type cob_opr = cobnode->operation();
29994 
29995                      if (
29996                           (details::e_div == cob_opr) ||
29997                           (details::e_mul == cob_opr)
29998                         )
29999                      {
30000                         details::expression_node<Type>* new_cobnode = error_node();
30001 
30002                         switch (cob_opr)
30003                         {
30004                            case details::e_div : new_cobnode = expr_gen.node_allocator_->
30005                                                     template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > >
30006                                                        (c / cobnode->c(), cobnode->move_branch(0));
30007                                                  break;
30008 
30009                            case details::e_mul : new_cobnode = expr_gen.node_allocator_->
30010                                                     template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
30011                                                        (c / cobnode->c(), cobnode->move_branch(0));
30012                                                  break;
30013 
30014                            default             : return error_node();
30015                         }
30016 
30017                         free_node(*expr_gen.node_allocator_,branch[1]);
30018 
30019                         return new_cobnode;
30020                      }
30021                   }
30022                }
30023                #ifndef exprtk_disable_enhanced_features
30024                else if (details::is_sf3ext_node(branch[1]))
30025                {
30026                   expression_node_ptr result = error_node();
30027 
30028                   const bool synthesis_result =
30029                      synthesize_sf4ext_expression::template compile_right<ctype>
30030                         (expr_gen, c, operation, branch[1], result);
30031 
30032                   if (synthesis_result)
30033                   {
30034                      free_node(*expr_gen.node_allocator_,branch[1]);
30035 
30036                      return result;
30037                   }
30038                }
30039                #endif
30040 
30041                switch (operation)
30042                {
30043                   #define case_stmt(op0,op1)                                                       \
30044                   case op0 : return expr_gen.node_allocator_->                                     \
30045                                 template allocate_tt<typename details::cob_node<Type,op1<Type> > > \
30046                                    (c,  branch[1]);                                                \
30047 
30048                   basic_opr_switch_statements
30049                   extended_opr_switch_statements
30050                   #undef case_stmt
30051                   default : return error_node();
30052                }
30053             }
30054          };
30055 
30056          struct synthesize_boc_expression
30057          {
processexprtk::parser::expression_generator::synthesize_boc_expression30058             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30059                                                       const details::operator_type& operation,
30060                                                       expression_node_ptr (&branch)[2])
30061             {
30062                const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
30063 
30064                details::free_node(*(expr_gen.node_allocator_), branch[1]);
30065 
30066                if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
30067                {
30068                   free_node(*expr_gen.node_allocator_, branch[0]);
30069 
30070                   return expr_gen(T(0));
30071                }
30072                else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
30073                {
30074                   free_node(*expr_gen.node_allocator_, branch[0]);
30075 
30076                   return expr_gen(std::numeric_limits<T>::quiet_NaN());
30077                }
30078                else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
30079                   return branch[0];
30080                else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
30081                   return branch[0];
30082 
30083                if (details::is_boc_node(branch[0]))
30084                {
30085                   // Simplify expressions of the form:
30086                   // 1. (((((((((x + 9) * 8) * 7) * 6) * 5) * 4) * 3) * 2) * 1) --> (x + 9) * 40320
30087                   // 2. (((((((((x + 9) + 8) + 7) + 6) + 5) + 4) + 3) + 2) + 1) --> x + 45
30088                   if (
30089                        (operation == details::e_mul) ||
30090                        (operation == details::e_add)
30091                      )
30092                   {
30093                      details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
30094 
30095                      if (operation == bocnode->operation())
30096                      {
30097                         switch (operation)
30098                         {
30099                            case details::e_add : bocnode->set_c(c + bocnode->c()); break;
30100                            case details::e_mul : bocnode->set_c(c * bocnode->c()); break;
30101                            default             : return error_node();
30102                         }
30103 
30104                         return bocnode;
30105                      }
30106                   }
30107                   else if (operation == details::e_div)
30108                   {
30109                      details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
30110                      details::operator_type        boc_opr = bocnode->operation();
30111 
30112                      if (
30113                           (details::e_div == boc_opr) ||
30114                           (details::e_mul == boc_opr)
30115                         )
30116                      {
30117                         switch (boc_opr)
30118                         {
30119                            case details::e_div : bocnode->set_c(c * bocnode->c()); break;
30120                            case details::e_mul : bocnode->set_c(bocnode->c() / c); break;
30121                            default             : return error_node();
30122                         }
30123 
30124                         return bocnode;
30125                      }
30126                   }
30127                   else if (operation == details::e_pow)
30128                   {
30129                      // (v ^ c0) ^ c1 --> v ^(c0 * c1)
30130                      details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
30131                      details::operator_type        boc_opr = bocnode->operation();
30132 
30133                      if (details::e_pow == boc_opr)
30134                      {
30135                         bocnode->set_c(bocnode->c() * c);
30136 
30137                         return bocnode;
30138                      }
30139                   }
30140                }
30141 
30142                #ifndef exprtk_disable_enhanced_features
30143                if (details::is_sf3ext_node(branch[0]))
30144                {
30145                   expression_node_ptr result = error_node();
30146 
30147                   const bool synthesis_result =
30148                      synthesize_sf4ext_expression::template compile_left<ctype>
30149                         (expr_gen, c, operation, branch[0], result);
30150 
30151                   if (synthesis_result)
30152                   {
30153                      free_node(*expr_gen.node_allocator_, branch[0]);
30154 
30155                      return result;
30156                   }
30157                }
30158                #endif
30159 
30160                switch (operation)
30161                {
30162                   #define case_stmt(op0,op1)                                                       \
30163                   case op0 : return expr_gen.node_allocator_->                                     \
30164                                 template allocate_cr<typename details::boc_node<Type,op1<Type> > > \
30165                                    (branch[0], c);                                                 \
30166 
30167                   basic_opr_switch_statements
30168                   extended_opr_switch_statements
30169                   #undef case_stmt
30170                   default : return error_node();
30171                }
30172             }
30173          };
30174 
30175          struct synthesize_cocob_expression
30176          {
processexprtk::parser::expression_generator::synthesize_cocob_expression30177             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30178                                                       const details::operator_type& operation,
30179                                                       expression_node_ptr (&branch)[2])
30180             {
30181                expression_node_ptr result = error_node();
30182 
30183                // (cob) o c --> cob
30184                if (details::is_cob_node(branch[0]))
30185                {
30186                   details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[0]);
30187 
30188                   const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
30189 
30190                   if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
30191                   {
30192                      free_node(*expr_gen.node_allocator_, branch[0]);
30193                      free_node(*expr_gen.node_allocator_, branch[1]);
30194 
30195                      return expr_gen(T(0));
30196                   }
30197                   else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
30198                   {
30199                      free_node(*expr_gen.node_allocator_, branch[0]);
30200                      free_node(*expr_gen.node_allocator_, branch[1]);
30201 
30202                      return expr_gen(T(std::numeric_limits<T>::quiet_NaN()));
30203                   }
30204                   else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
30205                   {
30206                      free_node(*expr_gen.node_allocator_, branch[1]);
30207 
30208                      return branch[0];
30209                   }
30210                   else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
30211                   {
30212                      free_node(*expr_gen.node_allocator_, branch[1]);
30213 
30214                      return branch[0];
30215                   }
30216                   else if (std::equal_to<T>()(T(1),c) && (details::e_div == operation))
30217                   {
30218                      free_node(*expr_gen.node_allocator_, branch[1]);
30219 
30220                      return branch[0];
30221                   }
30222 
30223                   const bool op_addsub = (details::e_add == cobnode->operation()) ||
30224                                          (details::e_sub == cobnode->operation()) ;
30225 
30226                   if (op_addsub)
30227                   {
30228                      switch (operation)
30229                      {
30230                         case details::e_add : cobnode->set_c(cobnode->c() + c); break;
30231                         case details::e_sub : cobnode->set_c(cobnode->c() - c); break;
30232                         default             : return error_node();
30233                      }
30234 
30235                      result = cobnode;
30236                   }
30237                   else if (details::e_mul == cobnode->operation())
30238                   {
30239                      switch (operation)
30240                      {
30241                         case details::e_mul : cobnode->set_c(cobnode->c() * c); break;
30242                         case details::e_div : cobnode->set_c(cobnode->c() / c); break;
30243                         default             : return error_node();
30244                      }
30245 
30246                      result = cobnode;
30247                   }
30248                   else if (details::e_div == cobnode->operation())
30249                   {
30250                      if (details::e_mul == operation)
30251                      {
30252                         cobnode->set_c(cobnode->c() * c);
30253                         result = cobnode;
30254                      }
30255                      else if (details::e_div == operation)
30256                      {
30257                         result = expr_gen.node_allocator_->
30258                                     template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
30259                                        (cobnode->c() / c, cobnode->move_branch(0));
30260 
30261                         free_node(*expr_gen.node_allocator_, branch[0]);
30262                      }
30263                   }
30264 
30265                   if (result)
30266                   {
30267                      free_node(*expr_gen.node_allocator_,branch[1]);
30268                   }
30269                }
30270 
30271                // c o (cob) --> cob
30272                else if (details::is_cob_node(branch[1]))
30273                {
30274                   details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
30275 
30276                   const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
30277 
30278                   if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
30279                   {
30280                      free_node(*expr_gen.node_allocator_, branch[0]);
30281                      free_node(*expr_gen.node_allocator_, branch[1]);
30282 
30283                      return expr_gen(T(0));
30284                   }
30285                   else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
30286                   {
30287                      free_node(*expr_gen.node_allocator_, branch[0]);
30288                      free_node(*expr_gen.node_allocator_, branch[1]);
30289 
30290                      return expr_gen(T(0));
30291                   }
30292                   else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
30293                   {
30294                      free_node(*expr_gen.node_allocator_, branch[0]);
30295 
30296                      return branch[1];
30297                   }
30298                   else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
30299                   {
30300                      free_node(*expr_gen.node_allocator_, branch[0]);
30301 
30302                      return branch[1];
30303                   }
30304 
30305                   if (details::e_add == cobnode->operation())
30306                   {
30307                      if (details::e_add == operation)
30308                      {
30309                         cobnode->set_c(c + cobnode->c());
30310                         result = cobnode;
30311                      }
30312                      else if (details::e_sub == operation)
30313                      {
30314                         result = expr_gen.node_allocator_->
30315                                     template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
30316                                        (c - cobnode->c(), cobnode->move_branch(0));
30317 
30318                         free_node(*expr_gen.node_allocator_,branch[1]);
30319                      }
30320                   }
30321                   else if (details::e_sub == cobnode->operation())
30322                   {
30323                      if (details::e_add == operation)
30324                      {
30325                         cobnode->set_c(c + cobnode->c());
30326                         result = cobnode;
30327                      }
30328                      else if (details::e_sub == operation)
30329                      {
30330                         result = expr_gen.node_allocator_->
30331                                     template allocate_tt<typename details::cob_node<Type,details::add_op<Type> > >
30332                                        (c - cobnode->c(), cobnode->move_branch(0));
30333 
30334                         free_node(*expr_gen.node_allocator_,branch[1]);
30335                      }
30336                   }
30337                   else if (details::e_mul == cobnode->operation())
30338                   {
30339                      if (details::e_mul == operation)
30340                      {
30341                         cobnode->set_c(c * cobnode->c());
30342                         result = cobnode;
30343                      }
30344                      else if (details::e_div == operation)
30345                      {
30346                         result = expr_gen.node_allocator_->
30347                                     template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
30348                                        (c / cobnode->c(), cobnode->move_branch(0));
30349 
30350                         free_node(*expr_gen.node_allocator_,branch[1]);
30351                      }
30352                   }
30353                   else if (details::e_div == cobnode->operation())
30354                   {
30355                      if (details::e_mul == operation)
30356                      {
30357                         cobnode->set_c(c * cobnode->c());
30358                         result = cobnode;
30359                      }
30360                      else if (details::e_div == operation)
30361                      {
30362                         result = expr_gen.node_allocator_->
30363                                     template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > >
30364                                        (c / cobnode->c(), cobnode->move_branch(0));
30365 
30366                         free_node(*expr_gen.node_allocator_,branch[1]);
30367                      }
30368                   }
30369 
30370                   if (result)
30371                   {
30372                      free_node(*expr_gen.node_allocator_,branch[0]);
30373                   }
30374                }
30375 
30376                return result;
30377             }
30378          };
30379 
30380          struct synthesize_coboc_expression
30381          {
processexprtk::parser::expression_generator::synthesize_coboc_expression30382             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30383                                                       const details::operator_type& operation,
30384                                                       expression_node_ptr (&branch)[2])
30385             {
30386                expression_node_ptr result = error_node();
30387 
30388                // (boc) o c --> boc
30389                if (details::is_boc_node(branch[0]))
30390                {
30391                   details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
30392 
30393                   const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
30394 
30395                   if (details::e_add == bocnode->operation())
30396                   {
30397                      switch (operation)
30398                      {
30399                         case details::e_add : bocnode->set_c(bocnode->c() + c); break;
30400                         case details::e_sub : bocnode->set_c(bocnode->c() - c); break;
30401                         default             : return error_node();
30402                      }
30403 
30404                      result = bocnode;
30405                   }
30406                   else if (details::e_mul == bocnode->operation())
30407                   {
30408                      switch (operation)
30409                      {
30410                         case details::e_mul : bocnode->set_c(bocnode->c() * c); break;
30411                         case details::e_div : bocnode->set_c(bocnode->c() / c); break;
30412                         default             : return error_node();
30413                      }
30414 
30415                      result = bocnode;
30416                   }
30417                   else if (details::e_sub == bocnode->operation())
30418                   {
30419                      if (details::e_add == operation)
30420                      {
30421                         result = expr_gen.node_allocator_->
30422                                     template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > >
30423                                        (bocnode->move_branch(0), c - bocnode->c());
30424 
30425                         free_node(*expr_gen.node_allocator_,branch[0]);
30426                      }
30427                      else if (details::e_sub == operation)
30428                      {
30429                         bocnode->set_c(bocnode->c() + c);
30430                         result = bocnode;
30431                      }
30432                   }
30433                   else if (details::e_div == bocnode->operation())
30434                   {
30435                      switch (operation)
30436                      {
30437                         case details::e_div : bocnode->set_c(bocnode->c() * c); break;
30438                         case details::e_mul : bocnode->set_c(bocnode->c() / c); break;
30439                         default             : return error_node();
30440                      }
30441 
30442                      result = bocnode;
30443                   }
30444 
30445                   if (result)
30446                   {
30447                      free_node(*expr_gen.node_allocator_, branch[1]);
30448                   }
30449                }
30450 
30451                // c o (boc) --> boc
30452                else if (details::is_boc_node(branch[1]))
30453                {
30454                   details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[1]);
30455 
30456                   const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
30457 
30458                   if (details::e_add == bocnode->operation())
30459                   {
30460                      if (details::e_add == operation)
30461                      {
30462                         bocnode->set_c(c + bocnode->c());
30463                         result = bocnode;
30464                      }
30465                      else if (details::e_sub == operation)
30466                      {
30467                         result = expr_gen.node_allocator_->
30468                                     template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
30469                                        (c - bocnode->c(), bocnode->move_branch(0));
30470 
30471                         free_node(*expr_gen.node_allocator_,branch[1]);
30472                      }
30473                   }
30474                   else if (details::e_sub == bocnode->operation())
30475                   {
30476                      if (details::e_add == operation)
30477                      {
30478                         result = expr_gen.node_allocator_->
30479                                     template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > >
30480                                        (bocnode->move_branch(0), c - bocnode->c());
30481 
30482                         free_node(*expr_gen.node_allocator_,branch[1]);
30483                      }
30484                      else if (details::e_sub == operation)
30485                      {
30486                         result = expr_gen.node_allocator_->
30487                                     template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
30488                                        (c + bocnode->c(), bocnode->move_branch(0));
30489 
30490                         free_node(*expr_gen.node_allocator_,branch[1]);
30491                      }
30492                   }
30493                   else if (details::e_mul == bocnode->operation())
30494                   {
30495                      if (details::e_mul == operation)
30496                      {
30497                         bocnode->set_c(c * bocnode->c());
30498                         result = bocnode;
30499                      }
30500                      else if (details::e_div == operation)
30501                      {
30502                         result = expr_gen.node_allocator_->
30503                                     template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
30504                                        (c / bocnode->c(), bocnode->move_branch(0));
30505 
30506                         free_node(*expr_gen.node_allocator_,branch[1]);
30507                      }
30508                   }
30509                   else if (details::e_div == bocnode->operation())
30510                   {
30511                      if (details::e_mul == operation)
30512                      {
30513                         bocnode->set_c(bocnode->c() / c);
30514                         result = bocnode;
30515                      }
30516                      else if (details::e_div == operation)
30517                      {
30518                         result = expr_gen.node_allocator_->
30519                                     template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
30520                                        (c * bocnode->c(), bocnode->move_branch(0));
30521 
30522                         free_node(*expr_gen.node_allocator_,branch[1]);
30523                      }
30524                   }
30525 
30526                   if (result)
30527                   {
30528                      free_node(*expr_gen.node_allocator_,branch[0]);
30529                   }
30530                }
30531 
30532                return result;
30533             }
30534          };
30535 
30536          #ifndef exprtk_disable_enhanced_features
synthesize_expression(const details::operator_type & operation,expression_node_ptr (& branch)[2],expression_node_ptr & result)30537          inline bool synthesize_expression(const details::operator_type& operation,
30538                                            expression_node_ptr (&branch)[2],
30539                                            expression_node_ptr& result)
30540          {
30541             result = error_node();
30542 
30543             if (!operation_optimisable(operation))
30544                return false;
30545 
30546             const std::string node_id = branch_to_id(branch);
30547 
30548             const typename synthesize_map_t::iterator itr = synthesize_map_.find(node_id);
30549 
30550             if (synthesize_map_.end() != itr)
30551             {
30552                result = itr->second((*this), operation, branch);
30553 
30554                return true;
30555             }
30556             else
30557                return false;
30558          }
30559 
30560          struct synthesize_vov_expression
30561          {
processexprtk::parser::expression_generator::synthesize_vov_expression30562             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30563                                                       const details::operator_type& operation,
30564                                                       expression_node_ptr (&branch)[2])
30565             {
30566                const Type& v1 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
30567                const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
30568 
30569                switch (operation)
30570                {
30571                   #define case_stmt(op0,op1)                                                       \
30572                   case op0 : return expr_gen.node_allocator_->                                     \
30573                                 template allocate_rr<typename details::vov_node<Type,op1<Type> > > \
30574                                    (v1, v2);                                                       \
30575 
30576                   basic_opr_switch_statements
30577                   extended_opr_switch_statements
30578                   #undef case_stmt
30579                   default : return error_node();
30580                }
30581             }
30582          };
30583 
30584          struct synthesize_cov_expression
30585          {
processexprtk::parser::expression_generator::synthesize_cov_expression30586             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30587                                                       const details::operator_type& operation,
30588                                                       expression_node_ptr (&branch)[2])
30589             {
30590                const Type  c = static_cast<details::literal_node<Type>*> (branch[0])->value();
30591                const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref  ();
30592 
30593                details::free_node(*(expr_gen.node_allocator_),branch[0]);
30594 
30595                if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
30596                   return expr_gen(T(0));
30597                else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
30598                   return expr_gen(T(0));
30599                else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
30600                   return static_cast<details::variable_node<Type>*>(branch[1]);
30601                else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
30602                   return static_cast<details::variable_node<Type>*>(branch[1]);
30603 
30604                switch (operation)
30605                {
30606                   #define case_stmt(op0,op1)                                                       \
30607                   case op0 : return expr_gen.node_allocator_->                                     \
30608                                 template allocate_cr<typename details::cov_node<Type,op1<Type> > > \
30609                                    (c, v);                                                         \
30610 
30611                   basic_opr_switch_statements
30612                   extended_opr_switch_statements
30613                   #undef case_stmt
30614                   default : return error_node();
30615                }
30616             }
30617          };
30618 
30619          struct synthesize_voc_expression
30620          {
processexprtk::parser::expression_generator::synthesize_voc_expression30621             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30622                                                       const details::operator_type& operation,
30623                                                       expression_node_ptr (&branch)[2])
30624             {
30625                const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref  ();
30626                const Type  c = static_cast<details::literal_node<Type>*> (branch[1])->value();
30627 
30628                details::free_node(*(expr_gen.node_allocator_), branch[1]);
30629 
30630                if (expr_gen.cardinal_pow_optimisable(operation,c))
30631                {
30632                   if (std::equal_to<T>()(T(1),c))
30633                      return branch[0];
30634                   else
30635                      return expr_gen.cardinal_pow_optimisation(v,c);
30636                }
30637                else if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
30638                   return expr_gen(T(0));
30639                else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
30640                   return expr_gen(std::numeric_limits<T>::quiet_NaN());
30641                else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
30642                   return static_cast<details::variable_node<Type>*>(branch[0]);
30643                else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
30644                   return static_cast<details::variable_node<Type>*>(branch[0]);
30645                else if (std::equal_to<T>()(T(1),c) && (details::e_div == operation))
30646                   return static_cast<details::variable_node<Type>*>(branch[0]);
30647 
30648                switch (operation)
30649                {
30650                   #define case_stmt(op0,op1)                                                       \
30651                   case op0 : return expr_gen.node_allocator_->                                     \
30652                                 template allocate_rc<typename details::voc_node<Type,op1<Type> > > \
30653                                    (v, c);                                                         \
30654 
30655                   basic_opr_switch_statements
30656                   extended_opr_switch_statements
30657                   #undef case_stmt
30658                   default : return error_node();
30659                }
30660             }
30661          };
30662 
30663          struct synthesize_sf3ext_expression
30664          {
30665             template <typename T0, typename T1, typename T2>
processexprtk::parser::expression_generator::synthesize_sf3ext_expression30666             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30667                                                       const details::operator_type& sf3opr,
30668                                                       T0 t0, T1 t1, T2 t2)
30669             {
30670                switch (sf3opr)
30671                {
30672                   #define case_stmt(op)                                                                              \
30673                   case details::e_sf##op : return details::T0oT1oT2_sf3ext<T,T0,T1,T2,details::sf##op##_op<Type> >:: \
30674                                 allocate(*(expr_gen.node_allocator_), t0, t1, t2);                                   \
30675 
30676                   case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
30677                   case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
30678                   case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
30679                   case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
30680                   case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
30681                   case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
30682                   case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
30683                   case_stmt(28) case_stmt(29) case_stmt(30)
30684                   #undef case_stmt
30685                   default : return error_node();
30686                }
30687             }
30688 
30689             template <typename T0, typename T1, typename T2>
compileexprtk::parser::expression_generator::synthesize_sf3ext_expression30690             static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id,
30691                                        T0 t0, T1 t1, T2 t2,
30692                                        expression_node_ptr& result)
30693             {
30694                details::operator_type sf3opr;
30695 
30696                if (!expr_gen.sf3_optimisable(id,sf3opr))
30697                   return false;
30698                else
30699                   result = synthesize_sf3ext_expression::template process<T0, T1, T2>
30700                               (expr_gen, sf3opr, t0, t1, t2);
30701 
30702                return true;
30703             }
30704          };
30705 
30706          struct synthesize_sf4ext_expression
30707          {
30708             template <typename T0, typename T1, typename T2, typename T3>
processexprtk::parser::expression_generator::synthesize_sf4ext_expression30709             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30710                                                       const details::operator_type& sf4opr,
30711                                                       T0 t0, T1 t1, T2 t2, T3 t3)
30712             {
30713                switch (sf4opr)
30714                {
30715                   #define case_stmt0(op)                                                                                      \
30716                   case details::e_sf##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sf##op##_op<Type> >:: \
30717                                 allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3);                                        \
30718 
30719 
30720                   #define case_stmt1(op)                                                                                             \
30721                   case details::e_sf4ext##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sfext##op##_op<Type> >:: \
30722                                 allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3);                                               \
30723 
30724                   case_stmt0(48) case_stmt0(49) case_stmt0(50) case_stmt0(51)
30725                   case_stmt0(52) case_stmt0(53) case_stmt0(54) case_stmt0(55)
30726                   case_stmt0(56) case_stmt0(57) case_stmt0(58) case_stmt0(59)
30727                   case_stmt0(60) case_stmt0(61) case_stmt0(62) case_stmt0(63)
30728                   case_stmt0(64) case_stmt0(65) case_stmt0(66) case_stmt0(67)
30729                   case_stmt0(68) case_stmt0(69) case_stmt0(70) case_stmt0(71)
30730                   case_stmt0(72) case_stmt0(73) case_stmt0(74) case_stmt0(75)
30731                   case_stmt0(76) case_stmt0(77) case_stmt0(78) case_stmt0(79)
30732                   case_stmt0(80) case_stmt0(81) case_stmt0(82) case_stmt0(83)
30733 
30734                   case_stmt1(00) case_stmt1(01) case_stmt1(02) case_stmt1(03)
30735                   case_stmt1(04) case_stmt1(05) case_stmt1(06) case_stmt1(07)
30736                   case_stmt1(08) case_stmt1(09) case_stmt1(10) case_stmt1(11)
30737                   case_stmt1(12) case_stmt1(13) case_stmt1(14) case_stmt1(15)
30738                   case_stmt1(16) case_stmt1(17) case_stmt1(18) case_stmt1(19)
30739                   case_stmt1(20) case_stmt1(21) case_stmt1(22) case_stmt1(23)
30740                   case_stmt1(24) case_stmt1(25) case_stmt1(26) case_stmt1(27)
30741                   case_stmt1(28) case_stmt1(29) case_stmt1(30) case_stmt1(31)
30742                   case_stmt1(32) case_stmt1(33) case_stmt1(34) case_stmt1(35)
30743                   case_stmt1(36) case_stmt1(37) case_stmt1(38) case_stmt1(39)
30744                   case_stmt1(40) case_stmt1(41) case_stmt1(42) case_stmt1(43)
30745                   case_stmt1(44) case_stmt1(45) case_stmt1(46) case_stmt1(47)
30746                   case_stmt1(48) case_stmt1(49) case_stmt1(50) case_stmt1(51)
30747                   case_stmt1(52) case_stmt1(53) case_stmt1(54) case_stmt1(55)
30748                   case_stmt1(56) case_stmt1(57) case_stmt1(58) case_stmt1(59)
30749                   case_stmt1(60) case_stmt1(61)
30750 
30751                   #undef case_stmt0
30752                   #undef case_stmt1
30753                   default : return error_node();
30754                }
30755             }
30756 
30757             template <typename T0, typename T1, typename T2, typename T3>
compileexprtk::parser::expression_generator::synthesize_sf4ext_expression30758             static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id,
30759                                        T0 t0, T1 t1, T2 t2, T3 t3,
30760                                        expression_node_ptr& result)
30761             {
30762                details::operator_type sf4opr;
30763 
30764                if (!expr_gen.sf4_optimisable(id,sf4opr))
30765                   return false;
30766                else
30767                   result = synthesize_sf4ext_expression::template process<T0, T1, T2, T3>
30768                               (expr_gen, sf4opr, t0, t1, t2, t3);
30769 
30770                return true;
30771             }
30772 
30773             // T o (sf3ext)
30774             template <typename ExternalType>
compile_rightexprtk::parser::expression_generator::synthesize_sf4ext_expression30775             static inline bool compile_right(expression_generator<Type>& expr_gen,
30776                                              ExternalType t,
30777                                              const details::operator_type& operation,
30778                                              expression_node_ptr& sf3node,
30779                                              expression_node_ptr& result)
30780             {
30781                if (!details::is_sf3ext_node(sf3node))
30782                   return false;
30783 
30784                typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr;
30785 
30786                sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node);
30787                const std::string id = "t" + expr_gen.to_str(operation) + "(" + n->type_id() + ")";
30788 
30789                switch (n->type())
30790                {
30791                   case details::expression_node<Type>::e_covoc : return compile_right_impl
30792                                                                     <typename covoc_t::sf3_type_node,ExternalType, ctype, vtype, ctype>
30793                                                                        (expr_gen, id, t, sf3node, result);
30794 
30795                   case details::expression_node<Type>::e_covov : return compile_right_impl
30796                                                                     <typename covov_t::sf3_type_node,ExternalType, ctype, vtype, vtype>
30797                                                                        (expr_gen, id, t, sf3node, result);
30798 
30799                   case details::expression_node<Type>::e_vocov : return compile_right_impl
30800                                                                     <typename vocov_t::sf3_type_node,ExternalType, vtype, ctype, vtype>
30801                                                                        (expr_gen, id, t, sf3node, result);
30802 
30803                   case details::expression_node<Type>::e_vovoc : return compile_right_impl
30804                                                                     <typename vovoc_t::sf3_type_node,ExternalType, vtype, vtype, ctype>
30805                                                                        (expr_gen, id, t, sf3node, result);
30806 
30807                   case details::expression_node<Type>::e_vovov : return compile_right_impl
30808                                                                     <typename vovov_t::sf3_type_node,ExternalType, vtype, vtype, vtype>
30809                                                                        (expr_gen, id, t, sf3node, result);
30810 
30811                   default                                      : return false;
30812                }
30813             }
30814 
30815             // (sf3ext) o T
30816             template <typename ExternalType>
compile_leftexprtk::parser::expression_generator::synthesize_sf4ext_expression30817             static inline bool compile_left(expression_generator<Type>& expr_gen,
30818                                             ExternalType t,
30819                                             const details::operator_type& operation,
30820                                             expression_node_ptr& sf3node,
30821                                             expression_node_ptr& result)
30822             {
30823                if (!details::is_sf3ext_node(sf3node))
30824                   return false;
30825 
30826                typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr;
30827 
30828                sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node);
30829 
30830                const std::string id = "(" + n->type_id() + ")" + expr_gen.to_str(operation) + "t";
30831 
30832                switch (n->type())
30833                {
30834                   case details::expression_node<Type>::e_covoc : return compile_left_impl
30835                                                                     <typename covoc_t::sf3_type_node,ExternalType, ctype, vtype, ctype>
30836                                                                        (expr_gen, id, t, sf3node, result);
30837 
30838                   case details::expression_node<Type>::e_covov : return compile_left_impl
30839                                                                     <typename covov_t::sf3_type_node,ExternalType, ctype, vtype, vtype>
30840                                                                        (expr_gen, id, t, sf3node, result);
30841 
30842                   case details::expression_node<Type>::e_vocov : return compile_left_impl
30843                                                                     <typename vocov_t::sf3_type_node,ExternalType, vtype, ctype, vtype>
30844                                                                        (expr_gen, id, t, sf3node, result);
30845 
30846                   case details::expression_node<Type>::e_vovoc : return compile_left_impl
30847                                                                     <typename vovoc_t::sf3_type_node,ExternalType, vtype, vtype, ctype>
30848                                                                        (expr_gen, id, t, sf3node, result);
30849 
30850                   case details::expression_node<Type>::e_vovov : return compile_left_impl
30851                                                                     <typename vovov_t::sf3_type_node,ExternalType, vtype, vtype, vtype>
30852                                                                        (expr_gen, id, t, sf3node, result);
30853 
30854                   default                                      : return false;
30855                }
30856             }
30857 
30858             template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2>
compile_right_implexprtk::parser::expression_generator::synthesize_sf4ext_expression30859             static inline bool compile_right_impl(expression_generator<Type>& expr_gen,
30860                                                   const std::string& id,
30861                                                   ExternalType t,
30862                                                   expression_node_ptr& node,
30863                                                   expression_node_ptr& result)
30864             {
30865                SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node);
30866 
30867                if (n)
30868                {
30869                   T0 t0 = n->t0();
30870                   T1 t1 = n->t1();
30871                   T2 t2 = n->t2();
30872 
30873                   return synthesize_sf4ext_expression::template compile<ExternalType, T0, T1, T2>
30874                             (expr_gen, id, t, t0, t1, t2, result);
30875                }
30876                else
30877                   return false;
30878             }
30879 
30880             template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2>
compile_left_implexprtk::parser::expression_generator::synthesize_sf4ext_expression30881             static inline bool compile_left_impl(expression_generator<Type>& expr_gen,
30882                                                  const std::string& id,
30883                                                  ExternalType t,
30884                                                  expression_node_ptr& node,
30885                                                  expression_node_ptr& result)
30886             {
30887                SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node);
30888 
30889                if (n)
30890                {
30891                   T0 t0 = n->t0();
30892                   T1 t1 = n->t1();
30893                   T2 t2 = n->t2();
30894 
30895                   return synthesize_sf4ext_expression::template compile<T0, T1, T2, ExternalType>
30896                             (expr_gen, id, t0, t1, t2, t, result);
30897                }
30898                else
30899                   return false;
30900             }
30901          };
30902 
30903          struct synthesize_vovov_expression0
30904          {
30905             typedef typename vovov_t::type0 node_type;
30906             typedef typename vovov_t::sf3_type sf3_type;
30907 
processexprtk::parser::expression_generator::synthesize_vovov_expression030908             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30909                                                       const details::operator_type& operation,
30910                                                       expression_node_ptr (&branch)[2])
30911             {
30912                // (v0 o0 v1) o1 (v2)
30913                const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
30914                const Type& v0 = vov->v0();
30915                const Type& v1 = vov->v1();
30916                const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
30917                const details::operator_type o0 = vov->operation();
30918                const details::operator_type o1 = operation;
30919 
30920                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30921                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30922 
30923                details::free_node(*(expr_gen.node_allocator_),branch[0]);
30924 
30925                expression_node_ptr result = error_node();
30926 
30927                if (expr_gen.parser_->settings_.strength_reduction_enabled())
30928                {
30929                   // (v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)
30930                   if ((details::e_div == o0) && (details::e_div == o1))
30931                   {
30932                      const bool synthesis_result =
30933                         synthesize_sf3ext_expression::
30934                            template compile<vtype,vtype,vtype>(expr_gen, "t/(t*t)", v0, v1, v2, result);
30935 
30936                      exprtk_debug(("(v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)\n"));
30937 
30938                      return (synthesis_result) ? result : error_node();
30939                   }
30940                }
30941 
30942                const bool synthesis_result =
30943                   synthesize_sf3ext_expression::template compile<vtype, vtype, vtype>
30944                      (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result);
30945 
30946                if (synthesis_result)
30947                   return result;
30948                else if (!expr_gen.valid_operator(o0,f0))
30949                   return error_node();
30950                else if (!expr_gen.valid_operator(o1,f1))
30951                   return error_node();
30952                else
30953                   return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1);
30954             }
30955 
idexprtk::parser::expression_generator::synthesize_vovov_expression030956             static inline std::string id(expression_generator<Type>& expr_gen,
30957                                          const details::operator_type o0, const details::operator_type o1)
30958             {
30959                return details::build_string()
30960                          << "(t" << expr_gen.to_str(o0)
30961                          << "t)" << expr_gen.to_str(o1)
30962                          << "t";
30963             }
30964          };
30965 
30966          struct synthesize_vovov_expression1
30967          {
30968             typedef typename vovov_t::type1 node_type;
30969             typedef typename vovov_t::sf3_type sf3_type;
30970 
processexprtk::parser::expression_generator::synthesize_vovov_expression130971             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30972                                                       const details::operator_type& operation,
30973                                                       expression_node_ptr (&branch)[2])
30974             {
30975                // (v0) o0 (v1 o1 v2)
30976                const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
30977                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
30978                const Type& v1 = vov->v0();
30979                const Type& v2 = vov->v1();
30980                const details::operator_type o0 = operation;
30981                const details::operator_type o1 = vov->operation();
30982 
30983                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30984                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30985 
30986                details::free_node(*(expr_gen.node_allocator_),branch[1]);
30987 
30988                expression_node_ptr result = error_node();
30989 
30990                if (expr_gen.parser_->settings_.strength_reduction_enabled())
30991                {
30992                   // v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1
30993                   if ((details::e_div == o0) && (details::e_div == o1))
30994                   {
30995                      const bool synthesis_result =
30996                         synthesize_sf3ext_expression::
30997                            template compile<vtype,vtype,vtype>(expr_gen, "(t*t)/t", v0, v2, v1, result);
30998 
30999                      exprtk_debug(("v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1\n"));
31000 
31001                      return (synthesis_result) ? result : error_node();
31002                   }
31003                }
31004 
31005                const bool synthesis_result =
31006                   synthesize_sf3ext_expression::template compile<vtype, vtype, vtype>
31007                      (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result);
31008 
31009                if (synthesis_result)
31010                   return result;
31011                else if (!expr_gen.valid_operator(o0,f0))
31012                   return error_node();
31013                else if (!expr_gen.valid_operator(o1,f1))
31014                   return error_node();
31015                else
31016                   return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1);
31017             }
31018 
idexprtk::parser::expression_generator::synthesize_vovov_expression131019             static inline std::string id(expression_generator<Type>& expr_gen,
31020                                          const details::operator_type o0, const details::operator_type o1)
31021             {
31022                return details::build_string()
31023                          << "t"  << expr_gen.to_str(o0)
31024                          << "(t" << expr_gen.to_str(o1)
31025                          << "t)";
31026             }
31027          };
31028 
31029          struct synthesize_vovoc_expression0
31030          {
31031             typedef typename vovoc_t::type0 node_type;
31032             typedef typename vovoc_t::sf3_type sf3_type;
31033 
processexprtk::parser::expression_generator::synthesize_vovoc_expression031034             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
31035                                                       const details::operator_type& operation,
31036                                                       expression_node_ptr (&branch)[2])
31037             {
31038                // (v0 o0 v1) o1 (c)
31039                const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
31040                const Type& v0 = vov->v0();
31041                const Type& v1 = vov->v1();
31042                const Type   c = static_cast<details::literal_node<Type>*>(branch[1])->value();
31043                const details::operator_type o0 = vov->operation();
31044                const details::operator_type o1 = operation;
31045 
31046                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31047                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31048 
31049                details::free_node(*(expr_gen.node_allocator_),branch[0]);
31050                details::free_node(*(expr_gen.node_allocator_),branch[1]);
31051 
31052                expression_node_ptr result = error_node();
31053 
31054                if (expr_gen.parser_->settings_.strength_reduction_enabled())
31055                {
31056                   // (v0 / v1) / c --> (vovoc) v0 / (v1 * c)
31057                   if ((details::e_div == o0) && (details::e_div == o1))
31058                   {
31059                      const bool synthesis_result =
31060                         synthesize_sf3ext_expression::
31061                            template compile<vtype,vtype,ctype>(expr_gen, "t/(t*t)", v0, v1, c, result);
31062 
31063                      exprtk_debug(("(v0 / v1) / c --> (vovoc) v0 / (v1 * c)\n"));
31064 
31065                      return (synthesis_result) ? result : error_node();
31066                   }
31067                }
31068 
31069                const bool synthesis_result =
31070                   synthesize_sf3ext_expression::template compile<vtype, vtype, ctype>
31071                      (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result);
31072 
31073                if (synthesis_result)
31074                   return result;
31075                else if (!expr_gen.valid_operator(o0,f0))
31076                   return error_node();
31077                else if (!expr_gen.valid_operator(o1,f1))
31078                   return error_node();
31079                else
31080                   return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1);
31081             }
31082 
idexprtk::parser::expression_generator::synthesize_vovoc_expression031083             static inline std::string id(expression_generator<Type>& expr_gen,
31084                                          const details::operator_type o0, const details::operator_type o1)
31085             {
31086                return details::build_string()
31087                          << "(t" << expr_gen.to_str(o0)
31088                          << "t)" << expr_gen.to_str(o1)
31089                          << "t";
31090             }
31091          };
31092 
31093          struct synthesize_vovoc_expression1
31094          {
31095             typedef typename vovoc_t::type1 node_type;
31096             typedef typename vovoc_t::sf3_type sf3_type;
31097 
processexprtk::parser::expression_generator::synthesize_vovoc_expression131098             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
31099                                                       const details::operator_type& operation,
31100                                                       expression_node_ptr (&branch)[2])
31101             {
31102                // (v0) o0 (v1 o1 c)
31103                const details::voc_base_node<Type>* voc = static_cast<const details::voc_base_node<Type>*>(branch[1]);
31104                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
31105                const Type& v1 = voc->v();
31106                const Type   c = voc->c();
31107                const details::operator_type o0 = operation;
31108                const details::operator_type o1 = voc->operation();
31109 
31110                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31111                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31112 
31113                details::free_node(*(expr_gen.node_allocator_),branch[1]);
31114 
31115                expression_node_ptr result = error_node();
31116 
31117                if (expr_gen.parser_->settings_.strength_reduction_enabled())
31118                {
31119                   // v0 / (v1 / c) --> (vocov) (v0 * c) / v1
31120                   if ((details::e_div == o0) && (details::e_div == o1))
31121                   {
31122                      const bool synthesis_result =
31123                         synthesize_sf3ext_expression::
31124                            template compile<vtype,ctype,vtype>(expr_gen, "(t*t)/t", v0, c, v1, result);
31125 
31126                      exprtk_debug(("v0 / (v1 / c) --> (vocov) (v0 * c) / v1\n"));
31127 
31128                      return (synthesis_result) ? result : error_node();
31129                   }
31130                }
31131 
31132                const bool synthesis_result =
31133                   synthesize_sf3ext_expression::template compile<vtype, vtype, ctype>
31134                      (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result);
31135 
31136                if (synthesis_result)
31137                   return result;
31138                else if (!expr_gen.valid_operator(o0,f0))
31139                   return error_node();
31140                else if (!expr_gen.valid_operator(o1,f1))
31141                   return error_node();
31142                else
31143                   return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1);
31144             }
31145 
idexprtk::parser::expression_generator::synthesize_vovoc_expression131146             static inline std::string id(expression_generator<Type>& expr_gen,
31147                                          const details::operator_type o0, const details::operator_type o1)
31148             {
31149                return details::build_string()
31150                          << "t"  << expr_gen.to_str(o0)
31151                          << "(t" << expr_gen.to_str(o1)
31152                          << "t)";
31153             }
31154          };
31155 
31156          struct synthesize_vocov_expression0
31157          {
31158             typedef typename vocov_t::type0 node_type;
31159             typedef typename vocov_t::sf3_type sf3_type;
31160 
processexprtk::parser::expression_generator::synthesize_vocov_expression031161             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
31162                                                       const details::operator_type& operation,
31163                                                       expression_node_ptr (&branch)[2])
31164             {
31165                // (v0 o0 c) o1 (v1)
31166                const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
31167                const Type& v0 = voc->v();
31168                const Type   c = voc->c();
31169                const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
31170                const details::operator_type o0 = voc->operation();
31171                const details::operator_type o1 = operation;
31172 
31173                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31174                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31175 
31176                details::free_node(*(expr_gen.node_allocator_),branch[0]);
31177 
31178                expression_node_ptr result = error_node();
31179 
31180                if (expr_gen.parser_->settings_.strength_reduction_enabled())
31181                {
31182                   // (v0 / c) / v1 --> (vovoc) v0 / (v1 * c)
31183                   if ((details::e_div == o0) && (details::e_div == o1))
31184                   {
31185                      const bool synthesis_result =
31186                         synthesize_sf3ext_expression::
31187                            template compile<vtype,vtype,ctype>(expr_gen, "t/(t*t)", v0, v1, c, result);
31188 
31189                      exprtk_debug(("(v0 / c) / v1 --> (vovoc) v0 / (v1 * c)\n"));
31190 
31191                      return (synthesis_result) ? result : error_node();
31192                   }
31193                }
31194 
31195                const bool synthesis_result =
31196                   synthesize_sf3ext_expression::template compile<vtype, ctype, vtype>
31197                      (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result);
31198 
31199                if (synthesis_result)
31200                   return result;
31201                else if (!expr_gen.valid_operator(o0,f0))
31202                   return error_node();
31203                else if (!expr_gen.valid_operator(o1,f1))
31204                   return error_node();
31205                else
31206                   return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1);
31207             }
31208 
idexprtk::parser::expression_generator::synthesize_vocov_expression031209             static inline std::string id(expression_generator<Type>& expr_gen,
31210                                          const details::operator_type o0, const details::operator_type o1)
31211             {
31212                return details::build_string()
31213                          << "(t" << expr_gen.to_str(o0)
31214                          << "t)" << expr_gen.to_str(o1)
31215                          << "t";
31216             }
31217          };
31218 
31219          struct synthesize_vocov_expression1
31220          {
31221             typedef typename vocov_t::type1 node_type;
31222             typedef typename vocov_t::sf3_type sf3_type;
31223 
processexprtk::parser::expression_generator::synthesize_vocov_expression131224             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
31225                                                       const details::operator_type& operation,
31226                                                       expression_node_ptr (&branch)[2])
31227             {
31228                // (v0) o0 (c o1 v1)
31229                const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
31230                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
31231                const Type   c = cov->c();
31232                const Type& v1 = cov->v();
31233                const details::operator_type o0 = operation;
31234                const details::operator_type o1 = cov->operation();
31235 
31236                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31237                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31238 
31239                details::free_node(*(expr_gen.node_allocator_),branch[1]);
31240 
31241                expression_node_ptr result = error_node();
31242 
31243                if (expr_gen.parser_->settings_.strength_reduction_enabled())
31244                {
31245                   // v0 / (c / v1) --> (vovoc) (v0 * v1) / c
31246                   if ((details::e_div == o0) && (details::e_div == o1))
31247                   {
31248                      const bool synthesis_result =
31249                         synthesize_sf3ext_expression::
31250                            template compile<vtype, vtype, ctype>(expr_gen, "(t*t)/t", v0, v1, c, result);
31251 
31252                      exprtk_debug(("v0 / (c / v1) --> (vovoc) (v0 * v1) / c\n"));
31253 
31254                      return (synthesis_result) ? result : error_node();
31255                   }
31256                }
31257 
31258                const bool synthesis_result =
31259                   synthesize_sf3ext_expression::template compile<vtype, ctype, vtype>
31260                      (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result);
31261 
31262                if (synthesis_result)
31263                   return result;
31264                else if (!expr_gen.valid_operator(o0,f0))
31265                   return error_node();
31266                else if (!expr_gen.valid_operator(o1,f1))
31267                   return error_node();
31268                else
31269                   return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1);
31270             }
31271 
idexprtk::parser::expression_generator::synthesize_vocov_expression131272             static inline std::string id(expression_generator<Type>& expr_gen,
31273                                          const details::operator_type o0, const details::operator_type o1)
31274             {
31275                return details::build_string()
31276                          << "t"  << expr_gen.to_str(o0)
31277                          << "(t" << expr_gen.to_str(o1)
31278                          << "t)";
31279             }
31280          };
31281 
31282          struct synthesize_covov_expression0
31283          {
31284             typedef typename covov_t::type0 node_type;
31285             typedef typename covov_t::sf3_type sf3_type;
31286 
processexprtk::parser::expression_generator::synthesize_covov_expression031287             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
31288                                                       const details::operator_type& operation,
31289                                                       expression_node_ptr (&branch)[2])
31290             {
31291                // (c o0 v0) o1 (v1)
31292                const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
31293                const Type   c = cov->c();
31294                const Type& v0 = cov->v();
31295                const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
31296                const details::operator_type o0 = cov->operation();
31297                const details::operator_type o1 = operation;
31298 
31299                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31300                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31301 
31302                details::free_node(*(expr_gen.node_allocator_),branch[0]);
31303 
31304                expression_node_ptr result = error_node();
31305 
31306                if (expr_gen.parser_->settings_.strength_reduction_enabled())
31307                {
31308                   // (c / v0) / v1 --> (covov) c / (v0 * v1)
31309                   if ((details::e_div == o0) && (details::e_div == o1))
31310                   {
31311                      const bool synthesis_result =
31312                         synthesize_sf3ext_expression::
31313                            template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", c, v0, v1, result);
31314 
31315                      exprtk_debug(("(c / v0) / v1 --> (covov) c / (v0 * v1)\n"));
31316 
31317                      return (synthesis_result) ? result : error_node();
31318                   }
31319                }
31320 
31321                const bool synthesis_result =
31322                   synthesize_sf3ext_expression::template compile<ctype, vtype, vtype>
31323                      (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result);
31324 
31325                if (synthesis_result)
31326                   return result;
31327                else if (!expr_gen.valid_operator(o0,f0))
31328                   return error_node();
31329                else if (!expr_gen.valid_operator(o1,f1))
31330                   return error_node();
31331                else
31332                   return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1);
31333             }
31334 
idexprtk::parser::expression_generator::synthesize_covov_expression031335             static inline std::string id(expression_generator<Type>& expr_gen,
31336                                          const details::operator_type o0, const details::operator_type o1)
31337             {
31338                return details::build_string()
31339                          << "(t" << expr_gen.to_str(o0)
31340                          << "t)" << expr_gen.to_str(o1)
31341                          << "t";
31342             }
31343          };
31344 
31345          struct synthesize_covov_expression1
31346          {
31347             typedef typename covov_t::type1 node_type;
31348             typedef typename covov_t::sf3_type sf3_type;
31349 
processexprtk::parser::expression_generator::synthesize_covov_expression131350             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
31351                                                       const details::operator_type& operation,
31352                                                       expression_node_ptr (&branch)[2])
31353             {
31354                // (c) o0 (v0 o1 v1)
31355                const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
31356                const Type   c = static_cast<details::literal_node<Type>*>(branch[0])->value();
31357                const Type& v0 = vov->v0();
31358                const Type& v1 = vov->v1();
31359                const details::operator_type o0 = operation;
31360                const details::operator_type o1 = vov->operation();
31361 
31362                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31363                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31364 
31365                details::free_node(*(expr_gen.node_allocator_),branch[0]);
31366                details::free_node(*(expr_gen.node_allocator_),branch[1]);
31367 
31368                expression_node_ptr result = error_node();
31369 
31370                if (expr_gen.parser_->settings_.strength_reduction_enabled())
31371                {
31372                   // c / (v0 / v1) --> (covov) (c * v1) / v0
31373                   if ((details::e_div == o0) && (details::e_div == o1))
31374                   {
31375                      const bool synthesis_result =
31376                         synthesize_sf3ext_expression::
31377                            template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", c, v1, v0, result);
31378 
31379                      exprtk_debug(("c / (v0 / v1) --> (covov) (c * v1) / v0\n"));
31380 
31381                      return (synthesis_result) ? result : error_node();
31382                   }
31383                }
31384 
31385                const bool synthesis_result =
31386                   synthesize_sf3ext_expression::template compile<ctype, vtype, vtype>
31387                      (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result);
31388 
31389                if (synthesis_result)
31390                   return result;
31391                else if (!expr_gen.valid_operator(o0,f0))
31392                   return error_node();
31393                else if (!expr_gen.valid_operator(o1,f1))
31394                   return error_node();
31395                else
31396                   return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1);
31397             }
31398 
idexprtk::parser::expression_generator::synthesize_covov_expression131399             static inline std::string id(expression_generator<Type>& expr_gen, const details::operator_type o0, const details::operator_type o1)
31400             {
31401                return details::build_string()
31402                          << "t"  << expr_gen.to_str(o0)
31403                          << "(t" << expr_gen.to_str(o1)
31404                          << "t)";
31405             }
31406          };
31407 
31408          struct synthesize_covoc_expression0
31409          {
31410             typedef typename covoc_t::type0 node_type;
31411             typedef typename covoc_t::sf3_type sf3_type;
31412 
processexprtk::parser::expression_generator::synthesize_covoc_expression031413             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
31414                                                       const details::operator_type& operation,
31415                                                       expression_node_ptr (&branch)[2])
31416             {
31417                // (c0 o0 v) o1 (c1)
31418                const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
31419                const Type  c0 = cov->c();
31420                const Type&  v = cov->v();
31421                const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
31422                const details::operator_type o0 = cov->operation();
31423                const details::operator_type o1 = operation;
31424 
31425                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31426                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31427 
31428                details::free_node(*(expr_gen.node_allocator_),branch[0]);
31429                details::free_node(*(expr_gen.node_allocator_),branch[1]);
31430 
31431                expression_node_ptr result = error_node();
31432 
31433                if (expr_gen.parser_->settings_.strength_reduction_enabled())
31434                {
31435                   // (c0 + v) + c1 --> (cov) (c0 + c1) + v
31436                   if ((details::e_add == o0) && (details::e_add == o1))
31437                   {
31438                      exprtk_debug(("(c0 + v) + c1 --> (cov) (c0 + c1) + v\n"));
31439 
31440                      return expr_gen.node_allocator_->
31441                                template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v);
31442                   }
31443                   // (c0 + v) - c1 --> (cov) (c0 - c1) + v
31444                   else if ((details::e_add == o0) && (details::e_sub == o1))
31445                   {
31446                      exprtk_debug(("(c0 + v) - c1 --> (cov) (c0 - c1) + v\n"));
31447 
31448                      return expr_gen.node_allocator_->
31449                                template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v);
31450                   }
31451                   // (c0 - v) + c1 --> (cov) (c0 + c1) - v
31452                   else if ((details::e_sub == o0) && (details::e_add == o1))
31453                   {
31454                      exprtk_debug(("(c0 - v) + c1 --> (cov) (c0 + c1) - v\n"));
31455 
31456                      return expr_gen.node_allocator_->
31457                                template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v);
31458                   }
31459                   // (c0 - v) - c1 --> (cov) (c0 - c1) - v
31460                   else if ((details::e_sub == o0) && (details::e_sub == o1))
31461                   {
31462                      exprtk_debug(("(c0 - v) - c1 --> (cov) (c0 - c1) - v\n"));
31463 
31464                      return expr_gen.node_allocator_->
31465                                template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v);
31466                   }
31467                   // (c0 * v) * c1 --> (cov) (c0 * c1) * v
31468                   else if ((details::e_mul == o0) && (details::e_mul == o1))
31469                   {
31470                      exprtk_debug(("(c0 * v) * c1 --> (cov) (c0 * c1) * v\n"));
31471 
31472                      return expr_gen.node_allocator_->
31473                                template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v);
31474                   }
31475                   // (c0 * v) / c1 --> (cov) (c0 / c1) * v
31476                   else if ((details::e_mul == o0) && (details::e_div == o1))
31477                   {
31478                      exprtk_debug(("(c0 * v) / c1 --> (cov) (c0 / c1) * v\n"));
31479 
31480                      return expr_gen.node_allocator_->
31481                                template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v);
31482                   }
31483                   // (c0 / v) * c1 --> (cov) (c0 * c1) / v
31484                   else if ((details::e_div == o0) && (details::e_mul == o1))
31485                   {
31486                      exprtk_debug(("(c0 / v) * c1 --> (cov) (c0 * c1) / v\n"));
31487 
31488                      return expr_gen.node_allocator_->
31489                                template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v);
31490                   }
31491                   // (c0 / v) / c1 --> (cov) (c0 / c1) / v
31492                   else if ((details::e_div == o0) && (details::e_div == o1))
31493                   {
31494                      exprtk_debug(("(c0 / v) / c1 --> (cov) (c0 / c1) / v\n"));
31495 
31496                      return expr_gen.node_allocator_->
31497                                template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v);
31498                   }
31499                }
31500 
31501                const bool synthesis_result =
31502                   synthesize_sf3ext_expression::template compile<ctype, vtype, ctype>
31503                      (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result);
31504 
31505                if (synthesis_result)
31506                   return result;
31507                else if (!expr_gen.valid_operator(o0,f0))
31508                   return error_node();
31509                else if (!expr_gen.valid_operator(o1,f1))
31510                   return error_node();
31511                else
31512                   return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1);
31513             }
31514 
idexprtk::parser::expression_generator::synthesize_covoc_expression031515             static inline std::string id(expression_generator<Type>& expr_gen,
31516                                          const details::operator_type o0, const details::operator_type o1)
31517             {
31518                return details::build_string()
31519                          << "(t" << expr_gen.to_str(o0)
31520                          << "t)" << expr_gen.to_str(o1)
31521                          << "t";
31522             }
31523          };
31524 
31525          struct synthesize_covoc_expression1
31526          {
31527             typedef typename covoc_t::type1 node_type;
31528             typedef typename covoc_t::sf3_type sf3_type;
31529 
processexprtk::parser::expression_generator::synthesize_covoc_expression131530             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
31531                                                       const details::operator_type& operation,
31532                                                       expression_node_ptr (&branch)[2])
31533             {
31534                // (c0) o0 (v o1 c1)
31535                const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);
31536                const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
31537                const Type&  v = voc->v();
31538                const Type  c1 = voc->c();
31539                const details::operator_type o0 = operation;
31540                const details::operator_type o1 = voc->operation();
31541 
31542                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31543                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31544 
31545                details::free_node(*(expr_gen.node_allocator_),branch[0]);
31546                details::free_node(*(expr_gen.node_allocator_),branch[1]);
31547 
31548                expression_node_ptr result = error_node();
31549 
31550                if (expr_gen.parser_->settings_.strength_reduction_enabled())
31551                {
31552                   // (c0) + (v + c1) --> (cov) (c0 + c1) + v
31553                   if ((details::e_add == o0) && (details::e_add == o1))
31554                   {
31555                      exprtk_debug(("(c0) + (v + c1) --> (cov) (c0 + c1) + v\n"));
31556 
31557                      return expr_gen.node_allocator_->
31558                                template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v);
31559                   }
31560                   // (c0) + (v - c1) --> (cov) (c0 - c1) + v
31561                   else if ((details::e_add == o0) && (details::e_sub == o1))
31562                   {
31563                      exprtk_debug(("(c0) + (v - c1) --> (cov) (c0 - c1) + v\n"));
31564 
31565                      return expr_gen.node_allocator_->
31566                                template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v);
31567                   }
31568                   // (c0) - (v + c1) --> (cov) (c0 - c1) - v
31569                   else if ((details::e_sub == o0) && (details::e_add == o1))
31570                   {
31571                      exprtk_debug(("(c0) - (v + c1) --> (cov) (c0 - c1) - v\n"));
31572 
31573                      return expr_gen.node_allocator_->
31574                                template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v);
31575                   }
31576                   // (c0) - (v - c1) --> (cov) (c0 + c1) - v
31577                   else if ((details::e_sub == o0) && (details::e_sub == o1))
31578                   {
31579                      exprtk_debug(("(c0) - (v - c1) --> (cov) (c0 + c1) - v\n"));
31580 
31581                      return expr_gen.node_allocator_->
31582                                template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v);
31583                   }
31584                   // (c0) * (v * c1) --> (voc) v * (c0 * c1)
31585                   else if ((details::e_mul == o0) && (details::e_mul == o1))
31586                   {
31587                      exprtk_debug(("(c0) * (v * c1) --> (voc) v * (c0 * c1)\n"));
31588 
31589                      return expr_gen.node_allocator_->
31590                                template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v);
31591                   }
31592                   // (c0) * (v / c1) --> (cov) (c0 / c1) * v
31593                   else if ((details::e_mul == o0) && (details::e_div == o1))
31594                   {
31595                      exprtk_debug(("(c0) * (v / c1) --> (cov) (c0 / c1) * v\n"));
31596 
31597                      return expr_gen.node_allocator_->
31598                                template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v);
31599                   }
31600                   // (c0) / (v * c1) --> (cov) (c0 / c1) / v
31601                   else if ((details::e_div == o0) && (details::e_mul == o1))
31602                   {
31603                      exprtk_debug(("(c0) / (v * c1) --> (cov) (c0 / c1) / v\n"));
31604 
31605                      return expr_gen.node_allocator_->
31606                                template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v);
31607                   }
31608                   // (c0) / (v / c1) --> (cov) (c0 * c1) / v
31609                   else if ((details::e_div == o0) && (details::e_div == o1))
31610                   {
31611                      exprtk_debug(("(c0) / (v / c1) --> (cov) (c0 * c1) / v\n"));
31612 
31613                      return expr_gen.node_allocator_->
31614                                template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v);
31615                   }
31616                }
31617 
31618                const bool synthesis_result =
31619                   synthesize_sf3ext_expression::template compile<ctype, vtype, ctype>
31620                      (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result);
31621 
31622                if (synthesis_result)
31623                   return result;
31624                else if (!expr_gen.valid_operator(o0,f0))
31625                   return error_node();
31626                else if (!expr_gen.valid_operator(o1,f1))
31627                   return error_node();
31628                else
31629                   return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1);
31630             }
31631 
idexprtk::parser::expression_generator::synthesize_covoc_expression131632             static inline std::string id(expression_generator<Type>& expr_gen,
31633                                          const details::operator_type o0, const details::operator_type o1)
31634             {
31635                return details::build_string()
31636                          << "t"  << expr_gen.to_str(o0)
31637                          << "(t" << expr_gen.to_str(o1)
31638                          << "t)";
31639             }
31640          };
31641 
31642          struct synthesize_cocov_expression0
31643          {
31644             typedef typename cocov_t::type0 node_type;
processexprtk::parser::expression_generator::synthesize_cocov_expression031645             static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
31646             {
31647                // (c0 o0 c1) o1 (v) - Not possible.
31648                return error_node();
31649             }
31650          };
31651 
31652          struct synthesize_cocov_expression1
31653          {
31654             typedef typename cocov_t::type1 node_type;
31655             typedef typename cocov_t::sf3_type sf3_type;
31656 
processexprtk::parser::expression_generator::synthesize_cocov_expression131657             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
31658                                                       const details::operator_type& operation,
31659                                                       expression_node_ptr (&branch)[2])
31660             {
31661                // (c0) o0 (c1 o1 v)
31662                const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
31663                const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
31664                const Type  c1 = cov->c();
31665                const Type&  v = cov->v();
31666                const details::operator_type o0 = operation;
31667                const details::operator_type o1 = cov->operation();
31668 
31669                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31670                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31671 
31672                details::free_node(*(expr_gen.node_allocator_),branch[0]);
31673                details::free_node(*(expr_gen.node_allocator_),branch[1]);
31674 
31675                expression_node_ptr result = error_node();
31676 
31677                if (expr_gen.parser_->settings_.strength_reduction_enabled())
31678                {
31679                   // (c0) + (c1 + v) --> (cov) (c0 + c1) + v
31680                   if ((details::e_add == o0) && (details::e_add == o1))
31681                   {
31682                      exprtk_debug(("(c0) + (c1 + v) --> (cov) (c0 + c1) + v\n"));
31683 
31684                      return expr_gen.node_allocator_->
31685                                template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v);
31686                   }
31687                   // (c0) + (c1 - v) --> (cov) (c0 + c1) - v
31688                   else if ((details::e_add == o0) && (details::e_sub == o1))
31689                   {
31690                      exprtk_debug(("(c0) + (c1 - v) --> (cov) (c0 + c1) - v\n"));
31691 
31692                      return expr_gen.node_allocator_->
31693                                template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v);
31694                   }
31695                   // (c0) - (c1 + v) --> (cov) (c0 - c1) - v
31696                   else if ((details::e_sub == o0) && (details::e_add == o1))
31697                   {
31698                      exprtk_debug(("(c0) - (c1 + v) --> (cov) (c0 - c1) - v\n"));
31699 
31700                      return expr_gen.node_allocator_->
31701                                template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v);
31702                   }
31703                   // (c0) - (c1 - v) --> (cov) (c0 - c1) + v
31704                   else if ((details::e_sub == o0) && (details::e_sub == o1))
31705                   {
31706                      exprtk_debug(("(c0) - (c1 - v) --> (cov) (c0 - c1) + v\n"));
31707 
31708                      return expr_gen.node_allocator_->
31709                                template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v);
31710                   }
31711                   // (c0) * (c1 * v) --> (cov) (c0 * c1) * v
31712                   else if ((details::e_mul == o0) && (details::e_mul == o1))
31713                   {
31714                      exprtk_debug(("(c0) * (c1 * v) --> (cov) (c0 * c1) * v\n"));
31715 
31716                      return expr_gen.node_allocator_->
31717                                template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v);
31718                   }
31719                   // (c0) * (c1 / v) --> (cov) (c0 * c1) / v
31720                   else if ((details::e_mul == o0) && (details::e_div == o1))
31721                   {
31722                      exprtk_debug(("(c0) * (c1 / v) --> (cov) (c0 * c1) / v\n"));
31723 
31724                      return expr_gen.node_allocator_->
31725                                template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v);
31726                   }
31727                   // (c0) / (c1 * v) --> (cov) (c0 / c1) / v
31728                   else if ((details::e_div == o0) && (details::e_mul == o1))
31729                   {
31730                      exprtk_debug(("(c0) / (c1 * v) --> (cov) (c0 / c1) / v\n"));
31731 
31732                      return expr_gen.node_allocator_->
31733                                template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v);
31734                   }
31735                   // (c0) / (c1 / v) --> (cov) (c0 / c1) * v
31736                   else if ((details::e_div == o0) && (details::e_div == o1))
31737                   {
31738                      exprtk_debug(("(c0) / (c1 / v) --> (cov) (c0 / c1) * v\n"));
31739 
31740                      return expr_gen.node_allocator_->
31741                                template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v);
31742                   }
31743                }
31744 
31745                const bool synthesis_result =
31746                   synthesize_sf3ext_expression::template compile<ctype, ctype, vtype>
31747                      (expr_gen, id(expr_gen, o0, o1), c0, c1, v, result);
31748 
31749                if (synthesis_result)
31750                   return result;
31751                else if (!expr_gen.valid_operator(o0,f0))
31752                   return error_node();
31753                else if (!expr_gen.valid_operator(o1,f1))
31754                   return error_node();
31755                else
31756                   return node_type::allocate(*(expr_gen.node_allocator_), c0, c1, v, f0, f1);
31757             }
31758 
idexprtk::parser::expression_generator::synthesize_cocov_expression131759             static inline std::string id(expression_generator<Type>& expr_gen, const details::operator_type o0, const details::operator_type o1)
31760             {
31761                return details::build_string()
31762                          << "t"  << expr_gen.to_str(o0)
31763                          << "(t" << expr_gen.to_str(o1)
31764                          << "t)";
31765             }
31766          };
31767 
31768          struct synthesize_vococ_expression0
31769          {
31770             typedef typename vococ_t::type0 node_type;
31771             typedef typename vococ_t::sf3_type sf3_type;
31772 
processexprtk::parser::expression_generator::synthesize_vococ_expression031773             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
31774                                                       const details::operator_type& operation,
31775                                                       expression_node_ptr (&branch)[2])
31776             {
31777                // (v o0 c0) o1 (c1)
31778                const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
31779                const Type&  v = voc->v();
31780                const Type& c0 = voc->c();
31781                const Type& c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
31782                const details::operator_type o0 = voc->operation();
31783                const details::operator_type o1 = operation;
31784 
31785                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31786                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31787 
31788                details::free_node(*(expr_gen.node_allocator_),branch[0]);
31789                details::free_node(*(expr_gen.node_allocator_),branch[1]);
31790 
31791                expression_node_ptr result = error_node();
31792 
31793                if (expr_gen.parser_->settings_.strength_reduction_enabled())
31794                {
31795                   // (v + c0) + c1 --> (voc) v + (c0 + c1)
31796                   if ((details::e_add == o0) && (details::e_add == o1))
31797                   {
31798                      exprtk_debug(("(v + c0) + c1 --> (voc) v + (c0 + c1)\n"));
31799 
31800                      return expr_gen.node_allocator_->
31801                                template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c0 + c1);
31802                   }
31803                   // (v + c0) - c1 --> (voc) v + (c0 - c1)
31804                   else if ((details::e_add == o0) && (details::e_sub == o1))
31805                   {
31806                      exprtk_debug(("(v + c0) - c1 --> (voc) v + (c0 - c1)\n"));
31807 
31808                      return expr_gen.node_allocator_->
31809                                template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c0 - c1);
31810                   }
31811                   // (v - c0) + c1 --> (voc) v - (c0 + c1)
31812                   else if ((details::e_sub == o0) && (details::e_add == o1))
31813                   {
31814                      exprtk_debug(("(v - c0) + c1 --> (voc) v - (c0 + c1)\n"));
31815 
31816                      return expr_gen.node_allocator_->
31817                                template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c1 - c0);
31818                   }
31819                   // (v - c0) - c1 --> (voc) v - (c0 + c1)
31820                   else if ((details::e_sub == o0) && (details::e_sub == o1))
31821                   {
31822                      exprtk_debug(("(v - c0) - c1 --> (voc) v - (c0 + c1)\n"));
31823 
31824                      return expr_gen.node_allocator_->
31825                                template allocate_rc<typename details::voc_node<Type,details::sub_op<Type> > >(v, c0 + c1);
31826                   }
31827                   // (v * c0) * c1 --> (voc) v * (c0 * c1)
31828                   else if ((details::e_mul == o0) && (details::e_mul == o1))
31829                   {
31830                      exprtk_debug(("(v * c0) * c1 --> (voc) v * (c0 * c1)\n"));
31831 
31832                      return expr_gen.node_allocator_->
31833                                template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c0 * c1);
31834                   }
31835                   // (v * c0) / c1 --> (voc) v * (c0 / c1)
31836                   else if ((details::e_mul == o0) && (details::e_div == o1))
31837                   {
31838                      exprtk_debug(("(v * c0) / c1 --> (voc) v * (c0 / c1)\n"));
31839 
31840                      return expr_gen.node_allocator_->
31841                                template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c0 / c1);
31842                   }
31843                   // (v / c0) * c1 --> (voc) v * (c1 / c0)
31844                   else if ((details::e_div == o0) && (details::e_mul == o1))
31845                   {
31846                      exprtk_debug(("(v / c0) * c1 --> (voc) v * (c1 / c0)\n"));
31847 
31848                      return expr_gen.node_allocator_->
31849                                template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c1 / c0);
31850                   }
31851                   // (v / c0) / c1 --> (voc) v / (c0 * c1)
31852                   else if ((details::e_div == o0) && (details::e_div == o1))
31853                   {
31854                      exprtk_debug(("(v / c0) / c1 --> (voc) v / (c0 * c1)\n"));
31855 
31856                      return expr_gen.node_allocator_->
31857                                template allocate_rc<typename details::voc_node<Type,details::div_op<Type> > >(v, c0 * c1);
31858                   }
31859                   // (v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1)
31860                   else if ((details::e_pow == o0) && (details::e_pow == o1))
31861                   {
31862                      exprtk_debug(("(v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1)\n"));
31863 
31864                      return expr_gen.node_allocator_->
31865                                template allocate_rc<typename details::voc_node<Type,details::pow_op<Type> > >(v, c0 * c1);
31866                   }
31867                }
31868 
31869                const bool synthesis_result =
31870                   synthesize_sf3ext_expression::template compile<vtype, ctype, ctype>
31871                      (expr_gen, id(expr_gen, o0, o1), v, c0, c1, result);
31872 
31873                if (synthesis_result)
31874                   return result;
31875                else if (!expr_gen.valid_operator(o0,f0))
31876                   return error_node();
31877                else if (!expr_gen.valid_operator(o1,f1))
31878                   return error_node();
31879                else
31880                   return node_type::allocate(*(expr_gen.node_allocator_), v, c0, c1, f0, f1);
31881             }
31882 
idexprtk::parser::expression_generator::synthesize_vococ_expression031883             static inline std::string id(expression_generator<Type>& expr_gen,
31884                                          const details::operator_type o0, const details::operator_type o1)
31885             {
31886                return details::build_string()
31887                          << "(t" << expr_gen.to_str(o0)
31888                          << "t)" << expr_gen.to_str(o1)
31889                          << "t";
31890             }
31891          };
31892 
31893          struct synthesize_vococ_expression1
31894          {
31895             typedef typename vococ_t::type0 node_type;
31896 
processexprtk::parser::expression_generator::synthesize_vococ_expression131897             static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
31898             {
31899                // (v) o0 (c0 o1 c1) - Not possible.
31900                exprtk_debug(("(v) o0 (c0 o1 c1) - Not possible.\n"));
31901                return error_node();
31902             }
31903          };
31904 
31905          struct synthesize_vovovov_expression0
31906          {
31907             typedef typename vovovov_t::type0 node_type;
31908             typedef typename vovovov_t::sf4_type sf4_type;
31909             typedef typename node_type::T0 T0;
31910             typedef typename node_type::T1 T1;
31911             typedef typename node_type::T2 T2;
31912             typedef typename node_type::T3 T3;
31913 
processexprtk::parser::expression_generator::synthesize_vovovov_expression031914             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
31915                                                       const details::operator_type& operation,
31916                                                       expression_node_ptr (&branch)[2])
31917             {
31918                // (v0 o0 v1) o1 (v2 o2 v3)
31919                const details::vov_base_node<Type>* vov0 = static_cast<details::vov_base_node<Type>*>(branch[0]);
31920                const details::vov_base_node<Type>* vov1 = static_cast<details::vov_base_node<Type>*>(branch[1]);
31921                const Type& v0 = vov0->v0();
31922                const Type& v1 = vov0->v1();
31923                const Type& v2 = vov1->v0();
31924                const Type& v3 = vov1->v1();
31925                const details::operator_type o0 = vov0->operation();
31926                const details::operator_type o1 = operation;
31927                const details::operator_type o2 = vov1->operation();
31928 
31929                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31930                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31931                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
31932 
31933                details::free_node(*(expr_gen.node_allocator_),branch[0]);
31934                details::free_node(*(expr_gen.node_allocator_),branch[1]);
31935 
31936                expression_node_ptr result = error_node();
31937 
31938                if (expr_gen.parser_->settings_.strength_reduction_enabled())
31939                {
31940                   // (v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)
31941                   if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
31942                   {
31943                      const bool synthesis_result =
31944                         synthesize_sf4ext_expression::
31945                            template compile<vtype,vtype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, v3, result);
31946 
31947                      exprtk_debug(("(v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)\n"));
31948 
31949                      return (synthesis_result) ? result : error_node();
31950                   }
31951                   // (v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)
31952                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
31953                   {
31954                      const bool synthesis_result =
31955                         synthesize_sf4ext_expression::
31956                            template compile<vtype,vtype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", v0, v3, v1, v2, result);
31957 
31958                      exprtk_debug(("(v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)\n"));
31959 
31960                      return (synthesis_result) ? result : error_node();
31961                   }
31962                   // (v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)
31963                   else if ((details::e_add == o0) && (details::e_div == o1) && (details::e_div == o2))
31964                   {
31965                      const bool synthesis_result =
31966                         synthesize_sf4ext_expression::
31967                            template compile<vtype,vtype,vtype,vtype>(expr_gen, "(t+t)*(t/t)", v0, v1, v3, v2, result);
31968 
31969                      exprtk_debug(("(v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)\n"));
31970 
31971                      return (synthesis_result) ? result : error_node();
31972                   }
31973                   // (v0 - v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)
31974                   else if ((details::e_sub == o0) && (details::e_div == o1) && (details::e_div == o2))
31975                   {
31976                      const bool synthesis_result =
31977                         synthesize_sf4ext_expression::
31978                            template compile<vtype,vtype,vtype,vtype>(expr_gen, "(t-t)*(t/t)", v0, v1, v3, v2, result);
31979 
31980                      exprtk_debug(("(v0 - v1) / (v2 / v3) --> (vovovov) (v0 - v1) * (v3 / v2)\n"));
31981 
31982                      return (synthesis_result) ? result : error_node();
31983                   }
31984                   // (v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2
31985                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
31986                   {
31987                      const bool synthesis_result =
31988                         synthesize_sf4ext_expression::
31989                            template compile<vtype,vtype,vtype,vtype>(expr_gen, "((t*t)*t)/t", v0, v1, v3, v2, result);
31990 
31991                      exprtk_debug(("(v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2\n"));
31992 
31993                      return (synthesis_result) ? result : error_node();
31994                   }
31995                }
31996 
31997                const bool synthesis_result =
31998                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
31999                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
32000 
32001                if (synthesis_result)
32002                   return result;
32003                else if (!expr_gen.valid_operator(o0,f0))
32004                   return error_node();
32005                else if (!expr_gen.valid_operator(o1,f1))
32006                   return error_node();
32007                else if (!expr_gen.valid_operator(o2,f2))
32008                   return error_node();
32009                else
32010                   return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
32011             }
32012 
idexprtk::parser::expression_generator::synthesize_vovovov_expression032013             static inline std::string id(expression_generator<Type>& expr_gen,
32014                                          const details::operator_type o0,
32015                                          const details::operator_type o1,
32016                                          const details::operator_type o2)
32017             {
32018                return details::build_string()
32019                          << "(t" << expr_gen.to_str(o0)
32020                          << "t)" << expr_gen.to_str(o1)
32021                          << "(t" << expr_gen.to_str(o2)
32022                          << "t)";
32023             }
32024          };
32025 
32026          struct synthesize_vovovoc_expression0
32027          {
32028             typedef typename vovovoc_t::type0 node_type;
32029             typedef typename vovovoc_t::sf4_type sf4_type;
32030             typedef typename node_type::T0 T0;
32031             typedef typename node_type::T1 T1;
32032             typedef typename node_type::T2 T2;
32033             typedef typename node_type::T3 T3;
32034 
processexprtk::parser::expression_generator::synthesize_vovovoc_expression032035             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32036                                                       const details::operator_type& operation,
32037                                                       expression_node_ptr (&branch)[2])
32038             {
32039                // (v0 o0 v1) o1 (v2 o2 c)
32040                const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
32041                const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);
32042                const Type& v0 = vov->v0();
32043                const Type& v1 = vov->v1();
32044                const Type& v2 = voc->v ();
32045                const Type   c = voc->c ();
32046                const details::operator_type o0 = vov->operation();
32047                const details::operator_type o1 = operation;
32048                const details::operator_type o2 = voc->operation();
32049 
32050                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32051                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
32052                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
32053 
32054                details::free_node(*(expr_gen.node_allocator_),branch[0]);
32055                details::free_node(*(expr_gen.node_allocator_),branch[1]);
32056 
32057                expression_node_ptr result = error_node();
32058 
32059                if (expr_gen.parser_->settings_.strength_reduction_enabled())
32060                {
32061                   // (v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c)
32062                   if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
32063                   {
32064                      const bool synthesis_result =
32065                         synthesize_sf4ext_expression::
32066                            template compile<vtype,vtype,vtype,ctype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result);
32067 
32068                      exprtk_debug(("(v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c)\n"));
32069 
32070                      return (synthesis_result) ? result : error_node();
32071                   }
32072                   // (v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2)
32073                   if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
32074                   {
32075                      const bool synthesis_result =
32076                         synthesize_sf4ext_expression::
32077                            template compile<vtype,ctype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result);
32078 
32079                      exprtk_debug(("(v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2)\n"));
32080 
32081                      return (synthesis_result) ? result : error_node();
32082                   }
32083                }
32084 
32085                const bool synthesis_result =
32086                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32087                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
32088 
32089                if (synthesis_result)
32090                   return result;
32091                else if (!expr_gen.valid_operator(o0,f0))
32092                   return error_node();
32093                else if (!expr_gen.valid_operator(o1,f1))
32094                   return error_node();
32095                else if (!expr_gen.valid_operator(o2,f2))
32096                   return error_node();
32097                else
32098                   return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
32099             }
32100 
idexprtk::parser::expression_generator::synthesize_vovovoc_expression032101             static inline std::string id(expression_generator<Type>& expr_gen,
32102                                          const details::operator_type o0,
32103                                          const details::operator_type o1,
32104                                          const details::operator_type o2)
32105             {
32106                return details::build_string()
32107                          << "(t" << expr_gen.to_str(o0)
32108                          << "t)" << expr_gen.to_str(o1)
32109                          << "(t" << expr_gen.to_str(o2)
32110                          << "t)";
32111             }
32112          };
32113 
32114          struct synthesize_vovocov_expression0
32115          {
32116             typedef typename vovocov_t::type0 node_type;
32117             typedef typename vovocov_t::sf4_type sf4_type;
32118             typedef typename node_type::T0 T0;
32119             typedef typename node_type::T1 T1;
32120             typedef typename node_type::T2 T2;
32121             typedef typename node_type::T3 T3;
32122 
processexprtk::parser::expression_generator::synthesize_vovocov_expression032123             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32124                                                       const details::operator_type& operation,
32125                                                       expression_node_ptr (&branch)[2])
32126             {
32127                // (v0 o0 v1) o1 (c o2 v2)
32128                const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
32129                const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
32130                const Type& v0 = vov->v0();
32131                const Type& v1 = vov->v1();
32132                const Type& v2 = cov->v ();
32133                const Type   c = cov->c ();
32134                const details::operator_type o0 = vov->operation();
32135                const details::operator_type o1 = operation;
32136                const details::operator_type o2 = cov->operation();
32137 
32138                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32139                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
32140                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
32141 
32142                details::free_node(*(expr_gen.node_allocator_),branch[0]);
32143                details::free_node(*(expr_gen.node_allocator_),branch[1]);
32144 
32145                expression_node_ptr result = error_node();
32146 
32147                if (expr_gen.parser_->settings_.strength_reduction_enabled())
32148                {
32149                   // (v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2)
32150                   if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
32151                   {
32152                      const bool synthesis_result =
32153                         synthesize_sf4ext_expression::
32154                            template compile<vtype,ctype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result);
32155 
32156                      exprtk_debug(("(v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2)\n"));
32157 
32158                      return (synthesis_result) ? result : error_node();
32159                   }
32160                   // (v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c)
32161                   if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
32162                   {
32163                      const bool synthesis_result =
32164                         synthesize_sf4ext_expression::
32165                            template compile<vtype,vtype,vtype,ctype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result);
32166 
32167                      exprtk_debug(("(v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c)\n"));
32168 
32169                      return (synthesis_result) ? result : error_node();
32170                   }
32171                }
32172 
32173                const bool synthesis_result =
32174                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32175                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
32176 
32177                if (synthesis_result)
32178                   return result;
32179                else if (!expr_gen.valid_operator(o0,f0))
32180                   return error_node();
32181                else if (!expr_gen.valid_operator(o1,f1))
32182                   return error_node();
32183                else if (!expr_gen.valid_operator(o2,f2))
32184                   return error_node();
32185                else
32186                   return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
32187             }
32188 
idexprtk::parser::expression_generator::synthesize_vovocov_expression032189             static inline std::string id(expression_generator<Type>& expr_gen,
32190                                          const details::operator_type o0,
32191                                          const details::operator_type o1,
32192                                          const details::operator_type o2)
32193             {
32194                return details::build_string()
32195                          << "(t" << expr_gen.to_str(o0)
32196                          << "t)" << expr_gen.to_str(o1)
32197                          << "(t" << expr_gen.to_str(o2)
32198                          << "t)";
32199             }
32200          };
32201 
32202          struct synthesize_vocovov_expression0
32203          {
32204             typedef typename vocovov_t::type0 node_type;
32205             typedef typename vocovov_t::sf4_type sf4_type;
32206             typedef typename node_type::T0 T0;
32207             typedef typename node_type::T1 T1;
32208             typedef typename node_type::T2 T2;
32209             typedef typename node_type::T3 T3;
32210 
processexprtk::parser::expression_generator::synthesize_vocovov_expression032211             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32212                                                       const details::operator_type& operation,
32213                                                       expression_node_ptr (&branch)[2])
32214             {
32215                // (v0 o0 c) o1 (v1 o2 v2)
32216                const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
32217                const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
32218                const Type   c = voc->c ();
32219                const Type& v0 = voc->v ();
32220                const Type& v1 = vov->v0();
32221                const Type& v2 = vov->v1();
32222                const details::operator_type o0 = voc->operation();
32223                const details::operator_type o1 = operation;
32224                const details::operator_type o2 = vov->operation();
32225 
32226                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32227                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
32228                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
32229 
32230                details::free_node(*(expr_gen.node_allocator_),branch[0]);
32231                details::free_node(*(expr_gen.node_allocator_),branch[1]);
32232 
32233                expression_node_ptr result = error_node();
32234 
32235                if (expr_gen.parser_->settings_.strength_reduction_enabled())
32236                {
32237                   // (v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2)
32238                   if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
32239                   {
32240                      const bool synthesis_result =
32241                         synthesize_sf4ext_expression::
32242                            template compile<vtype,vtype,ctype,vtype>(expr_gen, "(t*t)/(t*t)", v0, v1, c, v2, result);
32243 
32244                      exprtk_debug(("(v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2)\n"));
32245 
32246                      return (synthesis_result) ? result : error_node();
32247                   }
32248                   // (v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1)
32249                   if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
32250                   {
32251                      const bool synthesis_result =
32252                         synthesize_sf4ext_expression::
32253                            template compile<vtype,vtype,ctype,vtype>(expr_gen, "(t*t)/(t*t)", v0, v2, c, v1, result);
32254 
32255                      exprtk_debug(("(v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1)\n"));
32256 
32257                      return (synthesis_result) ? result : error_node();
32258                   }
32259                }
32260 
32261                const bool synthesis_result =
32262                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32263                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
32264 
32265                if (synthesis_result)
32266                   return result;
32267                else if (!expr_gen.valid_operator(o0,f0))
32268                   return error_node();
32269                else if (!expr_gen.valid_operator(o1,f1))
32270                   return error_node();
32271                else if (!expr_gen.valid_operator(o2,f2))
32272                   return error_node();
32273                else
32274                   return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
32275             }
32276 
idexprtk::parser::expression_generator::synthesize_vocovov_expression032277             static inline std::string id(expression_generator<Type>& expr_gen,
32278                                          const details::operator_type o0,
32279                                          const details::operator_type o1,
32280                                          const details::operator_type o2)
32281             {
32282                return details::build_string()
32283                          << "(t" << expr_gen.to_str(o0)
32284                          << "t)" << expr_gen.to_str(o1)
32285                          << "(t" << expr_gen.to_str(o2)
32286                          << "t)";
32287             }
32288          };
32289 
32290          struct synthesize_covovov_expression0
32291          {
32292             typedef typename covovov_t::type0 node_type;
32293             typedef typename covovov_t::sf4_type sf4_type;
32294             typedef typename node_type::T0 T0;
32295             typedef typename node_type::T1 T1;
32296             typedef typename node_type::T2 T2;
32297             typedef typename node_type::T3 T3;
32298 
processexprtk::parser::expression_generator::synthesize_covovov_expression032299             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32300                                                       const details::operator_type& operation,
32301                                                       expression_node_ptr (&branch)[2])
32302             {
32303                // (c o0 v0) o1 (v1 o2 v2)
32304                const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
32305                const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
32306                const Type   c = cov->c ();
32307                const Type& v0 = cov->v ();
32308                const Type& v1 = vov->v0();
32309                const Type& v2 = vov->v1();
32310                const details::operator_type o0 = cov->operation();
32311                const details::operator_type o1 = operation;
32312                const details::operator_type o2 = vov->operation();
32313 
32314                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32315                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
32316                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
32317 
32318                details::free_node(*(expr_gen.node_allocator_),branch[0]);
32319                details::free_node(*(expr_gen.node_allocator_),branch[1]);
32320 
32321                expression_node_ptr result = error_node();
32322 
32323                if (expr_gen.parser_->settings_.strength_reduction_enabled())
32324                {
32325                   // (c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2)
32326                   if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
32327                   {
32328                      const bool synthesis_result =
32329                         synthesize_sf4ext_expression::
32330                            template compile<ctype,vtype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", c, v1, v0, v2, result);
32331 
32332                      exprtk_debug(("(c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2)\n"));
32333 
32334                      return (synthesis_result) ? result : error_node();
32335                   }
32336                   // (c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1)
32337                   if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
32338                   {
32339                      const bool synthesis_result =
32340                         synthesize_sf4ext_expression::
32341                            template compile<ctype,vtype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", c, v2, v0, v1, result);
32342 
32343                      exprtk_debug(("(c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1)\n"));
32344 
32345                      return (synthesis_result) ? result : error_node();
32346                   }
32347                }
32348 
32349                const bool synthesis_result =
32350                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32351                      (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
32352 
32353                if (synthesis_result)
32354                   return result;
32355                else if (!expr_gen.valid_operator(o0,f0))
32356                   return error_node();
32357                else if (!expr_gen.valid_operator(o1,f1))
32358                   return error_node();
32359                else if (!expr_gen.valid_operator(o2,f2))
32360                   return error_node();
32361                else
32362                   return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
32363             }
32364 
idexprtk::parser::expression_generator::synthesize_covovov_expression032365             static inline std::string id(expression_generator<Type>& expr_gen,
32366                                          const details::operator_type o0,
32367                                          const details::operator_type o1,
32368                                          const details::operator_type o2)
32369             {
32370                return details::build_string()
32371                          << "(t" << expr_gen.to_str(o0)
32372                          << "t)" << expr_gen.to_str(o1)
32373                          << "(t" << expr_gen.to_str(o2)
32374                          << "t)";
32375             }
32376          };
32377 
32378          struct synthesize_covocov_expression0
32379          {
32380             typedef typename covocov_t::type0 node_type;
32381             typedef typename covocov_t::sf4_type sf4_type;
32382             typedef typename node_type::T0 T0;
32383             typedef typename node_type::T1 T1;
32384             typedef typename node_type::T2 T2;
32385             typedef typename node_type::T3 T3;
32386 
processexprtk::parser::expression_generator::synthesize_covocov_expression032387             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32388                                                       const details::operator_type& operation,
32389                                                       expression_node_ptr (&branch)[2])
32390             {
32391                // (c0 o0 v0) o1 (c1 o2 v1)
32392                const details::cov_base_node<Type>* cov0 = static_cast<details::cov_base_node<Type>*>(branch[0]);
32393                const details::cov_base_node<Type>* cov1 = static_cast<details::cov_base_node<Type>*>(branch[1]);
32394                const Type  c0 = cov0->c();
32395                const Type& v0 = cov0->v();
32396                const Type  c1 = cov1->c();
32397                const Type& v1 = cov1->v();
32398                const details::operator_type o0 = cov0->operation();
32399                const details::operator_type o1 = operation;
32400                const details::operator_type o2 = cov1->operation();
32401 
32402                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32403                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
32404                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
32405 
32406                details::free_node(*(expr_gen.node_allocator_),branch[0]);
32407                details::free_node(*(expr_gen.node_allocator_),branch[1]);
32408 
32409                expression_node_ptr result = error_node();
32410 
32411                if (expr_gen.parser_->settings_.strength_reduction_enabled())
32412                {
32413                   // (c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1
32414                   if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
32415                   {
32416                      const bool synthesis_result =
32417                         synthesize_sf3ext_expression::
32418                            template compile<ctype,vtype,vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
32419 
32420                      exprtk_debug(("(c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n"));
32421 
32422                      return (synthesis_result) ? result : error_node();
32423                   }
32424                   // (c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1
32425                   else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
32426                   {
32427                      const bool synthesis_result =
32428                         synthesize_sf3ext_expression::
32429                            template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
32430 
32431                      exprtk_debug(("(c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n"));
32432 
32433                      return (synthesis_result) ? result : error_node();
32434                   }
32435                   // (c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1
32436                   else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
32437                   {
32438                      const bool synthesis_result =
32439                         synthesize_sf3ext_expression::
32440                            template compile<ctype,vtype,vtype>(expr_gen, "(t-t)+t", (c0 - c1), v0, v1, result);
32441 
32442                      exprtk_debug(("(c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1\n"));
32443 
32444                      return (synthesis_result) ? result : error_node();
32445                   }
32446                   // (c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1
32447                   else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
32448                   {
32449                      const bool synthesis_result =
32450                         synthesize_sf3ext_expression::
32451                            template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
32452 
32453                      exprtk_debug(("(c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n"));
32454 
32455                      return (synthesis_result) ? result : error_node();
32456                   }
32457                   // (c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)
32458                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
32459                   {
32460                      const bool synthesis_result =
32461                         synthesize_sf3ext_expression::
32462                            template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
32463 
32464                      exprtk_debug(("(c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
32465 
32466                      return (synthesis_result) ? result : error_node();
32467                   }
32468                   // (c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)
32469                   else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
32470                   {
32471                      const bool synthesis_result =
32472                         synthesize_sf3ext_expression::
32473                            template compile<ctype,vtype,vtype>(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result);
32474 
32475                      exprtk_debug(("(c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)\n"));
32476 
32477                      return (synthesis_result) ? result : error_node();
32478                   }
32479                   // (c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0
32480                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
32481                   {
32482                      const bool synthesis_result =
32483                         synthesize_sf3ext_expression::
32484                            template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v1, v0, result);
32485 
32486                      exprtk_debug(("(c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0\n"));
32487 
32488                      return (synthesis_result) ? result : error_node();
32489                   }
32490                   // (c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)
32491                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
32492                   {
32493                      const bool synthesis_result =
32494                         synthesize_sf3ext_expression::
32495                            template compile<ctype,vtype,vtype>(expr_gen, "t*(t*t)", (c0 / c1), v0, v1, result);
32496 
32497                      exprtk_debug(("(c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
32498 
32499                      return (synthesis_result) ? result : error_node();
32500                   }
32501                   // (c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)
32502                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
32503                   {
32504                      const bool synthesis_result =
32505                         synthesize_sf3ext_expression::
32506                            template compile<ctype,vtype,vtype>(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result);
32507 
32508                      exprtk_debug(("(c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)\n"));
32509 
32510                      return (synthesis_result) ? result : error_node();
32511                   }
32512                   // (c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1)
32513                   else if (
32514                             (std::equal_to<T>()(c0,c1)) &&
32515                             (details::e_mul == o0)      &&
32516                             (details::e_mul == o2)      &&
32517                             (
32518                               (details::e_add == o1) ||
32519                               (details::e_sub == o1)
32520                             )
32521                           )
32522                   {
32523                      std::string specfunc;
32524 
32525                      switch (o1)
32526                      {
32527                         case details::e_add : specfunc = "t*(t+t)"; break;
32528                         case details::e_sub : specfunc = "t*(t-t)"; break;
32529                         default             : return error_node();
32530                      }
32531 
32532                      const bool synthesis_result =
32533                         synthesize_sf3ext_expression::
32534                            template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result);
32535 
32536                      exprtk_debug(("(c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n"));
32537 
32538                      return (synthesis_result) ? result : error_node();
32539                   }
32540                }
32541 
32542                const bool synthesis_result =
32543                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32544                      (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
32545 
32546                if (synthesis_result)
32547                   return result;
32548                else if (!expr_gen.valid_operator(o0,f0))
32549                   return error_node();
32550                else if (!expr_gen.valid_operator(o1,f1))
32551                   return error_node();
32552                else if (!expr_gen.valid_operator(o2,f2))
32553                   return error_node();
32554                else
32555                   return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
32556             }
32557 
idexprtk::parser::expression_generator::synthesize_covocov_expression032558             static inline std::string id(expression_generator<Type>& expr_gen,
32559                                          const details::operator_type o0,
32560                                          const details::operator_type o1,
32561                                          const details::operator_type o2)
32562             {
32563                return details::build_string()
32564                          << "(t" << expr_gen.to_str(o0)
32565                          << "t)" << expr_gen.to_str(o1)
32566                          << "(t" << expr_gen.to_str(o2)
32567                          << "t)";
32568             }
32569          };
32570 
32571          struct synthesize_vocovoc_expression0
32572          {
32573             typedef typename vocovoc_t::type0 node_type;
32574             typedef typename vocovoc_t::sf4_type sf4_type;
32575             typedef typename node_type::T0 T0;
32576             typedef typename node_type::T1 T1;
32577             typedef typename node_type::T2 T2;
32578             typedef typename node_type::T3 T3;
32579 
processexprtk::parser::expression_generator::synthesize_vocovoc_expression032580             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32581                                                       const details::operator_type& operation,
32582                                                       expression_node_ptr (&branch)[2])
32583             {
32584                // (v0 o0 c0) o1 (v1 o2 c1)
32585                const details::voc_base_node<Type>* voc0 = static_cast<details::voc_base_node<Type>*>(branch[0]);
32586                const details::voc_base_node<Type>* voc1 = static_cast<details::voc_base_node<Type>*>(branch[1]);
32587                const Type  c0 = voc0->c();
32588                const Type& v0 = voc0->v();
32589                const Type  c1 = voc1->c();
32590                const Type& v1 = voc1->v();
32591                const details::operator_type o0 = voc0->operation();
32592                const details::operator_type o1 = operation;
32593                const details::operator_type o2 = voc1->operation();
32594 
32595                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32596                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
32597                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
32598 
32599                details::free_node(*(expr_gen.node_allocator_),branch[0]);
32600                details::free_node(*(expr_gen.node_allocator_),branch[1]);
32601 
32602                expression_node_ptr result = error_node();
32603 
32604                if (expr_gen.parser_->settings_.strength_reduction_enabled())
32605                {
32606                   // (v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1
32607                   if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
32608                   {
32609                      const bool synthesis_result =
32610                         synthesize_sf3ext_expression::
32611                            template compile<ctype,vtype,vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
32612 
32613                      exprtk_debug(("(v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n"));
32614 
32615                      return (synthesis_result) ? result : error_node();
32616                   }
32617                   // (v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1
32618                   else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
32619                   {
32620                      const bool synthesis_result =
32621                         synthesize_sf3ext_expression::
32622                            template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
32623 
32624                      exprtk_debug(("(v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n"));
32625 
32626                      return (synthesis_result) ? result : error_node();
32627                   }
32628                   // (v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1
32629                   else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
32630                   {
32631                      const bool synthesis_result =
32632                         synthesize_sf3ext_expression::
32633                            template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c1 - c0), v0, v1, result);
32634 
32635                      exprtk_debug(("(v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1\n"));
32636 
32637                      return (synthesis_result) ? result : error_node();
32638                   }
32639                   // (v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1
32640                   else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
32641                   {
32642                      const bool synthesis_result =
32643                         synthesize_sf3ext_expression::
32644                            template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
32645 
32646                      exprtk_debug(("(v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n"));
32647 
32648                      return (synthesis_result) ? result : error_node();
32649                   }
32650                   // (v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)
32651                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
32652                   {
32653                      const bool synthesis_result =
32654                         synthesize_sf3ext_expression::
32655                            template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
32656 
32657                      exprtk_debug(("(v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
32658 
32659                      return (synthesis_result) ? result : error_node();
32660                   }
32661                   // (v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1
32662                   else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
32663                   {
32664                      const bool synthesis_result =
32665                         synthesize_sf3ext_expression::
32666                            template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", Type(1) / (c0 * c1), v0, v1, result);
32667 
32668                      exprtk_debug(("(v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1\n"));
32669 
32670                      return (synthesis_result) ? result : error_node();
32671                   }
32672                   // (v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1
32673                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
32674                   {
32675                      const bool synthesis_result =
32676                         synthesize_sf3ext_expression::
32677                            template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result);
32678 
32679                      exprtk_debug(("(v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1\n"));
32680 
32681                      return (synthesis_result) ? result : error_node();
32682                   }
32683                   // (v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)
32684                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
32685                   {
32686                      const bool synthesis_result =
32687                         synthesize_sf3ext_expression::
32688                            template compile<ctype,vtype,vtype>(expr_gen, "t*(t/t)", (c0 * c1), v0, v1, result);
32689 
32690                      exprtk_debug(("(v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n"));
32691 
32692                      return (synthesis_result) ? result : error_node();
32693                   }
32694                   // (v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1
32695                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
32696                   {
32697                      const bool synthesis_result =
32698                         synthesize_sf3ext_expression::
32699                            template compile<ctype,vtype,vtype>(expr_gen, "t*(t/t)", Type(1) / (c0 * c1), v0, v1, result);
32700 
32701                      exprtk_debug(("(v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1\n"));
32702 
32703                      return (synthesis_result) ? result : error_node();
32704                   }
32705                   // (v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1)
32706                   else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_add == o2))
32707                   {
32708                      const bool synthesis_result =
32709                         synthesize_sf4ext_expression::
32710                            template compile<vtype,ctype,vtype,ctype>(expr_gen, "(t*t)*(t+t)", v0, T(1) / c0, v1, c1, result);
32711 
32712                      exprtk_debug(("(v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1)\n"));
32713 
32714                      return (synthesis_result) ? result : error_node();
32715                   }
32716                   // (v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1)
32717                   else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_sub == o2))
32718                   {
32719                      const bool synthesis_result =
32720                         synthesize_sf4ext_expression::
32721                            template compile<vtype,ctype,vtype,ctype>(expr_gen, "(t*t)*(t-t)", v0, T(1) / c0, v1, c1, result);
32722 
32723                      exprtk_debug(("(v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1)\n"));
32724 
32725                      return (synthesis_result) ? result : error_node();
32726                   }
32727                   // (v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)
32728                   else if (
32729                             (std::equal_to<T>()(c0,c1)) &&
32730                             (details::e_mul == o0)      &&
32731                             (details::e_mul == o2)      &&
32732                             (
32733                               (details::e_add == o1) ||
32734                               (details::e_sub == o1)
32735                             )
32736                           )
32737                   {
32738                      std::string specfunc;
32739 
32740                      switch (o1)
32741                      {
32742                         case details::e_add : specfunc = "t*(t+t)"; break;
32743                         case details::e_sub : specfunc = "t*(t-t)"; break;
32744                         default             : return error_node();
32745                      }
32746 
32747                      const bool synthesis_result =
32748                         synthesize_sf3ext_expression::
32749                            template compile<ctype,vtype,vtype>(expr_gen, specfunc, c0, v0, v1, result);
32750 
32751                      exprtk_debug(("(v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n"));
32752 
32753                      return (synthesis_result) ? result : error_node();
32754                   }
32755                   // (v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c
32756                   else if (
32757                             (std::equal_to<T>()(c0,c1)) &&
32758                             (details::e_div == o0)      &&
32759                             (details::e_div == o2)      &&
32760                             (
32761                               (details::e_add == o1) ||
32762                               (details::e_sub == o1)
32763                             )
32764                           )
32765                   {
32766                      std::string specfunc;
32767 
32768                      switch (o1)
32769                      {
32770                         case details::e_add : specfunc = "(t+t)/t"; break;
32771                         case details::e_sub : specfunc = "(t-t)/t"; break;
32772                         default             : return error_node();
32773                      }
32774 
32775                      const bool synthesis_result =
32776                         synthesize_sf3ext_expression::
32777                            template compile<vtype,vtype,ctype>(expr_gen, specfunc, v0, v1, c0, result);
32778 
32779                      exprtk_debug(("(v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c\n"));
32780 
32781                      return (synthesis_result) ? result : error_node();
32782                   }
32783                }
32784 
32785                const bool synthesis_result =
32786                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32787                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
32788 
32789                if (synthesis_result)
32790                   return result;
32791                else if (!expr_gen.valid_operator(o0,f0))
32792                   return error_node();
32793                else if (!expr_gen.valid_operator(o1,f1))
32794                   return error_node();
32795                else if (!expr_gen.valid_operator(o2,f2))
32796                   return error_node();
32797                else
32798                   return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
32799             }
32800 
idexprtk::parser::expression_generator::synthesize_vocovoc_expression032801             static inline std::string id(expression_generator<Type>& expr_gen,
32802                                          const details::operator_type o0,
32803                                          const details::operator_type o1,
32804                                          const details::operator_type o2)
32805             {
32806                return details::build_string()
32807                          << "(t" << expr_gen.to_str(o0)
32808                          << "t)" << expr_gen.to_str(o1)
32809                          << "(t" << expr_gen.to_str(o2)
32810                          << "t)";
32811             }
32812          };
32813 
32814          struct synthesize_covovoc_expression0
32815          {
32816             typedef typename covovoc_t::type0 node_type;
32817             typedef typename covovoc_t::sf4_type sf4_type;
32818             typedef typename node_type::T0 T0;
32819             typedef typename node_type::T1 T1;
32820             typedef typename node_type::T2 T2;
32821             typedef typename node_type::T3 T3;
32822 
processexprtk::parser::expression_generator::synthesize_covovoc_expression032823             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32824                                                       const details::operator_type& operation,
32825                                                       expression_node_ptr (&branch)[2])
32826             {
32827                // (c0 o0 v0) o1 (v1 o2 c1)
32828                const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
32829                const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);
32830                const Type  c0 = cov->c();
32831                const Type& v0 = cov->v();
32832                const Type  c1 = voc->c();
32833                const Type& v1 = voc->v();
32834                const details::operator_type o0 = cov->operation();
32835                const details::operator_type o1 = operation;
32836                const details::operator_type o2 = voc->operation();
32837 
32838                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32839                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
32840                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
32841 
32842                details::free_node(*(expr_gen.node_allocator_),branch[0]);
32843                details::free_node(*(expr_gen.node_allocator_),branch[1]);
32844 
32845                expression_node_ptr result = error_node();
32846 
32847                if (expr_gen.parser_->settings_.strength_reduction_enabled())
32848                {
32849                   // (c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1
32850                   if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
32851                   {
32852                      const bool synthesis_result =
32853                         synthesize_sf3ext_expression::
32854                            template compile<ctype,vtype,vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
32855 
32856                      exprtk_debug(("(c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n"));
32857 
32858                      return (synthesis_result) ? result : error_node();
32859                   }
32860                   // (c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1
32861                   else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
32862                   {
32863                      const bool synthesis_result =
32864                         synthesize_sf3ext_expression::
32865                            template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
32866 
32867                      exprtk_debug(("(c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n"));
32868 
32869                      return (synthesis_result) ? result : error_node();
32870                   }
32871                   // (c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1
32872                   else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
32873                   {
32874                      const bool synthesis_result =
32875                         synthesize_sf3ext_expression::
32876                            template compile<ctype,vtype,vtype>(expr_gen, "t-(t+t)", (c0 + c1), v0, v1, result);
32877 
32878                      exprtk_debug(("(c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1\n"));
32879 
32880                      return (synthesis_result) ? result : error_node();
32881                   }
32882                   // (c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1
32883                   else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
32884                   {
32885                      const bool synthesis_result =
32886                         synthesize_sf3ext_expression::
32887                            template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
32888 
32889                      exprtk_debug(("(c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n"));
32890 
32891                      return (synthesis_result) ? result : error_node();
32892                   }
32893                   // (c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)
32894                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
32895                   {
32896                      const bool synthesis_result =
32897                         synthesize_sf3ext_expression::
32898                            template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
32899 
32900                      exprtk_debug(("(c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
32901 
32902                      return (synthesis_result) ? result : error_node();
32903                   }
32904                   // (c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)
32905                   else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
32906                   {
32907                      const bool synthesis_result =
32908                         synthesize_sf3ext_expression::
32909                            template compile<ctype,vtype,vtype>(expr_gen, "t*(t/t)", (c0 / c1), v1, v0, result);
32910 
32911                      exprtk_debug(("(c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)\n"));
32912 
32913                      return (synthesis_result) ? result : error_node();
32914                   }
32915                   // (c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1)
32916                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
32917                   {
32918                      const bool synthesis_result =
32919                         synthesize_sf3ext_expression::
32920                            template compile<ctype,vtype,vtype>(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result);
32921 
32922                      exprtk_debug(("(c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1)\n"));
32923 
32924                      return (synthesis_result) ? result : error_node();
32925                   }
32926                   // (c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)
32927                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
32928                   {
32929                      const bool synthesis_result =
32930                         synthesize_sf3ext_expression::
32931                            template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 * c1), v0, v1, result);
32932 
32933                      exprtk_debug(("(c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n"));
32934 
32935                      return (synthesis_result) ? result : error_node();
32936                   }
32937                   // (c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)
32938                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
32939                   {
32940                      const bool synthesis_result =
32941                         synthesize_sf3ext_expression::
32942                            template compile<ctype,vtype,vtype>(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result);
32943 
32944                      exprtk_debug(("(c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)\n"));
32945 
32946                      return (synthesis_result) ? result : error_node();
32947                   }
32948                   // (c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)
32949                   else if (
32950                             (std::equal_to<T>()(c0,c1)) &&
32951                             (details::e_mul == o0)      &&
32952                             (details::e_mul == o2)      &&
32953                             (
32954                               (details::e_add == o1) ||
32955                               (details::e_sub == o1)
32956                             )
32957                           )
32958                   {
32959                      std::string specfunc;
32960 
32961                      switch (o1)
32962                      {
32963                         case details::e_add : specfunc = "t*(t+t)"; break;
32964                         case details::e_sub : specfunc = "t*(t-t)"; break;
32965                         default             : return error_node();
32966                      }
32967 
32968                      const bool synthesis_result =
32969                         synthesize_sf3ext_expression::
32970                            template compile<ctype,vtype,vtype>(expr_gen,specfunc, c0, v0, v1, result);
32971 
32972                      exprtk_debug(("(c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n"));
32973 
32974                      return (synthesis_result) ? result : error_node();
32975                   }
32976                }
32977 
32978                const bool synthesis_result =
32979                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32980                      (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
32981 
32982                if (synthesis_result)
32983                   return result;
32984                else if (!expr_gen.valid_operator(o0,f0))
32985                   return error_node();
32986                else if (!expr_gen.valid_operator(o1,f1))
32987                   return error_node();
32988                else if (!expr_gen.valid_operator(o2,f2))
32989                   return error_node();
32990                else
32991                   return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
32992             }
32993 
idexprtk::parser::expression_generator::synthesize_covovoc_expression032994             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)
32998             {
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)";
33004             }
33005          };
33006 
33007          struct synthesize_vococov_expression0
33008          {
33009             typedef typename vococov_t::type0 node_type;
33010             typedef typename vococov_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;
33015 
processexprtk::parser::expression_generator::synthesize_vococov_expression033016             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33017                                                       const details::operator_type& operation,
33018                                                       expression_node_ptr (&branch)[2])
33019             {
33020                // (v0 o0 c0) o1 (c1 o2 v1)
33021                const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
33022                const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
33023                const Type  c0 = voc->c();
33024                const Type& v0 = voc->v();
33025                const Type  c1 = cov->c();
33026                const Type& v1 = cov->v();
33027                const details::operator_type o0 = voc->operation();
33028                const details::operator_type o1 = operation;
33029                const details::operator_type o2 = cov->operation();
33030 
33031                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
33032                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
33033                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33034 
33035                details::free_node(*(expr_gen.node_allocator_),branch[0]);
33036                details::free_node(*(expr_gen.node_allocator_),branch[1]);
33037 
33038                expression_node_ptr result = error_node();
33039 
33040                if (expr_gen.parser_->settings_.strength_reduction_enabled())
33041                {
33042                   // (v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1
33043                   if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
33044                   {
33045                      const bool synthesis_result =
33046                         synthesize_sf3ext_expression::
33047                            template compile<ctype,vtype,vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
33048 
33049                      exprtk_debug(("(v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n"));
33050 
33051                      return (synthesis_result) ? result : error_node();
33052                   }
33053                   // (v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1
33054                   else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
33055                   {
33056                      const bool synthesis_result =
33057                         synthesize_sf3ext_expression::
33058                            template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
33059 
33060                      exprtk_debug(("(v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n"));
33061 
33062                      return (synthesis_result) ? result : error_node();
33063                   }
33064                   // (v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)
33065                   else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
33066                   {
33067                      const bool synthesis_result =
33068                         synthesize_sf3ext_expression::
33069                            template compile<vtype,vtype,ctype>(expr_gen, "(t+t)-t", v0, v1, (c1 + c0), result);
33070 
33071                      exprtk_debug(("(v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)\n"));
33072 
33073                      return (synthesis_result) ? result : error_node();
33074                   }
33075                   // (v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1
33076                   else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
33077                   {
33078                      const bool synthesis_result =
33079                         synthesize_sf3ext_expression::
33080                            template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
33081 
33082                      exprtk_debug(("(v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n"));
33083 
33084                      return (synthesis_result) ? result : error_node();
33085                   }
33086                   // (v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)
33087                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
33088                   {
33089                      const bool synthesis_result =
33090                         synthesize_sf3ext_expression::
33091                            template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
33092 
33093                      exprtk_debug(("(v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
33094 
33095                      return (synthesis_result) ? result : error_node();
33096                   }
33097                   // (v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)
33098                   else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
33099                   {
33100                      const bool synthesis_result =
33101                         synthesize_sf3ext_expression::
33102                            template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result);
33103 
33104                      exprtk_debug(("(v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)\n"));
33105 
33106                      return (synthesis_result) ? result : error_node();
33107                   }
33108                   // (v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)
33109                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
33110                   {
33111                      const bool synthesis_result =
33112                         synthesize_sf3ext_expression::
33113                            template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 / c1), v0, v1, result);
33114 
33115                      exprtk_debug(("(v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
33116 
33117                      return (synthesis_result) ? result : error_node();
33118                   }
33119                   // (v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)
33120                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
33121                   {
33122                      const bool synthesis_result =
33123                         synthesize_sf3ext_expression::
33124                            template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", Type(1) / (c0 * c1), v0, v1, result);
33125 
33126                      exprtk_debug(("(v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)\n"));
33127 
33128                      return (synthesis_result) ? result : error_node();
33129                   }
33130                   // (v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1))
33131                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
33132                   {
33133                      const bool synthesis_result =
33134                         synthesize_sf3ext_expression::
33135                            template compile<vtype,vtype,ctype>(expr_gen, "(t*t)*t", v0, v1, Type(1) / (c0 * c1), result);
33136 
33137                      exprtk_debug(("(v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1))\n"));
33138 
33139                      return (synthesis_result) ? result : error_node();
33140                   }
33141                   // (v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)
33142                   else if (
33143                             (std::equal_to<T>()(c0,c1)) &&
33144                             (details::e_mul == o0)      &&
33145                             (details::e_mul == o2)      &&
33146                             (
33147                               (details::e_add == o1) || (details::e_sub == o1)
33148                             )
33149                           )
33150                   {
33151                      std::string specfunc;
33152 
33153                      switch (o1)
33154                      {
33155                         case details::e_add : specfunc = "t*(t+t)"; break;
33156                         case details::e_sub : specfunc = "t*(t-t)"; break;
33157                         default             : return error_node();
33158                      }
33159 
33160                      const bool synthesis_result =
33161                         synthesize_sf3ext_expression::
33162                            template compile<ctype,vtype,vtype>(expr_gen, specfunc, c0, v0, v1, result);
33163 
33164                      exprtk_debug(("(v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n"));
33165 
33166                      return (synthesis_result) ? result : error_node();
33167                   }
33168                }
33169 
33170                const bool synthesis_result =
33171                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33172                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result);
33173 
33174                if (synthesis_result)
33175                   return result;
33176                else if (!expr_gen.valid_operator(o0,f0))
33177                   return error_node();
33178                else if (!expr_gen.valid_operator(o1,f1))
33179                   return error_node();
33180                else if (!expr_gen.valid_operator(o2,f2))
33181                   return error_node();
33182                else
33183                   return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2);
33184             }
33185 
idexprtk::parser::expression_generator::synthesize_vococov_expression033186             static inline std::string id(expression_generator<Type>& expr_gen,
33187                                          const details::operator_type o0,
33188                                          const details::operator_type o1,
33189                                          const details::operator_type o2)
33190             {
33191                return details::build_string()
33192                          << "(t" << expr_gen.to_str(o0)
33193                          << "t)" << expr_gen.to_str(o1)
33194                          << "(t" << expr_gen.to_str(o2)
33195                          << "t)";
33196             }
33197          };
33198 
33199          struct synthesize_vovovov_expression1
33200          {
33201             typedef typename vovovov_t::type1 node_type;
33202             typedef typename vovovov_t::sf4_type sf4_type;
33203             typedef typename node_type::T0 T0;
33204             typedef typename node_type::T1 T1;
33205             typedef typename node_type::T2 T2;
33206             typedef typename node_type::T3 T3;
33207 
processexprtk::parser::expression_generator::synthesize_vovovov_expression133208             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33209                                                       const details::operator_type& operation,
33210                                                       expression_node_ptr (&branch)[2])
33211             {
33212                // v0 o0 (v1 o1 (v2 o2 v3))
33213                typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
33214 
33215                const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
33216                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
33217                const Type& v1 = vovov->t0();
33218                const Type& v2 = vovov->t1();
33219                const Type& v3 = vovov->t2();
33220                const details::operator_type o0 = operation;
33221                const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
33222                const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
33223 
33224                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
33225                binary_functor_t f1 = vovov->f0();
33226                binary_functor_t f2 = vovov->f1();
33227 
33228                details::free_node(*(expr_gen.node_allocator_),branch[1]);
33229 
33230                expression_node_ptr result = error_node();
33231 
33232                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result))
33233                   return result;
33234                else if (!expr_gen.valid_operator(o0,f0))
33235                   return error_node();
33236 
33237                exprtk_debug(("v0 o0 (v1 o1 (v2 o2 v3))\n"));
33238 
33239                return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2);
33240             }
33241 
idexprtk::parser::expression_generator::synthesize_vovovov_expression133242             static inline std::string id(expression_generator<Type>& expr_gen,
33243                                          const details::operator_type o0,
33244                                          const details::operator_type o1,
33245                                          const details::operator_type o2)
33246             {
33247                return details::build_string()
33248                          << "t"  << expr_gen.to_str(o0)
33249                          << "(t" << expr_gen.to_str(o1)
33250                          << "(t" << expr_gen.to_str(o2)
33251                          << "t))";
33252             }
33253          };
33254 
33255          struct synthesize_vovovoc_expression1
33256          {
33257             typedef typename vovovoc_t::type1 node_type;
33258             typedef typename vovovoc_t::sf4_type sf4_type;
33259             typedef typename node_type::T0 T0;
33260             typedef typename node_type::T1 T1;
33261             typedef typename node_type::T2 T2;
33262             typedef typename node_type::T3 T3;
33263 
processexprtk::parser::expression_generator::synthesize_vovovoc_expression133264             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33265                                                       const details::operator_type& operation,
33266                                                       expression_node_ptr (&branch)[2])
33267             {
33268                // v0 o0 (v1 o1 (v2 o2 c))
33269                typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t;
33270 
33271                const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
33272                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
33273                const Type& v1 = vovoc->t0();
33274                const Type& v2 = vovoc->t1();
33275                const Type   c = vovoc->t2();
33276                const details::operator_type o0 = operation;
33277                const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
33278                const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
33279 
33280                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
33281                binary_functor_t f1 = vovoc->f0();
33282                binary_functor_t f2 = vovoc->f1();
33283 
33284                details::free_node(*(expr_gen.node_allocator_),branch[1]);
33285 
33286                expression_node_ptr result = error_node();
33287 
33288                const bool synthesis_result =
33289                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33290                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
33291 
33292                if (synthesis_result)
33293                   return result;
33294                else if (!expr_gen.valid_operator(o0,f0))
33295                   return error_node();
33296 
33297                exprtk_debug(("v0 o0 (v1 o1 (v2 o2 c))\n"));
33298 
33299                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
33300             }
33301 
idexprtk::parser::expression_generator::synthesize_vovovoc_expression133302             static inline std::string id(expression_generator<Type>& expr_gen,
33303                                          const details::operator_type o0,
33304                                          const details::operator_type o1,
33305                                          const details::operator_type o2)
33306             {
33307                return details::build_string()
33308                          << "t"  << expr_gen.to_str(o0)
33309                          << "(t" << expr_gen.to_str(o1)
33310                          << "(t" << expr_gen.to_str(o2)
33311                          << "t))";
33312             }
33313          };
33314 
33315          struct synthesize_vovocov_expression1
33316          {
33317             typedef typename vovocov_t::type1 node_type;
33318             typedef typename vovocov_t::sf4_type sf4_type;
33319             typedef typename node_type::T0 T0;
33320             typedef typename node_type::T1 T1;
33321             typedef typename node_type::T2 T2;
33322             typedef typename node_type::T3 T3;
33323 
processexprtk::parser::expression_generator::synthesize_vovocov_expression133324             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33325                                                       const details::operator_type& operation,
33326                                                       expression_node_ptr (&branch)[2])
33327             {
33328                // v0 o0 (v1 o1 (c o2 v2))
33329                typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
33330 
33331                const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
33332                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
33333                const Type& v1 = vocov->t0();
33334                const Type   c = vocov->t1();
33335                const Type& v2 = vocov->t2();
33336                const details::operator_type o0 = operation;
33337                const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
33338                const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
33339 
33340                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
33341                binary_functor_t f1 = vocov->f0();
33342                binary_functor_t f2 = vocov->f1();
33343 
33344                details::free_node(*(expr_gen.node_allocator_),branch[1]);
33345 
33346                expression_node_ptr result = error_node();
33347 
33348                const bool synthesis_result =
33349                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33350                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
33351 
33352                if (synthesis_result)
33353                   return result;
33354                if (!expr_gen.valid_operator(o0,f0))
33355                   return error_node();
33356 
33357                exprtk_debug(("v0 o0 (v1 o1 (c o2 v2))\n"));
33358 
33359                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
33360             }
33361 
idexprtk::parser::expression_generator::synthesize_vovocov_expression133362             static inline std::string id(expression_generator<Type>& expr_gen,
33363                                          const details::operator_type o0,
33364                                          const details::operator_type o1,
33365                                          const details::operator_type o2)
33366             {
33367                return details::build_string()
33368                          << "t"  << expr_gen.to_str(o0)
33369                          << "(t" << expr_gen.to_str(o1)
33370                          << "(t" << expr_gen.to_str(o2)
33371                          << "t))";
33372             }
33373          };
33374 
33375          struct synthesize_vocovov_expression1
33376          {
33377             typedef typename vocovov_t::type1 node_type;
33378             typedef typename vocovov_t::sf4_type sf4_type;
33379             typedef typename node_type::T0 T0;
33380             typedef typename node_type::T1 T1;
33381             typedef typename node_type::T2 T2;
33382             typedef typename node_type::T3 T3;
33383 
processexprtk::parser::expression_generator::synthesize_vocovov_expression133384             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33385                                                       const details::operator_type& operation,
33386                                                       expression_node_ptr (&branch)[2])
33387             {
33388                // v0 o0 (c o1 (v1 o2 v2))
33389                typedef typename synthesize_covov_expression1::node_type lcl_covov_t;
33390 
33391                const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]);
33392                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
33393                const Type   c = covov->t0();
33394                const Type& v1 = covov->t1();
33395                const Type& v2 = covov->t2();
33396                const details::operator_type o0 = operation;
33397                const details::operator_type o1 = expr_gen.get_operator(covov->f0());
33398                const details::operator_type o2 = expr_gen.get_operator(covov->f1());
33399 
33400                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
33401                binary_functor_t f1 = covov->f0();
33402                binary_functor_t f2 = covov->f1();
33403 
33404                details::free_node(*(expr_gen.node_allocator_),branch[1]);
33405 
33406                expression_node_ptr result = error_node();
33407 
33408                const bool synthesis_result =
33409                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33410                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
33411 
33412                if (synthesis_result)
33413                   return result;
33414                else if (!expr_gen.valid_operator(o0,f0))
33415                   return error_node();
33416 
33417                exprtk_debug(("v0 o0 (c o1 (v1 o2 v2))\n"));
33418 
33419                return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
33420             }
33421 
idexprtk::parser::expression_generator::synthesize_vocovov_expression133422             static inline std::string id(expression_generator<Type>& expr_gen,
33423                                          const details::operator_type o0,
33424                                          const details::operator_type o1,
33425                                          const details::operator_type o2)
33426             {
33427                return details::build_string()
33428                          << "t"  << expr_gen.to_str(o0)
33429                          << "(t" << expr_gen.to_str(o1)
33430                          << "(t" << expr_gen.to_str(o2)
33431                          << "t))";
33432             }
33433          };
33434 
33435          struct synthesize_covovov_expression1
33436          {
33437             typedef typename covovov_t::type1 node_type;
33438             typedef typename covovov_t::sf4_type sf4_type;
33439             typedef typename node_type::T0 T0;
33440             typedef typename node_type::T1 T1;
33441             typedef typename node_type::T2 T2;
33442             typedef typename node_type::T3 T3;
33443 
processexprtk::parser::expression_generator::synthesize_covovov_expression133444             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33445                                                       const details::operator_type& operation,
33446                                                       expression_node_ptr (&branch)[2])
33447             {
33448                // c o0 (v0 o1 (v1 o2 v2))
33449                typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
33450 
33451                const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
33452                const Type   c = static_cast<details::literal_node<Type>*>(branch[0])->value();
33453                const Type& v0 = vovov->t0();
33454                const Type& v1 = vovov->t1();
33455                const Type& v2 = vovov->t2();
33456                const details::operator_type o0 = operation;
33457                const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
33458                const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
33459 
33460                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
33461                binary_functor_t f1 = vovov->f0();
33462                binary_functor_t f2 = vovov->f1();
33463 
33464                details::free_node(*(expr_gen.node_allocator_),branch[0]);
33465                details::free_node(*(expr_gen.node_allocator_),branch[1]);
33466 
33467                expression_node_ptr result = error_node();
33468 
33469                const bool synthesis_result =
33470                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33471                      (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
33472 
33473                if (synthesis_result)
33474                   return result;
33475                if (!expr_gen.valid_operator(o0,f0))
33476                   return error_node();
33477 
33478                exprtk_debug(("c o0 (v0 o1 (v1 o2 v2))\n"));
33479 
33480                return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
33481             }
33482 
idexprtk::parser::expression_generator::synthesize_covovov_expression133483             static inline std::string id(expression_generator<Type>& expr_gen,
33484                                          const details::operator_type o0,
33485                                          const details::operator_type o1,
33486                                          const details::operator_type o2)
33487             {
33488                return details::build_string()
33489                          << "t"  << expr_gen.to_str(o0)
33490                          << "(t" << expr_gen.to_str(o1)
33491                          << "(t" << expr_gen.to_str(o2)
33492                          << "t))";
33493             }
33494          };
33495 
33496          struct synthesize_covocov_expression1
33497          {
33498             typedef typename covocov_t::type1 node_type;
33499             typedef typename covocov_t::sf4_type sf4_type;
33500             typedef typename node_type::T0 T0;
33501             typedef typename node_type::T1 T1;
33502             typedef typename node_type::T2 T2;
33503             typedef typename node_type::T3 T3;
33504 
processexprtk::parser::expression_generator::synthesize_covocov_expression133505             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33506                                                       const details::operator_type& operation,
33507                                                       expression_node_ptr (&branch)[2])
33508             {
33509                // c0 o0 (v0 o1 (c1 o2 v1))
33510                typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
33511 
33512                const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
33513                const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
33514                const Type& v0 = vocov->t0();
33515                const Type  c1 = vocov->t1();
33516                const Type& v1 = vocov->t2();
33517                const details::operator_type o0 = operation;
33518                const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
33519                const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
33520 
33521                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
33522                binary_functor_t f1 = vocov->f0();
33523                binary_functor_t f2 = vocov->f1();
33524 
33525                details::free_node(*(expr_gen.node_allocator_),branch[0]);
33526                details::free_node(*(expr_gen.node_allocator_),branch[1]);
33527 
33528                expression_node_ptr result = error_node();
33529 
33530                const bool synthesis_result =
33531                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33532                      (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
33533 
33534                if (synthesis_result)
33535                   return result;
33536                else if (!expr_gen.valid_operator(o0,f0))
33537                   return error_node();
33538 
33539                exprtk_debug(("c0 o0 (v0 o1 (c1 o2 v1))\n"));
33540 
33541                return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
33542             }
33543 
idexprtk::parser::expression_generator::synthesize_covocov_expression133544             static inline std::string id(expression_generator<Type>& expr_gen,
33545                                          const details::operator_type o0,
33546                                          const details::operator_type o1,
33547                                          const details::operator_type o2)
33548             {
33549                return details::build_string()
33550                          << "t"  << expr_gen.to_str(o0)
33551                          << "(t" << expr_gen.to_str(o1)
33552                          << "(t" << expr_gen.to_str(o2)
33553                          << "t))";
33554             }
33555          };
33556 
33557          struct synthesize_vocovoc_expression1
33558          {
33559             typedef typename vocovoc_t::type1 node_type;
33560             typedef typename vocovoc_t::sf4_type sf4_type;
33561             typedef typename node_type::T0 T0;
33562             typedef typename node_type::T1 T1;
33563             typedef typename node_type::T2 T2;
33564             typedef typename node_type::T3 T3;
33565 
processexprtk::parser::expression_generator::synthesize_vocovoc_expression133566             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33567                                                       const details::operator_type& operation,
33568                                                       expression_node_ptr (&branch)[2])
33569             {
33570                // v0 o0 (c0 o1 (v1 o2 c2))
33571                typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t;
33572 
33573                const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]);
33574                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
33575                const Type  c0 = covoc->t0();
33576                const Type& v1 = covoc->t1();
33577                const Type  c1 = covoc->t2();
33578                const details::operator_type o0 = operation;
33579                const details::operator_type o1 = expr_gen.get_operator(covoc->f0());
33580                const details::operator_type o2 = expr_gen.get_operator(covoc->f1());
33581 
33582                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
33583                binary_functor_t f1 = covoc->f0();
33584                binary_functor_t f2 = covoc->f1();
33585 
33586                details::free_node(*(expr_gen.node_allocator_),branch[1]);
33587 
33588                expression_node_ptr result = error_node();
33589 
33590                const bool synthesis_result =
33591                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33592                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
33593 
33594                if (synthesis_result)
33595                   return result;
33596                else if (!expr_gen.valid_operator(o0,f0))
33597                   return error_node();
33598 
33599                exprtk_debug(("v0 o0 (c0 o1 (v1 o2 c2))\n"));
33600 
33601                return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
33602             }
33603 
idexprtk::parser::expression_generator::synthesize_vocovoc_expression133604             static inline std::string id(expression_generator<Type>& expr_gen,
33605                                          const details::operator_type o0,
33606                                          const details::operator_type o1,
33607                                          const details::operator_type o2)
33608             {
33609                return details::build_string()
33610                          << "t"  << expr_gen.to_str(o0)
33611                          << "(t" << expr_gen.to_str(o1)
33612                          << "(t" << expr_gen.to_str(o2)
33613                          << "t))";
33614             }
33615          };
33616 
33617          struct synthesize_covovoc_expression1
33618          {
33619             typedef typename covovoc_t::type1 node_type;
33620             typedef typename covovoc_t::sf4_type sf4_type;
33621             typedef typename node_type::T0 T0;
33622             typedef typename node_type::T1 T1;
33623             typedef typename node_type::T2 T2;
33624             typedef typename node_type::T3 T3;
processexprtk::parser::expression_generator::synthesize_covovoc_expression133625             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33626                                                       const details::operator_type& operation,
33627                                                       expression_node_ptr (&branch)[2])
33628             {
33629                // c0 o0 (v0 o1 (v1 o2 c1))
33630                typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t;
33631 
33632                const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
33633                const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
33634                const Type& v0 = vovoc->t0();
33635                const Type& v1 = vovoc->t1();
33636                const Type  c1 = vovoc->t2();
33637                const details::operator_type o0 = operation;
33638                const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
33639                const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
33640 
33641                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
33642                binary_functor_t f1 = vovoc->f0();
33643                binary_functor_t f2 = vovoc->f1();
33644 
33645                details::free_node(*(expr_gen.node_allocator_),branch[0]);
33646                details::free_node(*(expr_gen.node_allocator_),branch[1]);
33647 
33648                expression_node_ptr result = error_node();
33649 
33650                const bool synthesis_result =
33651                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33652                      (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
33653 
33654                if (synthesis_result)
33655                   return result;
33656                else if (!expr_gen.valid_operator(o0,f0))
33657                   return error_node();
33658 
33659                exprtk_debug(("c0 o0 (v0 o1 (v1 o2 c1))\n"));
33660 
33661                return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
33662             }
33663 
idexprtk::parser::expression_generator::synthesize_covovoc_expression133664             static inline std::string id(expression_generator<Type>& expr_gen,
33665                                          const details::operator_type o0,
33666                                          const details::operator_type o1,
33667                                          const details::operator_type o2)
33668             {
33669                return details::build_string()
33670                          << "t"  << expr_gen.to_str(o0)
33671                          << "(t" << expr_gen.to_str(o1)
33672                          << "(t" << expr_gen.to_str(o2)
33673                          << "t))";
33674             }
33675          };
33676 
33677          struct synthesize_vococov_expression1
33678          {
33679             typedef typename vococov_t::type1 node_type;
33680             typedef typename vococov_t::sf4_type sf4_type;
33681             typedef typename node_type::T0 T0;
33682             typedef typename node_type::T1 T1;
33683             typedef typename node_type::T2 T2;
33684             typedef typename node_type::T3 T3;
33685 
processexprtk::parser::expression_generator::synthesize_vococov_expression133686             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33687                                                       const details::operator_type& operation,
33688                                                       expression_node_ptr (&branch)[2])
33689             {
33690                // v0 o0 (c0 o1 (c1 o2 v1))
33691                typedef typename synthesize_cocov_expression1::node_type lcl_cocov_t;
33692 
33693                const lcl_cocov_t* cocov = static_cast<const lcl_cocov_t*>(branch[1]);
33694                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
33695                const Type  c0 = cocov->t0();
33696                const Type  c1 = cocov->t1();
33697                const Type& v1 = cocov->t2();
33698                const details::operator_type o0 = operation;
33699                const details::operator_type o1 = expr_gen.get_operator(cocov->f0());
33700                const details::operator_type o2 = expr_gen.get_operator(cocov->f1());
33701 
33702                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
33703                binary_functor_t f1 = cocov->f0();
33704                binary_functor_t f2 = cocov->f1();
33705 
33706                details::free_node(*(expr_gen.node_allocator_),branch[1]);
33707 
33708                expression_node_ptr result = error_node();
33709 
33710                const bool synthesis_result =
33711                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33712                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result);
33713 
33714                if (synthesis_result)
33715                   return result;
33716                else if (!expr_gen.valid_operator(o0,f0))
33717                   return error_node();
33718 
33719                exprtk_debug(("v0 o0 (c0 o1 (c1 o2 v1))\n"));
33720 
33721                return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2);
33722             }
33723 
idexprtk::parser::expression_generator::synthesize_vococov_expression133724             static inline std::string id(expression_generator<Type>& expr_gen,
33725                                          const details::operator_type o0,
33726                                          const details::operator_type o1,
33727                                          const details::operator_type o2)
33728             {
33729                return details::build_string()
33730                          << "t"  << expr_gen.to_str(o0)
33731                          << "(t" << expr_gen.to_str(o1)
33732                          << "(t" << expr_gen.to_str(o2)
33733                          << "t))";
33734             }
33735          };
33736 
33737          struct synthesize_vovovov_expression2
33738          {
33739             typedef typename vovovov_t::type2 node_type;
33740             typedef typename vovovov_t::sf4_type sf4_type;
33741             typedef typename node_type::T0 T0;
33742             typedef typename node_type::T1 T1;
33743             typedef typename node_type::T2 T2;
33744             typedef typename node_type::T3 T3;
33745 
processexprtk::parser::expression_generator::synthesize_vovovov_expression233746             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33747                                                       const details::operator_type& operation,
33748                                                       expression_node_ptr (&branch)[2])
33749             {
33750                // v0 o0 ((v1 o1 v2) o2 v3)
33751                typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
33752 
33753                const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
33754                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
33755                const Type& v1 = vovov->t0();
33756                const Type& v2 = vovov->t1();
33757                const Type& v3 = vovov->t2();
33758                const details::operator_type o0 = operation;
33759                const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
33760                const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
33761 
33762                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
33763                binary_functor_t f1 = vovov->f0();
33764                binary_functor_t f2 = vovov->f1();
33765 
33766                details::free_node(*(expr_gen.node_allocator_),branch[1]);
33767 
33768                expression_node_ptr result = error_node();
33769 
33770                const bool synthesis_result =
33771                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33772                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
33773 
33774                if (synthesis_result)
33775                   return result;
33776                else if (!expr_gen.valid_operator(o0,f0))
33777                   return error_node();
33778 
33779                exprtk_debug(("v0 o0 ((v1 o1 v2) o2 v3)\n"));
33780 
33781                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
33782             }
33783 
idexprtk::parser::expression_generator::synthesize_vovovov_expression233784             static inline std::string id(expression_generator<Type>& expr_gen,
33785                                          const details::operator_type o0,
33786                                          const details::operator_type o1,
33787                                          const details::operator_type o2)
33788             {
33789                return details::build_string()
33790                          << "t"   << expr_gen.to_str(o0)
33791                          << "((t" << expr_gen.to_str(o1)
33792                          << "t)"  << expr_gen.to_str(o2)
33793                          << "t)";
33794             }
33795          };
33796 
33797          struct synthesize_vovovoc_expression2
33798          {
33799             typedef typename vovovoc_t::type2 node_type;
33800             typedef typename vovovoc_t::sf4_type sf4_type;
33801             typedef typename node_type::T0 T0;
33802             typedef typename node_type::T1 T1;
33803             typedef typename node_type::T2 T2;
33804             typedef typename node_type::T3 T3;
33805 
processexprtk::parser::expression_generator::synthesize_vovovoc_expression233806             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33807                                                       const details::operator_type& operation,
33808                                                       expression_node_ptr (&branch)[2])
33809             {
33810                // v0 o0 ((v1 o1 v2) o2 c)
33811                typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t;
33812 
33813                const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
33814                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
33815                const Type& v1 = vovoc->t0();
33816                const Type& v2 = vovoc->t1();
33817                const Type   c = vovoc->t2();
33818                const details::operator_type o0 = operation;
33819                const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
33820                const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
33821 
33822                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
33823                binary_functor_t f1 = vovoc->f0();
33824                binary_functor_t f2 = vovoc->f1();
33825 
33826                details::free_node(*(expr_gen.node_allocator_),branch[1]);
33827 
33828                expression_node_ptr result = error_node();
33829 
33830                const bool synthesis_result =
33831                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33832                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
33833 
33834                if (synthesis_result)
33835                   return result;
33836                else if (!expr_gen.valid_operator(o0,f0))
33837                   return error_node();
33838 
33839                exprtk_debug(("v0 o0 ((v1 o1 v2) o2 c)\n"));
33840 
33841                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
33842             }
33843 
idexprtk::parser::expression_generator::synthesize_vovovoc_expression233844             static inline std::string id(expression_generator<Type>& expr_gen,
33845                                          const details::operator_type o0,
33846                                          const details::operator_type o1,
33847                                          const details::operator_type o2)
33848             {
33849                return details::build_string()
33850                          << "t"   << expr_gen.to_str(o0)
33851                          << "((t" << expr_gen.to_str(o1)
33852                          << "t)"  << expr_gen.to_str(o2)
33853                          << "t)";
33854             }
33855          };
33856 
33857          struct synthesize_vovocov_expression2
33858          {
33859             typedef typename vovocov_t::type2 node_type;
33860             typedef typename vovocov_t::sf4_type sf4_type;
33861             typedef typename node_type::T0 T0;
33862             typedef typename node_type::T1 T1;
33863             typedef typename node_type::T2 T2;
33864             typedef typename node_type::T3 T3;
33865 
processexprtk::parser::expression_generator::synthesize_vovocov_expression233866             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33867                                                       const details::operator_type& operation,
33868                                                       expression_node_ptr (&branch)[2])
33869             {
33870                // v0 o0 ((v1 o1 c) o2 v2)
33871                typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
33872 
33873                const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
33874                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
33875                const Type& v1 = vocov->t0();
33876                const Type   c = vocov->t1();
33877                const Type& v2 = vocov->t2();
33878                const details::operator_type o0 = operation;
33879                const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
33880                const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
33881 
33882                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
33883                binary_functor_t f1 = vocov->f0();
33884                binary_functor_t f2 = vocov->f1();
33885 
33886                details::free_node(*(expr_gen.node_allocator_),branch[1]);
33887 
33888                expression_node_ptr result = error_node();
33889 
33890                const bool synthesis_result =
33891                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33892                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
33893 
33894                if (synthesis_result)
33895                   return result;
33896                else if (!expr_gen.valid_operator(o0,f0))
33897                   return error_node();
33898 
33899                exprtk_debug(("v0 o0 ((v1 o1 c) o2 v2)\n"));
33900 
33901                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
33902             }
33903 
idexprtk::parser::expression_generator::synthesize_vovocov_expression233904             static inline std::string id(expression_generator<Type>& expr_gen,
33905                                          const details::operator_type o0,
33906                                          const details::operator_type o1,
33907                                          const details::operator_type o2)
33908             {
33909                return details::build_string()
33910                          << "t"   << expr_gen.to_str(o0)
33911                          << "((t" << expr_gen.to_str(o1)
33912                          << "t)"  << expr_gen.to_str(o2)
33913                          << "t)";
33914             }
33915          };
33916 
33917          struct synthesize_vocovov_expression2
33918          {
33919             typedef typename vocovov_t::type2 node_type;
33920             typedef typename vocovov_t::sf4_type sf4_type;
33921             typedef typename node_type::T0 T0;
33922             typedef typename node_type::T1 T1;
33923             typedef typename node_type::T2 T2;
33924             typedef typename node_type::T3 T3;
33925 
processexprtk::parser::expression_generator::synthesize_vocovov_expression233926             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33927                                                       const details::operator_type& operation,
33928                                                       expression_node_ptr (&branch)[2])
33929             {
33930                // v0 o0 ((c o1 v1) o2 v2)
33931                typedef typename synthesize_covov_expression0::node_type lcl_covov_t;
33932 
33933                const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]);
33934                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
33935                const Type   c = covov->t0();
33936                const Type& v1 = covov->t1();
33937                const Type& v2 = covov->t2();
33938                const details::operator_type o0 = operation;
33939                const details::operator_type o1 = expr_gen.get_operator(covov->f0());
33940                const details::operator_type o2 = expr_gen.get_operator(covov->f1());
33941 
33942                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
33943                binary_functor_t f1 = covov->f0();
33944                binary_functor_t f2 = covov->f1();
33945 
33946                details::free_node(*(expr_gen.node_allocator_),branch[1]);
33947 
33948                expression_node_ptr result = error_node();
33949 
33950                const bool synthesis_result =
33951                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33952                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
33953 
33954                if (synthesis_result)
33955                   return result;
33956                else if (!expr_gen.valid_operator(o0,f0))
33957                   return error_node();
33958 
33959                exprtk_debug(("v0 o0 ((c o1 v1) o2 v2)\n"));
33960 
33961                return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
33962             }
33963 
idexprtk::parser::expression_generator::synthesize_vocovov_expression233964             static inline std::string id(expression_generator<Type>& expr_gen,
33965                                          const details::operator_type o0,
33966                                          const details::operator_type o1,
33967                                          const details::operator_type o2)
33968             {
33969                return details::build_string()
33970                          << "t"   << expr_gen.to_str(o0)
33971                          << "((t" << expr_gen.to_str(o1)
33972                          << "t)"  << expr_gen.to_str(o2)
33973                          << "t)";
33974             }
33975          };
33976 
33977          struct synthesize_covovov_expression2
33978          {
33979             typedef typename covovov_t::type2 node_type;
33980             typedef typename covovov_t::sf4_type sf4_type;
33981             typedef typename node_type::T0 T0;
33982             typedef typename node_type::T1 T1;
33983             typedef typename node_type::T2 T2;
33984             typedef typename node_type::T3 T3;
33985 
processexprtk::parser::expression_generator::synthesize_covovov_expression233986             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33987                                                       const details::operator_type& operation,
33988                                                       expression_node_ptr (&branch)[2])
33989             {
33990                // c o0 ((v1 o1 v2) o2 v3)
33991                typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
33992 
33993                const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
33994                const Type   c = static_cast<details::literal_node<Type>*>(branch[0])->value();
33995                const Type& v0 = vovov->t0();
33996                const Type& v1 = vovov->t1();
33997                const Type& v2 = vovov->t2();
33998                const details::operator_type o0 = operation;
33999                const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
34000                const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
34001 
34002                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
34003                binary_functor_t f1 = vovov->f0();
34004                binary_functor_t f2 = vovov->f1();
34005 
34006                details::free_node(*(expr_gen.node_allocator_),branch[0]);
34007                details::free_node(*(expr_gen.node_allocator_),branch[1]);
34008 
34009                expression_node_ptr result = error_node();
34010 
34011                const bool synthesis_result =
34012                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34013                      (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
34014 
34015                if (synthesis_result)
34016                   return result;
34017                else if (!expr_gen.valid_operator(o0,f0))
34018                   return error_node();
34019 
34020                exprtk_debug(("c o0 ((v1 o1 v2) o2 v3)\n"));
34021 
34022                return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
34023             }
34024 
idexprtk::parser::expression_generator::synthesize_covovov_expression234025             static inline std::string id(expression_generator<Type>& expr_gen,
34026                                          const details::operator_type o0,
34027                                          const details::operator_type o1,
34028                                          const details::operator_type o2)
34029             {
34030                return details::build_string()
34031                          << "t"   << expr_gen.to_str(o0)
34032                          << "((t" << expr_gen.to_str(o1)
34033                          << "t)"  << expr_gen.to_str(o2)
34034                          << "t)";
34035             }
34036         };
34037 
34038          struct synthesize_covocov_expression2
34039          {
34040             typedef typename covocov_t::type2 node_type;
34041             typedef typename covocov_t::sf4_type sf4_type;
34042             typedef typename node_type::T0 T0;
34043             typedef typename node_type::T1 T1;
34044             typedef typename node_type::T2 T2;
34045             typedef typename node_type::T3 T3;
34046 
processexprtk::parser::expression_generator::synthesize_covocov_expression234047             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34048                                                       const details::operator_type& operation,
34049                                                       expression_node_ptr (&branch)[2])
34050             {
34051                // c0 o0 ((v0 o1 c1) o2 v1)
34052                typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
34053 
34054                const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
34055                const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
34056                const Type& v0 = vocov->t0();
34057                const Type  c1 = vocov->t1();
34058                const Type& v1 = vocov->t2();
34059                const details::operator_type o0 = operation;
34060                const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
34061                const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
34062 
34063                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
34064                binary_functor_t f1 = vocov->f0();
34065                binary_functor_t f2 = vocov->f1();
34066 
34067                details::free_node(*(expr_gen.node_allocator_),branch[0]);
34068                details::free_node(*(expr_gen.node_allocator_),branch[1]);
34069 
34070                expression_node_ptr result = error_node();
34071 
34072                const bool synthesis_result =
34073                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34074                      (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
34075 
34076                if (synthesis_result)
34077                   return result;
34078                else if (!expr_gen.valid_operator(o0,f0))
34079                   return error_node();
34080 
34081                exprtk_debug(("c0 o0 ((v0 o1 c1) o2 v1)\n"));
34082 
34083                return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
34084             }
34085 
idexprtk::parser::expression_generator::synthesize_covocov_expression234086             static inline std::string id(expression_generator<Type>& expr_gen,
34087                                          const details::operator_type o0,
34088                                          const details::operator_type o1,
34089                                          const details::operator_type o2)
34090             {
34091                return details::build_string()
34092                          << "t"   << expr_gen.to_str(o0)
34093                          << "((t" << expr_gen.to_str(o1)
34094                          << "t)"  << expr_gen.to_str(o2)
34095                          << "t)";
34096             }
34097          };
34098 
34099          struct synthesize_vocovoc_expression2
34100          {
34101             typedef typename vocovoc_t::type2 node_type;
34102             typedef typename vocovoc_t::sf4_type sf4_type;
34103             typedef typename node_type::T0 T0;
34104             typedef typename node_type::T1 T1;
34105             typedef typename node_type::T2 T2;
34106             typedef typename node_type::T3 T3;
34107 
processexprtk::parser::expression_generator::synthesize_vocovoc_expression234108             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34109                                                       const details::operator_type& operation,
34110                                                       expression_node_ptr (&branch)[2])
34111             {
34112                // v0 o0 ((c0 o1 v1) o2 c1)
34113                typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t;
34114 
34115                const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]);
34116                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
34117                const Type  c0 = covoc->t0();
34118                const Type& v1 = covoc->t1();
34119                const Type  c1 = covoc->t2();
34120                const details::operator_type o0 = operation;
34121                const details::operator_type o1 = expr_gen.get_operator(covoc->f0());
34122                const details::operator_type o2 = expr_gen.get_operator(covoc->f1());
34123 
34124                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
34125                binary_functor_t f1 = covoc->f0();
34126                binary_functor_t f2 = covoc->f1();
34127 
34128                details::free_node(*(expr_gen.node_allocator_),branch[1]);
34129 
34130                expression_node_ptr result = error_node();
34131 
34132                const bool synthesis_result =
34133                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34134                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
34135 
34136                if (synthesis_result)
34137                   return result;
34138                else if (!expr_gen.valid_operator(o0,f0))
34139                   return error_node();
34140 
34141                exprtk_debug(("v0 o0 ((c0 o1 v1) o2 c1)\n"));
34142 
34143                return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
34144             }
34145 
idexprtk::parser::expression_generator::synthesize_vocovoc_expression234146             static inline std::string id(expression_generator<Type>& expr_gen,
34147                                          const details::operator_type o0,
34148                                          const details::operator_type o1,
34149                                          const details::operator_type o2)
34150             {
34151                return details::build_string()
34152                          << "t"   << expr_gen.to_str(o0)
34153                          << "((t" << expr_gen.to_str(o1)
34154                          << "t)"  << expr_gen.to_str(o2)
34155                          << "t)";
34156             }
34157          };
34158 
34159          struct synthesize_covovoc_expression2
34160          {
34161             typedef typename covovoc_t::type2 node_type;
34162             typedef typename covovoc_t::sf4_type sf4_type;
34163             typedef typename node_type::T0 T0;
34164             typedef typename node_type::T1 T1;
34165             typedef typename node_type::T2 T2;
34166             typedef typename node_type::T3 T3;
34167 
processexprtk::parser::expression_generator::synthesize_covovoc_expression234168             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34169                                                       const details::operator_type& operation,
34170                                                       expression_node_ptr (&branch)[2])
34171             {
34172                // c0 o0 ((v0 o1 v1) o2 c1)
34173                typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t;
34174 
34175                const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
34176                const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
34177                const Type& v0 = vovoc->t0();
34178                const Type& v1 = vovoc->t1();
34179                const Type  c1 = vovoc->t2();
34180                const details::operator_type o0 = operation;
34181                const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
34182                const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
34183 
34184                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
34185                binary_functor_t f1 = vovoc->f0();
34186                binary_functor_t f2 = vovoc->f1();
34187 
34188                details::free_node(*(expr_gen.node_allocator_),branch[0]);
34189                details::free_node(*(expr_gen.node_allocator_),branch[1]);
34190 
34191                expression_node_ptr result = error_node();
34192 
34193                const bool synthesis_result =
34194                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34195                      (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
34196 
34197                if (synthesis_result)
34198                   return result;
34199                else if (!expr_gen.valid_operator(o0,f0))
34200                   return error_node();
34201 
34202                exprtk_debug(("c0 o0 ((v0 o1 v1) o2 c1)\n"));
34203 
34204                return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
34205             }
34206 
idexprtk::parser::expression_generator::synthesize_covovoc_expression234207             static inline std::string id(expression_generator<Type>& expr_gen,
34208                                          const details::operator_type o0,
34209                                          const details::operator_type o1,
34210                                          const details::operator_type o2)
34211             {
34212                return details::build_string()
34213                          << "t"   << expr_gen.to_str(o0)
34214                          << "((t" << expr_gen.to_str(o1)
34215                          << "t)"  << expr_gen.to_str(o2)
34216                          << "t)";
34217             }
34218          };
34219 
34220          struct synthesize_vococov_expression2
34221          {
34222             typedef typename vococov_t::type2 node_type;
processexprtk::parser::expression_generator::synthesize_vococov_expression234223             static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
34224             {
34225                // v0 o0 ((c0 o1 c1) o2 v1) - Not possible
34226                exprtk_debug(("v0 o0 ((c0 o1 c1) o2 v1) - Not possible\n"));
34227                return error_node();
34228             }
34229 
idexprtk::parser::expression_generator::synthesize_vococov_expression234230             static inline std::string id(expression_generator<Type>&,
34231                                          const details::operator_type, const details::operator_type, const details::operator_type)
34232             {
34233                return "INVALID";
34234             }
34235          };
34236 
34237          struct synthesize_vovovov_expression3
34238          {
34239             typedef typename vovovov_t::type3 node_type;
34240             typedef typename vovovov_t::sf4_type sf4_type;
34241             typedef typename node_type::T0 T0;
34242             typedef typename node_type::T1 T1;
34243             typedef typename node_type::T2 T2;
34244             typedef typename node_type::T3 T3;
34245 
processexprtk::parser::expression_generator::synthesize_vovovov_expression334246             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34247                                                       const details::operator_type& operation,
34248                                                       expression_node_ptr (&branch)[2])
34249             {
34250                // ((v0 o0 v1) o1 v2) o2 v3
34251                typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
34252 
34253                const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
34254                const Type& v0 = vovov->t0();
34255                const Type& v1 = vovov->t1();
34256                const Type& v2 = vovov->t2();
34257                const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
34258                const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
34259                const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
34260                const details::operator_type o2 = operation;
34261 
34262                binary_functor_t f0 = vovov->f0();
34263                binary_functor_t f1 = vovov->f1();
34264                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34265 
34266                details::free_node(*(expr_gen.node_allocator_),branch[0]);
34267 
34268                expression_node_ptr result = error_node();
34269 
34270                const bool synthesis_result =
34271                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34272                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
34273 
34274                if (synthesis_result)
34275                   return result;
34276                else if (!expr_gen.valid_operator(o2,f2))
34277                   return error_node();
34278 
34279                exprtk_debug(("((v0 o0 v1) o1 v2) o2 v3\n"));
34280 
34281                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
34282             }
34283 
idexprtk::parser::expression_generator::synthesize_vovovov_expression334284             static inline std::string id(expression_generator<Type>& expr_gen,
34285                                          const details::operator_type o0,
34286                                          const details::operator_type o1,
34287                                          const details::operator_type o2)
34288             {
34289                return details::build_string()
34290                          << "((t" << expr_gen.to_str(o0)
34291                          << "t)"  << expr_gen.to_str(o1)
34292                          << "t)"  << expr_gen.to_str(o2)
34293                          << "t";
34294             }
34295          };
34296 
34297          struct synthesize_vovovoc_expression3
34298          {
34299             typedef typename vovovoc_t::type3 node_type;
34300             typedef typename vovovoc_t::sf4_type sf4_type;
34301             typedef typename node_type::T0 T0;
34302             typedef typename node_type::T1 T1;
34303             typedef typename node_type::T2 T2;
34304             typedef typename node_type::T3 T3;
34305 
processexprtk::parser::expression_generator::synthesize_vovovoc_expression334306             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34307                                                       const details::operator_type& operation,
34308                                                       expression_node_ptr (&branch)[2])
34309             {
34310                // ((v0 o0 v1) o1 v2) o2 c
34311                typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
34312 
34313                const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
34314                const Type& v0 = vovov->t0();
34315                const Type& v1 = vovov->t1();
34316                const Type& v2 = vovov->t2();
34317                const Type   c = static_cast<details::literal_node<Type>*>(branch[1])->value();
34318                const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
34319                const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
34320                const details::operator_type o2 = operation;
34321 
34322                binary_functor_t f0 = vovov->f0();
34323                binary_functor_t f1 = vovov->f1();
34324                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34325 
34326                details::free_node(*(expr_gen.node_allocator_),branch[0]);
34327                details::free_node(*(expr_gen.node_allocator_),branch[1]);
34328 
34329                expression_node_ptr result = error_node();
34330 
34331                const bool synthesis_result =
34332                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34333                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
34334 
34335                if (synthesis_result)
34336                   return result;
34337                else if (!expr_gen.valid_operator(o2,f2))
34338                   return error_node();
34339 
34340                exprtk_debug(("((v0 o0 v1) o1 v2) o2 c\n"));
34341 
34342                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
34343             }
34344 
idexprtk::parser::expression_generator::synthesize_vovovoc_expression334345             static inline std::string id(expression_generator<Type>& expr_gen,
34346                                          const details::operator_type o0,
34347                                          const details::operator_type o1,
34348                                          const details::operator_type o2)
34349             {
34350                return details::build_string()
34351                          << "((t" << expr_gen.to_str(o0)
34352                          << "t)"  << expr_gen.to_str(o1)
34353                          << "t)"  << expr_gen.to_str(o2)
34354                          << "t";
34355             }
34356          };
34357 
34358          struct synthesize_vovocov_expression3
34359          {
34360             typedef typename vovocov_t::type3 node_type;
34361             typedef typename vovocov_t::sf4_type sf4_type;
34362             typedef typename node_type::T0 T0;
34363             typedef typename node_type::T1 T1;
34364             typedef typename node_type::T2 T2;
34365             typedef typename node_type::T3 T3;
34366 
processexprtk::parser::expression_generator::synthesize_vovocov_expression334367             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34368                                                       const details::operator_type& operation,
34369                                                       expression_node_ptr (&branch)[2])
34370             {
34371                // ((v0 o0 v1) o1 c) o2 v2
34372                typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t;
34373 
34374                const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]);
34375                const Type& v0 = vovoc->t0();
34376                const Type& v1 = vovoc->t1();
34377                const Type   c = vovoc->t2();
34378                const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
34379                const details::operator_type o0 = expr_gen.get_operator(vovoc->f0());
34380                const details::operator_type o1 = expr_gen.get_operator(vovoc->f1());
34381                const details::operator_type o2 = operation;
34382 
34383                binary_functor_t f0 = vovoc->f0();
34384                binary_functor_t f1 = vovoc->f1();
34385                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34386 
34387                details::free_node(*(expr_gen.node_allocator_),branch[0]);
34388 
34389                expression_node_ptr result = error_node();
34390 
34391                const bool synthesis_result =
34392                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34393                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
34394 
34395                if (synthesis_result)
34396                   return result;
34397                else if (!expr_gen.valid_operator(o2,f2))
34398                   return error_node();
34399 
34400                exprtk_debug(("((v0 o0 v1) o1 c) o2 v2\n"));
34401 
34402                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
34403             }
34404 
idexprtk::parser::expression_generator::synthesize_vovocov_expression334405             static inline std::string id(expression_generator<Type>& expr_gen,
34406                                          const details::operator_type o0,
34407                                          const details::operator_type o1,
34408                                          const details::operator_type o2)
34409             {
34410                return details::build_string()
34411                          << "((t" << expr_gen.to_str(o0)
34412                          << "t)"  << expr_gen.to_str(o1)
34413                          << "t)"  << expr_gen.to_str(o2)
34414                          << "t";
34415             }
34416          };
34417 
34418          struct synthesize_vocovov_expression3
34419          {
34420             typedef typename vocovov_t::type3 node_type;
34421             typedef typename vocovov_t::sf4_type sf4_type;
34422             typedef typename node_type::T0 T0;
34423             typedef typename node_type::T1 T1;
34424             typedef typename node_type::T2 T2;
34425             typedef typename node_type::T3 T3;
34426 
processexprtk::parser::expression_generator::synthesize_vocovov_expression334427             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34428                                                       const details::operator_type& operation,
34429                                                       expression_node_ptr (&branch)[2])
34430             {
34431                // ((v0 o0 c) o1 v1) o2 v2
34432                typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
34433 
34434                const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
34435                const Type& v0 = vocov->t0();
34436                const Type   c = vocov->t1();
34437                const Type& v1 = vocov->t2();
34438                const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
34439                const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
34440                const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
34441                const details::operator_type o2 = operation;
34442 
34443                binary_functor_t f0 = vocov->f0();
34444                binary_functor_t f1 = vocov->f1();
34445                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34446 
34447                details::free_node(*(expr_gen.node_allocator_),branch[0]);
34448 
34449                expression_node_ptr result = error_node();
34450 
34451                const bool synthesis_result =
34452                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34453                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
34454 
34455                if (synthesis_result)
34456                   return result;
34457                else if (!expr_gen.valid_operator(o2,f2))
34458                   return error_node();
34459 
34460                exprtk_debug(("((v0 o0 c) o1 v1) o2 v2\n"));
34461 
34462                return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
34463             }
34464 
idexprtk::parser::expression_generator::synthesize_vocovov_expression334465             static inline std::string id(expression_generator<Type>& expr_gen,
34466                                          const details::operator_type o0,
34467                                          const details::operator_type o1,
34468                                          const details::operator_type o2)
34469             {
34470                return details::build_string()
34471                          << "((t" << expr_gen.to_str(o0)
34472                          << "t)"  << expr_gen.to_str(o1)
34473                          << "t)"  << expr_gen.to_str(o2)
34474                          << "t";
34475             }
34476          };
34477 
34478          struct synthesize_covovov_expression3
34479          {
34480             typedef typename covovov_t::type3 node_type;
34481             typedef typename covovov_t::sf4_type sf4_type;
34482             typedef typename node_type::T0 T0;
34483             typedef typename node_type::T1 T1;
34484             typedef typename node_type::T2 T2;
34485             typedef typename node_type::T3 T3;
34486 
processexprtk::parser::expression_generator::synthesize_covovov_expression334487             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34488                                                       const details::operator_type& operation,
34489                                                       expression_node_ptr (&branch)[2])
34490             {
34491                // ((c o0 v0) o1 v1) o2 v2
34492                typedef typename synthesize_covov_expression0::node_type lcl_covov_t;
34493 
34494                const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
34495                const Type   c = covov->t0();
34496                const Type& v0 = covov->t1();
34497                const Type& v1 = covov->t2();
34498                const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
34499                const details::operator_type o0 = expr_gen.get_operator(covov->f0());
34500                const details::operator_type o1 = expr_gen.get_operator(covov->f1());
34501                const details::operator_type o2 = operation;
34502 
34503                binary_functor_t f0 = covov->f0();
34504                binary_functor_t f1 = covov->f1();
34505                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34506 
34507                details::free_node(*(expr_gen.node_allocator_),branch[0]);
34508 
34509                expression_node_ptr result = error_node();
34510 
34511                const bool synthesis_result =
34512                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34513                      (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
34514 
34515                if (synthesis_result)
34516                   return result;
34517                else if (!expr_gen.valid_operator(o2,f2))
34518                   return error_node();
34519 
34520                exprtk_debug(("((c o0 v0) o1 v1) o2 v2\n"));
34521 
34522                return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
34523             }
34524 
idexprtk::parser::expression_generator::synthesize_covovov_expression334525             static inline std::string id(expression_generator<Type>& expr_gen,
34526                                          const details::operator_type o0,
34527                                          const details::operator_type o1,
34528                                          const details::operator_type o2)
34529             {
34530                return details::build_string()
34531                          << "((t" << expr_gen.to_str(o0)
34532                          << "t)"  << expr_gen.to_str(o1)
34533                          << "t)"  << expr_gen.to_str(o2)
34534                          << "t";
34535             }
34536          };
34537 
34538          struct synthesize_covocov_expression3
34539          {
34540             typedef typename covocov_t::type3 node_type;
34541             typedef typename covocov_t::sf4_type sf4_type;
34542             typedef typename node_type::T0 T0;
34543             typedef typename node_type::T1 T1;
34544             typedef typename node_type::T2 T2;
34545             typedef typename node_type::T3 T3;
34546 
processexprtk::parser::expression_generator::synthesize_covocov_expression334547             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34548                                                       const details::operator_type& operation,
34549                                                       expression_node_ptr (&branch)[2])
34550             {
34551                // ((c0 o0 v0) o1 c1) o2 v1
34552                typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t;
34553 
34554                const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]);
34555                const Type  c0 = covoc->t0();
34556                const Type& v0 = covoc->t1();
34557                const Type  c1 = covoc->t2();
34558                const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
34559                const details::operator_type o0 = expr_gen.get_operator(covoc->f0());
34560                const details::operator_type o1 = expr_gen.get_operator(covoc->f1());
34561                const details::operator_type o2 = operation;
34562 
34563                binary_functor_t f0 = covoc->f0();
34564                binary_functor_t f1 = covoc->f1();
34565                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34566 
34567                details::free_node(*(expr_gen.node_allocator_),branch[0]);
34568 
34569                expression_node_ptr result = error_node();
34570 
34571                const bool synthesis_result =
34572                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34573                      (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
34574 
34575                if (synthesis_result)
34576                   return result;
34577                else if (!expr_gen.valid_operator(o2,f2))
34578                   return error_node();
34579 
34580                exprtk_debug(("((c0 o0 v0) o1 c1) o2 v1\n"));
34581 
34582                return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
34583             }
34584 
idexprtk::parser::expression_generator::synthesize_covocov_expression334585             static inline std::string id(expression_generator<Type>& expr_gen,
34586                                          const details::operator_type o0,
34587                                          const details::operator_type o1,
34588                                          const details::operator_type o2)
34589             {
34590                return details::build_string()
34591                          << "((t" << expr_gen.to_str(o0)
34592                          << "t)"  << expr_gen.to_str(o1)
34593                          << "t)"  << expr_gen.to_str(o2)
34594                          << "t";
34595             }
34596          };
34597 
34598          struct synthesize_vocovoc_expression3
34599          {
34600             typedef typename vocovoc_t::type3 node_type;
34601             typedef typename vocovoc_t::sf4_type sf4_type;
34602             typedef typename node_type::T0 T0;
34603             typedef typename node_type::T1 T1;
34604             typedef typename node_type::T2 T2;
34605             typedef typename node_type::T3 T3;
34606 
processexprtk::parser::expression_generator::synthesize_vocovoc_expression334607             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34608                                                       const details::operator_type& operation,
34609                                                       expression_node_ptr (&branch)[2])
34610             {
34611                // ((v0 o0 c0) o1 v1) o2 c1
34612                typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
34613 
34614                const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
34615                const Type& v0 = vocov->t0();
34616                const Type  c0 = vocov->t1();
34617                const Type& v1 = vocov->t2();
34618                const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
34619                const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
34620                const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
34621                const details::operator_type o2 = operation;
34622 
34623                binary_functor_t f0 = vocov->f0();
34624                binary_functor_t f1 = vocov->f1();
34625                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34626 
34627                details::free_node(*(expr_gen.node_allocator_),branch[0]);
34628                details::free_node(*(expr_gen.node_allocator_),branch[1]);
34629 
34630                expression_node_ptr result = error_node();
34631 
34632                const bool synthesis_result =
34633                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34634                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
34635 
34636                if (synthesis_result)
34637                   return result;
34638                else if (!expr_gen.valid_operator(o2,f2))
34639                   return error_node();
34640 
34641                exprtk_debug(("((v0 o0 c0) o1 v1) o2 c1\n"));
34642 
34643                return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
34644             }
34645 
idexprtk::parser::expression_generator::synthesize_vocovoc_expression334646             static inline std::string id(expression_generator<Type>& expr_gen,
34647                                          const details::operator_type o0,
34648                                          const details::operator_type o1,
34649                                          const details::operator_type o2)
34650             {
34651                return details::build_string()
34652                          << "((t" << expr_gen.to_str(o0)
34653                          << "t)"  << expr_gen.to_str(o1)
34654                          << "t)"  << expr_gen.to_str(o2)
34655                          << "t";
34656             }
34657          };
34658 
34659          struct synthesize_covovoc_expression3
34660          {
34661             typedef typename covovoc_t::type3 node_type;
34662             typedef typename covovoc_t::sf4_type sf4_type;
34663             typedef typename node_type::T0 T0;
34664             typedef typename node_type::T1 T1;
34665             typedef typename node_type::T2 T2;
34666             typedef typename node_type::T3 T3;
34667 
processexprtk::parser::expression_generator::synthesize_covovoc_expression334668             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34669                                                       const details::operator_type& operation,
34670                                                       expression_node_ptr (&branch)[2])
34671             {
34672                // ((c0 o0 v0) o1 v1) o2 c1
34673                typedef typename synthesize_covov_expression0::node_type lcl_covov_t;
34674 
34675                const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
34676                const Type  c0 = covov->t0();
34677                const Type& v0 = covov->t1();
34678                const Type& v1 = covov->t2();
34679                const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
34680                const details::operator_type o0 = expr_gen.get_operator(covov->f0());
34681                const details::operator_type o1 = expr_gen.get_operator(covov->f1());
34682                const details::operator_type o2 = operation;
34683 
34684                binary_functor_t f0 = covov->f0();
34685                binary_functor_t f1 = covov->f1();
34686                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34687 
34688                details::free_node(*(expr_gen.node_allocator_),branch[0]);
34689                details::free_node(*(expr_gen.node_allocator_),branch[1]);
34690 
34691                expression_node_ptr result = error_node();
34692 
34693                const bool synthesis_result =
34694                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34695                      (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
34696 
34697                if (synthesis_result)
34698                   return result;
34699                else if (!expr_gen.valid_operator(o2,f2))
34700                   return error_node();
34701 
34702                exprtk_debug(("((c0 o0 v0) o1 v1) o2 c1\n"));
34703 
34704                return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
34705             }
34706 
idexprtk::parser::expression_generator::synthesize_covovoc_expression334707             static inline std::string id(expression_generator<Type>& expr_gen,
34708                                          const details::operator_type o0,
34709                                          const details::operator_type o1,
34710                                          const details::operator_type o2)
34711             {
34712                return details::build_string()
34713                          << "((t" << expr_gen.to_str(o0)
34714                          << "t)"  << expr_gen.to_str(o1)
34715                          << "t)"  << expr_gen.to_str(o2)
34716                          << "t";
34717             }
34718          };
34719 
34720          struct synthesize_vococov_expression3
34721          {
34722             typedef typename vococov_t::type3 node_type;
34723             typedef typename vococov_t::sf4_type sf4_type;
34724             typedef typename node_type::T0 T0;
34725             typedef typename node_type::T1 T1;
34726             typedef typename node_type::T2 T2;
34727             typedef typename node_type::T3 T3;
34728 
processexprtk::parser::expression_generator::synthesize_vococov_expression334729             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34730                                                       const details::operator_type& operation,
34731                                                       expression_node_ptr (&branch)[2])
34732             {
34733                // ((v0 o0 c0) o1 c1) o2 v1
34734                typedef typename synthesize_vococ_expression0::node_type lcl_vococ_t;
34735 
34736                const lcl_vococ_t* vococ = static_cast<const lcl_vococ_t*>(branch[0]);
34737                const Type& v0 = vococ->t0();
34738                const Type  c0 = vococ->t1();
34739                const Type  c1 = vococ->t2();
34740                const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
34741                const details::operator_type o0 = expr_gen.get_operator(vococ->f0());
34742                const details::operator_type o1 = expr_gen.get_operator(vococ->f1());
34743                const details::operator_type o2 = operation;
34744 
34745                binary_functor_t f0 = vococ->f0();
34746                binary_functor_t f1 = vococ->f1();
34747                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34748 
34749                details::free_node(*(expr_gen.node_allocator_),branch[0]);
34750 
34751                expression_node_ptr result = error_node();
34752 
34753                const bool synthesis_result =
34754                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34755                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result);
34756 
34757                if (synthesis_result)
34758                   return result;
34759                else if (!expr_gen.valid_operator(o2,f2))
34760                   return error_node();
34761 
34762                exprtk_debug(("((v0 o0 c0) o1 c1) o2 v1\n"));
34763 
34764                return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2);
34765             }
34766 
idexprtk::parser::expression_generator::synthesize_vococov_expression334767             static inline std::string id(expression_generator<Type>& expr_gen,
34768                                          const details::operator_type o0,
34769                                          const details::operator_type o1,
34770                                          const details::operator_type o2)
34771             {
34772                return details::build_string()
34773                          << "((t" << expr_gen.to_str(o0)
34774                          << "t)"  << expr_gen.to_str(o1)
34775                          << "t)"  << expr_gen.to_str(o2)
34776                          << "t";
34777             }
34778          };
34779 
34780          struct synthesize_vovovov_expression4
34781          {
34782             typedef typename vovovov_t::type4 node_type;
34783             typedef typename vovovov_t::sf4_type sf4_type;
34784             typedef typename node_type::T0 T0;
34785             typedef typename node_type::T1 T1;
34786             typedef typename node_type::T2 T2;
34787             typedef typename node_type::T3 T3;
34788 
processexprtk::parser::expression_generator::synthesize_vovovov_expression434789             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34790                                                       const details::operator_type& operation,
34791                                                       expression_node_ptr (&branch)[2])
34792             {
34793                // (v0 o0 (v1 o1 v2)) o2 v3
34794                typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
34795 
34796                const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
34797                const Type& v0 = vovov->t0();
34798                const Type& v1 = vovov->t1();
34799                const Type& v2 = vovov->t2();
34800                const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
34801                const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
34802                const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
34803                const details::operator_type o2 = operation;
34804 
34805                binary_functor_t f0 = vovov->f0();
34806                binary_functor_t f1 = vovov->f1();
34807                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34808 
34809                details::free_node(*(expr_gen.node_allocator_),branch[0]);
34810 
34811                expression_node_ptr result = error_node();
34812 
34813                const bool synthesis_result =
34814                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34815                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
34816 
34817                if (synthesis_result)
34818                   return result;
34819                else if (!expr_gen.valid_operator(o2,f2))
34820                   return error_node();
34821 
34822                exprtk_debug(("(v0 o0 (v1 o1 v2)) o2 v3\n"));
34823 
34824                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
34825             }
34826 
idexprtk::parser::expression_generator::synthesize_vovovov_expression434827             static inline std::string id(expression_generator<Type>& expr_gen,
34828                                          const details::operator_type o0,
34829                                          const details::operator_type o1,
34830                                          const details::operator_type o2)
34831             {
34832                return details::build_string()
34833                          << "(t" << expr_gen.to_str(o0)
34834                          << "(t" << expr_gen.to_str(o1)
34835                          << "t)" << expr_gen.to_str(o2)
34836                          << "t";
34837             }
34838          };
34839 
34840          struct synthesize_vovovoc_expression4
34841          {
34842             typedef typename vovovoc_t::type4 node_type;
34843             typedef typename vovovoc_t::sf4_type sf4_type;
34844             typedef typename node_type::T0 T0;
34845             typedef typename node_type::T1 T1;
34846             typedef typename node_type::T2 T2;
34847             typedef typename node_type::T3 T3;
34848 
processexprtk::parser::expression_generator::synthesize_vovovoc_expression434849             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34850                                                       const details::operator_type& operation,
34851                                                       expression_node_ptr (&branch)[2])
34852             {
34853                // ((v0 o0 (v1 o1 v2)) o2 c)
34854                typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
34855 
34856                const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
34857                const Type& v0 = vovov->t0();
34858                const Type& v1 = vovov->t1();
34859                const Type& v2 = vovov->t2();
34860                const Type   c = static_cast<details::literal_node<Type>*>(branch[1])->value();
34861                const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
34862                const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
34863                const details::operator_type o2 = operation;
34864 
34865                binary_functor_t f0 = vovov->f0();
34866                binary_functor_t f1 = vovov->f1();
34867                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34868 
34869                details::free_node(*(expr_gen.node_allocator_),branch[0]);
34870                details::free_node(*(expr_gen.node_allocator_),branch[1]);
34871 
34872                expression_node_ptr result = error_node();
34873 
34874                const bool synthesis_result =
34875                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34876                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
34877 
34878                if (synthesis_result)
34879                   return result;
34880                else if (!expr_gen.valid_operator(o2,f2))
34881                   return error_node();
34882 
34883                exprtk_debug(("((v0 o0 (v1 o1 v2)) o2 c)\n"));
34884 
34885                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
34886             }
34887 
idexprtk::parser::expression_generator::synthesize_vovovoc_expression434888             static inline std::string id(expression_generator<Type>& expr_gen,
34889                                          const details::operator_type o0,
34890                                          const details::operator_type o1,
34891                                          const details::operator_type o2)
34892             {
34893                return details::build_string()
34894                          << "(t" << expr_gen.to_str(o0)
34895                          << "(t" << expr_gen.to_str(o1)
34896                          << "t)" << expr_gen.to_str(o2)
34897                          << "t";
34898             }
34899          };
34900 
34901          struct synthesize_vovocov_expression4
34902          {
34903             typedef typename vovocov_t::type4 node_type;
34904             typedef typename vovocov_t::sf4_type sf4_type;
34905             typedef typename node_type::T0 T0;
34906             typedef typename node_type::T1 T1;
34907             typedef typename node_type::T2 T2;
34908             typedef typename node_type::T3 T3;
34909 
processexprtk::parser::expression_generator::synthesize_vovocov_expression434910             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34911                                                       const details::operator_type& operation,
34912                                                       expression_node_ptr (&branch)[2])
34913             {
34914                // ((v0 o0 (v1 o1 c)) o2 v1)
34915                typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t;
34916 
34917                const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]);
34918                const Type& v0 = vovoc->t0();
34919                const Type& v1 = vovoc->t1();
34920                const Type   c = vovoc->t2();
34921                const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
34922                const details::operator_type o0 = expr_gen.get_operator(vovoc->f0());
34923                const details::operator_type o1 = expr_gen.get_operator(vovoc->f1());
34924                const details::operator_type o2 = operation;
34925 
34926                binary_functor_t f0 = vovoc->f0();
34927                binary_functor_t f1 = vovoc->f1();
34928                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34929 
34930                details::free_node(*(expr_gen.node_allocator_),branch[0]);
34931 
34932                expression_node_ptr result = error_node();
34933 
34934                const bool synthesis_result =
34935                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34936                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
34937 
34938                if (synthesis_result)
34939                   return result;
34940                else if (!expr_gen.valid_operator(o2,f2))
34941                   return error_node();
34942 
34943                exprtk_debug(("((v0 o0 (v1 o1 c)) o2 v1)\n"));
34944 
34945                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
34946             }
34947 
idexprtk::parser::expression_generator::synthesize_vovocov_expression434948             static inline std::string id(expression_generator<Type>& expr_gen,
34949                                          const details::operator_type o0,
34950                                          const details::operator_type o1,
34951                                          const details::operator_type o2)
34952             {
34953                return details::build_string()
34954                          << "(t" << expr_gen.to_str(o0)
34955                          << "(t" << expr_gen.to_str(o1)
34956                          << "t)" << expr_gen.to_str(o2)
34957                          << "t";
34958             }
34959          };
34960 
34961          struct synthesize_vocovov_expression4
34962          {
34963             typedef typename vocovov_t::type4 node_type;
34964             typedef typename vocovov_t::sf4_type sf4_type;
34965             typedef typename node_type::T0 T0;
34966             typedef typename node_type::T1 T1;
34967             typedef typename node_type::T2 T2;
34968             typedef typename node_type::T3 T3;
34969 
processexprtk::parser::expression_generator::synthesize_vocovov_expression434970             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34971                                                       const details::operator_type& operation,
34972                                                       expression_node_ptr (&branch)[2])
34973             {
34974                // ((v0 o0 (c o1 v1)) o2 v2)
34975                typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
34976 
34977                const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
34978                const Type& v0 = vocov->t0();
34979                const Type   c = vocov->t1();
34980                const Type& v1 = vocov->t2();
34981                const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
34982                const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
34983                const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
34984                const details::operator_type o2 = operation;
34985 
34986                binary_functor_t f0 = vocov->f0();
34987                binary_functor_t f1 = vocov->f1();
34988                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34989 
34990                details::free_node(*(expr_gen.node_allocator_),branch[0]);
34991                expression_node_ptr result = error_node();
34992 
34993                const bool synthesis_result =
34994                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34995                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
34996 
34997                if (synthesis_result)
34998                   return result;
34999                else if (!expr_gen.valid_operator(o2,f2))
35000                   return error_node();
35001 
35002                exprtk_debug(("((v0 o0 (c o1 v1)) o2 v2)\n"));
35003 
35004                return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
35005             }
35006 
idexprtk::parser::expression_generator::synthesize_vocovov_expression435007             static inline std::string id(expression_generator<Type>& expr_gen,
35008                                          const details::operator_type o0,
35009                                          const details::operator_type o1,
35010                                          const details::operator_type o2)
35011             {
35012                return details::build_string()
35013                          << "(t" << expr_gen.to_str(o0)
35014                          << "(t" << expr_gen.to_str(o1)
35015                          << "t)" << expr_gen.to_str(o2)
35016                          << "t";
35017             }
35018          };
35019 
35020          struct synthesize_covovov_expression4
35021          {
35022             typedef typename covovov_t::type4 node_type;
35023             typedef typename covovov_t::sf4_type sf4_type;
35024             typedef typename node_type::T0 T0;
35025             typedef typename node_type::T1 T1;
35026             typedef typename node_type::T2 T2;
35027             typedef typename node_type::T3 T3;
35028 
processexprtk::parser::expression_generator::synthesize_covovov_expression435029             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
35030                                                       const details::operator_type& operation,
35031                                                       expression_node_ptr (&branch)[2])
35032             {
35033                // ((c o0 (v0 o1 v1)) o2 v2)
35034                typedef typename synthesize_covov_expression1::node_type lcl_covov_t;
35035 
35036                const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
35037                const Type   c = covov->t0();
35038                const Type& v0 = covov->t1();
35039                const Type& v1 = covov->t2();
35040                const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
35041                const details::operator_type o0 = expr_gen.get_operator(covov->f0());
35042                const details::operator_type o1 = expr_gen.get_operator(covov->f1());
35043                const details::operator_type o2 = operation;
35044 
35045                binary_functor_t f0 = covov->f0();
35046                binary_functor_t f1 = covov->f1();
35047                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
35048 
35049                details::free_node(*(expr_gen.node_allocator_),branch[0]);
35050 
35051                expression_node_ptr result = error_node();
35052 
35053                const bool synthesis_result =
35054                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
35055                      (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
35056 
35057                if (synthesis_result)
35058                   return result;
35059                else if (!expr_gen.valid_operator(o2,f2))
35060                   return error_node();
35061 
35062                exprtk_debug(("((c o0 (v0 o1 v1)) o2 v2)\n"));
35063 
35064                return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
35065             }
35066 
idexprtk::parser::expression_generator::synthesize_covovov_expression435067             static inline std::string id(expression_generator<Type>& expr_gen,
35068                                          const details::operator_type o0,
35069                                          const details::operator_type o1,
35070                                          const details::operator_type o2)
35071             {
35072                return details::build_string()
35073                          << "(t" << expr_gen.to_str(o0)
35074                          << "(t" << expr_gen.to_str(o1)
35075                          << "t)" << expr_gen.to_str(o2)
35076                          << "t";
35077             }
35078          };
35079 
35080          struct synthesize_covocov_expression4
35081          {
35082             typedef typename covocov_t::type4 node_type;
35083             typedef typename covocov_t::sf4_type sf4_type;
35084             typedef typename node_type::T0 T0;
35085             typedef typename node_type::T1 T1;
35086             typedef typename node_type::T2 T2;
35087             typedef typename node_type::T3 T3;
35088 
processexprtk::parser::expression_generator::synthesize_covocov_expression435089             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
35090                                                       const details::operator_type& operation,
35091                                                       expression_node_ptr (&branch)[2])
35092             {
35093                // ((c0 o0 (v0 o1 c1)) o2 v1)
35094                typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t;
35095 
35096                const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]);
35097                const Type  c0 = covoc->t0();
35098                const Type& v0 = covoc->t1();
35099                const Type  c1 = covoc->t2();
35100                const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
35101                const details::operator_type o0 = expr_gen.get_operator(covoc->f0());
35102                const details::operator_type o1 = expr_gen.get_operator(covoc->f1());
35103                const details::operator_type o2 = operation;
35104 
35105                binary_functor_t f0 = covoc->f0();
35106                binary_functor_t f1 = covoc->f1();
35107                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
35108 
35109                details::free_node(*(expr_gen.node_allocator_),branch[0]);
35110 
35111                expression_node_ptr result = error_node();
35112 
35113                const bool synthesis_result =
35114                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
35115                      (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
35116 
35117                if (synthesis_result)
35118                   return result;
35119                else if (!expr_gen.valid_operator(o2,f2))
35120                   return error_node();
35121 
35122                exprtk_debug(("((c0 o0 (v0 o1 c1)) o2 v1)\n"));
35123 
35124                return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
35125             }
35126 
idexprtk::parser::expression_generator::synthesize_covocov_expression435127             static inline std::string id(expression_generator<Type>& expr_gen,
35128                                          const details::operator_type o0,
35129                                          const details::operator_type o1,
35130                                          const details::operator_type o2)
35131             {
35132                return details::build_string()
35133                          << "(t" << expr_gen.to_str(o0)
35134                          << "(t" << expr_gen.to_str(o1)
35135                          << "t)" << expr_gen.to_str(o2)
35136                          << "t";
35137             }
35138          };
35139 
35140          struct synthesize_vocovoc_expression4
35141          {
35142             typedef typename vocovoc_t::type4 node_type;
35143             typedef typename vocovoc_t::sf4_type sf4_type;
35144             typedef typename node_type::T0 T0;
35145             typedef typename node_type::T1 T1;
35146             typedef typename node_type::T2 T2;
35147             typedef typename node_type::T3 T3;
35148 
processexprtk::parser::expression_generator::synthesize_vocovoc_expression435149             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
35150                                                       const details::operator_type& operation,
35151                                                       expression_node_ptr (&branch)[2])
35152             {
35153                // ((v0 o0 (c0 o1 v1)) o2 c1)
35154                typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
35155 
35156                const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
35157                const Type& v0 = vocov->t0();
35158                const Type  c0 = vocov->t1();
35159                const Type& v1 = vocov->t2();
35160                const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
35161                const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
35162                const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
35163                const details::operator_type o2 = operation;
35164 
35165                binary_functor_t f0 = vocov->f0();
35166                binary_functor_t f1 = vocov->f1();
35167                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
35168 
35169                details::free_node(*(expr_gen.node_allocator_),branch[0]);
35170                details::free_node(*(expr_gen.node_allocator_),branch[1]);
35171 
35172                expression_node_ptr result = error_node();
35173 
35174                const bool synthesis_result =
35175                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
35176                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
35177 
35178                if (synthesis_result)
35179                   return result;
35180                else if (!expr_gen.valid_operator(o2,f2))
35181                   return error_node();
35182 
35183                exprtk_debug(("((v0 o0 (c0 o1 v1)) o2 c1)\n"));
35184 
35185                return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
35186             }
35187 
idexprtk::parser::expression_generator::synthesize_vocovoc_expression435188             static inline std::string id(expression_generator<Type>& expr_gen,
35189                                          const details::operator_type o0,
35190                                          const details::operator_type o1,
35191                                          const details::operator_type o2)
35192             {
35193                return details::build_string()
35194                          << "(t" << expr_gen.to_str(o0)
35195                          << "(t" << expr_gen.to_str(o1)
35196                          << "t)" << expr_gen.to_str(o2)
35197                          << "t";
35198             }
35199          };
35200 
35201          struct synthesize_covovoc_expression4
35202          {
35203             typedef typename covovoc_t::type4 node_type;
35204             typedef typename covovoc_t::sf4_type sf4_type;
35205             typedef typename node_type::T0 T0;
35206             typedef typename node_type::T1 T1;
35207             typedef typename node_type::T2 T2;
35208             typedef typename node_type::T3 T3;
35209 
processexprtk::parser::expression_generator::synthesize_covovoc_expression435210             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
35211                                                       const details::operator_type& operation,
35212                                                       expression_node_ptr (&branch)[2])
35213             {
35214                // ((c0 o0 (v0 o1 v1)) o2 c1)
35215                typedef typename synthesize_covov_expression1::node_type lcl_covov_t;
35216 
35217                const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
35218                const Type  c0 = covov->t0();
35219                const Type& v0 = covov->t1();
35220                const Type& v1 = covov->t2();
35221                const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
35222                const details::operator_type o0 = expr_gen.get_operator(covov->f0());
35223                const details::operator_type o1 = expr_gen.get_operator(covov->f1());
35224                const details::operator_type o2 = operation;
35225 
35226                binary_functor_t f0 = covov->f0();
35227                binary_functor_t f1 = covov->f1();
35228                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
35229 
35230                details::free_node(*(expr_gen.node_allocator_),branch[0]);
35231                details::free_node(*(expr_gen.node_allocator_),branch[1]);
35232 
35233                expression_node_ptr result = error_node();
35234 
35235                const bool synthesis_result =
35236                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
35237                      (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
35238 
35239                if (synthesis_result)
35240                   return result;
35241                else if (!expr_gen.valid_operator(o2,f2))
35242                   return error_node();
35243 
35244                exprtk_debug(("((c0 o0 (v0 o1 v1)) o2 c1)\n"));
35245 
35246                return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
35247             }
35248 
idexprtk::parser::expression_generator::synthesize_covovoc_expression435249             static inline std::string id(expression_generator<Type>& expr_gen,
35250                                          const details::operator_type o0,
35251                                          const details::operator_type o1,
35252                                          const details::operator_type o2)
35253             {
35254                return details::build_string()
35255                          << "(t" << expr_gen.to_str(o0)
35256                          << "(t" << expr_gen.to_str(o1)
35257                          << "t)" << expr_gen.to_str(o2)
35258                          << "t";
35259             }
35260          };
35261 
35262          struct synthesize_vococov_expression4
35263          {
35264             typedef typename vococov_t::type4 node_type;
processexprtk::parser::expression_generator::synthesize_vococov_expression435265             static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
35266             {
35267                // ((v0 o0 (c0 o1 c1)) o2 v1) - Not possible
35268                exprtk_debug(("((v0 o0 (c0 o1 c1)) o2 v1) - Not possible\n"));
35269                return error_node();
35270             }
35271 
idexprtk::parser::expression_generator::synthesize_vococov_expression435272             static inline std::string id(expression_generator<Type>&,
35273                                          const details::operator_type, const details::operator_type, const details::operator_type)
35274             {
35275                return "INVALID";
35276             }
35277          };
35278          #endif
35279 
synthesize_uvouv_expression(const details::operator_type & operation,expression_node_ptr (& branch)[2])35280          inline expression_node_ptr synthesize_uvouv_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
35281          {
35282             // Definition: uv o uv
35283             details::operator_type o0 = static_cast<details::uv_base_node<Type>*>(branch[0])->operation();
35284             details::operator_type o1 = static_cast<details::uv_base_node<Type>*>(branch[1])->operation();
35285             const Type& v0 = static_cast<details::uv_base_node<Type>*>(branch[0])->v();
35286             const Type& v1 = static_cast<details::uv_base_node<Type>*>(branch[1])->v();
35287             unary_functor_t u0 = reinterpret_cast<unary_functor_t> (0);
35288             unary_functor_t u1 = reinterpret_cast<unary_functor_t> (0);
35289             binary_functor_t f = reinterpret_cast<binary_functor_t>(0);
35290 
35291             if (!valid_operator(o0,u0))
35292                return error_node();
35293             else if (!valid_operator(o1,u1))
35294                return error_node();
35295             else if (!valid_operator(operation,f))
35296                return error_node();
35297 
35298             expression_node_ptr result = error_node();
35299 
35300             if (
35301                  (details::e_neg == o0) &&
35302                  (details::e_neg == o1)
35303                )
35304             {
35305                switch (operation)
35306                {
35307                   // (-v0 + -v1) --> -(v0 + v1)
35308                   case details::e_add : result = (*this)(details::e_neg,
35309                                                     node_allocator_->
35310                                                        allocate_rr<typename details::
35311                                                           vov_node<Type,details::add_op<Type> > >(v0, v1));
35312                                         exprtk_debug(("(-v0 + -v1) --> -(v0 + v1)\n"));
35313                                         break;
35314 
35315                   // (-v0 - -v1) --> (v1 - v0)
35316                   case details::e_sub : result = node_allocator_->
35317                                                     allocate_rr<typename details::
35318                                                        vov_node<Type,details::sub_op<Type> > >(v1, v0);
35319                                         exprtk_debug(("(-v0 - -v1) --> (v1 - v0)\n"));
35320                                         break;
35321 
35322                   // (-v0 * -v1) --> (v0 * v1)
35323                   case details::e_mul : result = node_allocator_->
35324                                                     allocate_rr<typename details::
35325                                                        vov_node<Type,details::mul_op<Type> > >(v0, v1);
35326                                         exprtk_debug(("(-v0 * -v1) --> (v0 * v1)\n"));
35327                                         break;
35328 
35329                   // (-v0 / -v1) --> (v0 / v1)
35330                   case details::e_div : result = node_allocator_->
35331                                                     allocate_rr<typename details::
35332                                                        vov_node<Type,details::div_op<Type> > >(v0, v1);
35333                                         exprtk_debug(("(-v0 / -v1) --> (v0 / v1)\n"));
35334                                         break;
35335 
35336                   default             : break;
35337                }
35338             }
35339 
35340             if (0 == result)
35341             {
35342                result = node_allocator_->
35343                             allocate_rrrrr<typename details::uvouv_node<Type> >(v0, v1, u0, u1, f);
35344             }
35345 
35346             details::free_all_nodes(*node_allocator_,branch);
35347             return result;
35348          }
35349 
35350          #undef basic_opr_switch_statements
35351          #undef extended_opr_switch_statements
35352          #undef unary_opr_switch_statements
35353 
35354          #ifndef exprtk_disable_string_capabilities
35355 
35356          #define string_opr_switch_statements          \
35357          case_stmt(details::  e_lt ,details::   lt_op) \
35358          case_stmt(details:: e_lte ,details::  lte_op) \
35359          case_stmt(details::  e_gt ,details::   gt_op) \
35360          case_stmt(details:: e_gte ,details::  gte_op) \
35361          case_stmt(details::  e_eq ,details::   eq_op) \
35362          case_stmt(details::  e_ne ,details::   ne_op) \
35363          case_stmt(details::e_in   ,details::   in_op) \
35364          case_stmt(details::e_like ,details:: like_op) \
35365          case_stmt(details::e_ilike,details::ilike_op) \
35366 
35367          template <typename T0, typename T1>
synthesize_str_xrox_expression_impl(const details::operator_type & opr,T0 s0,T1 s1,range_t rp0)35368          inline expression_node_ptr synthesize_str_xrox_expression_impl(const details::operator_type& opr,
35369                                                                         T0 s0, T1 s1,
35370                                                                         range_t rp0)
35371          {
35372             switch (opr)
35373             {
35374                #define case_stmt(op0,op1)                                                                       \
35375                case op0 : return node_allocator_->                                                              \
35376                              allocate_ttt<typename details::str_xrox_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \
35377                                 (s0, s1, rp0);                                                                  \
35378 
35379                string_opr_switch_statements
35380                #undef case_stmt
35381                default : return error_node();
35382             }
35383          }
35384 
35385          template <typename T0, typename T1>
synthesize_str_xoxr_expression_impl(const details::operator_type & opr,T0 s0,T1 s1,range_t rp1)35386          inline expression_node_ptr synthesize_str_xoxr_expression_impl(const details::operator_type& opr,
35387                                                                         T0 s0, T1 s1,
35388                                                                         range_t rp1)
35389          {
35390             switch (opr)
35391             {
35392                #define case_stmt(op0,op1)                                                                       \
35393                case op0 : return node_allocator_->                                                              \
35394                              allocate_ttt<typename details::str_xoxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \
35395                                 (s0, s1, rp1);                                                                  \
35396 
35397                string_opr_switch_statements
35398                #undef case_stmt
35399                default : return error_node();
35400             }
35401          }
35402 
35403          template <typename T0, typename T1>
synthesize_str_xroxr_expression_impl(const details::operator_type & opr,T0 s0,T1 s1,range_t rp0,range_t rp1)35404          inline expression_node_ptr synthesize_str_xroxr_expression_impl(const details::operator_type& opr,
35405                                                                          T0 s0, T1 s1,
35406                                                                          range_t rp0, range_t rp1)
35407          {
35408             switch (opr)
35409             {
35410                #define case_stmt(op0,op1)                                                                         \
35411                case op0 : return node_allocator_->                                                                \
35412                              allocate_tttt<typename details::str_xroxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \
35413                                 (s0, s1, rp0, rp1);                                                               \
35414 
35415                string_opr_switch_statements
35416                #undef case_stmt
35417                default : return error_node();
35418             }
35419          }
35420 
35421          template <typename T0, typename T1>
synthesize_sos_expression_impl(const details::operator_type & opr,T0 s0,T1 s1)35422          inline expression_node_ptr synthesize_sos_expression_impl(const details::operator_type& opr, T0 s0, T1 s1)
35423          {
35424             switch (opr)
35425             {
35426                #define case_stmt(op0,op1)                                                                  \
35427                case op0 : return node_allocator_->                                                         \
35428                              allocate_tt<typename details::sos_node<Type,T0,T1,op1<Type> >,T0,T1>(s0, s1); \
35429 
35430                string_opr_switch_statements
35431                #undef case_stmt
35432                default : return error_node();
35433             }
35434          }
35435 
synthesize_sos_expression(const details::operator_type & opr,expression_node_ptr (& branch)[2])35436          inline expression_node_ptr synthesize_sos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
35437          {
35438             std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref();
35439             std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref();
35440 
35441             return synthesize_sos_expression_impl<std::string&,std::string&>(opr, s0, s1);
35442          }
35443 
synthesize_sros_expression(const details::operator_type & opr,expression_node_ptr (& branch)[2])35444          inline expression_node_ptr synthesize_sros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
35445          {
35446             std::string&  s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref  ();
35447             std::string&  s1 = static_cast<details::stringvar_node<Type>*>   (branch[1])->ref  ();
35448             range_t      rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range();
35449 
35450             static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();
35451 
35452             free_node(*node_allocator_,branch[0]);
35453 
35454             return synthesize_str_xrox_expression_impl<std::string&,std::string&>(opr, s0, s1, rp0);
35455          }
35456 
synthesize_sosr_expression(const details::operator_type & opr,expression_node_ptr (& branch)[2])35457          inline expression_node_ptr synthesize_sosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
35458          {
35459             std::string&  s0 = static_cast<details::stringvar_node<Type>*>   (branch[0])->ref  ();
35460             std::string&  s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref  ();
35461             range_t      rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range();
35462 
35463             static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();
35464 
35465             free_node(*node_allocator_,branch[1]);
35466 
35467             return synthesize_str_xoxr_expression_impl<std::string&,std::string&>(opr, s0, s1, rp1);
35468          }
35469 
synthesize_socsr_expression(const details::operator_type & opr,expression_node_ptr (& branch)[2])35470          inline expression_node_ptr synthesize_socsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
35471          {
35472             std::string&  s0 = static_cast<details::stringvar_node<Type>*>         (branch[0])->ref  ();
35473             std::string   s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str  ();
35474             range_t      rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
35475 
35476             static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
35477 
35478             free_node(*node_allocator_,branch[1]);
35479 
35480             return synthesize_str_xoxr_expression_impl<std::string&, const std::string>(opr, s0, s1, rp1);
35481          }
35482 
synthesize_srosr_expression(const details::operator_type & opr,expression_node_ptr (& branch)[2])35483          inline expression_node_ptr synthesize_srosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
35484          {
35485             std::string&  s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref  ();
35486             std::string&  s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref  ();
35487             range_t      rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range();
35488             range_t      rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range();
35489 
35490             static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();
35491             static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();
35492 
35493             details::free_node(*node_allocator_,branch[0]);
35494             details::free_node(*node_allocator_,branch[1]);
35495 
35496             return synthesize_str_xroxr_expression_impl<std::string&,std::string&>(opr, s0, s1, rp0, rp1);
35497          }
35498 
synthesize_socs_expression(const details::operator_type & opr,expression_node_ptr (& branch)[2])35499          inline expression_node_ptr synthesize_socs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
35500          {
35501             std::string& s0 = static_cast<     details::stringvar_node<Type>*>(branch[0])->ref();
35502             std::string  s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
35503 
35504             details::free_node(*node_allocator_,branch[1]);
35505 
35506             return synthesize_sos_expression_impl<std::string&, const std::string>(opr, s0, s1);
35507          }
35508 
synthesize_csos_expression(const details::operator_type & opr,expression_node_ptr (& branch)[2])35509          inline expression_node_ptr synthesize_csos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
35510          {
35511             std::string  s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
35512             std::string& s1 = static_cast<     details::stringvar_node<Type>*>(branch[1])->ref();
35513 
35514             details::free_node(*node_allocator_,branch[0]);
35515 
35516             return synthesize_sos_expression_impl<const std::string,std::string&>(opr, s0, s1);
35517          }
35518 
synthesize_csosr_expression(const details::operator_type & opr,expression_node_ptr (& branch)[2])35519          inline expression_node_ptr synthesize_csosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
35520          {
35521             std::string   s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str  ();
35522             std::string&  s1 = static_cast<details::string_range_node<Type>*>  (branch[1])->ref  ();
35523             range_t      rp1 = static_cast<details::string_range_node<Type>*>  (branch[1])->range();
35524 
35525             static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();
35526 
35527             details::free_node(*node_allocator_,branch[0]);
35528             details::free_node(*node_allocator_,branch[1]);
35529 
35530             return synthesize_str_xoxr_expression_impl<const std::string,std::string&>(opr, s0, s1, rp1);
35531          }
35532 
synthesize_srocs_expression(const details::operator_type & opr,expression_node_ptr (& branch)[2])35533          inline expression_node_ptr synthesize_srocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
35534          {
35535             std::string&  s0 = static_cast<details::string_range_node<Type>*>  (branch[0])->ref  ();
35536             std::string   s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str  ();
35537             range_t      rp0 = static_cast<details::string_range_node<Type>*>  (branch[0])->range();
35538 
35539             static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();
35540 
35541             details::free_node(*node_allocator_,branch[0]);
35542             details::free_node(*node_allocator_,branch[1]);
35543 
35544             return synthesize_str_xrox_expression_impl<std::string&, const std::string>(opr, s0, s1, rp0);
35545          }
35546 
synthesize_srocsr_expression(const details::operator_type & opr,expression_node_ptr (& branch)[2])35547          inline expression_node_ptr synthesize_srocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
35548          {
35549             std::string&  s0 = static_cast<details::string_range_node<Type>*>      (branch[0])->ref  ();
35550             std::string   s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str  ();
35551             range_t      rp0 = static_cast<details::string_range_node<Type>*>      (branch[0])->range();
35552             range_t      rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
35553 
35554             static_cast<details::string_range_node<Type>*>      (branch[0])->range_ref().clear();
35555             static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
35556 
35557             details::free_node(*node_allocator_,branch[0]);
35558             details::free_node(*node_allocator_,branch[1]);
35559 
35560             return synthesize_str_xroxr_expression_impl<std::string&, const std::string>(opr, s0, s1, rp0, rp1);
35561          }
35562 
synthesize_csocs_expression(const details::operator_type & opr,expression_node_ptr (& branch)[2])35563          inline expression_node_ptr synthesize_csocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
35564          {
35565             const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
35566             const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
35567 
35568             expression_node_ptr result = error_node();
35569 
35570             if (details::e_add == opr)
35571                result = node_allocator_->allocate_c<details::string_literal_node<Type> >(s0 + s1);
35572             else if (details::e_in == opr)
35573                result = node_allocator_->allocate_c<details::literal_node<Type> >(details::in_op   <Type>::process(s0,s1));
35574             else if (details::e_like == opr)
35575                result = node_allocator_->allocate_c<details::literal_node<Type> >(details::like_op <Type>::process(s0,s1));
35576             else if (details::e_ilike == opr)
35577                result = node_allocator_->allocate_c<details::literal_node<Type> >(details::ilike_op<Type>::process(s0,s1));
35578             else
35579             {
35580                expression_node_ptr temp = synthesize_sos_expression_impl<const std::string, const std::string>(opr, s0, s1);
35581 
35582                const Type v = temp->value();
35583 
35584                details::free_node(*node_allocator_,temp);
35585 
35586                result = node_allocator_->allocate<literal_node_t>(v);
35587             }
35588 
35589             details::free_all_nodes(*node_allocator_,branch);
35590 
35591             return result;
35592          }
35593 
synthesize_csocsr_expression(const details::operator_type & opr,expression_node_ptr (& branch)[2])35594          inline expression_node_ptr synthesize_csocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
35595          {
35596             const std::string s0 = static_cast<details::string_literal_node<Type>*>    (branch[0])->str  ();
35597                   std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str  ();
35598             range_t          rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
35599 
35600             static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
35601 
35602             free_node(*node_allocator_,branch[0]);
35603             free_node(*node_allocator_,branch[1]);
35604 
35605             return synthesize_str_xoxr_expression_impl<const std::string, const std::string>(opr, s0, s1, rp1);
35606          }
35607 
synthesize_csros_expression(const details::operator_type & opr,expression_node_ptr (& branch)[2])35608          inline expression_node_ptr synthesize_csros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
35609          {
35610             std::string   s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str  ();
35611             std::string&  s1 = static_cast<details::stringvar_node<Type>*>         (branch[1])->ref  ();
35612             range_t      rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
35613 
35614             static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
35615 
35616             free_node(*node_allocator_,branch[0]);
35617 
35618             return synthesize_str_xrox_expression_impl<const std::string,std::string&>(opr, s0, s1, rp0);
35619          }
35620 
synthesize_csrosr_expression(const details::operator_type & opr,expression_node_ptr (& branch)[2])35621          inline expression_node_ptr synthesize_csrosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
35622          {
35623             const std::string  s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str  ();
35624                   std::string& s1 = static_cast<details::string_range_node<Type>*>      (branch[1])->ref  ();
35625             const range_t     rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
35626             const range_t     rp1 = static_cast<details::string_range_node<Type>*>      (branch[1])->range();
35627 
35628             static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
35629             static_cast<details::string_range_node<Type>*>      (branch[1])->range_ref().clear();
35630 
35631             free_node(*node_allocator_,branch[0]);
35632             free_node(*node_allocator_,branch[1]);
35633 
35634             return synthesize_str_xroxr_expression_impl<const std::string,std::string&>(opr, s0, s1, rp0, rp1);
35635          }
35636 
synthesize_csrocs_expression(const details::operator_type & opr,expression_node_ptr (& branch)[2])35637          inline expression_node_ptr synthesize_csrocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
35638          {
35639             const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str  ();
35640             const std::string s1 = static_cast<details::string_literal_node<Type>*>    (branch[1])->str  ();
35641             const range_t    rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
35642 
35643             static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
35644 
35645             details::free_all_nodes(*node_allocator_,branch);
35646 
35647             return synthesize_str_xrox_expression_impl<const std::string,std::string>(opr, s0, s1, rp0);
35648          }
35649 
synthesize_csrocsr_expression(const details::operator_type & opr,expression_node_ptr (& branch)[2])35650          inline expression_node_ptr synthesize_csrocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
35651          {
35652             const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str  ();
35653             const std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str  ();
35654             const range_t    rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
35655             const range_t    rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
35656 
35657             static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
35658             static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
35659 
35660             details::free_all_nodes(*node_allocator_,branch);
35661 
35662             return synthesize_str_xroxr_expression_impl<const std::string, const std::string>(opr, s0, s1, rp0, rp1);
35663          }
35664 
synthesize_strogen_expression(const details::operator_type & opr,expression_node_ptr (& branch)[2])35665          inline expression_node_ptr synthesize_strogen_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
35666          {
35667             switch (opr)
35668             {
35669                #define case_stmt(op0,op1)                                                       \
35670                case op0 : return node_allocator_->                                              \
35671                              allocate_ttt<typename details::str_sogens_node<Type,op1<Type> > >  \
35672                                 (opr, branch[0], branch[1]);                                    \
35673 
35674                string_opr_switch_statements
35675                #undef case_stmt
35676                default : return error_node();
35677             }
35678          }
35679          #endif
35680 
35681          #ifndef exprtk_disable_string_capabilities
synthesize_string_expression(const details::operator_type & opr,expression_node_ptr (& branch)[2])35682          inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
35683          {
35684             if ((0 == branch[0]) || (0 == branch[1]))
35685             {
35686                details::free_all_nodes(*node_allocator_,branch);
35687 
35688                return error_node();
35689             }
35690 
35691             const bool b0_is_s   = details::is_string_node            (branch[0]);
35692             const bool b0_is_cs  = details::is_const_string_node      (branch[0]);
35693             const bool b0_is_sr  = details::is_string_range_node      (branch[0]);
35694             const bool b0_is_csr = details::is_const_string_range_node(branch[0]);
35695 
35696             const bool b1_is_s   = details::is_string_node            (branch[1]);
35697             const bool b1_is_cs  = details::is_const_string_node      (branch[1]);
35698             const bool b1_is_sr  = details::is_string_range_node      (branch[1]);
35699             const bool b1_is_csr = details::is_const_string_range_node(branch[1]);
35700 
35701             const bool b0_is_gen = details::is_string_assignment_node (branch[0]) ||
35702                                    details::is_genricstring_range_node(branch[0]) ||
35703                                    details::is_string_concat_node     (branch[0]) ||
35704                                    details::is_string_function_node   (branch[0]) ||
35705                                    details::is_string_condition_node  (branch[0]) ||
35706                                    details::is_string_ccondition_node (branch[0]) ||
35707                                    details::is_string_vararg_node     (branch[0]) ;
35708 
35709             const bool b1_is_gen = details::is_string_assignment_node (branch[1]) ||
35710                                    details::is_genricstring_range_node(branch[1]) ||
35711                                    details::is_string_concat_node     (branch[1]) ||
35712                                    details::is_string_function_node   (branch[1]) ||
35713                                    details::is_string_condition_node  (branch[1]) ||
35714                                    details::is_string_ccondition_node (branch[1]) ||
35715                                    details::is_string_vararg_node     (branch[1]) ;
35716 
35717             if (details::e_add == opr)
35718             {
35719                if (!b0_is_cs || !b1_is_cs)
35720                {
35721                   return synthesize_expression<string_concat_node_t,2>(opr,branch);
35722                }
35723             }
35724 
35725             if (b0_is_gen || b1_is_gen)
35726             {
35727                return synthesize_strogen_expression(opr,branch);
35728             }
35729             else if (b0_is_s)
35730             {
35731                     if (b1_is_s  ) return synthesize_sos_expression   (opr,branch);
35732                else if (b1_is_cs ) return synthesize_socs_expression  (opr,branch);
35733                else if (b1_is_sr ) return synthesize_sosr_expression  (opr,branch);
35734                else if (b1_is_csr) return synthesize_socsr_expression (opr,branch);
35735             }
35736             else if (b0_is_cs)
35737             {
35738                     if (b1_is_s  ) return synthesize_csos_expression  (opr,branch);
35739                else if (b1_is_cs ) return synthesize_csocs_expression (opr,branch);
35740                else if (b1_is_sr ) return synthesize_csosr_expression (opr,branch);
35741                else if (b1_is_csr) return synthesize_csocsr_expression(opr,branch);
35742             }
35743             else if (b0_is_sr)
35744             {
35745                     if (b1_is_s  ) return synthesize_sros_expression  (opr,branch);
35746                else if (b1_is_sr ) return synthesize_srosr_expression (opr,branch);
35747                else if (b1_is_cs ) return synthesize_srocs_expression (opr,branch);
35748                else if (b1_is_csr) return synthesize_srocsr_expression(opr,branch);
35749             }
35750             else if (b0_is_csr)
35751             {
35752                     if (b1_is_s  ) return synthesize_csros_expression  (opr,branch);
35753                else if (b1_is_sr ) return synthesize_csrosr_expression (opr,branch);
35754                else if (b1_is_cs ) return synthesize_csrocs_expression (opr,branch);
35755                else if (b1_is_csr) return synthesize_csrocsr_expression(opr,branch);
35756             }
35757 
35758             return error_node();
35759          }
35760          #else
synthesize_string_expression(const details::operator_type &,expression_node_ptr (& branch)[2])35761          inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[2])
35762          {
35763             details::free_all_nodes(*node_allocator_,branch);
35764             return error_node();
35765          }
35766          #endif
35767 
35768          #ifndef exprtk_disable_string_capabilities
synthesize_string_expression(const details::operator_type & opr,expression_node_ptr (& branch)[3])35769          inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[3])
35770          {
35771             if (details::e_inrange != opr)
35772                return error_node();
35773             else if ((0 == branch[0]) || (0 == branch[1]) || (0 == branch[2]))
35774             {
35775                details::free_all_nodes(*node_allocator_,branch);
35776 
35777                return error_node();
35778             }
35779             else if (
35780                       details::is_const_string_node(branch[0]) &&
35781                       details::is_const_string_node(branch[1]) &&
35782                       details::is_const_string_node(branch[2])
35783                     )
35784             {
35785                const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
35786                const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
35787                const std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();
35788 
35789                const Type v = (((s0 <= s1) && (s1 <= s2)) ? Type(1) : Type(0));
35790 
35791                details::free_all_nodes(*node_allocator_,branch);
35792 
35793                return node_allocator_->allocate_c<details::literal_node<Type> >(v);
35794             }
35795             else if (
35796                       details::is_string_node(branch[0]) &&
35797                       details::is_string_node(branch[1]) &&
35798                       details::is_string_node(branch[2])
35799                     )
35800             {
35801                std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref();
35802                std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref();
35803                std::string& s2 = static_cast<details::stringvar_node<Type>*>(branch[2])->ref();
35804 
35805                typedef typename details::sosos_node<Type, std::string&, std::string&, std::string&, details::inrange_op<Type> > inrange_t;
35806 
35807                return node_allocator_->allocate_type<inrange_t, std::string&, std::string&, std::string&>(s0, s1, s2);
35808             }
35809             else if (
35810                       details::is_const_string_node(branch[0]) &&
35811                             details::is_string_node(branch[1]) &&
35812                       details::is_const_string_node(branch[2])
35813                     )
35814             {
35815                std::string  s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
35816                std::string& s1 = static_cast<     details::stringvar_node<Type>*>(branch[1])->ref();
35817                std::string  s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();
35818 
35819                typedef typename details::sosos_node<Type, std::string, std::string&, std::string, details::inrange_op<Type> > inrange_t;
35820 
35821                details::free_node(*node_allocator_,branch[0]);
35822                details::free_node(*node_allocator_,branch[2]);
35823 
35824                return node_allocator_->allocate_type<inrange_t, std::string, std::string&, std::string>(s0, s1, s2);
35825             }
35826             else if (
35827                             details::is_string_node(branch[0]) &&
35828                       details::is_const_string_node(branch[1]) &&
35829                             details::is_string_node(branch[2])
35830                     )
35831             {
35832                std::string&  s0 = static_cast<     details::stringvar_node<Type>*>(branch[0])->ref();
35833                std::string   s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
35834                std::string&  s2 = static_cast<     details::stringvar_node<Type>*>(branch[2])->ref();
35835 
35836                typedef typename details::sosos_node<Type, std::string&, std::string, std::string&, details::inrange_op<Type> > inrange_t;
35837 
35838                details::free_node(*node_allocator_,branch[1]);
35839 
35840                return node_allocator_->allocate_type<inrange_t, std::string&, std::string, std::string&>(s0, s1, s2);
35841             }
35842             else if (
35843                       details::is_string_node(branch[0]) &&
35844                       details::is_string_node(branch[1]) &&
35845                       details::is_const_string_node(branch[2])
35846                     )
35847             {
35848                std::string& s0 = static_cast<     details::stringvar_node<Type>*>(branch[0])->ref();
35849                std::string& s1 = static_cast<     details::stringvar_node<Type>*>(branch[1])->ref();
35850                std::string  s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();
35851 
35852                typedef typename details::sosos_node<Type, std::string&, std::string&, std::string, details::inrange_op<Type> > inrange_t;
35853 
35854                details::free_node(*node_allocator_,branch[2]);
35855 
35856                return node_allocator_->allocate_type<inrange_t, std::string&, std::string&, std::string>(s0, s1, s2);
35857             }
35858             else if (
35859                       details::is_const_string_node(branch[0]) &&
35860                       details::      is_string_node(branch[1]) &&
35861                       details::      is_string_node(branch[2])
35862                     )
35863             {
35864                std::string  s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
35865                std::string& s1 = static_cast<     details::stringvar_node<Type>*>(branch[1])->ref();
35866                std::string& s2 = static_cast<     details::stringvar_node<Type>*>(branch[2])->ref();
35867 
35868                typedef typename details::sosos_node<Type, std::string, std::string&, std::string&, details::inrange_op<Type> > inrange_t;
35869 
35870                details::free_node(*node_allocator_,branch[0]);
35871 
35872                return node_allocator_->allocate_type<inrange_t, std::string, std::string&, std::string&>(s0, s1, s2);
35873             }
35874             else
35875                return error_node();
35876          }
35877          #else
synthesize_string_expression(const details::operator_type &,expression_node_ptr (& branch)[3])35878          inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[3])
35879          {
35880             details::free_all_nodes(*node_allocator_,branch);
35881             return error_node();
35882          }
35883          #endif
35884 
synthesize_null_expression(const details::operator_type & operation,expression_node_ptr (& branch)[2])35885          inline expression_node_ptr synthesize_null_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
35886          {
35887             /*
35888              Note: The following are the type promotion rules
35889              that relate to operations that include 'null':
35890              0. null ==/!=     null --> true false
35891              1. null operation null --> null
35892              2. x    ==/!=     null --> true/false
35893              3. null ==/!=     x    --> true/false
35894              4. x   operation  null --> x
35895              5. null operation x    --> x
35896             */
35897 
35898             typedef typename details::null_eq_node<T> nulleq_node_t;
35899 
35900             const bool b0_null = details::is_null_node(branch[0]);
35901             const bool b1_null = details::is_null_node(branch[1]);
35902 
35903             if (b0_null && b1_null)
35904             {
35905                expression_node_ptr result = error_node();
35906 
35907                if (details::e_eq == operation)
35908                   result = node_allocator_->allocate_c<literal_node_t>(T(1));
35909                else if (details::e_ne == operation)
35910                   result = node_allocator_->allocate_c<literal_node_t>(T(0));
35911 
35912                if (result)
35913                {
35914                   details::free_node(*node_allocator_,branch[0]);
35915                   details::free_node(*node_allocator_,branch[1]);
35916 
35917                   return result;
35918                }
35919 
35920                details::free_node(*node_allocator_,branch[1]);
35921 
35922                return branch[0];
35923             }
35924             else if (details::e_eq == operation)
35925             {
35926                expression_node_ptr result = node_allocator_->
35927                                                 allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],true);
35928 
35929                details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]);
35930 
35931                return result;
35932             }
35933             else if (details::e_ne == operation)
35934             {
35935                expression_node_ptr result = node_allocator_->
35936                                                 allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],false);
35937 
35938                details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]);
35939 
35940                return result;
35941             }
35942             else if (b0_null)
35943             {
35944                details::free_node(*node_allocator_,branch[0]);
35945                branch[0] = branch[1];
35946                branch[1] = error_node();
35947             }
35948             else if (b1_null)
35949             {
35950                details::free_node(*node_allocator_,branch[1]);
35951                branch[1] = error_node();
35952             }
35953 
35954             if (
35955                  (details::e_add == operation) || (details::e_sub == operation) ||
35956                  (details::e_mul == operation) || (details::e_div == operation) ||
35957                  (details::e_mod == operation) || (details::e_pow == operation)
35958                )
35959             {
35960                return branch[0];
35961             }
35962 
35963             details::free_node(*node_allocator_, branch[0]);
35964 
35965             if (
35966                  (details::e_lt    == operation) || (details::e_lte  == operation) ||
35967                  (details::e_gt    == operation) || (details::e_gte  == operation) ||
35968                  (details::e_and   == operation) || (details::e_nand == operation) ||
35969                  (details::e_or    == operation) || (details::e_nor  == operation) ||
35970                  (details::e_xor   == operation) || (details::e_xnor == operation) ||
35971                  (details::e_in    == operation) || (details::e_like == operation) ||
35972                  (details::e_ilike == operation)
35973                )
35974             {
35975                return node_allocator_->allocate_c<literal_node_t>(T(0));
35976             }
35977 
35978             return node_allocator_->allocate<details::null_node<Type> >();
35979          }
35980 
35981          template <typename NodeType, std::size_t N>
synthesize_expression(const details::operator_type & operation,expression_node_ptr (& branch)[N])35982          inline expression_node_ptr synthesize_expression(const details::operator_type& operation, expression_node_ptr (&branch)[N])
35983          {
35984             if (
35985                  (details::e_in    == operation) ||
35986                  (details::e_like  == operation) ||
35987                  (details::e_ilike == operation)
35988                )
35989             {
35990                free_all_nodes(*node_allocator_,branch);
35991 
35992                return error_node();
35993             }
35994             else if (!details::all_nodes_valid<N>(branch))
35995             {
35996                free_all_nodes(*node_allocator_,branch);
35997 
35998                return error_node();
35999             }
36000             else if ((details::e_default != operation))
36001             {
36002                // Attempt simple constant folding optimisation.
36003                expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(operation,branch);
36004 
36005                if (is_constant_foldable<N>(branch))
36006                {
36007                   const Type v = expression_point->value();
36008                   details::free_node(*node_allocator_,expression_point);
36009 
36010                   return node_allocator_->allocate<literal_node_t>(v);
36011                }
36012                else
36013                   return expression_point;
36014             }
36015             else
36016                return error_node();
36017          }
36018 
36019          template <typename NodeType, std::size_t N>
synthesize_expression(F * f,expression_node_ptr (& branch)[N])36020          inline expression_node_ptr synthesize_expression(F* f, expression_node_ptr (&branch)[N])
36021          {
36022             if (!details::all_nodes_valid<N>(branch))
36023             {
36024                free_all_nodes(*node_allocator_,branch);
36025 
36026                return error_node();
36027             }
36028 
36029             typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t;
36030 
36031             // Attempt simple constant folding optimisation.
36032 
36033             expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(f);
36034             function_N_node_t* func_node_ptr = dynamic_cast<function_N_node_t*>(expression_point);
36035 
36036             if (0 == func_node_ptr)
36037             {
36038                free_all_nodes(*node_allocator_,branch);
36039 
36040                return error_node();
36041             }
36042             else
36043                func_node_ptr->init_branches(branch);
36044 
36045             if (is_constant_foldable<N>(branch) && !f->has_side_effects())
36046             {
36047                Type v = expression_point->value();
36048                details::free_node(*node_allocator_,expression_point);
36049 
36050                return node_allocator_->allocate<literal_node_t>(v);
36051             }
36052 
36053             parser_->state_.activate_side_effect("synthesize_expression(function<NT,N>)");
36054 
36055             return expression_point;
36056          }
36057 
36058          bool                     strength_reduction_enabled_;
36059          details::node_allocator* node_allocator_;
36060          synthesize_map_t         synthesize_map_;
36061          unary_op_map_t*          unary_op_map_;
36062          binary_op_map_t*         binary_op_map_;
36063          inv_binary_op_map_t*     inv_binary_op_map_;
36064          sf3_map_t*               sf3_map_;
36065          sf4_map_t*               sf4_map_;
36066          parser_t*                parser_;
36067       };
36068 
set_error(const parser_error::type & error_type)36069       inline void set_error(const parser_error::type& error_type)
36070       {
36071          error_list_.push_back(error_type);
36072       }
36073 
remove_last_error()36074       inline void remove_last_error()
36075       {
36076          if (!error_list_.empty())
36077          {
36078             error_list_.pop_back();
36079          }
36080       }
36081 
set_synthesis_error(const std::string & synthesis_error_message)36082       inline void set_synthesis_error(const std::string& synthesis_error_message)
36083       {
36084          if (synthesis_error_.empty())
36085          {
36086             synthesis_error_ = synthesis_error_message;
36087          }
36088       }
36089 
register_local_vars(expression<T> & e)36090       inline void register_local_vars(expression<T>& e)
36091       {
36092          for (std::size_t i = 0; i < sem_.size(); ++i)
36093          {
36094             scope_element& se = sem_.get_element(i);
36095 
36096             if (
36097                  (scope_element::e_variable == se.type) ||
36098                  (scope_element::e_vecelem  == se.type)
36099                )
36100             {
36101                if (se.var_node)
36102                {
36103                   e.register_local_var(se.var_node);
36104                }
36105 
36106                if (se.data)
36107                {
36108                   e.register_local_data(se.data, 1, 0);
36109                }
36110             }
36111             else if (scope_element::e_vector == se.type)
36112             {
36113                if (se.vec_node)
36114                {
36115                   e.register_local_var(se.vec_node);
36116                }
36117 
36118                if (se.data)
36119                {
36120                   e.register_local_data(se.data, se.size, 1);
36121                }
36122             }
36123             #ifndef exprtk_disable_string_capabilities
36124             else if (scope_element::e_string == se.type)
36125             {
36126                if (se.str_node)
36127                {
36128                   e.register_local_var(se.str_node);
36129                }
36130 
36131                if (se.data)
36132                {
36133                   e.register_local_data(se.data, se.size, 2);
36134                }
36135             }
36136             #endif
36137 
36138             se.var_node  = 0;
36139             se.vec_node  = 0;
36140             #ifndef exprtk_disable_string_capabilities
36141             se.str_node  = 0;
36142             #endif
36143             se.data      = 0;
36144             se.ref_count = 0;
36145             se.active    = false;
36146          }
36147       }
36148 
register_return_results(expression<T> & e)36149       inline void register_return_results(expression<T>& e)
36150       {
36151          e.register_return_results(results_context_);
36152          results_context_ = 0;
36153       }
36154 
load_unary_operations_map(unary_op_map_t & m)36155       inline void load_unary_operations_map(unary_op_map_t& m)
36156       {
36157          #define register_unary_op(Op,UnaryFunctor)             \
36158          m.insert(std::make_pair(Op,UnaryFunctor<T>::process)); \
36159 
36160          register_unary_op(details::  e_abs, details::  abs_op)
36161          register_unary_op(details:: e_acos, details:: acos_op)
36162          register_unary_op(details::e_acosh, details::acosh_op)
36163          register_unary_op(details:: e_asin, details:: asin_op)
36164          register_unary_op(details::e_asinh, details::asinh_op)
36165          register_unary_op(details::e_atanh, details::atanh_op)
36166          register_unary_op(details:: e_ceil, details:: ceil_op)
36167          register_unary_op(details::  e_cos, details::  cos_op)
36168          register_unary_op(details:: e_cosh, details:: cosh_op)
36169          register_unary_op(details::  e_exp, details::  exp_op)
36170          register_unary_op(details::e_expm1, details::expm1_op)
36171          register_unary_op(details::e_floor, details::floor_op)
36172          register_unary_op(details::  e_log, details::  log_op)
36173          register_unary_op(details::e_log10, details::log10_op)
36174          register_unary_op(details:: e_log2, details:: log2_op)
36175          register_unary_op(details::e_log1p, details::log1p_op)
36176          register_unary_op(details::  e_neg, details::  neg_op)
36177          register_unary_op(details::  e_pos, details::  pos_op)
36178          register_unary_op(details::e_round, details::round_op)
36179          register_unary_op(details::  e_sin, details::  sin_op)
36180          register_unary_op(details:: e_sinc, details:: sinc_op)
36181          register_unary_op(details:: e_sinh, details:: sinh_op)
36182          register_unary_op(details:: e_sqrt, details:: sqrt_op)
36183          register_unary_op(details::  e_tan, details::  tan_op)
36184          register_unary_op(details:: e_tanh, details:: tanh_op)
36185          register_unary_op(details::  e_cot, details::  cot_op)
36186          register_unary_op(details::  e_sec, details::  sec_op)
36187          register_unary_op(details::  e_csc, details::  csc_op)
36188          register_unary_op(details::  e_r2d, details::  r2d_op)
36189          register_unary_op(details::  e_d2r, details::  d2r_op)
36190          register_unary_op(details::  e_d2g, details::  d2g_op)
36191          register_unary_op(details::  e_g2d, details::  g2d_op)
36192          register_unary_op(details:: e_notl, details:: notl_op)
36193          register_unary_op(details::  e_sgn, details::  sgn_op)
36194          register_unary_op(details::  e_erf, details::  erf_op)
36195          register_unary_op(details:: e_erfc, details:: erfc_op)
36196          register_unary_op(details:: e_ncdf, details:: ncdf_op)
36197          register_unary_op(details:: e_frac, details:: frac_op)
36198          register_unary_op(details::e_trunc, details::trunc_op)
36199          #undef register_unary_op
36200       }
36201 
load_binary_operations_map(binary_op_map_t & m)36202       inline void load_binary_operations_map(binary_op_map_t& m)
36203       {
36204          typedef typename binary_op_map_t::value_type value_type;
36205 
36206          #define register_binary_op(Op,BinaryFunctor)        \
36207          m.insert(value_type(Op,BinaryFunctor<T>::process)); \
36208 
36209          register_binary_op(details:: e_add, details:: add_op)
36210          register_binary_op(details:: e_sub, details:: sub_op)
36211          register_binary_op(details:: e_mul, details:: mul_op)
36212          register_binary_op(details:: e_div, details:: div_op)
36213          register_binary_op(details:: e_mod, details:: mod_op)
36214          register_binary_op(details:: e_pow, details:: pow_op)
36215          register_binary_op(details::  e_lt, details::  lt_op)
36216          register_binary_op(details:: e_lte, details:: lte_op)
36217          register_binary_op(details::  e_gt, details::  gt_op)
36218          register_binary_op(details:: e_gte, details:: gte_op)
36219          register_binary_op(details::  e_eq, details::  eq_op)
36220          register_binary_op(details::  e_ne, details::  ne_op)
36221          register_binary_op(details:: e_and, details:: and_op)
36222          register_binary_op(details::e_nand, details::nand_op)
36223          register_binary_op(details::  e_or, details::  or_op)
36224          register_binary_op(details:: e_nor, details:: nor_op)
36225          register_binary_op(details:: e_xor, details:: xor_op)
36226          register_binary_op(details::e_xnor, details::xnor_op)
36227          #undef register_binary_op
36228       }
36229 
load_inv_binary_operations_map(inv_binary_op_map_t & m)36230       inline void load_inv_binary_operations_map(inv_binary_op_map_t& m)
36231       {
36232          typedef typename inv_binary_op_map_t::value_type value_type;
36233 
36234          #define register_binary_op(Op,BinaryFunctor)        \
36235          m.insert(value_type(BinaryFunctor<T>::process,Op)); \
36236 
36237          register_binary_op(details:: e_add, details:: add_op)
36238          register_binary_op(details:: e_sub, details:: sub_op)
36239          register_binary_op(details:: e_mul, details:: mul_op)
36240          register_binary_op(details:: e_div, details:: div_op)
36241          register_binary_op(details:: e_mod, details:: mod_op)
36242          register_binary_op(details:: e_pow, details:: pow_op)
36243          register_binary_op(details::  e_lt, details::  lt_op)
36244          register_binary_op(details:: e_lte, details:: lte_op)
36245          register_binary_op(details::  e_gt, details::  gt_op)
36246          register_binary_op(details:: e_gte, details:: gte_op)
36247          register_binary_op(details::  e_eq, details::  eq_op)
36248          register_binary_op(details::  e_ne, details::  ne_op)
36249          register_binary_op(details:: e_and, details:: and_op)
36250          register_binary_op(details::e_nand, details::nand_op)
36251          register_binary_op(details::  e_or, details::  or_op)
36252          register_binary_op(details:: e_nor, details:: nor_op)
36253          register_binary_op(details:: e_xor, details:: xor_op)
36254          register_binary_op(details::e_xnor, details::xnor_op)
36255          #undef register_binary_op
36256       }
36257 
load_sf3_map(sf3_map_t & sf3_map)36258       inline void load_sf3_map(sf3_map_t& sf3_map)
36259       {
36260          typedef std::pair<trinary_functor_t,details::operator_type> pair_t;
36261 
36262          #define register_sf3(Op)                                                                             \
36263          sf3_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \
36264 
36265          register_sf3(00) register_sf3(01) register_sf3(02) register_sf3(03)
36266          register_sf3(04) register_sf3(05) register_sf3(06) register_sf3(07)
36267          register_sf3(08) register_sf3(09) register_sf3(10) register_sf3(11)
36268          register_sf3(12) register_sf3(13) register_sf3(14) register_sf3(15)
36269          register_sf3(16) register_sf3(17) register_sf3(18) register_sf3(19)
36270          register_sf3(20) register_sf3(21) register_sf3(22) register_sf3(23)
36271          register_sf3(24) register_sf3(25) register_sf3(26) register_sf3(27)
36272          register_sf3(28) register_sf3(29) register_sf3(30)
36273          #undef register_sf3
36274 
36275          #define register_sf3_extid(Id, Op)                                        \
36276          sf3_map[Id] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \
36277 
36278          register_sf3_extid("(t-t)-t",23)  // (t-t)-t --> t-(t+t)
36279          #undef register_sf3_extid
36280       }
36281 
load_sf4_map(sf4_map_t & sf4_map)36282       inline void load_sf4_map(sf4_map_t& sf4_map)
36283       {
36284          typedef std::pair<quaternary_functor_t,details::operator_type> pair_t;
36285 
36286          #define register_sf4(Op)                                                                             \
36287          sf4_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \
36288 
36289          register_sf4(48) register_sf4(49) register_sf4(50) register_sf4(51)
36290          register_sf4(52) register_sf4(53) register_sf4(54) register_sf4(55)
36291          register_sf4(56) register_sf4(57) register_sf4(58) register_sf4(59)
36292          register_sf4(60) register_sf4(61) register_sf4(62) register_sf4(63)
36293          register_sf4(64) register_sf4(65) register_sf4(66) register_sf4(67)
36294          register_sf4(68) register_sf4(69) register_sf4(70) register_sf4(71)
36295          register_sf4(72) register_sf4(73) register_sf4(74) register_sf4(75)
36296          register_sf4(76) register_sf4(77) register_sf4(78) register_sf4(79)
36297          register_sf4(80) register_sf4(81) register_sf4(82) register_sf4(83)
36298          #undef register_sf4
36299 
36300          #define register_sf4ext(Op)                                                                                    \
36301          sf4_map[details::sfext##Op##_op<T>::id()] = pair_t(details::sfext##Op##_op<T>::process,details::e_sf4ext##Op); \
36302 
36303          register_sf4ext(00) register_sf4ext(01) register_sf4ext(02) register_sf4ext(03)
36304          register_sf4ext(04) register_sf4ext(05) register_sf4ext(06) register_sf4ext(07)
36305          register_sf4ext(08) register_sf4ext(09) register_sf4ext(10) register_sf4ext(11)
36306          register_sf4ext(12) register_sf4ext(13) register_sf4ext(14) register_sf4ext(15)
36307          register_sf4ext(16) register_sf4ext(17) register_sf4ext(18) register_sf4ext(19)
36308          register_sf4ext(20) register_sf4ext(21) register_sf4ext(22) register_sf4ext(23)
36309          register_sf4ext(24) register_sf4ext(25) register_sf4ext(26) register_sf4ext(27)
36310          register_sf4ext(28) register_sf4ext(29) register_sf4ext(30) register_sf4ext(31)
36311          register_sf4ext(32) register_sf4ext(33) register_sf4ext(34) register_sf4ext(35)
36312          register_sf4ext(36) register_sf4ext(36) register_sf4ext(38) register_sf4ext(39)
36313          register_sf4ext(40) register_sf4ext(41) register_sf4ext(42) register_sf4ext(43)
36314          register_sf4ext(44) register_sf4ext(45) register_sf4ext(46) register_sf4ext(47)
36315          register_sf4ext(48) register_sf4ext(49) register_sf4ext(50) register_sf4ext(51)
36316          register_sf4ext(52) register_sf4ext(53) register_sf4ext(54) register_sf4ext(55)
36317          register_sf4ext(56) register_sf4ext(57) register_sf4ext(58) register_sf4ext(59)
36318          register_sf4ext(60) register_sf4ext(61)
36319          #undef register_sf4ext
36320       }
36321 
results_ctx()36322       inline results_context_t& results_ctx()
36323       {
36324          if (0 == results_context_)
36325          {
36326             results_context_ = new results_context_t();
36327          }
36328 
36329          return (*results_context_);
36330       }
36331 
return_cleanup()36332       inline void return_cleanup()
36333       {
36334          #ifndef exprtk_disable_return_statement
36335          if (results_context_)
36336          {
36337             delete results_context_;
36338             results_context_ = 0;
36339          }
36340 
36341          state_.return_stmt_present = false;
36342          #endif
36343       }
36344 
36345    private:
36346 
36347       parser(const parser<T>&);
36348       parser<T>& operator=(const parser<T>&);
36349 
36350       settings_store settings_;
36351       expression_generator<T> expression_generator_;
36352       details::node_allocator node_allocator_;
36353       symtab_store symtab_store_;
36354       dependent_entity_collector dec_;
36355       std::deque<parser_error::type> error_list_;
36356       std::deque<bool> brkcnt_list_;
36357       parser_state state_;
36358       bool resolve_unknown_symbol_;
36359       results_context_t* results_context_;
36360       unknown_symbol_resolver* unknown_symbol_resolver_;
36361       unknown_symbol_resolver default_usr_;
36362       base_ops_map_t base_ops_map_;
36363       unary_op_map_t unary_op_map_;
36364       binary_op_map_t binary_op_map_;
36365       inv_binary_op_map_t inv_binary_op_map_;
36366       sf3_map_t sf3_map_;
36367       sf4_map_t sf4_map_;
36368       std::string synthesis_error_;
36369       scope_element_manager sem_;
36370 
36371       lexer::helper::helper_assembly helper_assembly_;
36372 
36373       lexer::helper::commutative_inserter       commutative_inserter_;
36374       lexer::helper::operator_joiner            operator_joiner_2_;
36375       lexer::helper::operator_joiner            operator_joiner_3_;
36376       lexer::helper::symbol_replacer            symbol_replacer_;
36377       lexer::helper::bracket_checker            bracket_checker_;
36378       lexer::helper::numeric_checker            numeric_checker_;
36379       lexer::helper::sequence_validator         sequence_validator_;
36380       lexer::helper::sequence_validator_3tokens sequence_validator_3tkns_;
36381 
36382       loop_runtime_check_ptr loop_runtime_check_;
36383 
36384       template <typename ParserType>
36385       friend void details::disable_type_checking(ParserType& p);
36386    };
36387 
36388    namespace details
36389    {
36390       template <typename T>
36391       struct collector_helper
36392       {
36393          typedef exprtk::symbol_table<T> symbol_table_t;
36394          typedef exprtk::expression<T>     expression_t;
36395          typedef exprtk::parser<T>             parser_t;
36396          typedef typename parser_t::dependent_entity_collector::symbol_t symbol_t;
36397          typedef typename parser_t::unknown_symbol_resolver usr_t;
36398 
36399          struct resolve_as_vector : public parser_t::unknown_symbol_resolver
36400          {
36401             typedef exprtk::parser<T> parser_t;
36402 
resolve_as_vectorexprtk::details::collector_helper::resolve_as_vector36403             resolve_as_vector()
36404             : usr_t(usr_t::e_usrmode_extended)
36405             {}
36406 
processexprtk::details::collector_helper::resolve_as_vector36407             virtual bool process(const std::string& unknown_symbol,
36408                                  symbol_table_t& symbol_table,
36409                                  std::string&)
36410             {
36411                static T v[1];
36412                symbol_table.add_vector(unknown_symbol,v);
36413                return true;
36414             }
36415          };
36416 
collection_passexprtk::details::collector_helper36417          static inline bool collection_pass(const std::string& expression_string,
36418                                             std::set<std::string>& symbol_set,
36419                                             const bool collect_variables,
36420                                             const bool collect_functions,
36421                                             const bool vector_pass,
36422                                             symbol_table_t& ext_symbol_table)
36423          {
36424             symbol_table_t symbol_table;
36425             expression_t   expression;
36426             parser_t       parser;
36427 
36428             resolve_as_vector vect_resolver;
36429 
36430             expression.register_symbol_table(symbol_table    );
36431             expression.register_symbol_table(ext_symbol_table);
36432 
36433             if (vector_pass)
36434                parser.enable_unknown_symbol_resolver(&vect_resolver);
36435             else
36436                parser.enable_unknown_symbol_resolver();
36437 
36438             if (collect_variables)
36439                parser.dec().collect_variables() = true;
36440 
36441             if (collect_functions)
36442                parser.dec().collect_functions() = true;
36443 
36444             bool pass_result = false;
36445 
36446             details::disable_type_checking(parser);
36447 
36448             if (parser.compile(expression_string, expression))
36449             {
36450                pass_result = true;
36451 
36452                std::deque<symbol_t> symb_list;
36453                parser.dec().symbols(symb_list);
36454 
36455                for (std::size_t i = 0; i < symb_list.size(); ++i)
36456                {
36457                   symbol_set.insert(symb_list[i].first);
36458                }
36459             }
36460 
36461             return pass_result;
36462          }
36463       };
36464    }
36465 
36466    template <typename Allocator,
36467              template <typename, typename> class Sequence>
collect_variables(const std::string & expression,Sequence<std::string,Allocator> & symbol_list)36468    inline bool collect_variables(const std::string& expression,
36469                                  Sequence<std::string, Allocator>& symbol_list)
36470    {
36471       typedef double T;
36472       typedef details::collector_helper<T> collect_t;
36473 
36474       collect_t::symbol_table_t null_symbol_table;
36475 
36476       std::set<std::string> symbol_set;
36477 
36478       const bool variable_pass = collect_t::collection_pass
36479                                     (expression, symbol_set, true, false, false, null_symbol_table);
36480       const bool vector_pass   = collect_t::collection_pass
36481                                     (expression, symbol_set, true, false,  true, null_symbol_table);
36482 
36483       if (!variable_pass && !vector_pass)
36484          return false;
36485 
36486       std::set<std::string>::iterator itr = symbol_set.begin();
36487 
36488       while (symbol_set.end() != itr)
36489       {
36490          symbol_list.push_back(*itr);
36491          ++itr;
36492       }
36493 
36494       return true;
36495    }
36496 
36497    template <typename T,
36498              typename Allocator,
36499              template <typename, typename> class Sequence>
collect_variables(const std::string & expression,exprtk::symbol_table<T> & extrnl_symbol_table,Sequence<std::string,Allocator> & symbol_list)36500    inline bool collect_variables(const std::string& expression,
36501                                  exprtk::symbol_table<T>& extrnl_symbol_table,
36502                                  Sequence<std::string, Allocator>& symbol_list)
36503    {
36504       typedef details::collector_helper<T> collect_t;
36505 
36506       std::set<std::string> symbol_set;
36507 
36508       const bool variable_pass = collect_t::collection_pass
36509                                     (expression, symbol_set, true, false, false, extrnl_symbol_table);
36510       const bool vector_pass   = collect_t::collection_pass
36511                                     (expression, symbol_set, true, false,  true, extrnl_symbol_table);
36512 
36513       if (!variable_pass && !vector_pass)
36514          return false;
36515 
36516       std::set<std::string>::iterator itr = symbol_set.begin();
36517 
36518       while (symbol_set.end() != itr)
36519       {
36520          symbol_list.push_back(*itr);
36521          ++itr;
36522       }
36523 
36524       return true;
36525    }
36526 
36527    template <typename Allocator,
36528              template <typename, typename> class Sequence>
collect_functions(const std::string & expression,Sequence<std::string,Allocator> & symbol_list)36529    inline bool collect_functions(const std::string& expression,
36530                                  Sequence<std::string, Allocator>& symbol_list)
36531    {
36532       typedef double T;
36533       typedef details::collector_helper<T> collect_t;
36534 
36535       collect_t::symbol_table_t null_symbol_table;
36536 
36537       std::set<std::string> symbol_set;
36538 
36539       const bool variable_pass = collect_t::collection_pass
36540                                     (expression, symbol_set, false, true, false, null_symbol_table);
36541       const bool vector_pass   = collect_t::collection_pass
36542                                     (expression, symbol_set, false, true,  true, null_symbol_table);
36543 
36544       if (!variable_pass && !vector_pass)
36545          return false;
36546 
36547       std::set<std::string>::iterator itr = symbol_set.begin();
36548 
36549       while (symbol_set.end() != itr)
36550       {
36551          symbol_list.push_back(*itr);
36552          ++itr;
36553       }
36554 
36555       return true;
36556    }
36557 
36558    template <typename T,
36559              typename Allocator,
36560              template <typename, typename> class Sequence>
collect_functions(const std::string & expression,exprtk::symbol_table<T> & extrnl_symbol_table,Sequence<std::string,Allocator> & symbol_list)36561    inline bool collect_functions(const std::string& expression,
36562                                  exprtk::symbol_table<T>& extrnl_symbol_table,
36563                                  Sequence<std::string, Allocator>& symbol_list)
36564    {
36565       typedef details::collector_helper<T> collect_t;
36566 
36567       std::set<std::string> symbol_set;
36568 
36569       const bool variable_pass = collect_t::collection_pass
36570                                     (expression, symbol_set, false, true, false, extrnl_symbol_table);
36571       const bool vector_pass   = collect_t::collection_pass
36572                                     (expression, symbol_set, false, true,  true, extrnl_symbol_table);
36573 
36574       if (!variable_pass && !vector_pass)
36575          return false;
36576 
36577       std::set<std::string>::iterator itr = symbol_set.begin();
36578 
36579       while (symbol_set.end() != itr)
36580       {
36581          symbol_list.push_back(*itr);
36582          ++itr;
36583       }
36584 
36585       return true;
36586    }
36587 
36588    template <typename T>
integrate(const expression<T> & e,T & x,const T & r0,const T & r1,const std::size_t number_of_intervals=1000000)36589    inline T integrate(const expression<T>& e,
36590                       T& x,
36591                       const T& r0, const T& r1,
36592                       const std::size_t number_of_intervals = 1000000)
36593    {
36594       if (r0 > r1)
36595          return T(0);
36596 
36597       const T h = (r1 - r0) / (T(2) * number_of_intervals);
36598       T total_area = T(0);
36599 
36600       for (std::size_t i = 0; i < number_of_intervals; ++i)
36601       {
36602          x = r0 + T(2) * i * h;
36603          const T y0 = e.value(); x += h;
36604          const T y1 = e.value(); x += h;
36605          const T y2 = e.value(); x += h;
36606          total_area += h * (y0 + T(4) * y1 + y2) / T(3);
36607       }
36608 
36609       return total_area;
36610    }
36611 
36612    template <typename T>
integrate(const expression<T> & e,const std::string & variable_name,const T & r0,const T & r1,const std::size_t number_of_intervals=1000000)36613    inline T integrate(const expression<T>& e,
36614                       const std::string& variable_name,
36615                       const T& r0, const T& r1,
36616                       const std::size_t number_of_intervals = 1000000)
36617    {
36618       const symbol_table<T>& sym_table = e.get_symbol_table();
36619 
36620       if (!sym_table.valid())
36621          return std::numeric_limits<T>::quiet_NaN();
36622 
36623       details::variable_node<T>* var = sym_table.get_variable(variable_name);
36624 
36625       if (var)
36626       {
36627          T& x = var->ref();
36628          const T x_original = x;
36629          const T result = integrate(e, x, r0, r1, number_of_intervals);
36630          x = x_original;
36631 
36632          return result;
36633       }
36634       else
36635          return std::numeric_limits<T>::quiet_NaN();
36636    }
36637 
36638    template <typename T>
derivative(const expression<T> & e,T & x,const T & h=T (0.00000001))36639    inline T derivative(const expression<T>& e,
36640                        T& x,
36641                        const T& h = T(0.00000001))
36642    {
36643       const T x_init = x;
36644       const T _2h    = T(2) * h;
36645 
36646       x = x_init + _2h;
36647       const T y0 = e.value();
36648       x = x_init +   h;
36649       const T y1 = e.value();
36650       x = x_init -   h;
36651       const T y2 = e.value();
36652       x = x_init - _2h;
36653       const T y3 = e.value();
36654       x = x_init;
36655 
36656       return (-y0 + T(8) * (y1 - y2) + y3) / (T(12) * h);
36657    }
36658 
36659    template <typename T>
second_derivative(const expression<T> & e,T & x,const T & h=T (0.00001))36660    inline T second_derivative(const expression<T>& e,
36661                               T& x,
36662                               const T& h = T(0.00001))
36663    {
36664       const T x_init = x;
36665       const T _2h    = T(2) * h;
36666 
36667       const T y = e.value();
36668       x = x_init + _2h;
36669       const T y0 = e.value();
36670       x = x_init +   h;
36671       const T y1 = e.value();
36672       x = x_init -   h;
36673       const T y2 = e.value();
36674       x = x_init - _2h;
36675       const T y3 = e.value();
36676       x = x_init;
36677 
36678       return (-y0 + T(16) * (y1 + y2) - T(30) * y - y3) / (T(12) * h * h);
36679    }
36680 
36681    template <typename T>
third_derivative(const expression<T> & e,T & x,const T & h=T (0.0001))36682    inline T third_derivative(const expression<T>& e,
36683                              T& x,
36684                              const T& h = T(0.0001))
36685    {
36686       const T x_init = x;
36687       const T _2h    = T(2) * h;
36688 
36689       x = x_init + _2h;
36690       const T y0 = e.value();
36691       x = x_init +   h;
36692       const T y1 = e.value();
36693       x = x_init -   h;
36694       const T y2 = e.value();
36695       x = x_init - _2h;
36696       const T y3 = e.value();
36697       x = x_init;
36698 
36699       return (y0 + T(2) * (y2 - y1) - y3) / (T(2) * h * h * h);
36700    }
36701 
36702    template <typename T>
derivative(const expression<T> & e,const std::string & variable_name,const T & h=T (0.00000001))36703    inline T derivative(const expression<T>& e,
36704                        const std::string& variable_name,
36705                        const T& h = T(0.00000001))
36706    {
36707       const symbol_table<T>& sym_table = e.get_symbol_table();
36708 
36709       if (!sym_table.valid())
36710       {
36711          return std::numeric_limits<T>::quiet_NaN();
36712       }
36713 
36714       details::variable_node<T>* var = sym_table.get_variable(variable_name);
36715 
36716       if (var)
36717       {
36718          T& x = var->ref();
36719          const T x_original = x;
36720          const T result = derivative(e, x, h);
36721          x = x_original;
36722 
36723          return result;
36724       }
36725       else
36726          return std::numeric_limits<T>::quiet_NaN();
36727    }
36728 
36729    template <typename T>
second_derivative(const expression<T> & e,const std::string & variable_name,const T & h=T (0.00001))36730    inline T second_derivative(const expression<T>& e,
36731                               const std::string& variable_name,
36732                               const T& h = T(0.00001))
36733    {
36734       const symbol_table<T>& sym_table = e.get_symbol_table();
36735 
36736       if (!sym_table.valid())
36737       {
36738          return std::numeric_limits<T>::quiet_NaN();
36739       }
36740 
36741       details::variable_node<T>* var = sym_table.get_variable(variable_name);
36742 
36743       if (var)
36744       {
36745          T& x = var->ref();
36746          const T x_original = x;
36747          const T result = second_derivative(e, x, h);
36748          x = x_original;
36749 
36750          return result;
36751       }
36752       else
36753          return std::numeric_limits<T>::quiet_NaN();
36754    }
36755 
36756    template <typename T>
third_derivative(const expression<T> & e,const std::string & variable_name,const T & h=T (0.0001))36757    inline T third_derivative(const expression<T>& e,
36758                              const std::string& variable_name,
36759                              const T& h = T(0.0001))
36760    {
36761       const symbol_table<T>& sym_table = e.get_symbol_table();
36762 
36763       if (!sym_table.valid())
36764       {
36765          return std::numeric_limits<T>::quiet_NaN();
36766       }
36767 
36768       details::variable_node<T>* var = sym_table.get_variable(variable_name);
36769 
36770       if (var)
36771       {
36772          T& x = var->ref();
36773          const T x_original = x;
36774          const T result = third_derivative(e, x, h);
36775          x = x_original;
36776 
36777          return result;
36778       }
36779       else
36780          return std::numeric_limits<T>::quiet_NaN();
36781    }
36782 
36783    /*
36784       Note: The following 'compute' routines are simple helpers,
36785       for quickly setting up the required pieces of code in order
36786       to evaluate an expression. By virtue of how they operate
36787       there will be an overhead with regards to their setup and
36788       teardown and hence should not be used in time critical
36789       sections of code.
36790       Furthermore they only assume a small sub set of variables,
36791       no string variables or user defined functions.
36792    */
36793    template <typename T>
compute(const std::string & expression_string,T & result)36794    inline bool compute(const std::string& expression_string, T& result)
36795    {
36796       // No variables
36797       symbol_table<T> symbol_table;
36798       symbol_table.add_constants();
36799 
36800       expression<T> expression;
36801       expression.register_symbol_table(symbol_table);
36802 
36803       parser<T> parser;
36804 
36805       if (parser.compile(expression_string,expression))
36806       {
36807          result = expression.value();
36808 
36809          return true;
36810       }
36811       else
36812          return false;
36813    }
36814 
36815    template <typename T>
compute(const std::string & expression_string,const T & x,T & result)36816    inline bool compute(const std::string& expression_string,
36817                        const T& x,
36818                        T& result)
36819    {
36820       // Only 'x'
36821       static const std::string x_var("x");
36822 
36823       symbol_table<T> symbol_table;
36824       symbol_table.add_constants();
36825       symbol_table.add_constant(x_var,x);
36826 
36827       expression<T> expression;
36828       expression.register_symbol_table(symbol_table);
36829 
36830       parser<T> parser;
36831 
36832       if (parser.compile(expression_string,expression))
36833       {
36834          result = expression.value();
36835 
36836          return true;
36837       }
36838       else
36839          return false;
36840    }
36841 
36842    template <typename T>
compute(const std::string & expression_string,const T & x,const T & y,T & result)36843    inline bool compute(const std::string& expression_string,
36844                        const T&x, const T& y,
36845                        T& result)
36846    {
36847       // Only 'x' and 'y'
36848       static const std::string x_var("x");
36849       static const std::string y_var("y");
36850 
36851       symbol_table<T> symbol_table;
36852       symbol_table.add_constants();
36853       symbol_table.add_constant(x_var,x);
36854       symbol_table.add_constant(y_var,y);
36855 
36856       expression<T> expression;
36857       expression.register_symbol_table(symbol_table);
36858 
36859       parser<T> parser;
36860 
36861       if (parser.compile(expression_string,expression))
36862       {
36863          result = expression.value();
36864 
36865          return true;
36866       }
36867       else
36868          return false;
36869    }
36870 
36871    template <typename T>
compute(const std::string & expression_string,const T & x,const T & y,const T & z,T & result)36872    inline bool compute(const std::string& expression_string,
36873                        const T& x, const T& y, const T& z,
36874                        T& result)
36875    {
36876       // Only 'x', 'y' or 'z'
36877       static const std::string x_var("x");
36878       static const std::string y_var("y");
36879       static const std::string z_var("z");
36880 
36881       symbol_table<T> symbol_table;
36882       symbol_table.add_constants();
36883       symbol_table.add_constant(x_var,x);
36884       symbol_table.add_constant(y_var,y);
36885       symbol_table.add_constant(z_var,z);
36886 
36887       expression<T> expression;
36888       expression.register_symbol_table(symbol_table);
36889 
36890       parser<T> parser;
36891 
36892       if (parser.compile(expression_string,expression))
36893       {
36894          result = expression.value();
36895 
36896          return true;
36897       }
36898       else
36899          return false;
36900    }
36901 
36902    template <typename T, std::size_t N>
36903    class polynomial : public ifunction<T>
36904    {
36905    private:
36906 
36907       template <typename Type, std::size_t NumberOfCoefficients>
36908       struct poly_impl { };
36909 
36910       template <typename Type>
36911       struct poly_impl <Type,12>
36912       {
evaluateexprtk::polynomial::poly_impl36913          static inline T evaluate(const Type x,
36914                                   const Type c12, const Type c11, const Type c10, const Type c9, const Type c8,
36915                                   const Type  c7, const Type  c6, const Type  c5, const Type c4, const Type c3,
36916                                   const Type  c2, const Type  c1, const Type  c0)
36917          {
36918             // 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
36919             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);
36920          }
36921       };
36922 
36923       template <typename Type>
36924       struct poly_impl <Type,11>
36925       {
evaluateexprtk::polynomial::poly_impl36926          static inline T evaluate(const Type x,
36927                                   const Type c11, const Type c10, const Type c9, const Type c8, const Type c7,
36928                                   const Type c6,  const Type  c5, const Type c4, const Type c3, const Type c2,
36929                                   const Type c1,  const Type  c0)
36930          {
36931             // 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
36932             return (((((((((((c11 * x + c10) * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
36933          }
36934       };
36935 
36936       template <typename Type>
36937       struct poly_impl <Type,10>
36938       {
evaluateexprtk::polynomial::poly_impl36939          static inline T evaluate(const Type x,
36940                                   const Type c10, const Type c9, const Type c8, const Type c7, const Type c6,
36941                                   const Type c5,  const Type c4, const Type c3, const Type c2, const Type c1,
36942                                   const Type c0)
36943          {
36944             // 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
36945             return ((((((((((c10 * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
36946          }
36947       };
36948 
36949       template <typename Type>
36950       struct poly_impl <Type,9>
36951       {
evaluateexprtk::polynomial::poly_impl36952          static inline T evaluate(const Type x,
36953                                   const Type c9, const Type c8, const Type c7, const Type c6, const Type c5,
36954                                   const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
36955          {
36956             // 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
36957             return (((((((((c9 * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
36958          }
36959       };
36960 
36961       template <typename Type>
36962       struct poly_impl <Type,8>
36963       {
evaluateexprtk::polynomial::poly_impl36964          static inline T evaluate(const Type x,
36965                                   const Type c8, const Type c7, const Type c6, const Type c5, const Type c4,
36966                                   const Type c3, const Type c2, const Type c1, const Type c0)
36967          {
36968             // 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
36969             return ((((((((c8 * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
36970          }
36971       };
36972 
36973       template <typename Type>
36974       struct poly_impl <Type,7>
36975       {
evaluateexprtk::polynomial::poly_impl36976          static inline T evaluate(const Type x,
36977                                   const Type c7, const Type c6, const Type c5, const Type c4, const Type c3,
36978                                   const Type c2, const Type c1, const Type c0)
36979          {
36980             // 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
36981             return (((((((c7 * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
36982          }
36983       };
36984 
36985       template <typename Type>
36986       struct poly_impl <Type,6>
36987       {
evaluateexprtk::polynomial::poly_impl36988          static inline T evaluate(const Type x,
36989                                   const Type c6, const Type c5, const Type c4, const Type c3, const Type c2,
36990                                   const Type c1, const Type c0)
36991          {
36992             // p(x) = c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
36993             return ((((((c6 * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
36994          }
36995       };
36996 
36997       template <typename Type>
36998       struct poly_impl <Type,5>
36999       {
evaluateexprtk::polynomial::poly_impl37000          static inline T evaluate(const Type x,
37001                                   const Type c5, const Type c4, const Type c3, const Type c2,
37002                                   const Type c1, const Type c0)
37003          {
37004             // p(x) = c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
37005             return (((((c5 * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
37006          }
37007       };
37008 
37009       template <typename Type>
37010       struct poly_impl <Type,4>
37011       {
evaluateexprtk::polynomial::poly_impl37012          static inline T evaluate(const Type x, const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
37013          {
37014             // p(x) = c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
37015             return ((((c4 * x + c3) * x + c2) * x + c1) * x + c0);
37016          }
37017       };
37018 
37019       template <typename Type>
37020       struct poly_impl <Type,3>
37021       {
evaluateexprtk::polynomial::poly_impl37022          static inline T evaluate(const Type x, const Type c3, const Type c2, const Type c1, const Type c0)
37023          {
37024             // p(x) = c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
37025             return (((c3 * x + c2) * x + c1) * x + c0);
37026          }
37027       };
37028 
37029       template <typename Type>
37030       struct poly_impl <Type,2>
37031       {
evaluateexprtk::polynomial::poly_impl37032          static inline T evaluate(const Type x, const Type c2, const Type c1, const Type c0)
37033          {
37034             // p(x) = c_2x^2 + c_1x^1 + c_0x^0
37035             return ((c2 * x + c1) * x + c0);
37036          }
37037       };
37038 
37039       template <typename Type>
37040       struct poly_impl <Type,1>
37041       {
evaluateexprtk::polynomial::poly_impl37042          static inline T evaluate(const Type x, const Type c1, const Type c0)
37043          {
37044             // p(x) = c_1x^1 + c_0x^0
37045             return (c1 * x + c0);
37046          }
37047       };
37048 
37049    public:
37050 
37051       using ifunction<T>::operator();
37052 
polynomial()37053       polynomial()
37054       : ifunction<T>((N+2 <= 20) ? (N + 2) : std::numeric_limits<std::size_t>::max())
37055       {
37056          disable_has_side_effects(*this);
37057       }
37058 
~polynomial()37059       virtual ~polynomial()
37060       {}
37061 
37062       #define poly_rtrn(NN) \
37063       return (NN != N) ? std::numeric_limits<T>::quiet_NaN() :
37064 
operator ()(const T & x,const T & c1,const T & c0)37065       inline virtual T operator() (const T& x, const T& c1, const T& c0)
37066       {
37067          poly_rtrn(1) (poly_impl<T,1>::evaluate(x, c1, c0));
37068       }
37069 
operator ()(const T & x,const T & c2,const T & c1,const T & c0)37070       inline virtual T operator() (const T& x, const T& c2, const T& c1, const T& c0)
37071       {
37072          poly_rtrn(2) (poly_impl<T,2>::evaluate(x, c2, c1, c0));
37073       }
37074 
operator ()(const T & x,const T & c3,const T & c2,const T & c1,const T & c0)37075       inline virtual T operator() (const T& x, const T& c3, const T& c2, const T& c1, const T& c0)
37076       {
37077          poly_rtrn(3) (poly_impl<T,3>::evaluate(x, c3, c2, c1, c0));
37078       }
37079 
operator ()(const T & x,const T & c4,const T & c3,const T & c2,const T & c1,const T & c0)37080       inline virtual T operator() (const T& x, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
37081       {
37082          poly_rtrn(4) (poly_impl<T,4>::evaluate(x, c4, c3, c2, c1, c0));
37083       }
37084 
operator ()(const T & x,const T & c5,const T & c4,const T & c3,const T & c2,const T & c1,const T & c0)37085       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)
37086       {
37087          poly_rtrn(5) (poly_impl<T,5>::evaluate(x, c5, c4, c3, c2, c1, c0));
37088       }
37089 
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)37090       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)
37091       {
37092          poly_rtrn(6) (poly_impl<T,6>::evaluate(x, c6, c5, c4, c3, c2, c1, c0));
37093       }
37094 
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)37095       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)
37096       {
37097          poly_rtrn(7) (poly_impl<T,7>::evaluate(x, c7, c6, c5, c4, c3, c2, c1, c0));
37098       }
37099 
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)37100       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)
37101       {
37102          poly_rtrn(8) (poly_impl<T,8>::evaluate(x, c8, c7, c6, c5, c4, c3, c2, c1, c0));
37103       }
37104 
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)37105       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)
37106       {
37107          poly_rtrn(9) (poly_impl<T,9>::evaluate(x, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0));
37108       }
37109 
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)37110       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)
37111       {
37112          poly_rtrn(10) (poly_impl<T,10>::evaluate(x, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0));
37113       }
37114 
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)37115       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)
37116       {
37117          poly_rtrn(11) (poly_impl<T,11>::evaluate(x, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0));
37118       }
37119 
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)37120       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)
37121       {
37122          poly_rtrn(12) (poly_impl<T,12>::evaluate(x, c12, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0));
37123       }
37124 
37125       #undef poly_rtrn
37126 
operator ()()37127       inline virtual T operator() ()
37128       {
37129          return std::numeric_limits<T>::quiet_NaN();
37130       }
37131 
operator ()(const T &)37132       inline virtual T operator() (const T&)
37133       {
37134          return std::numeric_limits<T>::quiet_NaN();
37135       }
37136 
operator ()(const T &,const T &)37137       inline virtual T operator() (const T&, const T&)
37138       {
37139          return std::numeric_limits<T>::quiet_NaN();
37140       }
37141    };
37142 
37143    template <typename T>
37144    class function_compositor
37145    {
37146    public:
37147 
37148       typedef exprtk::expression<T>             expression_t;
37149       typedef exprtk::symbol_table<T>           symbol_table_t;
37150       typedef exprtk::parser<T>                 parser_t;
37151       typedef typename parser_t::settings_store settings_t;
37152 
37153       struct function
37154       {
functionexprtk::function_compositor::function37155          function()
37156          {}
37157 
functionexprtk::function_compositor::function37158          function(const std::string& n)
37159          : name_(n)
37160          {}
37161 
functionexprtk::function_compositor::function37162          function(const std::string& name,
37163                   const std::string& expression)
37164          : name_(name),
37165            expression_(expression)
37166          {}
37167 
functionexprtk::function_compositor::function37168          function(const std::string& name,
37169                   const std::string& expression,
37170                   const std::string& v0)
37171          : name_(name),
37172            expression_(expression)
37173          {
37174             v_.push_back(v0);
37175          }
37176 
functionexprtk::function_compositor::function37177          function(const std::string& name,
37178                   const std::string& expression,
37179                   const std::string& v0, const std::string& v1)
37180          : name_(name),
37181            expression_(expression)
37182          {
37183             v_.push_back(v0); v_.push_back(v1);
37184          }
37185 
functionexprtk::function_compositor::function37186          function(const std::string& name,
37187                   const std::string& expression,
37188                   const std::string& v0, const std::string& v1,
37189                   const std::string& v2)
37190          : name_(name),
37191            expression_(expression)
37192          {
37193             v_.push_back(v0); v_.push_back(v1);
37194             v_.push_back(v2);
37195          }
37196 
functionexprtk::function_compositor::function37197          function(const std::string& name,
37198                   const std::string& expression,
37199                   const std::string& v0, const std::string& v1,
37200                   const std::string& v2, const std::string& v3)
37201          : name_(name),
37202            expression_(expression)
37203          {
37204             v_.push_back(v0); v_.push_back(v1);
37205             v_.push_back(v2); v_.push_back(v3);
37206          }
37207 
functionexprtk::function_compositor::function37208          function(const std::string& name,
37209                   const std::string& expression,
37210                   const std::string& v0, const std::string& v1,
37211                   const std::string& v2, const std::string& v3,
37212                   const std::string& v4)
37213          : name_(name),
37214            expression_(expression)
37215          {
37216             v_.push_back(v0); v_.push_back(v1);
37217             v_.push_back(v2); v_.push_back(v3);
37218             v_.push_back(v4);
37219          }
37220 
nameexprtk::function_compositor::function37221          inline function& name(const std::string& n)
37222          {
37223             name_ = n;
37224             return (*this);
37225          }
37226 
expressionexprtk::function_compositor::function37227          inline function& expression(const std::string& e)
37228          {
37229             expression_ = e;
37230             return (*this);
37231          }
37232 
varexprtk::function_compositor::function37233          inline function& var(const std::string& v)
37234          {
37235             v_.push_back(v);
37236             return (*this);
37237          }
37238 
37239          std::string name_;
37240          std::string expression_;
37241          std::deque<std::string> v_;
37242       };
37243 
37244    private:
37245 
37246       struct base_func : public exprtk::ifunction<T>
37247       {
37248          typedef const T&                       type;
37249          typedef exprtk::ifunction<T>     function_t;
37250          typedef std::vector<T*>            varref_t;
37251          typedef std::vector<T>                var_t;
37252          typedef std::pair<T*,std::size_t> lvarref_t;
37253          typedef std::vector<lvarref_t>    lvr_vec_t;
37254 
37255          using exprtk::ifunction<T>::operator();
37256 
base_funcexprtk::function_compositor::base_func37257          base_func(const std::size_t& pc = 0)
37258          : exprtk::ifunction<T>(pc),
37259            local_var_stack_size(0),
37260            stack_depth(0)
37261          {
37262             v.resize(pc);
37263          }
37264 
~base_funcexprtk::function_compositor::base_func37265          virtual ~base_func()
37266          {}
37267 
updateexprtk::function_compositor::base_func37268          inline void update(const T& v0)
37269          {
37270             (*v[0]) = v0;
37271          }
37272 
updateexprtk::function_compositor::base_func37273          inline void update(const T& v0, const T& v1)
37274          {
37275             (*v[0]) = v0; (*v[1]) = v1;
37276          }
37277 
updateexprtk::function_compositor::base_func37278          inline void update(const T& v0, const T& v1, const T& v2)
37279          {
37280             (*v[0]) = v0; (*v[1]) = v1;
37281             (*v[2]) = v2;
37282          }
37283 
updateexprtk::function_compositor::base_func37284          inline void update(const T& v0, const T& v1, const T& v2, const T& v3)
37285          {
37286             (*v[0]) = v0; (*v[1]) = v1;
37287             (*v[2]) = v2; (*v[3]) = v3;
37288          }
37289 
updateexprtk::function_compositor::base_func37290          inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4)
37291          {
37292             (*v[0]) = v0; (*v[1]) = v1;
37293             (*v[2]) = v2; (*v[3]) = v3;
37294             (*v[4]) = v4;
37295          }
37296 
updateexprtk::function_compositor::base_func37297          inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5)
37298          {
37299             (*v[0]) = v0; (*v[1]) = v1;
37300             (*v[2]) = v2; (*v[3]) = v3;
37301             (*v[4]) = v4; (*v[5]) = v5;
37302          }
37303 
setupexprtk::function_compositor::base_func37304          inline function_t& setup(expression_t& expr)
37305          {
37306             expression = expr;
37307 
37308             typedef typename expression_t::control_block::local_data_list_t ldl_t;
37309 
37310             const ldl_t ldl = expr.local_data_list();
37311 
37312             std::vector<std::size_t> index_list;
37313 
37314             for (std::size_t i = 0; i < ldl.size(); ++i)
37315             {
37316                if (ldl[i].size)
37317                {
37318                   index_list.push_back(i);
37319                }
37320             }
37321 
37322             std::size_t input_param_count = 0;
37323 
37324             for (std::size_t i = 0; i < index_list.size(); ++i)
37325             {
37326                const std::size_t index = index_list[i];
37327 
37328                if (i < (index_list.size() - v.size()))
37329                {
37330                   lv.push_back(
37331                         std::make_pair(
37332                            reinterpret_cast<T*>(ldl[index].pointer),
37333                            ldl[index].size));
37334 
37335                   local_var_stack_size += ldl[index].size;
37336                }
37337                else
37338                   v[input_param_count++] = reinterpret_cast<T*>(ldl[index].pointer);
37339             }
37340 
37341             clear_stack();
37342 
37343             return (*this);
37344          }
37345 
preexprtk::function_compositor::base_func37346          inline void pre()
37347          {
37348             if (stack_depth++)
37349             {
37350                if (!v.empty())
37351                {
37352                   var_t var_stack(v.size(),T(0));
37353                   copy(v,var_stack);
37354                   param_stack.push_back(var_stack);
37355                }
37356 
37357                if (!lv.empty())
37358                {
37359                   var_t local_var_stack(local_var_stack_size,T(0));
37360                   copy(lv,local_var_stack);
37361                   local_stack.push_back(local_var_stack);
37362                }
37363             }
37364          }
37365 
postexprtk::function_compositor::base_func37366          inline void post()
37367          {
37368             if (--stack_depth)
37369             {
37370                if (!v.empty())
37371                {
37372                   copy(param_stack.back(),v);
37373                   param_stack.pop_back();
37374                }
37375 
37376                if (!lv.empty())
37377                {
37378                   copy(local_stack.back(),lv);
37379                   local_stack.pop_back();
37380                }
37381             }
37382          }
37383 
copyexprtk::function_compositor::base_func37384          void copy(const varref_t& src_v, var_t& dest_v)
37385          {
37386             for (std::size_t i = 0; i < src_v.size(); ++i)
37387             {
37388                dest_v[i] = (*src_v[i]);
37389             }
37390          }
37391 
copyexprtk::function_compositor::base_func37392          void copy(const var_t& src_v, varref_t& dest_v)
37393          {
37394             for (std::size_t i = 0; i < src_v.size(); ++i)
37395             {
37396                (*dest_v[i]) = src_v[i];
37397             }
37398          }
37399 
copyexprtk::function_compositor::base_func37400          void copy(const lvr_vec_t& src_v, var_t& dest_v)
37401          {
37402             typename var_t::iterator itr = dest_v.begin();
37403             typedef  typename std::iterator_traits<typename var_t::iterator>::difference_type diff_t;
37404 
37405             for (std::size_t i = 0; i < src_v.size(); ++i)
37406             {
37407                lvarref_t vr = src_v[i];
37408 
37409                if (1 == vr.second)
37410                   *itr++ = (*vr.first);
37411                else
37412                {
37413                   std::copy(vr.first, vr.first + vr.second, itr);
37414                   itr += static_cast<diff_t>(vr.second);
37415                }
37416             }
37417          }
37418 
copyexprtk::function_compositor::base_func37419          void copy(const var_t& src_v, lvr_vec_t& dest_v)
37420          {
37421             typename var_t::const_iterator itr = src_v.begin();
37422             typedef  typename std::iterator_traits<typename var_t::iterator>::difference_type diff_t;
37423 
37424             for (std::size_t i = 0; i < src_v.size(); ++i)
37425             {
37426                lvarref_t vr = dest_v[i];
37427 
37428                if (1 == vr.second)
37429                   (*vr.first) = *itr++;
37430                else
37431                {
37432                   std::copy(itr, itr + static_cast<diff_t>(vr.second), vr.first);
37433                   itr += static_cast<diff_t>(vr.second);
37434                }
37435             }
37436          }
37437 
clear_stackexprtk::function_compositor::base_func37438          inline void clear_stack()
37439          {
37440             for (std::size_t i = 0; i < v.size(); ++i)
37441             {
37442                (*v[i]) = 0;
37443             }
37444          }
37445 
valueexprtk::function_compositor::base_func37446          inline virtual T value(expression_t& e)
37447          {
37448             return e.value();
37449          }
37450 
37451          expression_t expression;
37452          varref_t v;
37453          lvr_vec_t lv;
37454          std::size_t local_var_stack_size;
37455          std::size_t stack_depth;
37456          std::deque<var_t> param_stack;
37457          std::deque<var_t> local_stack;
37458       };
37459 
37460       typedef std::map<std::string,base_func*> funcparam_t;
37461 
37462       struct func_0param : public base_func
37463       {
37464          using exprtk::ifunction<T>::operator();
37465 
func_0paramexprtk::function_compositor::func_0param37466          func_0param() : base_func(0) {}
37467 
operator ()exprtk::function_compositor::func_0param37468          inline T operator() ()
37469          {
37470             return this->value(base_func::expression);
37471          }
37472       };
37473 
37474       typedef const T& type;
37475 
37476       template <typename BaseFuncType>
37477       struct scoped_bft
37478       {
scoped_bftexprtk::function_compositor::scoped_bft37479          explicit scoped_bft(BaseFuncType& bft)
37480          : bft_(bft)
37481          {
37482             bft_.pre ();
37483          }
37484 
~scoped_bftexprtk::function_compositor::scoped_bft37485         ~scoped_bft()
37486          {
37487             bft_.post();
37488          }
37489 
37490          BaseFuncType& bft_;
37491 
37492       private:
37493 
37494          scoped_bft(scoped_bft&);
37495          scoped_bft& operator=(scoped_bft&);
37496       };
37497 
37498       struct func_1param : public base_func
37499       {
37500          using exprtk::ifunction<T>::operator();
37501 
func_1paramexprtk::function_compositor::func_1param37502          func_1param() : base_func(1) {}
37503 
operator ()exprtk::function_compositor::func_1param37504          inline T operator() (type v0)
37505          {
37506             scoped_bft<func_1param> sb(*this);
37507             base_func::update(v0);
37508             return this->value(base_func::expression);
37509          }
37510       };
37511 
37512       struct func_2param : public base_func
37513       {
37514          using exprtk::ifunction<T>::operator();
37515 
func_2paramexprtk::function_compositor::func_2param37516          func_2param() : base_func(2) {}
37517 
operator ()exprtk::function_compositor::func_2param37518          inline T operator() (type v0, type v1)
37519          {
37520             scoped_bft<func_2param> sb(*this);
37521             base_func::update(v0, v1);
37522             return this->value(base_func::expression);
37523          }
37524       };
37525 
37526       struct func_3param : public base_func
37527       {
37528          using exprtk::ifunction<T>::operator();
37529 
func_3paramexprtk::function_compositor::func_3param37530          func_3param() : base_func(3) {}
37531 
operator ()exprtk::function_compositor::func_3param37532          inline T operator() (type v0, type v1, type v2)
37533          {
37534             scoped_bft<func_3param> sb(*this);
37535             base_func::update(v0, v1, v2);
37536             return this->value(base_func::expression);
37537          }
37538       };
37539 
37540       struct func_4param : public base_func
37541       {
37542          using exprtk::ifunction<T>::operator();
37543 
func_4paramexprtk::function_compositor::func_4param37544          func_4param() : base_func(4) {}
37545 
operator ()exprtk::function_compositor::func_4param37546          inline T operator() (type v0, type v1, type v2, type v3)
37547          {
37548             scoped_bft<func_4param> sb(*this);
37549             base_func::update(v0, v1, v2, v3);
37550             return this->value(base_func::expression);
37551          }
37552       };
37553 
37554       struct func_5param : public base_func
37555       {
37556          using exprtk::ifunction<T>::operator();
37557 
func_5paramexprtk::function_compositor::func_5param37558          func_5param() : base_func(5) {}
37559 
operator ()exprtk::function_compositor::func_5param37560          inline T operator() (type v0, type v1, type v2, type v3, type v4)
37561          {
37562             scoped_bft<func_5param> sb(*this);
37563             base_func::update(v0, v1, v2, v3, v4);
37564             return this->value(base_func::expression);
37565          }
37566       };
37567 
37568       struct func_6param : public base_func
37569       {
37570          using exprtk::ifunction<T>::operator();
37571 
func_6paramexprtk::function_compositor::func_6param37572          func_6param() : base_func(6) {}
37573 
operator ()exprtk::function_compositor::func_6param37574          inline T operator() (type v0, type v1, type v2, type v3, type v4, type v5)
37575          {
37576             scoped_bft<func_6param> sb(*this);
37577             base_func::update(v0, v1, v2, v3, v4, v5);
37578             return this->value(base_func::expression);
37579          }
37580       };
37581 
return_value(expression_t & e)37582       static T return_value(expression_t& e)
37583       {
37584          typedef exprtk::results_context<T> results_context_t;
37585          typedef typename results_context_t::type_store_t type_t;
37586          typedef typename type_t::scalar_view scalar_t;
37587 
37588          const T result = e.value();
37589 
37590          if (e.return_invoked())
37591          {
37592             // Due to the post compilation checks, it can be safely
37593             // assumed that there will be at least one parameter
37594             // and that the first parameter will always be scalar.
37595             return scalar_t(e.results()[0])();
37596          }
37597 
37598          return result;
37599       }
37600 
37601       #define def_fp_retval(N)                               \
37602       struct func_##N##param_retval : public func_##N##param \
37603       {                                                      \
37604          inline T value(expression_t& e)                     \
37605          {                                                   \
37606             return return_value(e);                          \
37607          }                                                   \
37608       };                                                     \
37609 
37610       def_fp_retval(0)
37611       def_fp_retval(1)
37612       def_fp_retval(2)
37613       def_fp_retval(3)
37614       def_fp_retval(4)
37615       def_fp_retval(5)
37616       def_fp_retval(6)
37617 
37618       template <typename Allocator,
37619                 template <typename, typename> class Sequence>
add(const std::string & name,const std::string & expression,const Sequence<std::string,Allocator> & var_list,const bool override=false)37620       inline bool add(const std::string& name,
37621                       const std::string& expression,
37622                       const Sequence<std::string,Allocator>& var_list,
37623                       const bool override = false)
37624       {
37625          const typename std::map<std::string,expression_t>::iterator itr = expr_map_.find(name);
37626 
37627          if (expr_map_.end() != itr)
37628          {
37629             if (!override)
37630             {
37631                exprtk_debug(("Compositor error(add): function '%s' already defined\n",
37632                              name.c_str()));
37633 
37634                return false;
37635             }
37636 
37637             remove(name, var_list.size());
37638          }
37639 
37640          if (compile_expression(name,expression,var_list))
37641          {
37642             const std::size_t n = var_list.size();
37643 
37644             fp_map_[n][name]->setup(expr_map_[name]);
37645 
37646             return true;
37647          }
37648          else
37649          {
37650             exprtk_debug(("Compositor error(add): Failed to compile function '%s'\n",
37651                           name.c_str()));
37652 
37653             return false;
37654          }
37655       }
37656 
37657    public:
37658 
function_compositor()37659       function_compositor()
37660       : parser_(settings_t::compile_all_opts +
37661                 settings_t::e_disable_zero_return),
37662         fp_map_(7)
37663       {}
37664 
function_compositor(const symbol_table_t & st)37665       function_compositor(const symbol_table_t& st)
37666       : symbol_table_(st),
37667         parser_(settings_t::compile_all_opts +
37668                 settings_t::e_disable_zero_return),
37669         fp_map_(7)
37670       {}
37671 
~function_compositor()37672      ~function_compositor()
37673       {
37674          clear();
37675       }
37676 
symbol_table()37677       inline symbol_table_t& symbol_table()
37678       {
37679          return symbol_table_;
37680       }
37681 
symbol_table() const37682       inline const symbol_table_t& symbol_table() const
37683       {
37684          return symbol_table_;
37685       }
37686 
add_auxiliary_symtab(symbol_table_t & symtab)37687       inline void add_auxiliary_symtab(symbol_table_t& symtab)
37688       {
37689          auxiliary_symtab_list_.push_back(&symtab);
37690       }
37691 
clear()37692       void clear()
37693       {
37694          symbol_table_.clear();
37695          expr_map_    .clear();
37696 
37697          for (std::size_t i = 0; i < fp_map_.size(); ++i)
37698          {
37699             typename funcparam_t::iterator itr = fp_map_[i].begin();
37700             typename funcparam_t::iterator end = fp_map_[i].end  ();
37701 
37702             while (itr != end)
37703             {
37704                delete itr->second;
37705                ++itr;
37706             }
37707 
37708             fp_map_[i].clear();
37709          }
37710       }
37711 
add(const function & f,const bool override=false)37712       inline bool add(const function& f, const bool override = false)
37713       {
37714          return add(f.name_, f.expression_, f.v_,override);
37715       }
37716 
37717    private:
37718 
37719       template <typename Allocator,
37720                 template <typename, typename> class Sequence>
compile_expression(const std::string & name,const std::string & expression,const Sequence<std::string,Allocator> & input_var_list,bool return_present=false)37721       bool compile_expression(const std::string& name,
37722                               const std::string& expression,
37723                               const Sequence<std::string,Allocator>& input_var_list,
37724                               bool  return_present = false)
37725       {
37726          expression_t compiled_expression;
37727          symbol_table_t local_symbol_table;
37728 
37729          local_symbol_table.load_from(symbol_table_);
37730          local_symbol_table.add_constants();
37731 
37732          if (!valid(name,input_var_list.size()))
37733             return false;
37734 
37735          if (!forward(name,
37736                       input_var_list.size(),
37737                       local_symbol_table,
37738                       return_present))
37739             return false;
37740 
37741          compiled_expression.register_symbol_table(local_symbol_table);
37742 
37743          for (std::size_t i = 0; i < auxiliary_symtab_list_.size(); ++i)
37744          {
37745             compiled_expression.register_symbol_table((*auxiliary_symtab_list_[i]));
37746          }
37747 
37748          std::string mod_expression;
37749 
37750          for (std::size_t i = 0; i < input_var_list.size(); ++i)
37751          {
37752             mod_expression += " var " + input_var_list[i] + "{};\n";
37753          }
37754 
37755          if (
37756               ('{' == details::front(expression)) &&
37757               ('}' == details::back (expression))
37758             )
37759             mod_expression += "~" + expression + ";";
37760          else
37761             mod_expression += "~{" + expression + "};";
37762 
37763          if (!parser_.compile(mod_expression,compiled_expression))
37764          {
37765             exprtk_debug(("Compositor Error: %s\n",parser_.error().c_str()));
37766             exprtk_debug(("Compositor modified expression: \n%s\n",mod_expression.c_str()));
37767 
37768             remove(name,input_var_list.size());
37769 
37770             return false;
37771          }
37772 
37773          if (!return_present && parser_.dec().return_present())
37774          {
37775             remove(name,input_var_list.size());
37776 
37777             return compile_expression(name, expression, input_var_list, true);
37778          }
37779 
37780          // Make sure every return point has a scalar as its first parameter
37781          if (parser_.dec().return_present())
37782          {
37783             typedef std::vector<std::string> str_list_t;
37784 
37785             str_list_t ret_param_list = parser_.dec().return_param_type_list();
37786 
37787             for (std::size_t i = 0; i < ret_param_list.size(); ++i)
37788             {
37789                const std::string& params = ret_param_list[i];
37790 
37791                if (params.empty() || ('T' != params[0]))
37792                {
37793                   exprtk_debug(("Compositor Error: Return statement in function '%s' is invalid\n",
37794                                 name.c_str()));
37795 
37796                   remove(name,input_var_list.size());
37797 
37798                   return false;
37799                }
37800             }
37801          }
37802 
37803          expr_map_[name] = compiled_expression;
37804 
37805          exprtk::ifunction<T>& ifunc = (*(fp_map_[input_var_list.size()])[name]);
37806 
37807          if (symbol_table_.add_function(name,ifunc))
37808             return true;
37809          else
37810          {
37811             exprtk_debug(("Compositor Error: Failed to add function '%s' to symbol table\n",
37812                           name.c_str()));
37813             return false;
37814          }
37815       }
37816 
symbol_used(const std::string & symbol) const37817       inline bool symbol_used(const std::string& symbol) const
37818       {
37819          return (
37820                   symbol_table_.is_variable       (symbol) ||
37821                   symbol_table_.is_stringvar      (symbol) ||
37822                   symbol_table_.is_function       (symbol) ||
37823                   symbol_table_.is_vector         (symbol) ||
37824                   symbol_table_.is_vararg_function(symbol)
37825                 );
37826       }
37827 
valid(const std::string & name,const std::size_t & arg_count) const37828       inline bool valid(const std::string& name,
37829                         const std::size_t& arg_count) const
37830       {
37831          if (arg_count > 6)
37832             return false;
37833          else if (symbol_used(name))
37834             return false;
37835          else if (fp_map_[arg_count].end() != fp_map_[arg_count].find(name))
37836             return false;
37837          else
37838             return true;
37839       }
37840 
forward(const std::string & name,const std::size_t & arg_count,symbol_table_t & sym_table,const bool ret_present=false)37841       inline bool forward(const std::string& name,
37842                           const std::size_t& arg_count,
37843                           symbol_table_t& sym_table,
37844                           const bool ret_present = false)
37845       {
37846          switch (arg_count)
37847          {
37848             #define case_stmt(N)                                     \
37849             case N : (fp_map_[arg_count])[name] =                    \
37850                      (!ret_present) ? static_cast<base_func*>        \
37851                                       (new func_##N##param) :        \
37852                                       static_cast<base_func*>        \
37853                                       (new func_##N##param_retval) ; \
37854                      break;                                          \
37855 
37856             case_stmt(0) case_stmt(1) case_stmt(2)
37857             case_stmt(3) case_stmt(4) case_stmt(5)
37858             case_stmt(6)
37859             #undef case_stmt
37860          }
37861 
37862          exprtk::ifunction<T>& ifunc = (*(fp_map_[arg_count])[name]);
37863 
37864          return sym_table.add_function(name,ifunc);
37865       }
37866 
remove(const std::string & name,const std::size_t & arg_count)37867       inline void remove(const std::string& name, const std::size_t& arg_count)
37868       {
37869          if (arg_count > 6)
37870             return;
37871 
37872          const typename std::map<std::string,expression_t>::iterator em_itr = expr_map_.find(name);
37873 
37874          if (expr_map_.end() != em_itr)
37875          {
37876             expr_map_.erase(em_itr);
37877          }
37878 
37879          const typename funcparam_t::iterator fp_itr = fp_map_[arg_count].find(name);
37880 
37881          if (fp_map_[arg_count].end() != fp_itr)
37882          {
37883             delete fp_itr->second;
37884             fp_map_[arg_count].erase(fp_itr);
37885          }
37886 
37887          symbol_table_.remove_function(name);
37888       }
37889 
37890    private:
37891 
37892       symbol_table_t symbol_table_;
37893       parser_t parser_;
37894       std::map<std::string,expression_t> expr_map_;
37895       std::vector<funcparam_t> fp_map_;
37896       std::vector<symbol_table_t*> auxiliary_symtab_list_;
37897    };
37898 
37899    template <typename T>
pgo_primer()37900    inline bool pgo_primer()
37901    {
37902       static const std::string expression_list[] =
37903              {
37904                 "(y + x)",
37905                 "2 * (y + x)",
37906                 "(2 * y + 2 * x)",
37907                 "(y + x / y) * (x - y / x)",
37908                 "x / ((x + y) * (x - y)) / y",
37909                 "1 - ((x * y) + (y / x)) - 3",
37910                 "sin(2 * x) + cos(pi / y)",
37911                 "1 - sin(2 * x) + cos(pi / y)",
37912                 "sqrt(1 - sin(2 * x) + cos(pi / y) / 3)",
37913                 "(x^2 / sin(2 * pi / y)) -x / 2",
37914                 "x + (cos(y - sin(2 / x * pi)) - sin(x - cos(2 * y / pi))) - y",
37915                 "clamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)",
37916                 "iclamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)",
37917                 "max(3.33, min(sqrt(1 - sin(2 * x) + cos(pi / y) / 3), 1.11))",
37918                 "if(avg(x,y) <= x + y, x - y, x * y) + 2 * pi / x",
37919                 "1.1x^1 + 2.2y^2 - 3.3x^3 + 4.4y^4 - 5.5x^5 + 6.6y^6 - 7.7x^27 + 8.8y^55",
37920                 "(yy + xx)",
37921                 "2 * (yy + xx)",
37922                 "(2 * yy + 2 * xx)",
37923                 "(yy + xx / yy) * (xx - yy / xx)",
37924                 "xx / ((xx + yy) * (xx - yy)) / yy",
37925                 "1 - ((xx * yy) + (yy / xx)) - 3",
37926                 "sin(2 * xx) + cos(pi / yy)",
37927                 "1 - sin(2 * xx) + cos(pi / yy)",
37928                 "sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3)",
37929                 "(xx^2 / sin(2 * pi / yy)) -xx / 2",
37930                 "xx + (cos(yy - sin(2 / xx * pi)) - sin(xx - cos(2 * yy / pi))) - yy",
37931                 "clamp(-1.0, sin(2 * pi * xx) + cos(yy / 2 * pi), +1.0)",
37932                 "max(3.33, min(sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3), 1.11))",
37933                 "if(avg(xx,yy) <= xx + yy, xx - yy, xx * yy) + 2 * pi / xx",
37934                 "1.1xx^1 + 2.2yy^2 - 3.3xx^3 + 4.4yy^4 - 5.5xx^5 + 6.6yy^6 - 7.7xx^27 + 8.8yy^55",
37935                 "(1.1*(2.2*(3.3*(4.4*(5.5*(6.6*(7.7*(8.8*(9.9+x)))))))))",
37936                 "(((((((((x+9.9)*8.8)*7.7)*6.6)*5.5)*4.4)*3.3)*2.2)*1.1)",
37937                 "(x + y) * z", "x + (y * z)", "(x + y) * 7", "x + (y * 7)",
37938                 "(x + 7) * y", "x + (7 * y)", "(7 + x) * y", "7 + (x * y)",
37939                 "(2 + x) * 3", "2 + (x * 3)", "(2 + 3) * x", "2 + (3 * x)",
37940                 "(x + 2) * 3", "x + (2 * 3)",
37941                 "(x + y) * (z / w)", "(x + y) * (z / 7)", "(x + y) * (7 / z)", "(x + 7) * (y / z)",
37942                 "(7 + x) * (y / z)", "(2 + x) * (y / z)", "(x + 2) * (y / 3)", "(2 + x) * (y / 3)",
37943                 "(x + 2) * (3 / y)", "x + (y * (z / w))", "x + (y * (z / 7))", "x + (y * (7 / z))",
37944                 "x + (7 * (y / z))", "7 + (x * (y / z))", "2 + (x * (3 / y))", "x + (2 * (y / 4))",
37945                 "2 + (x * (y / 3))", "x + (2 * (3 / y))",
37946                 "x + ((y * z) / w)", "x + ((y * z) / 7)", "x + ((y * 7) / z)", "x + ((7 * y) / z)",
37947                 "7 + ((y * z) / w)", "2 + ((x * 3) / y)", "x + ((2 * y) / 3)", "2 + ((x * y) / 3)",
37948                 "x + ((2 * 3) / y)", "(((x + y) * z) / w)",
37949                 "(((x + y) * z) / 7)", "(((x + y) * 7) / z)", "(((x + 7) * y) / z)", "(((7 + x) * y) / z)",
37950                 "(((2 + x) * 3) / y)", "(((x + 2) * y) / 3)", "(((2 + x) * y) / 3)", "(((x + 2) * 3) / y)",
37951                 "((x + (y * z)) / w)", "((x + (y * z)) / 7)", "((x + (y * 7)) / y)", "((x + (7 * y)) / z)",
37952                 "((7 + (x * y)) / z)", "((2 + (x * 3)) / y)", "((x + (2 * y)) / 3)", "((2 + (x * y)) / 3)",
37953                 "((x + (2 * 3)) / y)",
37954                 "(xx + yy) * zz", "xx + (yy * zz)",
37955                 "(xx + yy) * 7", "xx + (yy * 7)",
37956                 "(xx + 7) * yy", "xx + (7 * yy)",
37957                 "(7 + xx) * yy", "7 + (xx * yy)",
37958                 "(2 + x) * 3", "2 + (x * 3)",
37959                 "(2 + 3) * x", "2 + (3 * x)",
37960                 "(x + 2) * 3", "x + (2 * 3)",
37961                 "(xx + yy) * (zz / ww)", "(xx + yy) * (zz / 7)",
37962                 "(xx + yy) * (7 / zz)", "(xx + 7) * (yy / zz)",
37963                 "(7 + xx) * (yy / zz)", "(2 + xx) * (yy / zz)",
37964                 "(xx + 2) * (yy / 3)", "(2 + xx) * (yy / 3)",
37965                 "(xx + 2) * (3 / yy)", "xx + (yy * (zz / ww))",
37966                 "xx + (yy * (zz / 7))", "xx + (yy * (7 / zz))",
37967                 "xx + (7 * (yy / zz))", "7 + (xx * (yy / zz))",
37968                 "2 + (xx * (3 / yy))", "xx + (2 * (yy / 4))",
37969                 "2 + (xx * (yy / 3))", "xx + (2 * (3 / yy))",
37970                 "xx + ((yy * zz) / ww)", "xx + ((yy * zz) / 7)",
37971                 "xx + ((yy * 7) / zz)", "xx + ((7 * yy) / zz)",
37972                 "7 + ((yy * zz) / ww)", "2 + ((xx * 3) / yy)",
37973                 "xx + ((2 * yy) / 3)", "2 + ((xx * yy) / 3)",
37974                 "xx + ((2 * 3) / yy)", "(((xx + yy) * zz) / ww)",
37975                 "(((xx + yy) * zz) / 7)", "(((xx + yy) * 7) / zz)",
37976                 "(((xx + 7) * yy) / zz)", "(((7 + xx) * yy) / zz)",
37977                 "(((2 + xx) * 3) / yy)", "(((xx + 2) * yy) / 3)",
37978                 "(((2 + xx) * yy) / 3)", "(((xx + 2) * 3) / yy)",
37979                 "((xx + (yy * zz)) / ww)", "((xx + (yy * zz)) / 7)",
37980                 "((xx + (yy * 7)) / yy)", "((xx + (7 * yy)) / zz)",
37981                 "((7 + (xx * yy)) / zz)", "((2 + (xx * 3)) / yy)",
37982                 "((xx + (2 * yy)) / 3)", "((2 + (xx * yy)) / 3)",
37983                 "((xx + (2 * 3)) / yy)"
37984              };
37985 
37986       static const std::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string);
37987 
37988       T  x = T(0);
37989       T  y = T(0);
37990       T  z = T(0);
37991       T  w = T(0);
37992       T xx = T(0);
37993       T yy = T(0);
37994       T zz = T(0);
37995       T ww = T(0);
37996 
37997       exprtk::symbol_table<T> symbol_table;
37998       symbol_table.add_constants();
37999       symbol_table.add_variable( "x", x);
38000       symbol_table.add_variable( "y", y);
38001       symbol_table.add_variable( "z", z);
38002       symbol_table.add_variable( "w", w);
38003       symbol_table.add_variable("xx",xx);
38004       symbol_table.add_variable("yy",yy);
38005       symbol_table.add_variable("zz",zz);
38006       symbol_table.add_variable("ww",ww);
38007 
38008       typedef typename std::deque<exprtk::expression<T> > expr_list_t;
38009       expr_list_t expr_list;
38010 
38011       const std::size_t rounds = 50;
38012 
38013       {
38014          for (std::size_t r = 0; r < rounds; ++r)
38015          {
38016             expr_list.clear();
38017             exprtk::parser<T> parser;
38018 
38019             for (std::size_t i = 0; i < expression_list_size; ++i)
38020             {
38021                exprtk::expression<T> expression;
38022                expression.register_symbol_table(symbol_table);
38023 
38024                if (!parser.compile(expression_list[i],expression))
38025                {
38026                   return false;
38027                }
38028 
38029                expr_list.push_back(expression);
38030             }
38031          }
38032       }
38033 
38034       struct execute
38035       {
38036          static inline T process(T& x, T& y, expression<T>& expression)
38037          {
38038             static const T lower_bound = T(-20);
38039             static const T upper_bound = T(+20);
38040             static const T delta       = T(0.1);
38041 
38042             T total = T(0);
38043 
38044             for (x = lower_bound; x <= upper_bound; x += delta)
38045             {
38046                for (y = lower_bound; y <= upper_bound; y += delta)
38047                {
38048                   total += expression.value();
38049                }
38050             }
38051 
38052             return total;
38053          }
38054       };
38055 
38056       for (std::size_t i = 0; i < expr_list.size(); ++i)
38057       {
38058          execute::process( x,  y, expr_list[i]);
38059          execute::process(xx, yy, expr_list[i]);
38060       }
38061 
38062       {
38063          for (std::size_t i = 0; i < 10000; ++i)
38064          {
38065             const T v = T(123.456 + i);
38066 
38067             if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 1>::result(v),details::numeric::pow(v,T( 1)))))
38068                return false;
38069 
38070             #define else_stmt(N)                                                                                                           \
38071             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,N>::result(v),details::numeric::pow(v,T(N))))) \
38072                return false;                                                                                                               \
38073 
38074             else_stmt( 2) else_stmt( 3) else_stmt( 4) else_stmt( 5)
38075             else_stmt( 6) else_stmt( 7) else_stmt( 8) else_stmt( 9)
38076             else_stmt(10) else_stmt(11) else_stmt(12) else_stmt(13)
38077             else_stmt(14) else_stmt(15) else_stmt(16) else_stmt(17)
38078             else_stmt(18) else_stmt(19) else_stmt(20) else_stmt(21)
38079             else_stmt(22) else_stmt(23) else_stmt(24) else_stmt(25)
38080             else_stmt(26) else_stmt(27) else_stmt(28) else_stmt(29)
38081             else_stmt(30) else_stmt(31) else_stmt(32) else_stmt(33)
38082             else_stmt(34) else_stmt(35) else_stmt(36) else_stmt(37)
38083             else_stmt(38) else_stmt(39) else_stmt(40) else_stmt(41)
38084             else_stmt(42) else_stmt(43) else_stmt(44) else_stmt(45)
38085             else_stmt(46) else_stmt(47) else_stmt(48) else_stmt(49)
38086             else_stmt(50) else_stmt(51) else_stmt(52) else_stmt(53)
38087             else_stmt(54) else_stmt(55) else_stmt(56) else_stmt(57)
38088             else_stmt(58) else_stmt(59) else_stmt(60) else_stmt(61)
38089          }
38090       }
38091 
38092       return true;
38093    }
38094 }
38095 
38096 #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
38097 #   ifndef NOMINMAX
38098 #      define NOMINMAX
38099 #   endif
38100 #   ifndef WIN32_LEAN_AND_MEAN
38101 #      define WIN32_LEAN_AND_MEAN
38102 #   endif
38103 #   include <windows.h>
38104 #   include <ctime>
38105 #else
38106 #   include <ctime>
38107 #   include <sys/time.h>
38108 #   include <sys/types.h>
38109 #endif
38110 
38111 namespace exprtk
38112 {
38113    class timer
38114    {
38115    public:
38116 
38117       #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
timer()38118       timer()
38119       : in_use_(false)
38120       {
38121          QueryPerformanceFrequency(&clock_frequency_);
38122       }
38123 
start()38124       inline void start()
38125       {
38126          in_use_ = true;
38127          QueryPerformanceCounter(&start_time_);
38128       }
38129 
stop()38130       inline void stop()
38131       {
38132          QueryPerformanceCounter(&stop_time_);
38133          in_use_ = false;
38134       }
38135 
time() const38136       inline double time() const
38137       {
38138          return (1.0 * (stop_time_.QuadPart - start_time_.QuadPart)) / (1.0 * clock_frequency_.QuadPart);
38139       }
38140 
38141       #else
38142 
38143       timer()
38144       : in_use_(false)
38145       {
38146          start_time_.tv_sec  = 0;
38147          start_time_.tv_usec = 0;
38148          stop_time_.tv_sec   = 0;
38149          stop_time_.tv_usec  = 0;
38150       }
38151 
38152       inline void start()
38153       {
38154          in_use_ = true;
38155          gettimeofday(&start_time_,0);
38156       }
38157 
38158       inline void stop()
38159       {
38160          gettimeofday(&stop_time_, 0);
38161          in_use_ = false;
38162       }
38163 
38164       inline unsigned long long int usec_time() const
38165       {
38166          if (!in_use_)
38167          {
38168             if (stop_time_.tv_sec >= start_time_.tv_sec)
38169             {
38170                return 1000000LLU * static_cast<details::_uint64_t>(stop_time_.tv_sec  - start_time_.tv_sec ) +
38171                                    static_cast<details::_uint64_t>(stop_time_.tv_usec - start_time_.tv_usec) ;
38172             }
38173             else
38174                return std::numeric_limits<details::_uint64_t>::max();
38175          }
38176          else
38177             return std::numeric_limits<details::_uint64_t>::max();
38178       }
38179 
38180       inline double time() const
38181       {
38182          return usec_time() * 0.000001;
38183       }
38184 
38185       #endif
38186 
in_use() const38187       inline bool in_use() const
38188       {
38189          return in_use_;
38190       }
38191 
38192    private:
38193 
38194       bool in_use_;
38195 
38196       #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
38197          LARGE_INTEGER start_time_;
38198          LARGE_INTEGER stop_time_;
38199          LARGE_INTEGER clock_frequency_;
38200       #else
38201          struct timeval start_time_;
38202          struct timeval stop_time_;
38203       #endif
38204    };
38205 
38206 } // namespace exprtk
38207 
38208 #ifndef exprtk_disable_rtl_io
38209 namespace exprtk
38210 {
38211    namespace rtl { namespace io { namespace details
38212    {
38213       template <typename T>
print_type(const std::string & fmt,const T v,exprtk::details::numeric::details::real_type_tag)38214       inline void print_type(const std::string& fmt,
38215                              const T v,
38216                              exprtk::details::numeric::details::real_type_tag)
38217       {
38218          printf(fmt.c_str(),v);
38219       }
38220 
38221       template <typename T>
38222       struct print_impl
38223       {
38224          typedef typename igeneric_function<T>::generic_type generic_type;
38225          typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
38226          typedef typename generic_type::scalar_view scalar_t;
38227          typedef typename generic_type::vector_view vector_t;
38228          typedef typename generic_type::string_view string_t;
38229          typedef typename exprtk::details::numeric::details::number_type<T>::type num_type;
38230 
processexprtk::rtl::io::details::print_impl38231          static void process(const std::string& scalar_format, parameter_list_t parameters)
38232          {
38233             for (std::size_t i = 0; i < parameters.size(); ++i)
38234             {
38235                generic_type& gt = parameters[i];
38236 
38237                switch (gt.type)
38238                {
38239                   case generic_type::e_scalar : print(scalar_format,scalar_t(gt));
38240                                                 break;
38241 
38242                   case generic_type::e_vector : print(scalar_format,vector_t(gt));
38243                                                 break;
38244 
38245                   case generic_type::e_string : print(string_t(gt));
38246                                                 break;
38247 
38248                   default                     : continue;
38249                }
38250             }
38251          }
38252 
printexprtk::rtl::io::details::print_impl38253          static inline void print(const std::string& scalar_format, const scalar_t& s)
38254          {
38255             print_type(scalar_format,s(),num_type());
38256          }
38257 
printexprtk::rtl::io::details::print_impl38258          static inline void print(const std::string& scalar_format, const vector_t& v)
38259          {
38260             for (std::size_t i = 0; i < v.size(); ++i)
38261             {
38262                print_type(scalar_format,v[i],num_type());
38263 
38264                if ((i + 1) < v.size())
38265                   printf(" ");
38266             }
38267          }
38268 
printexprtk::rtl::io::details::print_impl38269          static inline void print(const string_t& s)
38270          {
38271             printf("%s",to_str(s).c_str());
38272          }
38273       };
38274 
38275    } // namespace exprtk::rtl::io::details
38276 
38277    template <typename T>
38278    struct print : public exprtk::igeneric_function<T>
38279    {
38280       typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
38281 
38282       using exprtk::igeneric_function<T>::operator();
38283 
printexprtk::rtl::io::print38284       print(const std::string& scalar_format = "%10.5f")
38285       : scalar_format_(scalar_format)
38286       {
38287          exprtk::enable_zero_parameters(*this);
38288       }
38289 
operator ()exprtk::rtl::io::print38290       inline T operator() (parameter_list_t parameters)
38291       {
38292          details::print_impl<T>::process(scalar_format_,parameters);
38293          return T(0);
38294       }
38295 
38296       std::string scalar_format_;
38297    };
38298 
38299    template <typename T>
38300    struct println : public exprtk::igeneric_function<T>
38301    {
38302       typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
38303 
38304       using exprtk::igeneric_function<T>::operator();
38305 
printlnexprtk::rtl::io::println38306       println(const std::string& scalar_format = "%10.5f")
38307       : scalar_format_(scalar_format)
38308       {
38309          exprtk::enable_zero_parameters(*this);
38310       }
38311 
operator ()exprtk::rtl::io::println38312       inline T operator() (parameter_list_t parameters)
38313       {
38314          details::print_impl<T>::process(scalar_format_,parameters);
38315          printf("\n");
38316          return T(0);
38317       }
38318 
38319       std::string scalar_format_;
38320    };
38321 
38322    template <typename T>
38323    struct package
38324    {
38325       print  <T> p;
38326       println<T> pl;
38327 
register_packageexprtk::rtl::io::package38328       bool register_package(exprtk::symbol_table<T>& symtab)
38329       {
38330          #define exprtk_register_function(FunctionName,FunctionType)              \
38331          if (!symtab.add_function(FunctionName,FunctionType))                     \
38332          {                                                                        \
38333             exprtk_debug((                                                        \
38334               "exprtk::rtl::io::register_package - Failed to add function: %s\n", \
38335               FunctionName));                                                     \
38336             return false;                                                         \
38337          }                                                                        \
38338 
38339          exprtk_register_function("print"  ,  p)
38340          exprtk_register_function("println", pl)
38341          #undef exprtk_register_function
38342 
38343          return true;
38344       }
38345    };
38346 
38347    } // namespace exprtk::rtl::io
38348    } // namespace exprtk::rtl
38349 }    // namespace exprtk
38350 #endif
38351 
38352 #ifndef exprtk_disable_rtl_io_file
38353 #include <fstream>
38354 namespace exprtk
38355 {
38356    namespace rtl { namespace io { namespace file { namespace details
38357    {
38358       enum file_mode
38359       {
38360          e_error = 0,
38361          e_read  = 1,
38362          e_write = 2,
38363          e_rdwrt = 4
38364       };
38365 
38366       struct file_descriptor
38367       {
file_descriptorexprtk::rtl::io::file::details::file_descriptor38368          file_descriptor(const std::string& fname, const std::string& access)
38369          : stream_ptr(0),
38370            mode(get_file_mode(access)),
38371            file_name(fname)
38372          {}
38373 
38374          void*       stream_ptr;
38375          file_mode   mode;
38376          std::string file_name;
38377 
openexprtk::rtl::io::file::details::file_descriptor38378          bool open()
38379          {
38380             if (e_read == mode)
38381             {
38382                std::ifstream* stream = new std::ifstream(file_name.c_str(),std::ios::binary);
38383 
38384                if (!(*stream))
38385                {
38386                   file_name.clear();
38387                   delete stream;
38388 
38389                   return false;
38390                }
38391                else
38392                   stream_ptr = stream;
38393 
38394                return true;
38395             }
38396             else if (e_write == mode)
38397             {
38398                std::ofstream* stream = new std::ofstream(file_name.c_str(),std::ios::binary);
38399 
38400                if (!(*stream))
38401                {
38402                   file_name.clear();
38403                   delete stream;
38404 
38405                   return false;
38406                }
38407                else
38408                   stream_ptr = stream;
38409 
38410                return true;
38411             }
38412             else if (e_rdwrt == mode)
38413             {
38414                std::fstream* stream = new std::fstream(file_name.c_str(),std::ios::binary);
38415 
38416                if (!(*stream))
38417                {
38418                   file_name.clear();
38419                   delete stream;
38420 
38421                   return false;
38422                }
38423                else
38424                   stream_ptr = stream;
38425 
38426                return true;
38427             }
38428             else
38429                return false;
38430          }
38431 
38432          template <typename Stream, typename Ptr>
closeexprtk::rtl::io::file::details::file_descriptor38433          void close(Ptr& p)
38434          {
38435             Stream* stream = reinterpret_cast<Stream*>(p);
38436             stream->close();
38437             delete stream;
38438             p = reinterpret_cast<Ptr>(0);
38439          }
38440 
closeexprtk::rtl::io::file::details::file_descriptor38441          bool close()
38442          {
38443             switch (mode)
38444             {
38445                case e_read  : close<std::ifstream>(stream_ptr);
38446                               break;
38447 
38448                case e_write : close<std::ofstream>(stream_ptr);
38449                               break;
38450 
38451                case e_rdwrt : close<std::fstream> (stream_ptr);
38452                               break;
38453 
38454                default      : return false;
38455             }
38456 
38457             return true;
38458          }
38459 
38460          template <typename View>
writeexprtk::rtl::io::file::details::file_descriptor38461          bool write(const View& view, const std::size_t amount, const std::size_t offset = 0)
38462          {
38463             switch (mode)
38464             {
38465                case e_write : reinterpret_cast<std::ofstream*>(stream_ptr)->
38466                                  write(reinterpret_cast<const char*>(view.begin() + offset), amount * sizeof(typename View::value_t));
38467                               break;
38468 
38469                case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)->
38470                                  write(reinterpret_cast<const char*>(view.begin() + offset) , amount * sizeof(typename View::value_t));
38471                               break;
38472 
38473                default      : return false;
38474             }
38475 
38476             return true;
38477          }
38478 
38479          template <typename View>
readexprtk::rtl::io::file::details::file_descriptor38480          bool read(View& view, const std::size_t amount, const std::size_t offset = 0)
38481          {
38482             switch (mode)
38483             {
38484                case e_read  : reinterpret_cast<std::ifstream*>(stream_ptr)->
38485                                  read(reinterpret_cast<char*>(view.begin() + offset), amount * sizeof(typename View::value_t));
38486                               break;
38487 
38488                case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)->
38489                                  read(reinterpret_cast<char*>(view.begin() + offset) , amount * sizeof(typename View::value_t));
38490                               break;
38491 
38492                default      : return false;
38493             }
38494 
38495             return true;
38496          }
38497 
getlineexprtk::rtl::io::file::details::file_descriptor38498          bool getline(std::string& s)
38499          {
38500             switch (mode)
38501             {
38502                case e_read  : return (!!std::getline(*reinterpret_cast<std::ifstream*>(stream_ptr),s));
38503                case e_rdwrt : return (!!std::getline(*reinterpret_cast<std::fstream* >(stream_ptr),s));
38504                default      : return false;
38505             }
38506          }
38507 
eofexprtk::rtl::io::file::details::file_descriptor38508          bool eof() const
38509          {
38510             switch (mode)
38511             {
38512                case e_read  : return reinterpret_cast<std::ifstream*>(stream_ptr)->eof();
38513                case e_write : return reinterpret_cast<std::ofstream*>(stream_ptr)->eof();
38514                case e_rdwrt : return reinterpret_cast<std::fstream* >(stream_ptr)->eof();
38515                default      : return true;
38516             }
38517          }
38518 
get_file_modeexprtk::rtl::io::file::details::file_descriptor38519          file_mode get_file_mode(const std::string& access) const
38520          {
38521             if (access.empty() || access.size() > 2)
38522                return e_error;
38523 
38524             std::size_t w_cnt = 0;
38525             std::size_t r_cnt = 0;
38526 
38527             for (std::size_t i = 0; i < access.size(); ++i)
38528             {
38529                switch (std::tolower(access[i]))
38530                {
38531                   case 'r' : r_cnt++; break;
38532                   case 'w' : w_cnt++; break;
38533                   default  : return e_error;
38534                }
38535             }
38536 
38537             if ((0 == r_cnt) && (0 == w_cnt))
38538                return e_error;
38539             else if ((r_cnt > 1) || (w_cnt > 1))
38540                return e_error;
38541             else if ((1 == r_cnt) && (1 == w_cnt))
38542                return e_rdwrt;
38543             else if (1 == r_cnt)
38544                return e_read;
38545             else
38546                return e_write;
38547          }
38548       };
38549 
38550       template <typename T>
make_handle(T v)38551       file_descriptor* make_handle(T v)
38552       {
38553          file_descriptor* fd = reinterpret_cast<file_descriptor*>(0);
38554 
38555          std::memcpy(reinterpret_cast<char*>(&fd),
38556                      reinterpret_cast<const char*>(&v),
38557                      sizeof(fd));
38558          return fd;
38559       }
38560 
38561       template <typename T>
perform_check()38562       void perform_check()
38563       {
38564          #ifdef _MSC_VER
38565          #pragma warning(push)
38566          #pragma warning(disable: 4127)
38567          #endif
38568          if (sizeof(T) < sizeof(void*))
38569          {
38570             throw std::runtime_error("exprtk::rtl::io::file - Error - pointer size larger than holder.");
38571          }
38572          #ifdef _MSC_VER
38573          #pragma warning(pop)
38574          #endif
38575       }
38576 
38577    } // namespace exprtk::rtl::io::file::details
38578 
38579    template <typename T>
38580    class open : public exprtk::igeneric_function<T>
38581    {
38582    public:
38583 
38584       typedef typename exprtk::igeneric_function<T> igfun_t;
38585       typedef typename igfun_t::parameter_list_t    parameter_list_t;
38586       typedef typename igfun_t::generic_type        generic_type;
38587       typedef typename generic_type::string_view    string_t;
38588 
38589       using exprtk::igeneric_function<T>::operator();
38590 
open()38591       open()
38592       : exprtk::igeneric_function<T>("S|SS")
38593       { details::perform_check<T>(); }
38594 
operator ()(const std::size_t & ps_index,parameter_list_t parameters)38595       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38596       {
38597          std::string file_name = to_str(string_t(parameters[0]));
38598          std::string access;
38599 
38600          if (file_name.empty())
38601             return T(0);
38602 
38603          if (0 == ps_index)
38604             access = "r";
38605          else if (0 == string_t(parameters[1]).size())
38606             return T(0);
38607          else
38608             access = to_str(string_t(parameters[1]));
38609 
38610          details::file_descriptor* fd = new details::file_descriptor(file_name,access);
38611 
38612          if (fd->open())
38613          {
38614             T t = T(0);
38615 
38616             std::memcpy(reinterpret_cast<char*>(&t ),
38617                         reinterpret_cast<char*>(&fd),
38618                         sizeof(fd));
38619             return t;
38620          }
38621          else
38622          {
38623             delete fd;
38624             return T(0);
38625          }
38626       }
38627    };
38628 
38629    template <typename T>
38630    struct close : public exprtk::ifunction<T>
38631    {
38632       using exprtk::ifunction<T>::operator();
38633 
closeexprtk::rtl::io::file::close38634       close()
38635       : exprtk::ifunction<T>(1)
38636       { details::perform_check<T>(); }
38637 
operator ()exprtk::rtl::io::file::close38638       inline T operator() (const T& v)
38639       {
38640          details::file_descriptor* fd = details::make_handle(v);
38641 
38642          if (!fd->close())
38643             return T(0);
38644 
38645          delete fd;
38646 
38647          return T(1);
38648       }
38649    };
38650 
38651    template <typename T>
38652    class write : public exprtk::igeneric_function<T>
38653    {
38654    public:
38655 
38656       typedef typename exprtk::igeneric_function<T> igfun_t;
38657       typedef typename igfun_t::parameter_list_t    parameter_list_t;
38658       typedef typename igfun_t::generic_type        generic_type;
38659       typedef typename generic_type::string_view    string_t;
38660       typedef typename generic_type::scalar_view    scalar_t;
38661       typedef typename generic_type::vector_view    vector_t;
38662 
38663       using exprtk::igeneric_function<T>::operator();
38664 
write()38665       write()
38666       : igfun_t("TS|TST|TV|TVT")
38667       { details::perform_check<T>(); }
38668 
operator ()(const std::size_t & ps_index,parameter_list_t parameters)38669       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38670       {
38671          details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])());
38672 
38673          std::size_t amount = 0;
38674 
38675          switch (ps_index)
38676          {
38677             case 0  : {
38678                          const string_t buffer(parameters[1]);
38679                          amount = buffer.size();
38680                          return T(fd->write(buffer, amount) ? 1 : 0);
38681                       }
38682 
38683             case 1  : {
38684                          const string_t buffer(parameters[1]);
38685                          amount = std::min(buffer.size(),
38686                                            static_cast<std::size_t>(scalar_t(parameters[2])()));
38687                          return T(fd->write(buffer, amount) ? 1 : 0);
38688                       }
38689 
38690             case 2  : {
38691                          const vector_t vec(parameters[1]);
38692                          amount = vec.size();
38693                          return T(fd->write(vec, amount) ? 1 : 0);
38694                       }
38695 
38696             case 3  : {
38697                          const vector_t vec(parameters[1]);
38698                          amount = std::min(vec.size(),
38699                                            static_cast<std::size_t>(scalar_t(parameters[2])()));
38700                          return T(fd->write(vec, amount) ? 1 : 0);
38701                       }
38702          }
38703 
38704          return T(0);
38705       }
38706    };
38707 
38708    template <typename T>
38709    class read : public exprtk::igeneric_function<T>
38710    {
38711    public:
38712 
38713       typedef typename exprtk::igeneric_function<T> igfun_t;
38714       typedef typename igfun_t::parameter_list_t    parameter_list_t;
38715       typedef typename igfun_t::generic_type        generic_type;
38716       typedef typename generic_type::string_view    string_t;
38717       typedef typename generic_type::scalar_view    scalar_t;
38718       typedef typename generic_type::vector_view    vector_t;
38719 
38720       using exprtk::igeneric_function<T>::operator();
38721 
read()38722       read()
38723       : igfun_t("TS|TST|TV|TVT")
38724       { details::perform_check<T>(); }
38725 
operator ()(const std::size_t & ps_index,parameter_list_t parameters)38726       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38727       {
38728          details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])());
38729 
38730          std::size_t amount = 0;
38731 
38732          switch (ps_index)
38733          {
38734             case 0  : {
38735                          string_t buffer(parameters[1]);
38736                          amount = buffer.size();
38737                          return T(fd->read(buffer,amount) ? 1 : 0);
38738                       }
38739 
38740             case 1  : {
38741                          string_t buffer(parameters[1]);
38742                          amount = std::min(buffer.size(),
38743                                            static_cast<std::size_t>(scalar_t(parameters[2])()));
38744                          return T(fd->read(buffer,amount) ? 1 : 0);
38745                       }
38746 
38747             case 2  : {
38748                          vector_t vec(parameters[1]);
38749                          amount = vec.size();
38750                          return T(fd->read(vec,amount) ? 1 : 0);
38751                       }
38752 
38753             case 3  : {
38754                          vector_t vec(parameters[1]);
38755                          amount = std::min(vec.size(),
38756                                            static_cast<std::size_t>(scalar_t(parameters[2])()));
38757                          return T(fd->read(vec,amount) ? 1 : 0);
38758                       }
38759          }
38760 
38761          return T(0);
38762       }
38763    };
38764 
38765    template <typename T>
38766    class getline : public exprtk::igeneric_function<T>
38767    {
38768    public:
38769 
38770       typedef typename exprtk::igeneric_function<T> igfun_t;
38771       typedef typename igfun_t::parameter_list_t    parameter_list_t;
38772       typedef typename igfun_t::generic_type        generic_type;
38773       typedef typename generic_type::string_view    string_t;
38774       typedef typename generic_type::scalar_view    scalar_t;
38775 
38776       using exprtk::igeneric_function<T>::operator();
38777 
getline()38778       getline()
38779       : igfun_t("T",igfun_t::e_rtrn_string)
38780       { details::perform_check<T>(); }
38781 
operator ()(std::string & result,parameter_list_t parameters)38782       inline T operator() (std::string& result,
38783                            parameter_list_t parameters)
38784       {
38785          details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])());
38786          return T(fd->getline(result) ? 1 : 0);
38787       }
38788    };
38789 
38790    template <typename T>
38791    struct eof : public exprtk::ifunction<T>
38792    {
38793       using exprtk::ifunction<T>::operator();
38794 
eofexprtk::rtl::io::file::eof38795       eof()
38796       : exprtk::ifunction<T>(1)
38797       { details::perform_check<T>(); }
38798 
operator ()exprtk::rtl::io::file::eof38799       inline T operator() (const T& v)
38800       {
38801          details::file_descriptor* fd = details::make_handle(v);
38802 
38803          return (fd->eof() ? T(1) : T(0));
38804       }
38805    };
38806 
38807    template <typename T>
38808    struct package
38809    {
38810       open   <T> o;
38811       close  <T> c;
38812       write  <T> w;
38813       read   <T> r;
38814       getline<T> g;
38815       eof    <T> e;
38816 
register_packageexprtk::rtl::io::file::package38817       bool register_package(exprtk::symbol_table<T>& symtab)
38818       {
38819          #define exprtk_register_function(FunctionName,FunctionType)                    \
38820          if (!symtab.add_function(FunctionName,FunctionType))                           \
38821          {                                                                              \
38822             exprtk_debug((                                                              \
38823               "exprtk::rtl::io::file::register_package - Failed to add function: %s\n", \
38824               FunctionName));                                                           \
38825             return false;                                                               \
38826          }                                                                              \
38827 
38828          exprtk_register_function("open"   ,o)
38829          exprtk_register_function("close"  ,c)
38830          exprtk_register_function("write"  ,w)
38831          exprtk_register_function("read"   ,r)
38832          exprtk_register_function("getline",g)
38833          exprtk_register_function("eof"    ,e)
38834          #undef exprtk_register_function
38835 
38836          return true;
38837       }
38838    };
38839 
38840    } // namespace exprtk::rtl::io::file
38841    } // namespace exprtk::rtl::io
38842    } // namespace exprtk::rtl
38843 }    // namespace exprtk
38844 #endif
38845 
38846 #ifndef exprtk_disable_rtl_vecops
38847 namespace exprtk
38848 {
38849    namespace rtl { namespace vecops {
38850 
38851    namespace helper
38852    {
38853       template <typename Vector>
invalid_range(const Vector & v,const std::size_t r0,const std::size_t r1)38854       inline bool invalid_range(const Vector& v, const std::size_t r0, const std::size_t r1)
38855       {
38856          if (r0 > (v.size() - 1))
38857             return true;
38858          else if (r1 > (v.size() - 1))
38859             return true;
38860          else if (r1 < r0)
38861             return true;
38862          else
38863             return false;
38864       }
38865 
38866       template <typename T>
38867       struct load_vector_range
38868       {
38869          typedef typename exprtk::igeneric_function<T> igfun_t;
38870          typedef typename igfun_t::parameter_list_t    parameter_list_t;
38871          typedef typename igfun_t::generic_type        generic_type;
38872          typedef typename generic_type::scalar_view    scalar_t;
38873          typedef typename generic_type::vector_view    vector_t;
38874 
processexprtk::rtl::vecops::helper::load_vector_range38875          static inline bool process(parameter_list_t& parameters,
38876                                     std::size_t& r0, std::size_t& r1,
38877                                     const std::size_t& r0_prmidx,
38878                                     const std::size_t& r1_prmidx,
38879                                     const std::size_t vec_idx = 0)
38880          {
38881             if (r0_prmidx >= parameters.size())
38882                return false;
38883 
38884             if (r1_prmidx >= parameters.size())
38885                return false;
38886 
38887             if (!scalar_t(parameters[r0_prmidx]).to_uint(r0))
38888                return false;
38889 
38890             if (!scalar_t(parameters[r1_prmidx]).to_uint(r1))
38891                return false;
38892 
38893             return !invalid_range(vector_t(parameters[vec_idx]), r0, r1);
38894          }
38895       };
38896    }
38897 
38898    namespace details
38899    {
38900       template <typename T>
kahan_sum(T & sum,T & error,const T v)38901       inline void kahan_sum(T& sum, T& error, const T v)
38902       {
38903          const T x = v - error;
38904          const T y = sum + x;
38905          error = (y - sum) - x;
38906          sum = y;
38907       }
38908 
38909    } // namespace exprtk::rtl::details
38910 
38911    template <typename T>
38912    class all_true : public exprtk::igeneric_function<T>
38913    {
38914    public:
38915 
38916       typedef typename exprtk::igeneric_function<T> igfun_t;
38917       typedef typename igfun_t::parameter_list_t    parameter_list_t;
38918       typedef typename igfun_t::generic_type        generic_type;
38919       typedef typename generic_type::vector_view    vector_t;
38920 
38921       using exprtk::igeneric_function<T>::operator();
38922 
all_true()38923       all_true()
38924       : exprtk::igeneric_function<T>("V|VTT")
38925         /*
38926            Overloads:
38927            0. V   - vector
38928            1. VTT - vector, r0, r1
38929         */
38930       {}
38931 
operator ()(const std::size_t & ps_index,parameter_list_t parameters)38932       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38933       {
38934          const vector_t vec(parameters[0]);
38935 
38936          std::size_t r0 = 0;
38937          std::size_t r1 = vec.size() - 1;
38938 
38939          if (
38940               (1 == ps_index) &&
38941               !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
38942             )
38943             return std::numeric_limits<T>::quiet_NaN();
38944 
38945          for (std::size_t i = r0; i <= r1; ++i)
38946          {
38947             if (vec[i] == T(0))
38948             {
38949                return T(0);
38950             }
38951          }
38952 
38953          return T(1);
38954       }
38955    };
38956 
38957    template <typename T>
38958    class all_false : public exprtk::igeneric_function<T>
38959    {
38960    public:
38961 
38962       typedef typename exprtk::igeneric_function<T> igfun_t;
38963       typedef typename igfun_t::parameter_list_t    parameter_list_t;
38964       typedef typename igfun_t::generic_type        generic_type;
38965       typedef typename generic_type::vector_view    vector_t;
38966 
38967       using exprtk::igeneric_function<T>::operator();
38968 
all_false()38969       all_false()
38970       : exprtk::igeneric_function<T>("V|VTT")
38971         /*
38972            Overloads:
38973            0. V   - vector
38974            1. VTT - vector, r0, r1
38975         */
38976       {}
38977 
operator ()(const std::size_t & ps_index,parameter_list_t parameters)38978       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38979       {
38980          const vector_t vec(parameters[0]);
38981 
38982          std::size_t r0 = 0;
38983          std::size_t r1 = vec.size() - 1;
38984 
38985          if (
38986               (1 == ps_index) &&
38987               !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
38988             )
38989             return std::numeric_limits<T>::quiet_NaN();
38990 
38991          for (std::size_t i = r0; i <= r1; ++i)
38992          {
38993             if (vec[i] != T(0))
38994             {
38995                return T(0);
38996             }
38997          }
38998 
38999          return T(1);
39000       }
39001    };
39002 
39003    template <typename T>
39004    class any_true : public exprtk::igeneric_function<T>
39005    {
39006    public:
39007 
39008       typedef typename exprtk::igeneric_function<T> igfun_t;
39009       typedef typename igfun_t::parameter_list_t    parameter_list_t;
39010       typedef typename igfun_t::generic_type        generic_type;
39011       typedef typename generic_type::vector_view    vector_t;
39012 
39013       using exprtk::igeneric_function<T>::operator();
39014 
any_true()39015       any_true()
39016       : exprtk::igeneric_function<T>("V|VTT")
39017         /*
39018            Overloads:
39019            0. V   - vector
39020            1. VTT - vector, r0, r1
39021         */
39022       {}
39023 
operator ()(const std::size_t & ps_index,parameter_list_t parameters)39024       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
39025       {
39026          const vector_t vec(parameters[0]);
39027 
39028          std::size_t r0 = 0;
39029          std::size_t r1 = vec.size() - 1;
39030 
39031          if (
39032               (1 == ps_index) &&
39033               !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
39034             )
39035             return std::numeric_limits<T>::quiet_NaN();
39036 
39037          for (std::size_t i = r0; i <= r1; ++i)
39038          {
39039             if (vec[i] != T(0))
39040             {
39041                return T(1);
39042             }
39043          }
39044 
39045          return T(0);
39046       }
39047    };
39048 
39049    template <typename T>
39050    class any_false : public exprtk::igeneric_function<T>
39051    {
39052    public:
39053 
39054       typedef typename exprtk::igeneric_function<T> igfun_t;
39055       typedef typename igfun_t::parameter_list_t    parameter_list_t;
39056       typedef typename igfun_t::generic_type        generic_type;
39057       typedef typename generic_type::vector_view    vector_t;
39058 
39059       using exprtk::igeneric_function<T>::operator();
39060 
any_false()39061       any_false()
39062       : exprtk::igeneric_function<T>("V|VTT")
39063         /*
39064            Overloads:
39065            0. V   - vector
39066            1. VTT - vector, r0, r1
39067         */
39068       {}
39069 
operator ()(const std::size_t & ps_index,parameter_list_t parameters)39070       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
39071       {
39072          const vector_t vec(parameters[0]);
39073 
39074          std::size_t r0 = 0;
39075          std::size_t r1 = vec.size() - 1;
39076 
39077          if (
39078               (1 == ps_index) &&
39079               !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
39080             )
39081             return std::numeric_limits<T>::quiet_NaN();
39082 
39083          for (std::size_t i = r0; i <= r1; ++i)
39084          {
39085             if (vec[i] == T(0))
39086             {
39087                return T(1);
39088             }
39089          }
39090 
39091          return T(0);
39092       }
39093    };
39094 
39095    template <typename T>
39096    class count : public exprtk::igeneric_function<T>
39097    {
39098    public:
39099 
39100       typedef typename exprtk::igeneric_function<T> igfun_t;
39101       typedef typename igfun_t::parameter_list_t    parameter_list_t;
39102       typedef typename igfun_t::generic_type        generic_type;
39103       typedef typename generic_type::vector_view    vector_t;
39104 
39105       using exprtk::igeneric_function<T>::operator();
39106 
count()39107       count()
39108       : exprtk::igeneric_function<T>("V|VTT")
39109         /*
39110            Overloads:
39111            0. V   - vector
39112            1. VTT - vector, r0, r1
39113         */
39114       {}
39115 
operator ()(const std::size_t & ps_index,parameter_list_t parameters)39116       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
39117       {
39118          const vector_t vec(parameters[0]);
39119 
39120          std::size_t r0 = 0;
39121          std::size_t r1 = vec.size() - 1;
39122 
39123          if (
39124               (1 == ps_index) &&
39125               !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
39126             )
39127             return std::numeric_limits<T>::quiet_NaN();
39128 
39129          std::size_t cnt = 0;
39130 
39131          for (std::size_t i = r0; i <= r1; ++i)
39132          {
39133             if (vec[i] != T(0)) ++cnt;
39134          }
39135 
39136          return T(cnt);
39137       }
39138    };
39139 
39140    template <typename T>
39141    class copy : public exprtk::igeneric_function<T>
39142    {
39143    public:
39144 
39145       typedef typename exprtk::igeneric_function<T> igfun_t;
39146       typedef typename igfun_t::parameter_list_t    parameter_list_t;
39147       typedef typename igfun_t::generic_type        generic_type;
39148       typedef typename generic_type::scalar_view    scalar_t;
39149       typedef typename generic_type::vector_view    vector_t;
39150 
39151       using exprtk::igeneric_function<T>::operator();
39152 
copy()39153       copy()
39154       : exprtk::igeneric_function<T>("VV|VTTVTT")
39155         /*
39156            Overloads:
39157            0. VV     - x(vector), y(vector)
39158            1. VTTVTT - x(vector), xr0, xr1, y(vector), yr0, yr1,
39159         */
39160       {}
39161 
operator ()(const std::size_t & ps_index,parameter_list_t parameters)39162       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
39163       {
39164          const vector_t x(parameters[0]);
39165                vector_t y(parameters[(0 == ps_index) ? 1 : 3]);
39166 
39167          std::size_t xr0 = 0;
39168          std::size_t xr1 = x.size() - 1;
39169 
39170          std::size_t yr0 = 0;
39171          std::size_t yr1 = y.size() - 1;
39172 
39173          if (1 == ps_index)
39174          {
39175             if (
39176                  !helper::load_vector_range<T>::process(parameters, xr0, xr1, 1, 2, 0) ||
39177                  !helper::load_vector_range<T>::process(parameters, yr0, yr1, 4, 5, 3)
39178                )
39179                return T(0);
39180          }
39181 
39182          const std::size_t n = std::min(xr1 - xr0 + 1, yr1 - yr0 + 1);
39183 
39184          std::copy(x.begin() + xr0, x.begin() + xr0 + n, y.begin() + yr0);
39185 
39186          return T(n);
39187       }
39188    };
39189 
39190    template <typename T>
39191    class rol : public exprtk::igeneric_function<T>
39192    {
39193    public:
39194 
39195       typedef typename exprtk::igeneric_function<T> igfun_t;
39196       typedef typename igfun_t::parameter_list_t    parameter_list_t;
39197       typedef typename igfun_t::generic_type        generic_type;
39198       typedef typename generic_type::scalar_view    scalar_t;
39199       typedef typename generic_type::vector_view    vector_t;
39200 
39201       using exprtk::igeneric_function<T>::operator();
39202 
rol()39203       rol()
39204       : exprtk::igeneric_function<T>("VT|VTTT")
39205         /*
39206            Overloads:
39207            0. VT   - vector, N
39208            1. VTTT - vector, N, r0, r1
39209         */
39210       {}
39211 
operator ()(const std::size_t & ps_index,parameter_list_t parameters)39212       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
39213       {
39214          vector_t vec(parameters[0]);
39215 
39216          std::size_t n  = 0;
39217          std::size_t r0 = 0;
39218          std::size_t r1 = vec.size() - 1;
39219 
39220          if (!scalar_t(parameters[1]).to_uint(n))
39221             return T(0);
39222 
39223          if (
39224               (1 == ps_index) &&
39225               !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
39226             )
39227             return T(0);
39228 
39229          const std::size_t dist  = r1 - r0 + 1;
39230          const std::size_t shift = n % dist;
39231 
39232          std::rotate(
39233             vec.begin() + r0,
39234             vec.begin() + r0 + shift,
39235             vec.begin() + r1 + 1);
39236 
39237          return T(1);
39238       }
39239    };
39240 
39241    template <typename T>
39242    class ror : public exprtk::igeneric_function<T>
39243    {
39244    public:
39245 
39246       typedef typename exprtk::igeneric_function<T> igfun_t;
39247       typedef typename igfun_t::parameter_list_t    parameter_list_t;
39248       typedef typename igfun_t::generic_type        generic_type;
39249       typedef typename generic_type::scalar_view    scalar_t;
39250       typedef typename generic_type::vector_view    vector_t;
39251 
39252       using exprtk::igeneric_function<T>::operator();
39253 
ror()39254       ror()
39255       : exprtk::igeneric_function<T>("VT|VTTT")
39256         /*
39257            Overloads:
39258            0. VT   - vector, N
39259            1. VTTT - vector, N, r0, r1
39260         */
39261       {}
39262 
operator ()(const std::size_t & ps_index,parameter_list_t parameters)39263       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
39264       {
39265          vector_t vec(parameters[0]);
39266 
39267          std::size_t n  = 0;
39268          std::size_t r0 = 0;
39269          std::size_t r1 = vec.size() - 1;
39270 
39271          if (!scalar_t(parameters[1]).to_uint(n))
39272             return T(0);
39273 
39274          if (
39275               (1 == ps_index) &&
39276               !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
39277             )
39278             return T(0);
39279 
39280          std::size_t dist  = r1 - r0 + 1;
39281          std::size_t shift = (dist - (n % dist)) % dist;
39282 
39283          std::rotate(
39284             vec.begin() + r0,
39285             vec.begin() + r0 + shift,
39286             vec.begin() + r1 + 1);
39287 
39288          return T(1);
39289       }
39290    };
39291 
39292    template <typename T>
39293    class shift_left : public exprtk::igeneric_function<T>
39294    {
39295    public:
39296 
39297       typedef typename exprtk::igeneric_function<T> igfun_t;
39298       typedef typename igfun_t::parameter_list_t    parameter_list_t;
39299       typedef typename igfun_t::generic_type        generic_type;
39300       typedef typename generic_type::scalar_view    scalar_t;
39301       typedef typename generic_type::vector_view    vector_t;
39302 
39303       using exprtk::igeneric_function<T>::operator();
39304 
shift_left()39305       shift_left()
39306       : exprtk::igeneric_function<T>("VT|VTTT")
39307         /*
39308            Overloads:
39309            0. VT   - vector, N
39310            1. VTTT - vector, N, r0, r1
39311         */
39312       {}
39313 
operator ()(const std::size_t & ps_index,parameter_list_t parameters)39314       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
39315       {
39316          vector_t vec(parameters[0]);
39317 
39318          std::size_t n  = 0;
39319          std::size_t r0 = 0;
39320          std::size_t r1 = vec.size() - 1;
39321 
39322          if (!scalar_t(parameters[1]).to_uint(n))
39323             return T(0);
39324 
39325          if (
39326               (1 == ps_index) &&
39327               !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
39328             )
39329             return T(0);
39330 
39331          const std::size_t dist  = r1 - r0 + 1;
39332 
39333          if (n > dist)
39334             return T(0);
39335 
39336          std::rotate(
39337             vec.begin() + r0,
39338             vec.begin() + r0 + n,
39339             vec.begin() + r1 + 1);
39340 
39341          for (std::size_t i = r1 - n + 1; i <= r1; ++i)
39342          {
39343             vec[i] = T(0);
39344          }
39345 
39346          return T(1);
39347       }
39348    };
39349 
39350    template <typename T>
39351    class shift_right : public exprtk::igeneric_function<T>
39352    {
39353    public:
39354 
39355       typedef typename exprtk::igeneric_function<T> igfun_t;
39356       typedef typename igfun_t::parameter_list_t    parameter_list_t;
39357       typedef typename igfun_t::generic_type        generic_type;
39358       typedef typename generic_type::scalar_view    scalar_t;
39359       typedef typename generic_type::vector_view    vector_t;
39360 
39361       using exprtk::igeneric_function<T>::operator();
39362 
shift_right()39363       shift_right()
39364       : exprtk::igeneric_function<T>("VT|VTTT")
39365         /*
39366            Overloads:
39367            0. VT   - vector, N
39368            1. VTTT - vector, N, r0, r1
39369         */
39370       {}
39371 
operator ()(const std::size_t & ps_index,parameter_list_t parameters)39372       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
39373       {
39374          vector_t vec(parameters[0]);
39375 
39376          std::size_t n  = 0;
39377          std::size_t r0 = 0;
39378          std::size_t r1 = vec.size() - 1;
39379 
39380          if (!scalar_t(parameters[1]).to_uint(n))
39381             return T(0);
39382 
39383          if (
39384               (1 == ps_index) &&
39385               !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
39386             )
39387             return T(0);
39388 
39389          const std::size_t dist  = r1 - r0 + 1;
39390 
39391          if (n > dist)
39392             return T(0);
39393 
39394          const std::size_t shift = (dist - (n % dist)) % dist;
39395 
39396          std::rotate(
39397             vec.begin() + r0,
39398             vec.begin() + r0 + shift,
39399             vec.begin() + r1 + 1);
39400 
39401          for (std::size_t i = r0; i < r0 + n; ++i)
39402          {
39403             vec[i] = T(0);
39404          }
39405 
39406          return T(1);
39407       }
39408    };
39409 
39410    template <typename T>
39411    class sort : public exprtk::igeneric_function<T>
39412    {
39413    public:
39414 
39415       typedef typename exprtk::igeneric_function<T> igfun_t;
39416       typedef typename igfun_t::parameter_list_t    parameter_list_t;
39417       typedef typename igfun_t::generic_type        generic_type;
39418       typedef typename generic_type::string_view    string_t;
39419       typedef typename generic_type::vector_view    vector_t;
39420 
39421       using exprtk::igeneric_function<T>::operator();
39422 
sort()39423       sort()
39424       : exprtk::igeneric_function<T>("V|VTT|VS|VSTT")
39425         /*
39426            Overloads:
39427            0. V    - vector
39428            1. VTT  - vector, r0, r1
39429            2. VS   - vector, string
39430            3. VSTT - vector, string, r0, r1
39431         */
39432       {}
39433 
operator ()(const std::size_t & ps_index,parameter_list_t parameters)39434       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
39435       {
39436          vector_t vec(parameters[0]);
39437 
39438          std::size_t r0 = 0;
39439          std::size_t r1 = vec.size() - 1;
39440 
39441          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0))
39442             return T(0);
39443          if ((3 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
39444             return T(0);
39445 
39446          bool ascending = true;
39447 
39448          if ((2 == ps_index) || (3 == ps_index))
39449          {
39450             if (exprtk::details::imatch(to_str(string_t(parameters[1])),"ascending"))
39451                ascending = true;
39452             else if (exprtk::details::imatch(to_str(string_t(parameters[1])),"descending"))
39453                ascending = false;
39454             else
39455                return T(0);
39456          }
39457 
39458          if (ascending)
39459             std::sort(vec.begin() + r0, vec.begin() + r1 + 1, std::less<T>   ());
39460          else
39461             std::sort(vec.begin() + r0, vec.begin() + r1 + 1, std::greater<T>());
39462 
39463          return T(1);
39464       }
39465    };
39466 
39467    template <typename T>
39468    class nthelement : public exprtk::igeneric_function<T>
39469    {
39470    public:
39471 
39472       typedef typename exprtk::igeneric_function<T> igfun_t;
39473       typedef typename igfun_t::parameter_list_t    parameter_list_t;
39474       typedef typename igfun_t::generic_type        generic_type;
39475       typedef typename generic_type::scalar_view    scalar_t;
39476       typedef typename generic_type::vector_view    vector_t;
39477 
39478       using exprtk::igeneric_function<T>::operator();
39479 
nthelement()39480       nthelement()
39481       : exprtk::igeneric_function<T>("VT|VTTT")
39482         /*
39483            Overloads:
39484            0. VT   - vector, nth-element
39485            1. VTTT - vector, nth-element, r0, r1
39486         */
39487       {}
39488 
operator ()(const std::size_t & ps_index,parameter_list_t parameters)39489       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
39490       {
39491          vector_t vec(parameters[0]);
39492 
39493          std::size_t n  = 0;
39494          std::size_t r0 = 0;
39495          std::size_t r1 = vec.size() - 1;
39496 
39497          if (!scalar_t(parameters[1]).to_uint(n))
39498             return T(0);
39499 
39500          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
39501             return std::numeric_limits<T>::quiet_NaN();
39502 
39503          std::nth_element(vec.begin() + r0, vec.begin() + r0 + n , vec.begin() + r1 + 1);
39504 
39505          return T(1);
39506       }
39507    };
39508 
39509    template <typename T>
39510    class iota : public exprtk::igeneric_function<T>
39511    {
39512    public:
39513 
39514       typedef typename exprtk::igeneric_function<T> igfun_t;
39515       typedef typename igfun_t::parameter_list_t    parameter_list_t;
39516       typedef typename igfun_t::generic_type        generic_type;
39517       typedef typename generic_type::scalar_view    scalar_t;
39518       typedef typename generic_type::vector_view    vector_t;
39519 
39520       using exprtk::igeneric_function<T>::operator();
39521 
iota()39522       iota()
39523       : exprtk::igeneric_function<T>("VT|VTT|VTTT|VTTTT")
39524         /*
39525            Overloads:
39526            0. VT    - vector, increment
39527            1. VTT   - vector, increment, base
39528            2. VTTTT - vector, increment, r0, r1
39529            3. VTTTT - vector, increment, base, r0, r1
39530         */
39531       {}
39532 
operator ()(const std::size_t & ps_index,parameter_list_t parameters)39533       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
39534       {
39535          vector_t vec(parameters[0]);
39536 
39537          T increment = scalar_t(parameters[1])();
39538          T base      = ((1 == ps_index) || (3 == ps_index)) ? scalar_t(parameters[2])() : T(0);
39539 
39540          std::size_t r0 = 0;
39541          std::size_t r1 = vec.size() - 1;
39542 
39543          if ((2 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
39544             return std::numeric_limits<T>::quiet_NaN();
39545          else if ((3 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 3, 4, 0))
39546             return std::numeric_limits<T>::quiet_NaN();
39547          else
39548          {
39549             long long j = 0;
39550 
39551             for (std::size_t i = r0; i <= r1; ++i, ++j)
39552             {
39553                vec[i] = base + (increment * j);
39554             }
39555          }
39556 
39557          return T(1);
39558       }
39559    };
39560 
39561    template <typename T>
39562    class sumk : public exprtk::igeneric_function<T>
39563    {
39564    public:
39565 
39566       typedef typename exprtk::igeneric_function<T> igfun_t;
39567       typedef typename igfun_t::parameter_list_t    parameter_list_t;
39568       typedef typename igfun_t::generic_type        generic_type;
39569       typedef typename generic_type::vector_view    vector_t;
39570 
39571       using exprtk::igeneric_function<T>::operator();
39572 
sumk()39573       sumk()
39574       : exprtk::igeneric_function<T>("V|VTT")
39575         /*
39576            Overloads:
39577            0. V   - vector
39578            1. VTT - vector, r0, r1
39579         */
39580       {}
39581 
operator ()(const std::size_t & ps_index,parameter_list_t parameters)39582       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
39583       {
39584          const vector_t vec(parameters[0]);
39585 
39586          std::size_t r0 = 0;
39587          std::size_t r1 = vec.size() - 1;
39588 
39589          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0))
39590             return std::numeric_limits<T>::quiet_NaN();
39591 
39592          T result = T(0);
39593          T error  = T(0);
39594 
39595          for (std::size_t i = r0; i <= r1; ++i)
39596          {
39597             details::kahan_sum(result, error, vec[i]);
39598          }
39599 
39600          return result;
39601       }
39602    };
39603 
39604    template <typename T>
39605    class axpy : public exprtk::igeneric_function<T>
39606    {
39607    public:
39608 
39609       typedef typename exprtk::igeneric_function<T> igfun_t;
39610       typedef typename igfun_t::parameter_list_t    parameter_list_t;
39611       typedef typename igfun_t::generic_type        generic_type;
39612       typedef typename generic_type::scalar_view    scalar_t;
39613       typedef typename generic_type::vector_view    vector_t;
39614 
39615       using exprtk::igeneric_function<T>::operator();
39616 
axpy()39617       axpy()
39618       : exprtk::igeneric_function<T>("TVV|TVVTT")
39619         /*
39620            y <- ax + y
39621            Overloads:
39622            0. TVV   - a, x(vector), y(vector)
39623            1. TVVTT - a, x(vector), y(vector), r0, r1
39624         */
39625       {}
39626 
operator ()(const std::size_t & ps_index,parameter_list_t parameters)39627       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
39628       {
39629          const vector_t x(parameters[1]);
39630                vector_t y(parameters[2]);
39631 
39632          std::size_t r0 = 0;
39633          std::size_t r1 = std::min(x.size(),y.size()) - 1;
39634 
39635          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 3, 4, 1))
39636             return std::numeric_limits<T>::quiet_NaN();
39637          else if (helper::invalid_range(y, r0, r1))
39638             return std::numeric_limits<T>::quiet_NaN();
39639 
39640          const T a = scalar_t(parameters[0])();
39641 
39642          for (std::size_t i = r0; i <= r1; ++i)
39643          {
39644             y[i] = (a * x[i]) + y[i];
39645          }
39646 
39647          return T(1);
39648       }
39649    };
39650 
39651    template <typename T>
39652    class axpby : public exprtk::igeneric_function<T>
39653    {
39654    public:
39655 
39656       typedef typename exprtk::igeneric_function<T> igfun_t;
39657       typedef typename igfun_t::parameter_list_t    parameter_list_t;
39658       typedef typename igfun_t::generic_type        generic_type;
39659       typedef typename generic_type::scalar_view    scalar_t;
39660       typedef typename generic_type::vector_view    vector_t;
39661 
39662       using exprtk::igeneric_function<T>::operator();
39663 
axpby()39664       axpby()
39665       : exprtk::igeneric_function<T>("TVTV|TVTVTT")
39666         /*
39667            y <- ax + by
39668            Overloads:
39669            0. TVTV   - a, x(vector), b, y(vector)
39670            1. TVTVTT - a, x(vector), b, y(vector), r0, r1
39671         */
39672       {}
39673 
operator ()(const std::size_t & ps_index,parameter_list_t parameters)39674       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
39675       {
39676          const vector_t x(parameters[1]);
39677                vector_t y(parameters[3]);
39678 
39679          std::size_t r0 = 0;
39680          std::size_t r1 = std::min(x.size(),y.size()) - 1;
39681 
39682          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1))
39683             return std::numeric_limits<T>::quiet_NaN();
39684          else if (helper::invalid_range(y, r0, r1))
39685             return std::numeric_limits<T>::quiet_NaN();
39686 
39687          const T a = scalar_t(parameters[0])();
39688          const T b = scalar_t(parameters[2])();
39689 
39690          for (std::size_t i = r0; i <= r1; ++i)
39691          {
39692             y[i] = (a * x[i]) + (b * y[i]);
39693          }
39694 
39695          return T(1);
39696       }
39697    };
39698 
39699    template <typename T>
39700    class axpyz : public exprtk::igeneric_function<T>
39701    {
39702    public:
39703 
39704       typedef typename exprtk::igeneric_function<T> igfun_t;
39705       typedef typename igfun_t::parameter_list_t    parameter_list_t;
39706       typedef typename igfun_t::generic_type        generic_type;
39707       typedef typename generic_type::scalar_view    scalar_t;
39708       typedef typename generic_type::vector_view    vector_t;
39709 
39710       using exprtk::igeneric_function<T>::operator();
39711 
axpyz()39712       axpyz()
39713       : exprtk::igeneric_function<T>("TVVV|TVVVTT")
39714         /*
39715            z <- ax + y
39716            Overloads:
39717            0. TVVV   - a, x(vector), y(vector), z(vector)
39718            1. TVVVTT - a, x(vector), y(vector), z(vector), r0, r1
39719         */
39720       {}
39721 
operator ()(const std::size_t & ps_index,parameter_list_t parameters)39722       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
39723       {
39724          const vector_t x(parameters[1]);
39725          const vector_t y(parameters[2]);
39726                vector_t z(parameters[3]);
39727 
39728          std::size_t r0 = 0;
39729          std::size_t r1 = std::min(x.size(),y.size()) - 1;
39730 
39731          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 3, 4, 1))
39732             return std::numeric_limits<T>::quiet_NaN();
39733          else if (helper::invalid_range(y, r0, r1))
39734             return std::numeric_limits<T>::quiet_NaN();
39735          else if (helper::invalid_range(z, r0, r1))
39736             return std::numeric_limits<T>::quiet_NaN();
39737 
39738          const T a = scalar_t(parameters[0])();
39739 
39740          for (std::size_t i = r0; i <= r1; ++i)
39741          {
39742             z[i] = (a * x[i]) + y[i];
39743          }
39744 
39745          return T(1);
39746       }
39747    };
39748 
39749    template <typename T>
39750    class axpbyz : public exprtk::igeneric_function<T>
39751    {
39752    public:
39753 
39754       typedef typename exprtk::igeneric_function<T> igfun_t;
39755       typedef typename igfun_t::parameter_list_t    parameter_list_t;
39756       typedef typename igfun_t::generic_type        generic_type;
39757       typedef typename generic_type::scalar_view    scalar_t;
39758       typedef typename generic_type::vector_view    vector_t;
39759 
39760       using exprtk::igeneric_function<T>::operator();
39761 
axpbyz()39762       axpbyz()
39763       : exprtk::igeneric_function<T>("TVTVV|TVTVVTT")
39764         /*
39765            z <- ax + by
39766            Overloads:
39767            0. TVTVV   - a, x(vector), b, y(vector), z(vector)
39768            1. TVTVVTT - a, x(vector), b, y(vector), z(vector), r0, r1
39769         */
39770       {}
39771 
operator ()(const std::size_t & ps_index,parameter_list_t parameters)39772       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
39773       {
39774          const vector_t x(parameters[1]);
39775          const vector_t y(parameters[3]);
39776                vector_t z(parameters[4]);
39777 
39778          std::size_t r0 = 0;
39779          std::size_t r1 = std::min(x.size(),y.size()) - 1;
39780 
39781          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1))
39782             return std::numeric_limits<T>::quiet_NaN();
39783          else if (helper::invalid_range(y, r0, r1))
39784             return std::numeric_limits<T>::quiet_NaN();
39785          else if (helper::invalid_range(z, r0, r1))
39786             return std::numeric_limits<T>::quiet_NaN();
39787 
39788          const T a = scalar_t(parameters[0])();
39789          const T b = scalar_t(parameters[2])();
39790 
39791          for (std::size_t i = r0; i <= r1; ++i)
39792          {
39793             z[i] = (a * x[i]) + (b * y[i]);
39794          }
39795 
39796          return T(1);
39797       }
39798    };
39799 
39800    template <typename T>
39801    class axpbz : public exprtk::igeneric_function<T>
39802    {
39803    public:
39804 
39805       typedef typename exprtk::igeneric_function<T> igfun_t;
39806       typedef typename igfun_t::parameter_list_t    parameter_list_t;
39807       typedef typename igfun_t::generic_type        generic_type;
39808       typedef typename generic_type::scalar_view    scalar_t;
39809       typedef typename generic_type::vector_view    vector_t;
39810 
39811       using exprtk::igeneric_function<T>::operator();
39812 
axpbz()39813       axpbz()
39814       : exprtk::igeneric_function<T>("TVTV|TVTVTT")
39815         /*
39816            z <- ax + b
39817            Overloads:
39818            0. TVTV   - a, x(vector), b, z(vector)
39819            1. TVTVTT - a, x(vector), b, z(vector), r0, r1
39820         */
39821       {}
39822 
operator ()(const std::size_t & ps_index,parameter_list_t parameters)39823       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
39824       {
39825          const vector_t x(parameters[1]);
39826                vector_t z(parameters[3]);
39827 
39828          std::size_t r0 = 0;
39829          std::size_t r1 = x.size() - 1;
39830 
39831          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1))
39832             return std::numeric_limits<T>::quiet_NaN();
39833          else if (helper::invalid_range(z, r0, r1))
39834             return std::numeric_limits<T>::quiet_NaN();
39835 
39836          const T a = scalar_t(parameters[0])();
39837          const T b = scalar_t(parameters[2])();
39838 
39839          for (std::size_t i = r0; i <= r1; ++i)
39840          {
39841             z[i] = (a * x[i]) + b;
39842          }
39843 
39844          return T(1);
39845       }
39846    };
39847 
39848    template <typename T>
39849    class dot : public exprtk::igeneric_function<T>
39850    {
39851    public:
39852 
39853       typedef typename exprtk::igeneric_function<T> igfun_t;
39854       typedef typename igfun_t::parameter_list_t    parameter_list_t;
39855       typedef typename igfun_t::generic_type        generic_type;
39856       typedef typename generic_type::scalar_view    scalar_t;
39857       typedef typename generic_type::vector_view    vector_t;
39858 
39859       using exprtk::igeneric_function<T>::operator();
39860 
dot()39861       dot()
39862       : exprtk::igeneric_function<T>("VV|VVTT")
39863         /*
39864            Overloads:
39865            0. VV   - x(vector), y(vector)
39866            1. VVTT - x(vector), y(vector), r0, r1
39867         */
39868       {}
39869 
operator ()(const std::size_t & ps_index,parameter_list_t parameters)39870       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
39871       {
39872          const vector_t x(parameters[0]);
39873          const vector_t y(parameters[1]);
39874 
39875          std::size_t r0 = 0;
39876          std::size_t r1 = std::min(x.size(),y.size()) - 1;
39877 
39878          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
39879             return std::numeric_limits<T>::quiet_NaN();
39880          else if (helper::invalid_range(y, r0, r1))
39881             return std::numeric_limits<T>::quiet_NaN();
39882 
39883          T result = T(0);
39884 
39885          for (std::size_t i = r0; i <= r1; ++i)
39886          {
39887             result += (x[i] * y[i]);
39888          }
39889 
39890          return result;
39891       }
39892    };
39893 
39894    template <typename T>
39895    class dotk : public exprtk::igeneric_function<T>
39896    {
39897    public:
39898 
39899       typedef typename exprtk::igeneric_function<T> igfun_t;
39900       typedef typename igfun_t::parameter_list_t    parameter_list_t;
39901       typedef typename igfun_t::generic_type        generic_type;
39902       typedef typename generic_type::scalar_view    scalar_t;
39903       typedef typename generic_type::vector_view    vector_t;
39904 
39905       using exprtk::igeneric_function<T>::operator();
39906 
dotk()39907       dotk()
39908       : exprtk::igeneric_function<T>("VV|VVTT")
39909         /*
39910            Overloads:
39911            0. VV   - x(vector), y(vector)
39912            1. VVTT - x(vector), y(vector), r0, r1
39913         */
39914       {}
39915 
operator ()(const std::size_t & ps_index,parameter_list_t parameters)39916       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
39917       {
39918          const vector_t x(parameters[0]);
39919          const vector_t y(parameters[1]);
39920 
39921          std::size_t r0 = 0;
39922          std::size_t r1 = std::min(x.size(),y.size()) - 1;
39923 
39924          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
39925             return std::numeric_limits<T>::quiet_NaN();
39926          else if (helper::invalid_range(y, r0, r1))
39927             return std::numeric_limits<T>::quiet_NaN();
39928 
39929          T result = T(0);
39930          T error  = T(0);
39931 
39932          for (std::size_t i = r0; i <= r1; ++i)
39933          {
39934             details::kahan_sum(result, error, (x[i] * y[i]));
39935          }
39936 
39937          return result;
39938       }
39939    };
39940 
39941    template <typename T>
39942    struct package
39943    {
39944       all_true   <T> at;
39945       all_false  <T> af;
39946       any_true   <T> nt;
39947       any_false  <T> nf;
39948       count      <T>  c;
39949       copy       <T> cp;
39950       rol        <T> rl;
39951       ror        <T> rr;
39952       shift_left <T> sl;
39953       shift_right<T> sr;
39954       sort       <T> st;
39955       nthelement <T> ne;
39956       iota       <T> ia;
39957       sumk       <T> sk;
39958       axpy       <T> b1_axpy;
39959       axpby      <T> b1_axpby;
39960       axpyz      <T> b1_axpyz;
39961       axpbyz     <T> b1_axpbyz;
39962       axpbz      <T> b1_axpbz;
39963       dot        <T> dt;
39964       dotk       <T> dtk;
39965 
register_packageexprtk::rtl::vecops::package39966       bool register_package(exprtk::symbol_table<T>& symtab)
39967       {
39968          #define exprtk_register_function(FunctionName,FunctionType)                  \
39969          if (!symtab.add_function(FunctionName,FunctionType))                         \
39970          {                                                                            \
39971             exprtk_debug((                                                            \
39972               "exprtk::rtl::vecops::register_package - Failed to add function: %s\n", \
39973               FunctionName));                                                         \
39974             return false;                                                             \
39975          }                                                                            \
39976 
39977          exprtk_register_function("all_true"     ,at)
39978          exprtk_register_function("all_false"    ,af)
39979          exprtk_register_function("any_true"     ,nt)
39980          exprtk_register_function("any_false"    ,nf)
39981          exprtk_register_function("count"        , c)
39982          exprtk_register_function("copy"         ,cp)
39983          exprtk_register_function("rotate_left"  ,rl)
39984          exprtk_register_function("rol"          ,rl)
39985          exprtk_register_function("rotate_right" ,rr)
39986          exprtk_register_function("ror"          ,rr)
39987          exprtk_register_function("shftl"        ,sl)
39988          exprtk_register_function("shftr"        ,sr)
39989          exprtk_register_function("sort"         ,st)
39990          exprtk_register_function("nth_element"  ,ne)
39991          exprtk_register_function("iota"         ,ia)
39992          exprtk_register_function("sumk"         ,sk)
39993          exprtk_register_function("axpy"    ,b1_axpy)
39994          exprtk_register_function("axpby"  ,b1_axpby)
39995          exprtk_register_function("axpyz"  ,b1_axpyz)
39996          exprtk_register_function("axpbyz",b1_axpbyz)
39997          exprtk_register_function("axpbz"  ,b1_axpbz)
39998          exprtk_register_function("dot"          ,dt)
39999          exprtk_register_function("dotk"        ,dtk)
40000          #undef exprtk_register_function
40001 
40002          return true;
40003       }
40004    };
40005 
40006    } // namespace exprtk::rtl::vecops
40007    } // namespace exprtk::rtl
40008 }    // namespace exprtk
40009 #endif
40010 
40011 namespace exprtk
40012 {
40013    namespace information
40014    {
40015       static const char* library = "Mathematical Expression Toolkit";
40016       static const char* version = "2.718281828459045235360287471352"
40017                                    "66249775724709369995957496696762"
40018                                    "77240766303535475945713821785251"
40019                                    "66427427466391932003059921817413";
40020       static const char* date    = "20210101";
40021 
data()40022       static inline std::string data()
40023       {
40024          static const std::string info_str = std::string(library) +
40025                                              std::string(" v") + std::string(version) +
40026                                              std::string(" (") + date + std::string(")");
40027          return info_str;
40028       }
40029 
40030    } // namespace information
40031 
40032    #ifdef exprtk_debug
40033    #undef exprtk_debug
40034    #endif
40035 
40036    #ifdef exprtk_error_location
40037    #undef exprtk_error_location
40038    #endif
40039 
40040    #ifdef exprtk_disable_fallthrough_begin
40041    #undef exprtk_disable_fallthrough_begin
40042    #endif
40043 
40044    #ifdef exprtk_disable_fallthrough_end
40045    #undef exprtk_disable_fallthrough_end
40046    #endif
40047 
40048 } // namespace exprtk
40049 
40050 #endif
40051