]> sigrok.org Git - pulseview.git/blob - pv/exprtk.hpp
Implement MathSignal
[pulseview.git] / pv / exprtk.hpp
1 /*
2  ******************************************************************
3  *           C++ Mathematical Expression Toolkit Library          *
4  *                                                                *
5  * Author: Arash Partow (1999-2020)                               *
6  * URL: http://www.partow.net/programming/exprtk/index.html       *
7  *                                                                *
8  * Copyright notice:                                              *
9  * Free use of the C++ Mathematical Expression Toolkit Library is *
10  * permitted under the guidelines and in accordance with the most *
11  * current version of the MIT License.                            *
12  * http://www.opensource.org/licenses/MIT                         *
13  *                                                                *
14  * Example expressions:                                           *
15  * (00) (y + x / y) * (x - y / x)                                 *
16  * (01) (x^2 / sin(2 * pi / y)) - x / 2                           *
17  * (02) sqrt(1 - (x^2))                                           *
18  * (03) 1 - sin(2 * x) + cos(pi / y)                              *
19  * (04) a * exp(2 * t) + c                                        *
20  * (05) if(((x + 2) == 3) and ((y + 5) <= 9),1 + w, 2 / z)        *
21  * (06) (avg(x,y) <= x + y ? x - y : x * y) + 2 * pi / x          *
22  * (07) z := x + sin(2 * pi / y)                                  *
23  * (08) u := 2 * (pi * z) / (w := x + cos(y / pi))                *
24  * (09) clamp(-1,sin(2 * pi * x) + cos(y / 2 * pi),+1)            *
25  * (10) inrange(-2,m,+2) == if(({-2 <= m} and [m <= +2]),1,0)     *
26  * (11) (2sin(x)cos(2y)7 + 1) == (2 * sin(x) * cos(2*y) * 7 + 1)  *
27  * (12) (x ilike 's*ri?g') and [y < (3 z^7 + w)]                  *
28  *                                                                *
29  ******************************************************************
30 */
31
32
33 #ifndef INCLUDE_EXPRTK_HPP
34 #define INCLUDE_EXPRTK_HPP
35
36
37 #include <algorithm>
38 #include <cctype>
39 #include <cmath>
40 #include <complex>
41 #include <cstdio>
42 #include <cstdlib>
43 #include <cstring>
44 #include <deque>
45 #include <exception>
46 #include <functional>
47 #include <iterator>
48 #include <limits>
49 #include <list>
50 #include <map>
51 #include <set>
52 #include <stack>
53 #include <stdexcept>
54 #include <string>
55 #include <utility>
56 #include <vector>
57
58
59 namespace exprtk
60 {
61    #ifdef exprtk_enable_debugging
62      #define exprtk_debug(params) printf params
63    #else
64      #define exprtk_debug(params) (void)0
65    #endif
66
67    #define exprtk_error_location             \
68    "exprtk.hpp:" + details::to_str(__LINE__) \
69
70    #if defined(__GNUC__) && (__GNUC__  >= 7)
71
72       #define exprtk_disable_fallthrough_begin                      \
73       _Pragma ("GCC diagnostic push")                               \
74       _Pragma ("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") \
75
76       #define exprtk_disable_fallthrough_end                        \
77       _Pragma ("GCC diagnostic pop")                                \
78
79    #else
80       #define exprtk_disable_fallthrough_begin (void)0;
81       #define exprtk_disable_fallthrough_end   (void)0;
82    #endif
83
84    namespace details
85    {
86       typedef unsigned char            uchar_t;
87       typedef char                      char_t;
88       typedef uchar_t*               uchar_ptr;
89       typedef char_t*                 char_ptr;
90       typedef uchar_t const*        uchar_cptr;
91       typedef char_t const*          char_cptr;
92       typedef unsigned long long int _uint64_t;
93       typedef long long int           _int64_t;
94
95       inline bool is_whitespace(const char_t c)
96       {
97          return (' '  == c) || ('\n' == c) ||
98                 ('\r' == c) || ('\t' == c) ||
99                 ('\b' == c) || ('\v' == c) ||
100                 ('\f' == c) ;
101       }
102
103       inline bool is_operator_char(const char_t c)
104       {
105          return ('+' == c) || ('-' == c) ||
106                 ('*' == c) || ('/' == c) ||
107                 ('^' == c) || ('<' == c) ||
108                 ('>' == c) || ('=' == c) ||
109                 (',' == c) || ('!' == c) ||
110                 ('(' == c) || (')' == c) ||
111                 ('[' == c) || (']' == c) ||
112                 ('{' == c) || ('}' == c) ||
113                 ('%' == c) || (':' == c) ||
114                 ('?' == c) || ('&' == c) ||
115                 ('|' == c) || (';' == c) ;
116       }
117
118       inline bool is_letter(const char_t c)
119       {
120          return (('a' <= c) && (c <= 'z')) ||
121                 (('A' <= c) && (c <= 'Z')) ;
122       }
123
124       inline bool is_digit(const char_t c)
125       {
126          return ('0' <= c) && (c <= '9');
127       }
128
129       inline bool is_letter_or_digit(const char_t c)
130       {
131          return is_letter(c) || is_digit(c);
132       }
133
134       inline bool is_left_bracket(const char_t c)
135       {
136          return ('(' == c) || ('[' == c) || ('{' == c);
137       }
138
139       inline bool is_right_bracket(const char_t c)
140       {
141          return (')' == c) || (']' == c) || ('}' == c);
142       }
143
144       inline bool is_bracket(const char_t c)
145       {
146          return is_left_bracket(c) || is_right_bracket(c);
147       }
148
149       inline bool is_sign(const char_t c)
150       {
151          return ('+' == c) || ('-' == c);
152       }
153
154       inline bool is_invalid(const char_t c)
155       {
156          return !is_whitespace   (c) &&
157                 !is_operator_char(c) &&
158                 !is_letter       (c) &&
159                 !is_digit        (c) &&
160                 ('.'  != c)          &&
161                 ('_'  != c)          &&
162                 ('$'  != c)          &&
163                 ('~'  != c)          &&
164                 ('\'' != c);
165       }
166
167       #ifndef exprtk_disable_caseinsensitivity
168       inline void case_normalise(std::string& s)
169       {
170          for (std::size_t i = 0; i < s.size(); ++i)
171          {
172             s[i] = static_cast<std::string::value_type>(std::tolower(s[i]));
173          }
174       }
175
176       inline bool imatch(const char_t c1, const char_t c2)
177       {
178          return std::tolower(c1) == std::tolower(c2);
179       }
180
181       inline bool imatch(const std::string& s1, const std::string& s2)
182       {
183          if (s1.size() == s2.size())
184          {
185             for (std::size_t i = 0; i < s1.size(); ++i)
186             {
187                if (std::tolower(s1[i]) != std::tolower(s2[i]))
188                {
189                   return false;
190                }
191             }
192
193             return true;
194          }
195
196          return false;
197       }
198
199       struct ilesscompare
200       {
201          inline bool operator() (const std::string& s1, const std::string& s2) const
202          {
203             const std::size_t length = std::min(s1.size(),s2.size());
204
205             for (std::size_t i = 0; i < length;  ++i)
206             {
207                const char_t c1 = static_cast<char>(std::tolower(s1[i]));
208                const char_t c2 = static_cast<char>(std::tolower(s2[i]));
209
210                if (c1 > c2)
211                   return false;
212                else if (c1 < c2)
213                   return true;
214             }
215
216             return s1.size() < s2.size();
217          }
218       };
219
220       #else
221       inline void case_normalise(std::string&)
222       {}
223
224       inline bool imatch(const char_t c1, const char_t c2)
225       {
226          return c1 == c2;
227       }
228
229       inline bool imatch(const std::string& s1, const std::string& s2)
230       {
231          return s1 == s2;
232       }
233
234       struct ilesscompare
235       {
236          inline bool operator() (const std::string& s1, const std::string& s2) const
237          {
238             return s1 < s2;
239          }
240       };
241       #endif
242
243       inline bool is_valid_sf_symbol(const std::string& symbol)
244       {
245          // Special function: $f12 or $F34
246          return (4 == symbol.size())  &&
247                 ('$' == symbol[0])    &&
248                 imatch('f',symbol[1]) &&
249                 is_digit(symbol[2])   &&
250                 is_digit(symbol[3]);
251       }
252
253       inline const char_t& front(const std::string& s)
254       {
255          return s[0];
256       }
257
258       inline const char_t& back(const std::string& s)
259       {
260          return s[s.size() - 1];
261       }
262
263       inline std::string to_str(int i)
264       {
265          if (0 == i)
266             return std::string("0");
267
268          std::string result;
269
270          if (i < 0)
271          {
272             for ( ; i; i /= 10)
273             {
274                result += '0' + char(-(i % 10));
275             }
276
277             result += '-';
278          }
279          else
280          {
281             for ( ; i; i /= 10)
282             {
283                result += '0' + char(i % 10);
284             }
285          }
286
287          std::reverse(result.begin(), result.end());
288
289          return result;
290       }
291
292       inline std::string to_str(std::size_t i)
293       {
294          return to_str(static_cast<int>(i));
295       }
296
297       inline bool is_hex_digit(const std::string::value_type digit)
298       {
299          return (('0' <= digit) && (digit <= '9')) ||
300                 (('A' <= digit) && (digit <= 'F')) ||
301                 (('a' <= digit) && (digit <= 'f')) ;
302       }
303
304       inline uchar_t hex_to_bin(uchar_t h)
305       {
306          if (('0' <= h) && (h <= '9'))
307             return (h - '0');
308          else
309             return static_cast<unsigned char>(std::toupper(h) - 'A');
310       }
311
312       template <typename Iterator>
313       inline void parse_hex(Iterator& itr, Iterator end, std::string::value_type& result)
314       {
315          if (
316               (end !=  (itr    )) &&
317               (end !=  (itr + 1)) &&
318               (end !=  (itr + 2)) &&
319               (end !=  (itr + 3)) &&
320               ('0' == *(itr    )) &&
321               (
322                 ('x' == *(itr + 1)) ||
323                 ('X' == *(itr + 1))
324               ) &&
325               (is_hex_digit(*(itr + 2))) &&
326               (is_hex_digit(*(itr + 3)))
327             )
328          {
329             result = hex_to_bin(static_cast<uchar_t>(*(itr + 2))) << 4 |
330                      hex_to_bin(static_cast<uchar_t>(*(itr + 3))) ;
331             itr += 3;
332          }
333          else
334             result = '\0';
335       }
336
337       inline void cleanup_escapes(std::string& s)
338       {
339          typedef std::string::iterator str_itr_t;
340
341          str_itr_t itr1 = s.begin();
342          str_itr_t itr2 = s.begin();
343          str_itr_t end  = s.end  ();
344
345          std::size_t removal_count  = 0;
346
347          while (end != itr1)
348          {
349             if ('\\' == (*itr1))
350             {
351                ++removal_count;
352
353                if (end == ++itr1)
354                   break;
355                else if ('\\' != (*itr1))
356                {
357                   switch (*itr1)
358                   {
359                      case 'n' : (*itr1) = '\n'; break;
360                      case 'r' : (*itr1) = '\r'; break;
361                      case 't' : (*itr1) = '\t'; break;
362                      case '0' : parse_hex(itr1, end, (*itr1));
363                                 removal_count += 3;
364                                 break;
365                   }
366
367                   continue;
368                }
369             }
370
371             if (itr1 != itr2)
372             {
373                (*itr2) = (*itr1);
374             }
375
376             ++itr1;
377             ++itr2;
378          }
379
380          s.resize(s.size() - removal_count);
381       }
382
383       class build_string
384       {
385       public:
386
387          build_string(const std::size_t& initial_size = 64)
388          {
389             data_.reserve(initial_size);
390          }
391
392          inline build_string& operator << (const std::string& s)
393          {
394             data_ += s;
395             return (*this);
396          }
397
398          inline build_string& operator << (char_cptr s)
399          {
400             data_ += std::string(s);
401             return (*this);
402          }
403
404          inline operator std::string () const
405          {
406             return data_;
407          }
408
409          inline std::string as_string() const
410          {
411             return data_;
412          }
413
414       private:
415
416          std::string data_;
417       };
418
419       static const std::string reserved_words[] =
420                                   {
421                                     "break",  "case",  "continue",  "default",  "false",  "for",
422                                     "if", "else", "ilike",  "in", "like", "and",  "nand", "nor",
423                                     "not",  "null",  "or",   "repeat", "return",  "shl",  "shr",
424                                     "swap", "switch", "true",  "until", "var",  "while", "xnor",
425                                     "xor", "&", "|"
426                                   };
427
428       static const std::size_t reserved_words_size = sizeof(reserved_words) / sizeof(std::string);
429
430       static const std::string reserved_symbols[] =
431                                   {
432                                     "abs",  "acos",  "acosh",  "and",  "asin",  "asinh", "atan",
433                                     "atanh", "atan2", "avg",  "break", "case", "ceil",  "clamp",
434                                     "continue",   "cos",   "cosh",   "cot",   "csc",  "default",
435                                     "deg2grad",  "deg2rad",   "equal",  "erf",   "erfc",  "exp",
436                                     "expm1",  "false",   "floor",  "for",   "frac",  "grad2deg",
437                                     "hypot", "iclamp", "if",  "else", "ilike", "in",  "inrange",
438                                     "like",  "log",  "log10", "log2",  "logn",  "log1p", "mand",
439                                     "max", "min",  "mod", "mor",  "mul", "ncdf",  "nand", "nor",
440                                     "not",   "not_equal",   "null",   "or",   "pow",  "rad2deg",
441                                     "repeat", "return", "root", "round", "roundn", "sec", "sgn",
442                                     "shl", "shr", "sin", "sinc", "sinh", "sqrt",  "sum", "swap",
443                                     "switch", "tan",  "tanh", "true",  "trunc", "until",  "var",
444                                     "while", "xnor", "xor", "&", "|"
445                                   };
446
447       static const std::size_t reserved_symbols_size = sizeof(reserved_symbols) / sizeof(std::string);
448
449       static const std::string base_function_list[] =
450                                   {
451                                     "abs", "acos",  "acosh", "asin",  "asinh", "atan",  "atanh",
452                                     "atan2",  "avg",  "ceil",  "clamp",  "cos",  "cosh",  "cot",
453                                     "csc",  "equal",  "erf",  "erfc",  "exp",  "expm1", "floor",
454                                     "frac", "hypot", "iclamp",  "like", "log", "log10",  "log2",
455                                     "logn", "log1p", "mand", "max", "min", "mod", "mor",  "mul",
456                                     "ncdf",  "pow",  "root",  "round",  "roundn",  "sec", "sgn",
457                                     "sin", "sinc", "sinh", "sqrt", "sum", "swap", "tan", "tanh",
458                                     "trunc",  "not_equal",  "inrange",  "deg2grad",   "deg2rad",
459                                     "rad2deg", "grad2deg"
460                                   };
461
462       static const std::size_t base_function_list_size = sizeof(base_function_list) / sizeof(std::string);
463
464       static const std::string logic_ops_list[] =
465                                   {
466                                     "and", "nand", "nor", "not", "or",  "xnor", "xor", "&", "|"
467                                   };
468
469       static const std::size_t logic_ops_list_size = sizeof(logic_ops_list) / sizeof(std::string);
470
471       static const std::string cntrl_struct_list[] =
472                                   {
473                                      "if", "switch", "for", "while", "repeat", "return"
474                                   };
475
476       static const std::size_t cntrl_struct_list_size = sizeof(cntrl_struct_list) / sizeof(std::string);
477
478       static const std::string arithmetic_ops_list[] =
479                                   {
480                                     "+", "-", "*", "/", "%", "^"
481                                   };
482
483       static const std::size_t arithmetic_ops_list_size = sizeof(arithmetic_ops_list) / sizeof(std::string);
484
485       static const std::string assignment_ops_list[] =
486                                   {
487                                     ":=", "+=", "-=",
488                                     "*=", "/=", "%="
489                                   };
490
491       static const std::size_t assignment_ops_list_size = sizeof(assignment_ops_list) / sizeof(std::string);
492
493       static const std::string inequality_ops_list[] =
494                                   {
495                                      "<",  "<=", "==",
496                                      "=",  "!=", "<>",
497                                     ">=",  ">"
498                                   };
499
500       static const std::size_t inequality_ops_list_size = sizeof(inequality_ops_list) / sizeof(std::string);
501
502       inline bool is_reserved_word(const std::string& symbol)
503       {
504          for (std::size_t i = 0; i < reserved_words_size; ++i)
505          {
506             if (imatch(symbol, reserved_words[i]))
507             {
508                return true;
509             }
510          }
511
512          return false;
513       }
514
515       inline bool is_reserved_symbol(const std::string& symbol)
516       {
517          for (std::size_t i = 0; i < reserved_symbols_size; ++i)
518          {
519             if (imatch(symbol, reserved_symbols[i]))
520             {
521                return true;
522             }
523          }
524
525          return false;
526       }
527
528       inline bool is_base_function(const std::string& function_name)
529       {
530          for (std::size_t i = 0; i < base_function_list_size; ++i)
531          {
532             if (imatch(function_name, base_function_list[i]))
533             {
534                return true;
535             }
536          }
537
538          return false;
539       }
540
541       inline bool is_control_struct(const std::string& cntrl_strct)
542       {
543          for (std::size_t i = 0; i < cntrl_struct_list_size; ++i)
544          {
545             if (imatch(cntrl_strct, cntrl_struct_list[i]))
546             {
547                return true;
548             }
549          }
550
551          return false;
552       }
553
554       inline bool is_logic_opr(const std::string& lgc_opr)
555       {
556          for (std::size_t i = 0; i < logic_ops_list_size; ++i)
557          {
558             if (imatch(lgc_opr, logic_ops_list[i]))
559             {
560                return true;
561             }
562          }
563
564          return false;
565       }
566
567       struct cs_match
568       {
569          static inline bool cmp(const char_t c0, const char_t c1)
570          {
571             return (c0 == c1);
572          }
573       };
574
575       struct cis_match
576       {
577          static inline bool cmp(const char_t c0, const char_t c1)
578          {
579             return (std::tolower(c0) == std::tolower(c1));
580          }
581       };
582
583       template <typename Iterator, typename Compare>
584       inline bool match_impl(const Iterator pattern_begin,
585                              const Iterator pattern_end  ,
586                              const Iterator data_begin   ,
587                              const Iterator data_end     ,
588                              const typename std::iterator_traits<Iterator>::value_type& zero_or_more,
589                              const typename std::iterator_traits<Iterator>::value_type& zero_or_one )
590       {
591          const Iterator null_itr(0);
592
593          Iterator d_itr    = data_begin;
594          Iterator p_itr    = pattern_begin;
595          Iterator tb_p_itr = null_itr;
596          Iterator tb_d_itr = null_itr;
597
598          while (d_itr != data_end)
599          {
600             if (zero_or_more == *p_itr)
601             {
602                while ((pattern_end != p_itr) && ((zero_or_more == *p_itr) || (zero_or_one == *p_itr)))
603                {
604                   ++p_itr;
605                }
606
607                if (pattern_end == p_itr)
608                   return true;
609
610                const typename std::iterator_traits<Iterator>::value_type c = *(p_itr);
611
612                while ((data_end != d_itr) && !Compare::cmp(c,*d_itr))
613                {
614                   ++d_itr;
615                }
616
617                tb_p_itr = p_itr;
618                tb_d_itr = d_itr;
619
620                continue;
621             }
622             else if (!Compare::cmp(*p_itr, *d_itr) && (zero_or_one != *p_itr))
623             {
624                if (null_itr == tb_d_itr)
625                   return false;
626
627                d_itr = tb_d_itr++;
628                p_itr = tb_p_itr;
629
630                continue;
631             }
632
633             ++p_itr;
634             ++d_itr;
635          }
636
637          while ((pattern_end != p_itr) && ((zero_or_more == *p_itr) || (zero_or_one == *p_itr)))
638          {
639             ++p_itr;
640          }
641
642          return (pattern_end == p_itr);
643       }
644
645       inline bool wc_match(const std::string& wild_card,
646                            const std::string& str)
647       {
648          return match_impl<char_cptr,cs_match>(wild_card.data(),
649                                                wild_card.data() + wild_card.size(),
650                                                str.data(),
651                                                str.data() + str.size(),
652                                                '*',
653                                                '?');
654       }
655
656       inline bool wc_imatch(const std::string& wild_card,
657                             const std::string& str)
658       {
659          return match_impl<char_cptr,cis_match>(wild_card.data(),
660                                                 wild_card.data() + wild_card.size(),
661                                                 str.data(),
662                                                 str.data() + str.size(),
663                                                 '*',
664                                                 '?');
665       }
666
667       inline bool sequence_match(const std::string& pattern,
668                                  const std::string& str,
669                                  std::size_t&       diff_index,
670                                  char_t&            diff_value)
671       {
672          if (str.empty())
673          {
674             return ("Z" == pattern);
675          }
676          else if ('*' == pattern[0])
677             return false;
678
679          typedef std::string::const_iterator itr_t;
680
681          itr_t p_itr = pattern.begin();
682          itr_t s_itr = str    .begin();
683
684          itr_t p_end = pattern.end();
685          itr_t s_end = str    .end();
686
687          while ((s_end != s_itr) && (p_end != p_itr))
688          {
689             if ('*' == (*p_itr))
690             {
691                const char_t target = static_cast<char>(std::toupper(*(p_itr - 1)));
692
693                if ('*' == target)
694                {
695                   diff_index = static_cast<std::size_t>(std::distance(str.begin(),s_itr));
696                   diff_value = static_cast<char>(std::toupper(*p_itr));
697
698                   return false;
699                }
700                else
701                   ++p_itr;
702
703                while (s_itr != s_end)
704                {
705                   if (target != std::toupper(*s_itr))
706                      break;
707                   else
708                      ++s_itr;
709                }
710
711                continue;
712             }
713             else if (
714                       ('?' != *p_itr) &&
715                       std::toupper(*p_itr) != std::toupper(*s_itr)
716                     )
717             {
718                diff_index = static_cast<std::size_t>(std::distance(str.begin(),s_itr));
719                diff_value = static_cast<char>(std::toupper(*p_itr));
720
721                return false;
722             }
723
724             ++p_itr;
725             ++s_itr;
726          }
727
728          return (
729                   (s_end == s_itr) &&
730                   (
731                     (p_end ==  p_itr) ||
732                     ('*'   == *p_itr)
733                   )
734                 );
735       }
736
737       static const double pow10[] = {
738                                       1.0,
739                                       1.0E+001, 1.0E+002, 1.0E+003, 1.0E+004,
740                                       1.0E+005, 1.0E+006, 1.0E+007, 1.0E+008,
741                                       1.0E+009, 1.0E+010, 1.0E+011, 1.0E+012,
742                                       1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016
743                                     };
744
745       static const std::size_t pow10_size = sizeof(pow10) / sizeof(double);
746
747       namespace numeric
748       {
749          namespace constant
750          {
751             static const double e       =  2.71828182845904523536028747135266249775724709369996;
752             static const double pi      =  3.14159265358979323846264338327950288419716939937510;
753             static const double pi_2    =  1.57079632679489661923132169163975144209858469968755;
754             static const double pi_4    =  0.78539816339744830961566084581987572104929234984378;
755             static const double pi_180  =  0.01745329251994329576923690768488612713442871888542;
756             static const double _1_pi   =  0.31830988618379067153776752674502872406891929148091;
757             static const double _2_pi   =  0.63661977236758134307553505349005744813783858296183;
758             static const double _180_pi = 57.29577951308232087679815481410517033240547246656443;
759             static const double log2    =  0.69314718055994530941723212145817656807550013436026;
760             static const double sqrt2   =  1.41421356237309504880168872420969807856967187537695;
761          }
762
763          namespace details
764          {
765             struct unknown_type_tag { unknown_type_tag() {} };
766             struct real_type_tag    { real_type_tag   () {} };
767             struct complex_type_tag { complex_type_tag() {} };
768             struct int_type_tag     { int_type_tag    () {} };
769
770             template <typename T>
771             struct number_type
772             {
773                typedef unknown_type_tag type;
774                number_type() {}
775             };
776
777             #define exprtk_register_real_type_tag(T)             \
778             template<> struct number_type<T>                     \
779             { typedef real_type_tag type; number_type() {} };    \
780
781             #define exprtk_register_complex_type_tag(T)          \
782             template<> struct number_type<std::complex<T> >      \
783             { typedef complex_type_tag type; number_type() {} }; \
784
785             #define exprtk_register_int_type_tag(T)              \
786             template<> struct number_type<T>                     \
787             { typedef int_type_tag type; number_type() {} };     \
788
789             exprtk_register_real_type_tag(double     )
790             exprtk_register_real_type_tag(long double)
791             exprtk_register_real_type_tag(float      )
792
793             exprtk_register_complex_type_tag(double     )
794             exprtk_register_complex_type_tag(long double)
795             exprtk_register_complex_type_tag(float      )
796
797             exprtk_register_int_type_tag(short         )
798             exprtk_register_int_type_tag(int           )
799             exprtk_register_int_type_tag(_int64_t      )
800             exprtk_register_int_type_tag(unsigned short)
801             exprtk_register_int_type_tag(unsigned int  )
802             exprtk_register_int_type_tag(_uint64_t     )
803
804             #undef exprtk_register_real_type_tag
805             #undef exprtk_register_int_type_tag
806
807             template <typename T>
808             struct epsilon_type
809             {
810                static inline T value()
811                {
812                   const T epsilon = T(0.0000000001);
813                   return epsilon;
814                }
815             };
816
817             template <>
818             struct epsilon_type <float>
819             {
820                static inline float value()
821                {
822                   const float epsilon = float(0.000001f);
823                   return epsilon;
824                }
825             };
826
827             template <>
828             struct epsilon_type <long double>
829             {
830                static inline long double value()
831                {
832                   const long double epsilon = (long double)(0.000000000001);
833                   return epsilon;
834                }
835             };
836
837             template <typename T>
838             inline bool is_nan_impl(const T v, real_type_tag)
839             {
840                return std::not_equal_to<T>()(v,v);
841             }
842
843             template <typename T>
844             inline int to_int32_impl(const T v, real_type_tag)
845             {
846                return static_cast<int>(v);
847             }
848
849             template <typename T>
850             inline _int64_t to_int64_impl(const T v, real_type_tag)
851             {
852                return static_cast<_int64_t>(v);
853             }
854
855             template <typename T>
856             inline bool is_true_impl(const T v)
857             {
858                return std::not_equal_to<T>()(T(0),v);
859             }
860
861             template <typename T>
862             inline bool is_false_impl(const T v)
863             {
864                return std::equal_to<T>()(T(0),v);
865             }
866
867             template <typename T>
868             inline T abs_impl(const T v, real_type_tag)
869             {
870                return ((v < T(0)) ? -v : v);
871             }
872
873             template <typename T>
874             inline T min_impl(const T v0, const T v1, real_type_tag)
875             {
876                return std::min<T>(v0,v1);
877             }
878
879             template <typename T>
880             inline T max_impl(const T v0, const T v1, real_type_tag)
881             {
882                return std::max<T>(v0,v1);
883             }
884
885             template <typename T>
886             inline T equal_impl(const T v0, const T v1, real_type_tag)
887             {
888                const T epsilon = epsilon_type<T>::value();
889                return (abs_impl(v0 - v1,real_type_tag()) <= (std::max(T(1),std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? T(1) : T(0);
890             }
891
892             inline float equal_impl(const float v0, const float v1, real_type_tag)
893             {
894                const float epsilon = epsilon_type<float>::value();
895                return (abs_impl(v0 - v1,real_type_tag()) <= (std::max(1.0f,std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? 1.0f : 0.0f;
896             }
897
898             template <typename T>
899             inline T equal_impl(const T v0, const T v1, int_type_tag)
900             {
901                return (v0 == v1) ? 1 : 0;
902             }
903
904             template <typename T>
905             inline T expm1_impl(const T v, real_type_tag)
906             {
907                // return std::expm1<T>(v);
908                if (abs_impl(v,real_type_tag()) < T(0.00001))
909                   return v + (T(0.5) * v * v);
910                else
911                   return std::exp(v) - T(1);
912             }
913
914             template <typename T>
915             inline T expm1_impl(const T v, int_type_tag)
916             {
917                return T(std::exp<double>(v)) - T(1);
918             }
919
920             template <typename T>
921             inline T nequal_impl(const T v0, const T v1, real_type_tag)
922             {
923                typedef real_type_tag rtg;
924                const T epsilon = epsilon_type<T>::value();
925                return (abs_impl(v0 - v1,rtg()) > (std::max(T(1),std::max(abs_impl(v0,rtg()),abs_impl(v1,rtg()))) * epsilon)) ? T(1) : T(0);
926             }
927
928             inline float nequal_impl(const float v0, const float v1, real_type_tag)
929             {
930                typedef real_type_tag rtg;
931                const float epsilon = epsilon_type<float>::value();
932                return (abs_impl(v0 - v1,rtg()) > (std::max(1.0f,std::max(abs_impl(v0,rtg()),abs_impl(v1,rtg()))) * epsilon)) ? 1.0f : 0.0f;
933             }
934
935             template <typename T>
936             inline T nequal_impl(const T v0, const T v1, int_type_tag)
937             {
938                return (v0 != v1) ? 1 : 0;
939             }
940
941             template <typename T>
942             inline T modulus_impl(const T v0, const T v1, real_type_tag)
943             {
944                return std::fmod(v0,v1);
945             }
946
947             template <typename T>
948             inline T modulus_impl(const T v0, const T v1, int_type_tag)
949             {
950                return v0 % v1;
951             }
952
953             template <typename T>
954             inline T pow_impl(const T v0, const T v1, real_type_tag)
955             {
956                return std::pow(v0,v1);
957             }
958
959             template <typename T>
960             inline T pow_impl(const T v0, const T v1, int_type_tag)
961             {
962                return std::pow(static_cast<double>(v0),static_cast<double>(v1));
963             }
964
965             template <typename T>
966             inline T logn_impl(const T v0, const T v1, real_type_tag)
967             {
968                return std::log(v0) / std::log(v1);
969             }
970
971             template <typename T>
972             inline T logn_impl(const T v0, const T v1, int_type_tag)
973             {
974                return static_cast<T>(logn_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag()));
975             }
976
977             template <typename T>
978             inline T log1p_impl(const T v, real_type_tag)
979             {
980                if (v > T(-1))
981                {
982                   if (abs_impl(v,real_type_tag()) > T(0.0001))
983                   {
984                      return std::log(T(1) + v);
985                   }
986                   else
987                      return (T(-0.5) * v + T(1)) * v;
988                }
989                else
990                   return std::numeric_limits<T>::quiet_NaN();
991             }
992
993             template <typename T>
994             inline T log1p_impl(const T v, int_type_tag)
995             {
996                if (v > T(-1))
997                {
998                   return std::log(T(1) + v);
999                }
1000                else
1001                   return std::numeric_limits<T>::quiet_NaN();
1002             }
1003
1004             template <typename T>
1005             inline T root_impl(const T v0, const T v1, real_type_tag)
1006             {
1007                if (v1 < T(0))
1008                   return std::numeric_limits<T>::quiet_NaN();
1009
1010                const std::size_t n = static_cast<std::size_t>(v1);
1011
1012                if ((v0 < T(0)) && (0 == (n % 2)))
1013                   return std::numeric_limits<T>::quiet_NaN();
1014
1015                return std::pow(v0, T(1) / n);
1016             }
1017
1018             template <typename T>
1019             inline T root_impl(const T v0, const T v1, int_type_tag)
1020             {
1021                return root_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag());
1022             }
1023
1024             template <typename T>
1025             inline T round_impl(const T v, real_type_tag)
1026             {
1027                return ((v < T(0)) ? std::ceil(v - T(0.5)) : std::floor(v + T(0.5)));
1028             }
1029
1030             template <typename T>
1031             inline T roundn_impl(const T v0, const T v1, real_type_tag)
1032             {
1033                const int index = std::max<int>(0, std::min<int>(pow10_size - 1, (int)std::floor(v1)));
1034                const T p10 = T(pow10[index]);
1035
1036                if (v0 < T(0))
1037                   return T(std::ceil ((v0 * p10) - T(0.5)) / p10);
1038                else
1039                   return T(std::floor((v0 * p10) + T(0.5)) / p10);
1040             }
1041
1042             template <typename T>
1043             inline T roundn_impl(const T v0, const T, int_type_tag)
1044             {
1045                return v0;
1046             }
1047
1048             template <typename T>
1049             inline T hypot_impl(const T v0, const T v1, real_type_tag)
1050             {
1051                return std::sqrt((v0 * v0) + (v1 * v1));
1052             }
1053
1054             template <typename T>
1055             inline T hypot_impl(const T v0, const T v1, int_type_tag)
1056             {
1057                return static_cast<T>(std::sqrt(static_cast<double>((v0 * v0) + (v1 * v1))));
1058             }
1059
1060             template <typename T>
1061             inline T atan2_impl(const T v0, const T v1, real_type_tag)
1062             {
1063                return std::atan2(v0,v1);
1064             }
1065
1066             template <typename T>
1067             inline T atan2_impl(const T, const T, int_type_tag)
1068             {
1069                return 0;
1070             }
1071
1072             template <typename T>
1073             inline T shr_impl(const T v0, const T v1, real_type_tag)
1074             {
1075                return v0 * (T(1) / std::pow(T(2),static_cast<T>(static_cast<int>(v1))));
1076             }
1077
1078             template <typename T>
1079             inline T shr_impl(const T v0, const T v1, int_type_tag)
1080             {
1081                return v0 >> v1;
1082             }
1083
1084             template <typename T>
1085             inline T shl_impl(const T v0, const T v1, real_type_tag)
1086             {
1087                return v0 * std::pow(T(2),static_cast<T>(static_cast<int>(v1)));
1088             }
1089
1090             template <typename T>
1091             inline T shl_impl(const T v0, const T v1, int_type_tag)
1092             {
1093                return v0 << v1;
1094             }
1095
1096             template <typename T>
1097             inline T sgn_impl(const T v, real_type_tag)
1098             {
1099                     if (v > T(0)) return T(+1);
1100                else if (v < T(0)) return T(-1);
1101                else               return T( 0);
1102             }
1103
1104             template <typename T>
1105             inline T sgn_impl(const T v, int_type_tag)
1106             {
1107                     if (v > T(0)) return T(+1);
1108                else if (v < T(0)) return T(-1);
1109                else               return T( 0);
1110             }
1111
1112             template <typename T>
1113             inline T and_impl(const T v0, const T v1, real_type_tag)
1114             {
1115                return (is_true_impl(v0) && is_true_impl(v1)) ? T(1) : T(0);
1116             }
1117
1118             template <typename T>
1119             inline T and_impl(const T v0, const T v1, int_type_tag)
1120             {
1121                return v0 && v1;
1122             }
1123
1124             template <typename T>
1125             inline T nand_impl(const T v0, const T v1, real_type_tag)
1126             {
1127                return (is_false_impl(v0) || is_false_impl(v1)) ? T(1) : T(0);
1128             }
1129
1130             template <typename T>
1131             inline T nand_impl(const T v0, const T v1, int_type_tag)
1132             {
1133                return !(v0 && v1);
1134             }
1135
1136             template <typename T>
1137             inline T or_impl(const T v0, const T v1, real_type_tag)
1138             {
1139                return (is_true_impl(v0) || is_true_impl(v1)) ? T(1) : T(0);
1140             }
1141
1142             template <typename T>
1143             inline T or_impl(const T v0, const T v1, int_type_tag)
1144             {
1145                return (v0 || v1);
1146             }
1147
1148             template <typename T>
1149             inline T nor_impl(const T v0, const T v1, real_type_tag)
1150             {
1151                return (is_false_impl(v0) && is_false_impl(v1)) ? T(1) : T(0);
1152             }
1153
1154             template <typename T>
1155             inline T nor_impl(const T v0, const T v1, int_type_tag)
1156             {
1157                return !(v0 || v1);
1158             }
1159
1160             template <typename T>
1161             inline T xor_impl(const T v0, const T v1, real_type_tag)
1162             {
1163                return (is_false_impl(v0) != is_false_impl(v1)) ? T(1) : T(0);
1164             }
1165
1166             template <typename T>
1167             inline T xor_impl(const T v0, const T v1, int_type_tag)
1168             {
1169                return v0 ^ v1;
1170             }
1171
1172             template <typename T>
1173             inline T xnor_impl(const T v0, const T v1, real_type_tag)
1174             {
1175                const bool v0_true = is_true_impl(v0);
1176                const bool v1_true = is_true_impl(v1);
1177
1178                if ((v0_true &&  v1_true) || (!v0_true && !v1_true))
1179                   return T(1);
1180                else
1181                   return T(0);
1182             }
1183
1184             template <typename T>
1185             inline T xnor_impl(const T v0, const T v1, int_type_tag)
1186             {
1187                const bool v0_true = is_true_impl(v0);
1188                const bool v1_true = is_true_impl(v1);
1189
1190                if ((v0_true &&  v1_true) || (!v0_true && !v1_true))
1191                   return T(1);
1192                else
1193                   return T(0);
1194             }
1195
1196             #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER)
1197             #define exprtk_define_erf(TT,impl)           \
1198             inline TT erf_impl(TT v) { return impl(v); } \
1199
1200             exprtk_define_erf(      float,::erff)
1201             exprtk_define_erf(     double,::erf )
1202             exprtk_define_erf(long double,::erfl)
1203             #undef exprtk_define_erf
1204             #endif
1205
1206             template <typename T>
1207             inline T erf_impl(T v, real_type_tag)
1208             {
1209                #if defined(_MSC_VER) && (_MSC_VER < 1900)
1210                // Credits: Abramowitz & Stegun Equations 7.1.25-28
1211                static const T c[] = {
1212                                       T( 1.26551223), T(1.00002368),
1213                                       T( 0.37409196), T(0.09678418),
1214                                       T(-0.18628806), T(0.27886807),
1215                                       T(-1.13520398), T(1.48851587),
1216                                       T(-0.82215223), T(0.17087277)
1217                                     };
1218
1219                const T t = T(1) / (T(1) + T(0.5) * abs_impl(v,real_type_tag()));
1220
1221                T result = T(1) - t * std::exp((-v * v) -
1222                                       c[0] + t * (c[1] + t *
1223                                      (c[2] + t * (c[3] + t *
1224                                      (c[4] + t * (c[5] + t *
1225                                      (c[6] + t * (c[7] + t *
1226                                      (c[8] + t * (c[9]))))))))));
1227
1228                return (v >= T(0)) ? result : -result;
1229                #else
1230                return erf_impl(v);
1231                #endif
1232             }
1233
1234             template <typename T>
1235             inline T erf_impl(T v, int_type_tag)
1236             {
1237                return erf_impl(static_cast<double>(v),real_type_tag());
1238             }
1239
1240             #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER)
1241             #define exprtk_define_erfc(TT,impl)           \
1242             inline TT erfc_impl(TT v) { return impl(v); } \
1243
1244             exprtk_define_erfc(      float,::erfcf)
1245             exprtk_define_erfc(     double,::erfc )
1246             exprtk_define_erfc(long double,::erfcl)
1247             #undef exprtk_define_erfc
1248             #endif
1249
1250             template <typename T>
1251             inline T erfc_impl(T v, real_type_tag)
1252             {
1253                #if defined(_MSC_VER) && (_MSC_VER < 1900)
1254                return T(1) - erf_impl(v,real_type_tag());
1255                #else
1256                return erfc_impl(v);
1257                #endif
1258             }
1259
1260             template <typename T>
1261             inline T erfc_impl(T v, int_type_tag)
1262             {
1263                return erfc_impl(static_cast<double>(v),real_type_tag());
1264             }
1265
1266             template <typename T>
1267             inline T ncdf_impl(T v, real_type_tag)
1268             {
1269                T cnd = T(0.5) * (T(1) + erf_impl(
1270                                            abs_impl(v,real_type_tag()) /
1271                                            T(numeric::constant::sqrt2),real_type_tag()));
1272                return  (v < T(0)) ? (T(1) - cnd) : cnd;
1273             }
1274
1275             template <typename T>
1276             inline T ncdf_impl(T v, int_type_tag)
1277             {
1278                return ncdf_impl(static_cast<double>(v),real_type_tag());
1279             }
1280
1281             template <typename T>
1282             inline T sinc_impl(T v, real_type_tag)
1283             {
1284                if (std::abs(v) >= std::numeric_limits<T>::epsilon())
1285                    return(std::sin(v) / v);
1286                else
1287                   return T(1);
1288             }
1289
1290             template <typename T>
1291             inline T sinc_impl(T v, int_type_tag)
1292             {
1293                return sinc_impl(static_cast<double>(v),real_type_tag());
1294             }
1295
1296             template <typename T> inline T  acos_impl(const T v, real_type_tag) { return std::acos (v); }
1297             template <typename T> inline T acosh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) - T(1))); }
1298             template <typename T> inline T  asin_impl(const T v, real_type_tag) { return std::asin (v); }
1299             template <typename T> inline T asinh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) + T(1))); }
1300             template <typename T> inline T  atan_impl(const T v, real_type_tag) { return std::atan (v); }
1301             template <typename T> inline T atanh_impl(const T v, real_type_tag) { return (std::log(T(1) + v) - std::log(T(1) - v)) / T(2); }
1302             template <typename T> inline T  ceil_impl(const T v, real_type_tag) { return std::ceil (v); }
1303             template <typename T> inline T   cos_impl(const T v, real_type_tag) { return std::cos  (v); }
1304             template <typename T> inline T  cosh_impl(const T v, real_type_tag) { return std::cosh (v); }
1305             template <typename T> inline T   exp_impl(const T v, real_type_tag) { return std::exp  (v); }
1306             template <typename T> inline T floor_impl(const T v, real_type_tag) { return std::floor(v); }
1307             template <typename T> inline T   log_impl(const T v, real_type_tag) { return std::log  (v); }
1308             template <typename T> inline T log10_impl(const T v, real_type_tag) { return std::log10(v); }
1309             template <typename T> inline T  log2_impl(const T v, real_type_tag) { return std::log(v)/T(numeric::constant::log2); }
1310             template <typename T> inline T   neg_impl(const T v, real_type_tag) { return -v;            }
1311             template <typename T> inline T   pos_impl(const T v, real_type_tag) { return +v;            }
1312             template <typename T> inline T   sin_impl(const T v, real_type_tag) { return std::sin  (v); }
1313             template <typename T> inline T  sinh_impl(const T v, real_type_tag) { return std::sinh (v); }
1314             template <typename T> inline T  sqrt_impl(const T v, real_type_tag) { return std::sqrt (v); }
1315             template <typename T> inline T   tan_impl(const T v, real_type_tag) { return std::tan  (v); }
1316             template <typename T> inline T  tanh_impl(const T v, real_type_tag) { return std::tanh (v); }
1317             template <typename T> inline T   cot_impl(const T v, real_type_tag) { return T(1) / std::tan(v); }
1318             template <typename T> inline T   sec_impl(const T v, real_type_tag) { return T(1) / std::cos(v); }
1319             template <typename T> inline T   csc_impl(const T v, real_type_tag) { return T(1) / std::sin(v); }
1320             template <typename T> inline T   r2d_impl(const T v, real_type_tag) { return (v * T(numeric::constant::_180_pi)); }
1321             template <typename T> inline T   d2r_impl(const T v, real_type_tag) { return (v * T(numeric::constant::pi_180));  }
1322             template <typename T> inline T   d2g_impl(const T v, real_type_tag) { return (v * T(20.0/9.0)); }
1323             template <typename T> inline T   g2d_impl(const T v, real_type_tag) { return (v * T(9.0/20.0)); }
1324             template <typename T> inline T  notl_impl(const T v, real_type_tag) { return (std::not_equal_to<T>()(T(0),v) ? T(0) : T(1)); }
1325             template <typename T> inline T  frac_impl(const T v, real_type_tag) { return (v - static_cast<long long>(v)); }
1326             template <typename T> inline T trunc_impl(const T v, real_type_tag) { return T(static_cast<long long>(v));    }
1327
1328             template <typename T> inline T const_pi_impl(real_type_tag) { return T(numeric::constant::pi); }
1329             template <typename T> inline T const_e_impl (real_type_tag) { return T(numeric::constant::e);  }
1330
1331             template <typename T> inline T   abs_impl(const T v, int_type_tag) { return ((v >= T(0)) ? v : -v); }
1332             template <typename T> inline T   exp_impl(const T v, int_type_tag) { return std::exp  (v); }
1333             template <typename T> inline T   log_impl(const T v, int_type_tag) { return std::log  (v); }
1334             template <typename T> inline T log10_impl(const T v, int_type_tag) { return std::log10(v); }
1335             template <typename T> inline T  log2_impl(const T v, int_type_tag) { return std::log(v)/T(numeric::constant::log2); }
1336             template <typename T> inline T   neg_impl(const T v, int_type_tag) { return -v;            }
1337             template <typename T> inline T   pos_impl(const T v, int_type_tag) { return +v;            }
1338             template <typename T> inline T  ceil_impl(const T v, int_type_tag) { return v;             }
1339             template <typename T> inline T floor_impl(const T v, int_type_tag) { return v;             }
1340             template <typename T> inline T round_impl(const T v, int_type_tag) { return v;             }
1341             template <typename T> inline T  notl_impl(const T v, int_type_tag) { return !v;            }
1342             template <typename T> inline T  sqrt_impl(const T v, int_type_tag) { return std::sqrt (v); }
1343             template <typename T> inline T  frac_impl(const T  , int_type_tag) { return T(0);          }
1344             template <typename T> inline T trunc_impl(const T v, int_type_tag) { return v;             }
1345             template <typename T> inline T  acos_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1346             template <typename T> inline T acosh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1347             template <typename T> inline T  asin_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1348             template <typename T> inline T asinh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1349             template <typename T> inline T  atan_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1350             template <typename T> inline T atanh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1351             template <typename T> inline T   cos_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1352             template <typename T> inline T  cosh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1353             template <typename T> inline T   sin_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1354             template <typename T> inline T  sinh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1355             template <typename T> inline T   tan_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1356             template <typename T> inline T  tanh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1357             template <typename T> inline T   cot_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1358             template <typename T> inline T   sec_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1359             template <typename T> inline T   csc_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1360
1361             template <typename T>
1362             inline bool is_integer_impl(const T& v, real_type_tag)
1363             {
1364                return std::equal_to<T>()(T(0),std::fmod(v,T(1)));
1365             }
1366
1367             template <typename T>
1368             inline bool is_integer_impl(const T&, int_type_tag)
1369             {
1370                return true;
1371             }
1372          }
1373
1374          template <typename Type>
1375          struct numeric_info { enum { length = 0, size = 32, bound_length = 0, min_exp = 0, max_exp = 0 }; };
1376
1377          template<> struct numeric_info<int>         { enum { length = 10, size = 16, bound_length = 9}; };
1378          template<> struct numeric_info<float>       { enum { min_exp =  -38, max_exp =  +38}; };
1379          template<> struct numeric_info<double>      { enum { min_exp = -308, max_exp = +308}; };
1380          template<> struct numeric_info<long double> { enum { min_exp = -308, max_exp = +308}; };
1381
1382          template <typename T>
1383          inline int to_int32(const T v)
1384          {
1385             const typename details::number_type<T>::type num_type;
1386             return to_int32_impl(v, num_type);
1387          }
1388
1389          template <typename T>
1390          inline _int64_t to_int64(const T v)
1391          {
1392             const typename details::number_type<T>::type num_type;
1393             return to_int64_impl(v, num_type);
1394          }
1395
1396          template <typename T>
1397          inline bool is_nan(const T v)
1398          {
1399             const typename details::number_type<T>::type num_type;
1400             return is_nan_impl(v, num_type);
1401          }
1402
1403          template <typename T>
1404          inline T min(const T v0, const T v1)
1405          {
1406             const typename details::number_type<T>::type num_type;
1407             return min_impl(v0, v1, num_type);
1408          }
1409
1410          template <typename T>
1411          inline T max(const T v0, const T v1)
1412          {
1413             const typename details::number_type<T>::type num_type;
1414             return max_impl(v0, v1, num_type);
1415          }
1416
1417          template <typename T>
1418          inline T equal(const T v0, const T v1)
1419          {
1420             const typename details::number_type<T>::type num_type;
1421             return equal_impl(v0, v1, num_type);
1422          }
1423
1424          template <typename T>
1425          inline T nequal(const T v0, const T v1)
1426          {
1427             const typename details::number_type<T>::type num_type;
1428             return nequal_impl(v0, v1, num_type);
1429          }
1430
1431          template <typename T>
1432          inline T modulus(const T v0, const T v1)
1433          {
1434             const typename details::number_type<T>::type num_type;
1435             return modulus_impl(v0, v1, num_type);
1436          }
1437
1438          template <typename T>
1439          inline T pow(const T v0, const T v1)
1440          {
1441             const typename details::number_type<T>::type num_type;
1442             return pow_impl(v0, v1, num_type);
1443          }
1444
1445          template <typename T>
1446          inline T logn(const T v0, const T v1)
1447          {
1448             const typename details::number_type<T>::type num_type;
1449             return logn_impl(v0, v1, num_type);
1450          }
1451
1452          template <typename T>
1453          inline T root(const T v0, const T v1)
1454          {
1455             const typename details::number_type<T>::type num_type;
1456             return root_impl(v0, v1, num_type);
1457          }
1458
1459          template <typename T>
1460          inline T roundn(const T v0, const T v1)
1461          {
1462             const typename details::number_type<T>::type num_type;
1463             return roundn_impl(v0, v1, num_type);
1464          }
1465
1466          template <typename T>
1467          inline T hypot(const T v0, const T v1)
1468          {
1469             const typename details::number_type<T>::type num_type;
1470             return hypot_impl(v0, v1, num_type);
1471          }
1472
1473          template <typename T>
1474          inline T atan2(const T v0, const T v1)
1475          {
1476             const typename details::number_type<T>::type num_type;
1477             return atan2_impl(v0, v1, num_type);
1478          }
1479
1480          template <typename T>
1481          inline T shr(const T v0, const T v1)
1482          {
1483             const typename details::number_type<T>::type num_type;
1484             return shr_impl(v0, v1, num_type);
1485          }
1486
1487          template <typename T>
1488          inline T shl(const T v0, const T v1)
1489          {
1490             const typename details::number_type<T>::type num_type;
1491             return shl_impl(v0, v1, num_type);
1492          }
1493
1494          template <typename T>
1495          inline T and_opr(const T v0, const T v1)
1496          {
1497             const typename details::number_type<T>::type num_type;
1498             return and_impl(v0, v1, num_type);
1499          }
1500
1501          template <typename T>
1502          inline T nand_opr(const T v0, const T v1)
1503          {
1504             const typename details::number_type<T>::type num_type;
1505             return nand_impl(v0, v1, num_type);
1506          }
1507
1508          template <typename T>
1509          inline T or_opr(const T v0, const T v1)
1510          {
1511             const typename details::number_type<T>::type num_type;
1512             return or_impl(v0, v1, num_type);
1513          }
1514
1515          template <typename T>
1516          inline T nor_opr(const T v0, const T v1)
1517          {
1518             const typename details::number_type<T>::type num_type;
1519             return nor_impl(v0, v1, num_type);
1520          }
1521
1522          template <typename T>
1523          inline T xor_opr(const T v0, const T v1)
1524          {
1525             const typename details::number_type<T>::type num_type;
1526             return xor_impl(v0, v1, num_type);
1527          }
1528
1529          template <typename T>
1530          inline T xnor_opr(const T v0, const T v1)
1531          {
1532             const typename details::number_type<T>::type num_type;
1533             return xnor_impl(v0, v1, num_type);
1534          }
1535
1536          template <typename T>
1537          inline bool is_integer(const T v)
1538          {
1539             const typename details::number_type<T>::type num_type;
1540             return is_integer_impl(v, num_type);
1541          }
1542
1543          template <typename T, unsigned int N>
1544          struct fast_exp
1545          {
1546             static inline T result(T v)
1547             {
1548                unsigned int k = N;
1549                T l = T(1);
1550
1551                while (k)
1552                {
1553                   if (k & 1)
1554                   {
1555                      l *= v;
1556                      --k;
1557                   }
1558
1559                   v *= v;
1560                   k >>= 1;
1561                }
1562
1563                return l;
1564             }
1565          };
1566
1567          template <typename T> struct fast_exp<T,10> { static inline T result(T v) { T v_5 = fast_exp<T,5>::result(v); return v_5 * v_5; } };
1568          template <typename T> struct fast_exp<T, 9> { static inline T result(T v) { return fast_exp<T,8>::result(v) * v; } };
1569          template <typename T> struct fast_exp<T, 8> { static inline T result(T v) { T v_4 = fast_exp<T,4>::result(v); return v_4 * v_4; } };
1570          template <typename T> struct fast_exp<T, 7> { static inline T result(T v) { return fast_exp<T,6>::result(v) * v; } };
1571          template <typename T> struct fast_exp<T, 6> { static inline T result(T v) { T v_3 = fast_exp<T,3>::result(v); return v_3 * v_3; } };
1572          template <typename T> struct fast_exp<T, 5> { static inline T result(T v) { return fast_exp<T,4>::result(v) * v; } };
1573          template <typename T> struct fast_exp<T, 4> { static inline T result(T v) { T v_2 = v * v; return v_2 * v_2; } };
1574          template <typename T> struct fast_exp<T, 3> { static inline T result(T v) { return v * v * v; } };
1575          template <typename T> struct fast_exp<T, 2> { static inline T result(T v) { return v * v;     } };
1576          template <typename T> struct fast_exp<T, 1> { static inline T result(T v) { return v;         } };
1577          template <typename T> struct fast_exp<T, 0> { static inline T result(T  ) { return T(1);      } };
1578
1579          #define exprtk_define_unary_function(FunctionName)        \
1580          template <typename T>                                     \
1581          inline T FunctionName (const T v)                         \
1582          {                                                         \
1583             const typename details::number_type<T>::type num_type; \
1584             return  FunctionName##_impl(v,num_type);               \
1585          }                                                         \
1586
1587          exprtk_define_unary_function(abs  )
1588          exprtk_define_unary_function(acos )
1589          exprtk_define_unary_function(acosh)
1590          exprtk_define_unary_function(asin )
1591          exprtk_define_unary_function(asinh)
1592          exprtk_define_unary_function(atan )
1593          exprtk_define_unary_function(atanh)
1594          exprtk_define_unary_function(ceil )
1595          exprtk_define_unary_function(cos  )
1596          exprtk_define_unary_function(cosh )
1597          exprtk_define_unary_function(exp  )
1598          exprtk_define_unary_function(expm1)
1599          exprtk_define_unary_function(floor)
1600          exprtk_define_unary_function(log  )
1601          exprtk_define_unary_function(log10)
1602          exprtk_define_unary_function(log2 )
1603          exprtk_define_unary_function(log1p)
1604          exprtk_define_unary_function(neg  )
1605          exprtk_define_unary_function(pos  )
1606          exprtk_define_unary_function(round)
1607          exprtk_define_unary_function(sin  )
1608          exprtk_define_unary_function(sinc )
1609          exprtk_define_unary_function(sinh )
1610          exprtk_define_unary_function(sqrt )
1611          exprtk_define_unary_function(tan  )
1612          exprtk_define_unary_function(tanh )
1613          exprtk_define_unary_function(cot  )
1614          exprtk_define_unary_function(sec  )
1615          exprtk_define_unary_function(csc  )
1616          exprtk_define_unary_function(r2d  )
1617          exprtk_define_unary_function(d2r  )
1618          exprtk_define_unary_function(d2g  )
1619          exprtk_define_unary_function(g2d  )
1620          exprtk_define_unary_function(notl )
1621          exprtk_define_unary_function(sgn  )
1622          exprtk_define_unary_function(erf  )
1623          exprtk_define_unary_function(erfc )
1624          exprtk_define_unary_function(ncdf )
1625          exprtk_define_unary_function(frac )
1626          exprtk_define_unary_function(trunc)
1627          #undef exprtk_define_unary_function
1628       }
1629
1630       template <typename T>
1631       inline T compute_pow10(T d, const int exponent)
1632       {
1633          static const double fract10[] =
1634          {
1635            0.0,
1636            1.0E+001, 1.0E+002, 1.0E+003, 1.0E+004, 1.0E+005, 1.0E+006, 1.0E+007, 1.0E+008, 1.0E+009, 1.0E+010,
1637            1.0E+011, 1.0E+012, 1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016, 1.0E+017, 1.0E+018, 1.0E+019, 1.0E+020,
1638            1.0E+021, 1.0E+022, 1.0E+023, 1.0E+024, 1.0E+025, 1.0E+026, 1.0E+027, 1.0E+028, 1.0E+029, 1.0E+030,
1639            1.0E+031, 1.0E+032, 1.0E+033, 1.0E+034, 1.0E+035, 1.0E+036, 1.0E+037, 1.0E+038, 1.0E+039, 1.0E+040,
1640            1.0E+041, 1.0E+042, 1.0E+043, 1.0E+044, 1.0E+045, 1.0E+046, 1.0E+047, 1.0E+048, 1.0E+049, 1.0E+050,
1641            1.0E+051, 1.0E+052, 1.0E+053, 1.0E+054, 1.0E+055, 1.0E+056, 1.0E+057, 1.0E+058, 1.0E+059, 1.0E+060,
1642            1.0E+061, 1.0E+062, 1.0E+063, 1.0E+064, 1.0E+065, 1.0E+066, 1.0E+067, 1.0E+068, 1.0E+069, 1.0E+070,
1643            1.0E+071, 1.0E+072, 1.0E+073, 1.0E+074, 1.0E+075, 1.0E+076, 1.0E+077, 1.0E+078, 1.0E+079, 1.0E+080,
1644            1.0E+081, 1.0E+082, 1.0E+083, 1.0E+084, 1.0E+085, 1.0E+086, 1.0E+087, 1.0E+088, 1.0E+089, 1.0E+090,
1645            1.0E+091, 1.0E+092, 1.0E+093, 1.0E+094, 1.0E+095, 1.0E+096, 1.0E+097, 1.0E+098, 1.0E+099, 1.0E+100,
1646            1.0E+101, 1.0E+102, 1.0E+103, 1.0E+104, 1.0E+105, 1.0E+106, 1.0E+107, 1.0E+108, 1.0E+109, 1.0E+110,
1647            1.0E+111, 1.0E+112, 1.0E+113, 1.0E+114, 1.0E+115, 1.0E+116, 1.0E+117, 1.0E+118, 1.0E+119, 1.0E+120,
1648            1.0E+121, 1.0E+122, 1.0E+123, 1.0E+124, 1.0E+125, 1.0E+126, 1.0E+127, 1.0E+128, 1.0E+129, 1.0E+130,
1649            1.0E+131, 1.0E+132, 1.0E+133, 1.0E+134, 1.0E+135, 1.0E+136, 1.0E+137, 1.0E+138, 1.0E+139, 1.0E+140,
1650            1.0E+141, 1.0E+142, 1.0E+143, 1.0E+144, 1.0E+145, 1.0E+146, 1.0E+147, 1.0E+148, 1.0E+149, 1.0E+150,
1651            1.0E+151, 1.0E+152, 1.0E+153, 1.0E+154, 1.0E+155, 1.0E+156, 1.0E+157, 1.0E+158, 1.0E+159, 1.0E+160,
1652            1.0E+161, 1.0E+162, 1.0E+163, 1.0E+164, 1.0E+165, 1.0E+166, 1.0E+167, 1.0E+168, 1.0E+169, 1.0E+170,
1653            1.0E+171, 1.0E+172, 1.0E+173, 1.0E+174, 1.0E+175, 1.0E+176, 1.0E+177, 1.0E+178, 1.0E+179, 1.0E+180,
1654            1.0E+181, 1.0E+182, 1.0E+183, 1.0E+184, 1.0E+185, 1.0E+186, 1.0E+187, 1.0E+188, 1.0E+189, 1.0E+190,
1655            1.0E+191, 1.0E+192, 1.0E+193, 1.0E+194, 1.0E+195, 1.0E+196, 1.0E+197, 1.0E+198, 1.0E+199, 1.0E+200,
1656            1.0E+201, 1.0E+202, 1.0E+203, 1.0E+204, 1.0E+205, 1.0E+206, 1.0E+207, 1.0E+208, 1.0E+209, 1.0E+210,
1657            1.0E+211, 1.0E+212, 1.0E+213, 1.0E+214, 1.0E+215, 1.0E+216, 1.0E+217, 1.0E+218, 1.0E+219, 1.0E+220,
1658            1.0E+221, 1.0E+222, 1.0E+223, 1.0E+224, 1.0E+225, 1.0E+226, 1.0E+227, 1.0E+228, 1.0E+229, 1.0E+230,
1659            1.0E+231, 1.0E+232, 1.0E+233, 1.0E+234, 1.0E+235, 1.0E+236, 1.0E+237, 1.0E+238, 1.0E+239, 1.0E+240,
1660            1.0E+241, 1.0E+242, 1.0E+243, 1.0E+244, 1.0E+245, 1.0E+246, 1.0E+247, 1.0E+248, 1.0E+249, 1.0E+250,
1661            1.0E+251, 1.0E+252, 1.0E+253, 1.0E+254, 1.0E+255, 1.0E+256, 1.0E+257, 1.0E+258, 1.0E+259, 1.0E+260,
1662            1.0E+261, 1.0E+262, 1.0E+263, 1.0E+264, 1.0E+265, 1.0E+266, 1.0E+267, 1.0E+268, 1.0E+269, 1.0E+270,
1663            1.0E+271, 1.0E+272, 1.0E+273, 1.0E+274, 1.0E+275, 1.0E+276, 1.0E+277, 1.0E+278, 1.0E+279, 1.0E+280,
1664            1.0E+281, 1.0E+282, 1.0E+283, 1.0E+284, 1.0E+285, 1.0E+286, 1.0E+287, 1.0E+288, 1.0E+289, 1.0E+290,
1665            1.0E+291, 1.0E+292, 1.0E+293, 1.0E+294, 1.0E+295, 1.0E+296, 1.0E+297, 1.0E+298, 1.0E+299, 1.0E+300,
1666            1.0E+301, 1.0E+302, 1.0E+303, 1.0E+304, 1.0E+305, 1.0E+306, 1.0E+307, 1.0E+308
1667          };
1668
1669          static const int fract10_size = static_cast<int>(sizeof(fract10) / sizeof(double));
1670
1671          const int e = std::abs(exponent);
1672
1673          if (exponent >= std::numeric_limits<T>::min_exponent10)
1674          {
1675             if (e < fract10_size)
1676             {
1677                if (exponent > 0)
1678                   return T(d * fract10[e]);
1679                else
1680                   return T(d / fract10[e]);
1681             }
1682             else
1683                return T(d * std::pow(10.0, 10.0 * exponent));
1684          }
1685          else
1686          {
1687                      d /= T(fract10[           -std::numeric_limits<T>::min_exponent10]);
1688             return T(d /    fract10[-exponent + std::numeric_limits<T>::min_exponent10]);
1689          }
1690       }
1691
1692       template <typename Iterator, typename T>
1693       inline bool string_to_type_converter_impl_ref(Iterator& itr, const Iterator end, T& result)
1694       {
1695          if (itr == end)
1696             return false;
1697
1698          const bool negative = ('-' == (*itr));
1699
1700          if (negative || ('+' == (*itr)))
1701          {
1702             if (end == ++itr)
1703                return false;
1704          }
1705
1706          static const uchar_t zero = static_cast<uchar_t>('0');
1707
1708          while ((end != itr) && (zero == (*itr))) ++itr;
1709
1710          bool return_result = true;
1711          unsigned int digit = 0;
1712          const std::size_t length  = static_cast<std::size_t>(std::distance(itr,end));
1713
1714          if (length <= 4)
1715          {
1716             exprtk_disable_fallthrough_begin
1717             switch (length)
1718             {
1719                #ifdef exprtk_use_lut
1720
1721                #define exprtk_process_digit                          \
1722                if ((digit = details::digit_table[(int)*itr++]) < 10) \
1723                   result = result * 10 + (digit);                    \
1724                else                                                  \
1725                {                                                     \
1726                   return_result = false;                             \
1727                   break;                                             \
1728                }                                                     \
1729
1730                #else
1731
1732                #define exprtk_process_digit         \
1733                if ((digit = (*itr++ - zero)) < 10)  \
1734                   result = result * T(10) + digit;  \
1735                else                                 \
1736                {                                    \
1737                   return_result = false;            \
1738                   break;                            \
1739                }                                    \
1740
1741                #endif
1742
1743                case  4 : exprtk_process_digit
1744                case  3 : exprtk_process_digit
1745                case  2 : exprtk_process_digit
1746                case  1 : if ((digit = (*itr - zero))>= 10) { digit = 0; return_result = false; }
1747
1748                #undef exprtk_process_digit
1749             }
1750             exprtk_disable_fallthrough_end
1751          }
1752          else
1753             return_result = false;
1754
1755          if (length && return_result)
1756          {
1757             result = result * 10 + static_cast<T>(digit);
1758             ++itr;
1759          }
1760
1761          result = negative ? -result : result;
1762          return return_result;
1763       }
1764
1765       template <typename Iterator, typename T>
1766       static inline bool parse_nan(Iterator& itr, const Iterator end, T& t)
1767       {
1768          typedef typename std::iterator_traits<Iterator>::value_type type;
1769
1770          static const std::size_t nan_length = 3;
1771
1772          if (std::distance(itr,end) != static_cast<int>(nan_length))
1773             return false;
1774
1775          if (static_cast<type>('n') == (*itr))
1776          {
1777             if (
1778                  (static_cast<type>('a') != *(itr + 1)) ||
1779                  (static_cast<type>('n') != *(itr + 2))
1780                )
1781             {
1782                return false;
1783             }
1784          }
1785          else if (
1786                    (static_cast<type>('A') != *(itr + 1)) ||
1787                    (static_cast<type>('N') != *(itr + 2))
1788                  )
1789          {
1790             return false;
1791          }
1792
1793          t = std::numeric_limits<T>::quiet_NaN();
1794
1795          return true;
1796       }
1797
1798       template <typename Iterator, typename T>
1799       static inline bool parse_inf(Iterator& itr, const Iterator end, T& t, bool negative)
1800       {
1801          static const char_t inf_uc[] = "INFINITY";
1802          static const char_t inf_lc[] = "infinity";
1803          static const std::size_t inf_length = 8;
1804
1805          const std::size_t length = static_cast<std::size_t>(std::distance(itr,end));
1806
1807          if ((3 != length) && (inf_length != length))
1808             return false;
1809
1810          char_cptr inf_itr = ('i' == (*itr)) ? inf_lc : inf_uc;
1811
1812          while (end != itr)
1813          {
1814             if (*inf_itr == static_cast<char>(*itr))
1815             {
1816                ++itr;
1817                ++inf_itr;
1818                continue;
1819             }
1820             else
1821                return false;
1822          }
1823
1824          if (negative)
1825             t = -std::numeric_limits<T>::infinity();
1826          else
1827             t =  std::numeric_limits<T>::infinity();
1828
1829          return true;
1830       }
1831
1832       template <typename Iterator, typename T>
1833       inline bool string_to_real(Iterator& itr_external, const Iterator end, T& t, numeric::details::real_type_tag)
1834       {
1835          if (end == itr_external) return false;
1836
1837          Iterator itr = itr_external;
1838
1839          T d = T(0);
1840
1841          const bool negative = ('-' == (*itr));
1842
1843          if (negative || '+' == (*itr))
1844          {
1845             if (end == ++itr)
1846                return false;
1847          }
1848
1849          bool instate = false;
1850
1851          static const char_t zero = static_cast<uchar_t>('0');
1852
1853          #define parse_digit_1(d)          \
1854          if ((digit = (*itr - zero)) < 10) \
1855             { d = d * T(10) + digit; }     \
1856          else                              \
1857             { break; }                     \
1858          if (end == ++itr) break;          \
1859
1860          #define parse_digit_2(d)          \
1861          if ((digit = (*itr - zero)) < 10) \
1862             { d = d * T(10) + digit; }     \
1863          else { break; }                   \
1864             ++itr;                         \
1865
1866          if ('.' != (*itr))
1867          {
1868             const Iterator curr = itr;
1869
1870             while ((end != itr) && (zero == (*itr))) ++itr;
1871
1872             unsigned int digit;
1873
1874             while (end != itr)
1875             {
1876                // Note: For 'physical' superscalar architectures it
1877                // is advised that the following loop be: 4xPD1 and 1xPD2
1878                #ifdef exprtk_enable_superscalar
1879                parse_digit_1(d)
1880                parse_digit_1(d)
1881                #endif
1882                parse_digit_1(d)
1883                parse_digit_1(d)
1884                parse_digit_2(d)
1885             }
1886
1887             if (curr != itr) instate = true;
1888          }
1889
1890          int exponent = 0;
1891
1892          if (end != itr)
1893          {
1894             if ('.' == (*itr))
1895             {
1896                const Iterator curr = ++itr;
1897                unsigned int digit;
1898                T tmp_d = T(0);
1899
1900                while (end != itr)
1901                {
1902                   #ifdef exprtk_enable_superscalar
1903                   parse_digit_1(tmp_d)
1904                   parse_digit_1(tmp_d)
1905                   parse_digit_1(tmp_d)
1906                   #endif
1907                   parse_digit_1(tmp_d)
1908                   parse_digit_1(tmp_d)
1909                   parse_digit_2(tmp_d)
1910                }
1911
1912                if (curr != itr)
1913                {
1914                   instate = true;
1915                   d += compute_pow10(tmp_d,static_cast<int>(-std::distance(curr,itr)));
1916                }
1917
1918                #undef parse_digit_1
1919                #undef parse_digit_2
1920             }
1921
1922             if (end != itr)
1923             {
1924                typename std::iterator_traits<Iterator>::value_type c = (*itr);
1925
1926                if (('e' == c) || ('E' == c))
1927                {
1928                   int exp = 0;
1929
1930                   if (!details::string_to_type_converter_impl_ref(++itr, end, exp))
1931                   {
1932                      if (end == itr)
1933                         return false;
1934                      else
1935                         c = (*itr);
1936                   }
1937
1938                   exponent += exp;
1939                }
1940
1941                if (end != itr)
1942                {
1943                   if (('f' == c) || ('F' == c) || ('l' == c) || ('L' == c))
1944                      ++itr;
1945                   else if ('#' == c)
1946                   {
1947                      if (end == ++itr)
1948                         return false;
1949                      else if (('I' <= (*itr)) && ((*itr) <= 'n'))
1950                      {
1951                         if (('i' == (*itr)) || ('I' == (*itr)))
1952                         {
1953                            return parse_inf(itr, end, t, negative);
1954                         }
1955                         else if (('n' == (*itr)) || ('N' == (*itr)))
1956                         {
1957                            return parse_nan(itr, end, t);
1958                         }
1959                         else
1960                            return false;
1961                      }
1962                      else
1963                         return false;
1964                   }
1965                   else if (('I' <= (*itr)) && ((*itr) <= 'n'))
1966                   {
1967                      if (('i' == (*itr)) || ('I' == (*itr)))
1968                      {
1969                         return parse_inf(itr, end, t, negative);
1970                      }
1971                      else if (('n' == (*itr)) || ('N' == (*itr)))
1972                      {
1973                         return parse_nan(itr, end, t);
1974                      }
1975                      else
1976                         return false;
1977                   }
1978                   else
1979                      return false;
1980                }
1981             }
1982          }
1983
1984          if ((end != itr) || (!instate))
1985             return false;
1986          else if (exponent)
1987             d = compute_pow10(d,exponent);
1988
1989          t = static_cast<T>((negative) ? -d : d);
1990          return true;
1991       }
1992
1993       template <typename T>
1994       inline bool string_to_real(const std::string& s, T& t)
1995       {
1996          const typename numeric::details::number_type<T>::type num_type;
1997
1998          char_cptr begin = s.data();
1999          char_cptr end   = s.data() + s.size();
2000
2001          return string_to_real(begin, end, t, num_type);
2002       }
2003
2004       template <typename T>
2005       struct functor_t
2006       {
2007          /*
2008             Note: The following definitions for Type, may require tweaking
2009                   based on the compiler and target architecture. The benchmark
2010                   should provide enough information to make the right choice.
2011          */
2012          //typedef T Type;
2013          //typedef const T Type;
2014          typedef const T& Type;
2015          typedef       T& RefType;
2016          typedef T (*qfunc_t)(Type t0, Type t1, Type t2, Type t3);
2017          typedef T (*tfunc_t)(Type t0, Type t1, Type t2);
2018          typedef T (*bfunc_t)(Type t0, Type t1);
2019          typedef T (*ufunc_t)(Type t0);
2020       };
2021
2022    } // namespace details
2023
2024    namespace lexer
2025    {
2026       struct token
2027       {
2028          enum token_type
2029          {
2030             e_none        =   0, e_error       =   1, e_err_symbol  =   2,
2031             e_err_number  =   3, e_err_string  =   4, e_err_sfunc   =   5,
2032             e_eof         =   6, e_number      =   7, e_symbol      =   8,
2033             e_string      =   9, e_assign      =  10, e_addass      =  11,
2034             e_subass      =  12, e_mulass      =  13, e_divass      =  14,
2035             e_modass      =  15, e_shr         =  16, e_shl         =  17,
2036             e_lte         =  18, e_ne          =  19, e_gte         =  20,
2037             e_swap        =  21, e_lt          = '<', e_gt          = '>',
2038             e_eq          = '=', e_rbracket    = ')', e_lbracket    = '(',
2039             e_rsqrbracket = ']', e_lsqrbracket = '[', e_rcrlbracket = '}',
2040             e_lcrlbracket = '{', e_comma       = ',', e_add         = '+',
2041             e_sub         = '-', e_div         = '/', e_mul         = '*',
2042             e_mod         = '%', e_pow         = '^', e_colon       = ':',
2043             e_ternary     = '?'
2044          };
2045
2046          token()
2047          : type(e_none),
2048            value(""),
2049            position(std::numeric_limits<std::size_t>::max())
2050          {}
2051
2052          void clear()
2053          {
2054             type     = e_none;
2055             value    = "";
2056             position = std::numeric_limits<std::size_t>::max();
2057          }
2058
2059          template <typename Iterator>
2060          inline token& set_operator(const token_type tt,
2061                                     const Iterator begin, const Iterator end,
2062                                     const Iterator base_begin = Iterator(0))
2063          {
2064             type = tt;
2065             value.assign(begin,end);
2066             if (base_begin)
2067                position = static_cast<std::size_t>(std::distance(base_begin,begin));
2068             return (*this);
2069          }
2070
2071          template <typename Iterator>
2072          inline token& set_symbol(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
2073          {
2074             type = e_symbol;
2075             value.assign(begin,end);
2076             if (base_begin)
2077                position = static_cast<std::size_t>(std::distance(base_begin,begin));
2078             return (*this);
2079          }
2080
2081          template <typename Iterator>
2082          inline token& set_numeric(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
2083          {
2084             type = e_number;
2085             value.assign(begin,end);
2086             if (base_begin)
2087                position = static_cast<std::size_t>(std::distance(base_begin,begin));
2088             return (*this);
2089          }
2090
2091          template <typename Iterator>
2092          inline token& set_string(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
2093          {
2094             type = e_string;
2095             value.assign(begin,end);
2096             if (base_begin)
2097                position = static_cast<std::size_t>(std::distance(base_begin,begin));
2098             return (*this);
2099          }
2100
2101          inline token& set_string(const std::string& s, const std::size_t p)
2102          {
2103             type     = e_string;
2104             value    = s;
2105             position = p;
2106             return (*this);
2107          }
2108
2109          template <typename Iterator>
2110          inline token& set_error(const token_type et,
2111                                  const Iterator begin, const Iterator end,
2112                                  const Iterator base_begin = Iterator(0))
2113          {
2114             if (
2115                  (e_error      == et) ||
2116                  (e_err_symbol == et) ||
2117                  (e_err_number == et) ||
2118                  (e_err_string == et) ||
2119                  (e_err_sfunc  == et)
2120                )
2121             {
2122                type = et;
2123             }
2124             else
2125                type = e_error;
2126
2127             value.assign(begin,end);
2128
2129             if (base_begin)
2130                position = static_cast<std::size_t>(std::distance(base_begin,begin));
2131
2132             return (*this);
2133          }
2134
2135          static inline std::string to_str(token_type t)
2136          {
2137             switch (t)
2138             {
2139                case e_none        : return "NONE";
2140                case e_error       : return "ERROR";
2141                case e_err_symbol  : return "ERROR_SYMBOL";
2142                case e_err_number  : return "ERROR_NUMBER";
2143                case e_err_string  : return "ERROR_STRING";
2144                case e_eof         : return "EOF";
2145                case e_number      : return "NUMBER";
2146                case e_symbol      : return "SYMBOL";
2147                case e_string      : return "STRING";
2148                case e_assign      : return ":=";
2149                case e_addass      : return "+=";
2150                case e_subass      : return "-=";
2151                case e_mulass      : return "*=";
2152                case e_divass      : return "/=";
2153                case e_modass      : return "%=";
2154                case e_shr         : return ">>";
2155                case e_shl         : return "<<";
2156                case e_lte         : return "<=";
2157                case e_ne          : return "!=";
2158                case e_gte         : return ">=";
2159                case e_lt          : return "<";
2160                case e_gt          : return ">";
2161                case e_eq          : return "=";
2162                case e_rbracket    : return ")";
2163                case e_lbracket    : return "(";
2164                case e_rsqrbracket : return "]";
2165                case e_lsqrbracket : return "[";
2166                case e_rcrlbracket : return "}";
2167                case e_lcrlbracket : return "{";
2168                case e_comma       : return ",";
2169                case e_add         : return "+";
2170                case e_sub         : return "-";
2171                case e_div         : return "/";
2172                case e_mul         : return "*";
2173                case e_mod         : return "%";
2174                case e_pow         : return "^";
2175                case e_colon       : return ":";
2176                case e_ternary     : return "?";
2177                case e_swap        : return "<=>";
2178                default            : return "UNKNOWN";
2179             }
2180          }
2181
2182          inline bool is_error() const
2183          {
2184             return (
2185                      (e_error      == type) ||
2186                      (e_err_symbol == type) ||
2187                      (e_err_number == type) ||
2188                      (e_err_string == type) ||
2189                      (e_err_sfunc  == type)
2190                    );
2191          }
2192
2193          token_type type;
2194          std::string value;
2195          std::size_t position;
2196       };
2197
2198       class generator
2199       {
2200       public:
2201
2202          typedef token token_t;
2203          typedef std::vector<token_t> token_list_t;
2204          typedef std::vector<token_t>::iterator token_list_itr_t;
2205          typedef details::char_t char_t;
2206
2207          generator()
2208          : base_itr_(0),
2209            s_itr_   (0),
2210            s_end_   (0)
2211          {
2212             clear();
2213          }
2214
2215          inline void clear()
2216          {
2217             base_itr_ = 0;
2218             s_itr_    = 0;
2219             s_end_    = 0;
2220             token_list_.clear();
2221             token_itr_ = token_list_.end();
2222             store_token_itr_ = token_list_.end();
2223          }
2224
2225          inline bool process(const std::string& str)
2226          {
2227             base_itr_ = str.data();
2228             s_itr_    = str.data();
2229             s_end_    = str.data() + str.size();
2230
2231             eof_token_.set_operator(token_t::e_eof,s_end_,s_end_,base_itr_);
2232             token_list_.clear();
2233
2234             while (!is_end(s_itr_))
2235             {
2236                scan_token();
2237
2238                if (!token_list_.empty() && token_list_.back().is_error())
2239                   return false;
2240             }
2241
2242             return true;
2243          }
2244
2245          inline bool empty() const
2246          {
2247             return token_list_.empty();
2248          }
2249
2250          inline std::size_t size() const
2251          {
2252             return token_list_.size();
2253          }
2254
2255          inline void begin()
2256          {
2257             token_itr_ = token_list_.begin();
2258             store_token_itr_ = token_list_.begin();
2259          }
2260
2261          inline void store()
2262          {
2263             store_token_itr_ = token_itr_;
2264          }
2265
2266          inline void restore()
2267          {
2268             token_itr_ = store_token_itr_;
2269          }
2270
2271          inline token_t& next_token()
2272          {
2273             if (token_list_.end() != token_itr_)
2274             {
2275                return *token_itr_++;
2276             }
2277             else
2278                return eof_token_;
2279          }
2280
2281          inline token_t& peek_next_token()
2282          {
2283             if (token_list_.end() != token_itr_)
2284             {
2285                return *token_itr_;
2286             }
2287             else
2288                return eof_token_;
2289          }
2290
2291          inline token_t& operator[](const std::size_t& index)
2292          {
2293             if (index < token_list_.size())
2294                return token_list_[index];
2295             else
2296                return eof_token_;
2297          }
2298
2299          inline token_t operator[](const std::size_t& index) const
2300          {
2301             if (index < token_list_.size())
2302                return token_list_[index];
2303             else
2304                return eof_token_;
2305          }
2306
2307          inline bool finished() const
2308          {
2309             return (token_list_.end() == token_itr_);
2310          }
2311
2312          inline void insert_front(token_t::token_type tk_type)
2313          {
2314             if (
2315                  !token_list_.empty() &&
2316                  (token_list_.end() != token_itr_)
2317                )
2318             {
2319                token_t t = *token_itr_;
2320
2321                t.type     = tk_type;
2322                token_itr_ = token_list_.insert(token_itr_,t);
2323             }
2324          }
2325
2326          inline std::string substr(const std::size_t& begin, const std::size_t& end)
2327          {
2328             const details::char_cptr begin_itr = ((base_itr_ + begin) < s_end_) ? (base_itr_ + begin) : s_end_;
2329             const details::char_cptr end_itr   = ((base_itr_ +   end) < s_end_) ? (base_itr_ +   end) : s_end_;
2330
2331             return std::string(begin_itr,end_itr);
2332          }
2333
2334          inline std::string remaining() const
2335          {
2336             if (finished())
2337                return "";
2338             else if (token_list_.begin() != token_itr_)
2339                return std::string(base_itr_ + (token_itr_ - 1)->position, s_end_);
2340             else
2341                return std::string(base_itr_ + token_itr_->position, s_end_);
2342          }
2343
2344       private:
2345
2346          inline bool is_end(details::char_cptr itr)
2347          {
2348             return (s_end_ == itr);
2349          }
2350
2351          inline bool is_comment_start(details::char_cptr itr)
2352          {
2353             #ifndef exprtk_disable_comments
2354             const char_t c0 = *(itr + 0);
2355             const char_t c1 = *(itr + 1);
2356
2357             if ('#' == c0)
2358                return true;
2359             else if (!is_end(itr + 1))
2360             {
2361                if (('/' == c0) && ('/' == c1)) return true;
2362                if (('/' == c0) && ('*' == c1)) return true;
2363             }
2364             #endif
2365             return false;
2366          }
2367
2368          inline void skip_whitespace()
2369          {
2370             while (!is_end(s_itr_) && details::is_whitespace(*s_itr_))
2371             {
2372                ++s_itr_;
2373             }
2374          }
2375
2376          inline void skip_comments()
2377          {
2378             #ifndef exprtk_disable_comments
2379             // The following comment styles are supported:
2380             // 1. // .... \n
2381             // 2. #  .... \n
2382             // 3. /* .... */
2383             struct test
2384             {
2385                static inline bool comment_start(const char_t c0, const char_t c1, int& mode, int& incr)
2386                {
2387                   mode = 0;
2388                        if ('#' == c0)    { mode = 1; incr = 1; }
2389                   else if ('/' == c0)
2390                   {
2391                           if ('/' == c1) { mode = 1; incr = 2; }
2392                      else if ('*' == c1) { mode = 2; incr = 2; }
2393                   }
2394                   return (0 != mode);
2395                }
2396
2397                static inline bool comment_end(const char_t c0, const char_t c1, int& mode)
2398                {
2399                   if (
2400                        ((1 == mode) && ('\n' == c0)) ||
2401                        ((2 == mode) && ( '*' == c0) && ('/' == c1))
2402                      )
2403                   {
2404                      mode = 0;
2405                      return true;
2406                   }
2407                   else
2408                      return false;
2409                }
2410             };
2411
2412             int mode      = 0;
2413             int increment = 0;
2414
2415             if (is_end(s_itr_))
2416                return;
2417             else if (!test::comment_start(*s_itr_, *(s_itr_ + 1), mode, increment))
2418                return;
2419
2420             details::char_cptr cmt_start = s_itr_;
2421
2422             s_itr_ += increment;
2423
2424             while (!is_end(s_itr_))
2425             {
2426                if ((1 == mode) && test::comment_end(*s_itr_, 0, mode))
2427                {
2428                   ++s_itr_;
2429                   return;
2430                }
2431
2432                if ((2 == mode))
2433                {
2434                   if (!is_end((s_itr_ + 1)) && test::comment_end(*s_itr_, *(s_itr_ + 1), mode))
2435                   {
2436                      s_itr_ += 2;
2437                      return;
2438                   }
2439                }
2440
2441                 ++s_itr_;
2442             }
2443
2444             if (2 == mode)
2445             {
2446                token_t t;
2447                t.set_error(token::e_error, cmt_start, cmt_start + mode, base_itr_);
2448                token_list_.push_back(t);
2449             }
2450             #endif
2451          }
2452
2453          inline void scan_token()
2454          {
2455             if (details::is_whitespace(*s_itr_))
2456             {
2457                skip_whitespace();
2458                return;
2459             }
2460             else if (is_comment_start(s_itr_))
2461             {
2462                skip_comments();
2463                return;
2464             }
2465             else if (details::is_operator_char(*s_itr_))
2466             {
2467                scan_operator();
2468                return;
2469             }
2470             else if (details::is_letter(*s_itr_))
2471             {
2472                scan_symbol();
2473                return;
2474             }
2475             else if (details::is_digit((*s_itr_)) || ('.' == (*s_itr_)))
2476             {
2477                scan_number();
2478                return;
2479             }
2480             else if ('$' == (*s_itr_))
2481             {
2482                scan_special_function();
2483                return;
2484             }
2485             #ifndef exprtk_disable_string_capabilities
2486             else if ('\'' == (*s_itr_))
2487             {
2488                scan_string();
2489                return;
2490             }
2491             #endif
2492             else if ('~' == (*s_itr_))
2493             {
2494                token_t t;
2495                t.set_symbol(s_itr_, s_itr_ + 1, base_itr_);
2496                token_list_.push_back(t);
2497                ++s_itr_;
2498                return;
2499             }
2500             else
2501             {
2502                token_t t;
2503                t.set_error(token::e_error, s_itr_, s_itr_ + 2, base_itr_);
2504                token_list_.push_back(t);
2505                ++s_itr_;
2506             }
2507          }
2508
2509          inline void scan_operator()
2510          {
2511             token_t t;
2512
2513             const char_t c0 = s_itr_[0];
2514
2515             if (!is_end(s_itr_ + 1))
2516             {
2517                const char_t c1 = s_itr_[1];
2518
2519                if (!is_end(s_itr_ + 2))
2520                {
2521                   const char_t c2 = s_itr_[2];
2522
2523                   if ((c0 == '<') && (c1 == '=') && (c2 == '>'))
2524                   {
2525                      t.set_operator(token_t::e_swap, s_itr_, s_itr_ + 3, base_itr_);
2526                      token_list_.push_back(t);
2527                      s_itr_ += 3;
2528                      return;
2529                   }
2530                }
2531
2532                token_t::token_type ttype = token_t::e_none;
2533
2534                     if ((c0 == '<') && (c1 == '=')) ttype = token_t::e_lte;
2535                else if ((c0 == '>') && (c1 == '=')) ttype = token_t::e_gte;
2536                else if ((c0 == '<') && (c1 == '>')) ttype = token_t::e_ne;
2537                else if ((c0 == '!') && (c1 == '=')) ttype = token_t::e_ne;
2538                else if ((c0 == '=') && (c1 == '=')) ttype = token_t::e_eq;
2539                else if ((c0 == ':') && (c1 == '=')) ttype = token_t::e_assign;
2540                else if ((c0 == '<') && (c1 == '<')) ttype = token_t::e_shl;
2541                else if ((c0 == '>') && (c1 == '>')) ttype = token_t::e_shr;
2542                else if ((c0 == '+') && (c1 == '=')) ttype = token_t::e_addass;
2543                else if ((c0 == '-') && (c1 == '=')) ttype = token_t::e_subass;
2544                else if ((c0 == '*') && (c1 == '=')) ttype = token_t::e_mulass;
2545                else if ((c0 == '/') && (c1 == '=')) ttype = token_t::e_divass;
2546                else if ((c0 == '%') && (c1 == '=')) ttype = token_t::e_modass;
2547
2548                if (token_t::e_none != ttype)
2549                {
2550                   t.set_operator(ttype, s_itr_, s_itr_ + 2, base_itr_);
2551                   token_list_.push_back(t);
2552                   s_itr_ += 2;
2553                   return;
2554                }
2555             }
2556
2557             if ('<' == c0)
2558                t.set_operator(token_t::e_lt , s_itr_, s_itr_ + 1, base_itr_);
2559             else if ('>' == c0)
2560                t.set_operator(token_t::e_gt , s_itr_, s_itr_ + 1, base_itr_);
2561             else if (';' == c0)
2562                t.set_operator(token_t::e_eof, s_itr_, s_itr_ + 1, base_itr_);
2563             else if ('&' == c0)
2564                t.set_symbol(s_itr_, s_itr_ + 1, base_itr_);
2565             else if ('|' == c0)
2566                t.set_symbol(s_itr_, s_itr_ + 1, base_itr_);
2567             else
2568                t.set_operator(token_t::token_type(c0), s_itr_, s_itr_ + 1, base_itr_);
2569
2570             token_list_.push_back(t);
2571             ++s_itr_;
2572          }
2573
2574          inline void scan_symbol()
2575          {
2576             details::char_cptr initial_itr = s_itr_;
2577
2578             while (!is_end(s_itr_))
2579             {
2580                if (!details::is_letter_or_digit(*s_itr_) && ('_' != (*s_itr_)))
2581                {
2582                   if ('.' != (*s_itr_))
2583                      break;
2584                   /*
2585                      Permit symbols that contain a 'dot'
2586                      Allowed   : abc.xyz, a123.xyz, abc.123, abc_.xyz a123_.xyz abc._123
2587                      Disallowed: .abc, abc.<white-space>, abc.<eof>, abc.<operator +,-,*,/...>
2588                   */
2589                   if (
2590                        (s_itr_ != initial_itr)                     &&
2591                        !is_end(s_itr_ + 1)                         &&
2592                        !details::is_letter_or_digit(*(s_itr_ + 1)) &&
2593                        ('_' != (*(s_itr_ + 1)))
2594                      )
2595                      break;
2596                }
2597
2598                ++s_itr_;
2599             }
2600
2601             token_t t;
2602             t.set_symbol(initial_itr,s_itr_,base_itr_);
2603             token_list_.push_back(t);
2604          }
2605
2606          inline void scan_number()
2607          {
2608             /*
2609                Attempt to match a valid numeric value in one of the following formats:
2610                (01) 123456
2611                (02) 123456.
2612                (03) 123.456
2613                (04) 123.456e3
2614                (05) 123.456E3
2615                (06) 123.456e+3
2616                (07) 123.456E+3
2617                (08) 123.456e-3
2618                (09) 123.456E-3
2619                (00) .1234
2620                (11) .1234e3
2621                (12) .1234E+3
2622                (13) .1234e+3
2623                (14) .1234E-3
2624                (15) .1234e-3
2625             */
2626
2627             details::char_cptr initial_itr = s_itr_;
2628             bool dot_found                 = false;
2629             bool e_found                   = false;
2630             bool post_e_sign_found         = false;
2631             bool post_e_digit_found        = false;
2632             token_t t;
2633
2634             while (!is_end(s_itr_))
2635             {
2636                if ('.' == (*s_itr_))
2637                {
2638                   if (dot_found)
2639                   {
2640                      t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
2641                      token_list_.push_back(t);
2642                      return;
2643                   }
2644
2645                   dot_found = true;
2646                   ++s_itr_;
2647
2648                   continue;
2649                }
2650                else if ('e' == std::tolower(*s_itr_))
2651                {
2652                   const char_t& c = *(s_itr_ + 1);
2653
2654                   if (is_end(s_itr_ + 1))
2655                   {
2656                      t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
2657                      token_list_.push_back(t);
2658
2659                      return;
2660                   }
2661                   else if (
2662                             ('+' != c) &&
2663                             ('-' != c) &&
2664                             !details::is_digit(c)
2665                           )
2666                   {
2667                      t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
2668                      token_list_.push_back(t);
2669
2670                      return;
2671                   }
2672
2673                   e_found = true;
2674                   ++s_itr_;
2675
2676                   continue;
2677                }
2678                else if (e_found && details::is_sign(*s_itr_) && !post_e_digit_found)
2679                {
2680                   if (post_e_sign_found)
2681                   {
2682                      t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
2683                      token_list_.push_back(t);
2684
2685                      return;
2686                   }
2687
2688                   post_e_sign_found = true;
2689                   ++s_itr_;
2690
2691                   continue;
2692                }
2693                else if (e_found && details::is_digit(*s_itr_))
2694                {
2695                   post_e_digit_found = true;
2696                   ++s_itr_;
2697
2698                   continue;
2699                }
2700                else if (('.' != (*s_itr_)) && !details::is_digit(*s_itr_))
2701                   break;
2702                else
2703                   ++s_itr_;
2704             }
2705
2706             t.set_numeric(initial_itr, s_itr_, base_itr_);
2707             token_list_.push_back(t);
2708
2709             return;
2710          }
2711
2712          inline void scan_special_function()
2713          {
2714             details::char_cptr initial_itr = s_itr_;
2715             token_t t;
2716
2717             // $fdd(x,x,x) = at least 11 chars
2718             if (std::distance(s_itr_,s_end_) < 11)
2719             {
2720                t.set_error(token::e_err_sfunc, initial_itr, s_itr_, base_itr_);
2721                token_list_.push_back(t);
2722
2723                return;
2724             }
2725
2726             if (
2727                  !(('$' == *s_itr_)                       &&
2728                    (details::imatch  ('f',*(s_itr_ + 1))) &&
2729                    (details::is_digit(*(s_itr_ + 2)))     &&
2730                    (details::is_digit(*(s_itr_ + 3))))
2731                )
2732             {
2733                t.set_error(token::e_err_sfunc, initial_itr, s_itr_, base_itr_);
2734                token_list_.push_back(t);
2735
2736                return;
2737             }
2738
2739             s_itr_ += 4; // $fdd = 4chars
2740
2741             t.set_symbol(initial_itr, s_itr_, base_itr_);
2742             token_list_.push_back(t);
2743
2744             return;
2745          }
2746
2747          #ifndef exprtk_disable_string_capabilities
2748          inline void scan_string()
2749          {
2750             details::char_cptr initial_itr = s_itr_ + 1;
2751             token_t t;
2752
2753             if (std::distance(s_itr_,s_end_) < 2)
2754             {
2755                t.set_error(token::e_err_string, s_itr_, s_end_, base_itr_);
2756                token_list_.push_back(t);
2757                return;
2758             }
2759
2760             ++s_itr_;
2761
2762             bool escaped_found = false;
2763             bool escaped = false;
2764
2765             while (!is_end(s_itr_))
2766             {
2767                if (!escaped && ('\\' == *s_itr_))
2768                {
2769                   escaped_found = true;
2770                   escaped = true;
2771                   ++s_itr_;
2772
2773                   continue;
2774                }
2775                else if (!escaped)
2776                {
2777                   if ('\'' == *s_itr_)
2778                      break;
2779                }
2780                else if (escaped)
2781                {
2782                   if (!is_end(s_itr_) && ('0' == *(s_itr_)))
2783                   {
2784                      /*
2785                         Note: The following 'awkward' conditional is
2786                               due to various broken msvc compilers.
2787                      */
2788                      #if defined(_MSC_VER) && (_MSC_VER == 1600)
2789                      const bool within_range = !is_end(s_itr_ + 2) &&
2790                                                !is_end(s_itr_ + 3) ;
2791                      #else
2792                      const bool within_range = !is_end(s_itr_ + 1) &&
2793                                                !is_end(s_itr_ + 2) &&
2794                                                !is_end(s_itr_ + 3) ;
2795                      #endif
2796
2797                      const bool x_seperator  = ('x' == *(s_itr_ + 1)) ||
2798                                                ('X' == *(s_itr_ + 1)) ;
2799
2800                      const bool both_digits  = details::is_hex_digit(*(s_itr_ + 2)) &&
2801                                                details::is_hex_digit(*(s_itr_ + 3)) ;
2802
2803                      if (!within_range || !x_seperator || !both_digits)
2804                      {
2805                         t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_);
2806                         token_list_.push_back(t);
2807
2808                         return;
2809                      }
2810                      else
2811                         s_itr_ += 3;
2812                   }
2813
2814                   escaped = false;
2815                }
2816
2817                ++s_itr_;
2818             }
2819
2820             if (is_end(s_itr_))
2821             {
2822                t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_);
2823                token_list_.push_back(t);
2824
2825                return;
2826             }
2827
2828             if (!escaped_found)
2829                t.set_string(initial_itr, s_itr_, base_itr_);
2830             else
2831             {
2832                std::string parsed_string(initial_itr,s_itr_);
2833
2834                details::cleanup_escapes(parsed_string);
2835
2836                t.set_string(
2837                     parsed_string,
2838                     static_cast<std::size_t>(std::distance(base_itr_,initial_itr)));
2839             }
2840
2841             token_list_.push_back(t);
2842             ++s_itr_;
2843
2844             return;
2845          }
2846          #endif
2847
2848       private:
2849
2850          token_list_t     token_list_;
2851          token_list_itr_t token_itr_;
2852          token_list_itr_t store_token_itr_;
2853          token_t eof_token_;
2854          details::char_cptr base_itr_;
2855          details::char_cptr s_itr_;
2856          details::char_cptr s_end_;
2857
2858          friend class token_scanner;
2859          friend class token_modifier;
2860          friend class token_inserter;
2861          friend class token_joiner;
2862       };
2863
2864       class helper_interface
2865       {
2866       public:
2867
2868          virtual void init()                     {              }
2869          virtual void reset()                    {              }
2870          virtual bool result()                   { return true; }
2871          virtual std::size_t process(generator&) { return 0;    }
2872          virtual ~helper_interface()             {              }
2873       };
2874
2875       class token_scanner : public helper_interface
2876       {
2877       public:
2878
2879          virtual ~token_scanner()
2880          {}
2881
2882          explicit token_scanner(const std::size_t& stride)
2883          : stride_(stride)
2884          {
2885             if (stride > 4)
2886             {
2887                throw std::invalid_argument("token_scanner() - Invalid stride value");
2888             }
2889          }
2890
2891          inline std::size_t process(generator& g)
2892          {
2893             if (g.token_list_.size() >= stride_)
2894             {
2895                for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i)
2896                {
2897                   token t;
2898
2899                   switch (stride_)
2900                   {
2901                      case 1 :
2902                               {
2903                                  const token& t0 = g.token_list_[i];
2904
2905                                  if (!operator()(t0))
2906                                  {
2907                                     return i;
2908                                  }
2909                               }
2910                               break;
2911
2912                      case 2 :
2913                               {
2914                                  const token& t0 = g.token_list_[i    ];
2915                                  const token& t1 = g.token_list_[i + 1];
2916
2917                                  if (!operator()(t0, t1))
2918                                  {
2919                                     return i;
2920                                  }
2921                               }
2922                               break;
2923
2924                      case 3 :
2925                               {
2926                                  const token& t0 = g.token_list_[i    ];
2927                                  const token& t1 = g.token_list_[i + 1];
2928                                  const token& t2 = g.token_list_[i + 2];
2929
2930                                  if (!operator()(t0, t1, t2))
2931                                  {
2932                                     return i;
2933                                  }
2934                               }
2935                               break;
2936
2937                      case 4 :
2938                               {
2939                                  const token& t0 = g.token_list_[i    ];
2940                                  const token& t1 = g.token_list_[i + 1];
2941                                  const token& t2 = g.token_list_[i + 2];
2942                                  const token& t3 = g.token_list_[i + 3];
2943
2944                                  if (!operator()(t0, t1, t2, t3))
2945                                  {
2946                                     return i;
2947                                  }
2948                               }
2949                               break;
2950                   }
2951                }
2952             }
2953
2954             return (g.token_list_.size() - stride_ + 1);
2955          }
2956
2957          virtual bool operator() (const token&)
2958          {
2959             return false;
2960          }
2961
2962          virtual bool operator() (const token&, const token&)
2963          {
2964             return false;
2965          }
2966
2967          virtual bool operator() (const token&, const token&, const token&)
2968          {
2969             return false;
2970          }
2971
2972          virtual bool operator() (const token&, const token&, const token&, const token&)
2973          {
2974             return false;
2975          }
2976
2977       private:
2978
2979          const std::size_t stride_;
2980       };
2981
2982       class token_modifier : public helper_interface
2983       {
2984       public:
2985
2986          inline std::size_t process(generator& g)
2987          {
2988             std::size_t changes = 0;
2989
2990             for (std::size_t i = 0; i < g.token_list_.size(); ++i)
2991             {
2992                if (modify(g.token_list_[i])) changes++;
2993             }
2994
2995             return changes;
2996          }
2997
2998          virtual bool modify(token& t) = 0;
2999       };
3000
3001       class token_inserter : public helper_interface
3002       {
3003       public:
3004
3005          explicit token_inserter(const std::size_t& stride)
3006          : stride_(stride)
3007          {
3008             if (stride > 5)
3009             {
3010                throw std::invalid_argument("token_inserter() - Invalid stride value");
3011             }
3012          }
3013
3014          inline std::size_t process(generator& g)
3015          {
3016             if (g.token_list_.empty())
3017                return 0;
3018             else if (g.token_list_.size() < stride_)
3019                return 0;
3020
3021             std::size_t changes = 0;
3022
3023             for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i)
3024             {
3025                int insert_index = -1;
3026                token t;
3027
3028                switch (stride_)
3029                {
3030                   case 1 : insert_index = insert(g.token_list_[i],t);
3031                            break;
3032
3033                   case 2 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], t);
3034                            break;
3035
3036                   case 3 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], g.token_list_[i + 2], t);
3037                            break;
3038
3039                   case 4 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], g.token_list_[i + 2], g.token_list_[i + 3], t);
3040                            break;
3041
3042                   case 5 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], g.token_list_[i + 2], g.token_list_[i + 3], g.token_list_[i + 4], t);
3043                            break;
3044                }
3045
3046                typedef std::iterator_traits<generator::token_list_t::iterator>::difference_type diff_t;
3047
3048                if ((insert_index >= 0) && (insert_index <= (static_cast<int>(stride_) + 1)))
3049                {
3050                   g.token_list_.insert(
3051                      g.token_list_.begin() + static_cast<diff_t>(i + static_cast<std::size_t>(insert_index)), t);
3052
3053                   changes++;
3054                }
3055             }
3056
3057             return changes;
3058          }
3059
3060          #define token_inserter_empty_body \
3061          {                                 \
3062             return -1;                     \
3063          }                                 \
3064
3065          inline virtual int insert(const token&, token&)
3066          token_inserter_empty_body
3067
3068          inline virtual int insert(const token&, const token&, token&)
3069          token_inserter_empty_body
3070
3071          inline virtual int insert(const token&, const token&, const token&, token&)
3072          token_inserter_empty_body
3073
3074          inline virtual int insert(const token&, const token&, const token&, const token&, token&)
3075          token_inserter_empty_body
3076
3077          inline virtual int insert(const token&, const token&, const token&, const token&, const token&, token&)
3078          token_inserter_empty_body
3079
3080          #undef token_inserter_empty_body
3081
3082       private:
3083
3084          const std::size_t stride_;
3085       };
3086
3087       class token_joiner : public helper_interface
3088       {
3089       public:
3090
3091          explicit token_joiner(const std::size_t& stride)
3092          : stride_(stride)
3093          {}
3094
3095          inline std::size_t process(generator& g)
3096          {
3097             if (g.token_list_.empty())
3098                return 0;
3099
3100             switch (stride_)
3101             {
3102                case 2  : return process_stride_2(g);
3103                case 3  : return process_stride_3(g);
3104                default : return 0;
3105             }
3106          }
3107
3108          virtual bool join(const token&, const token&, token&)               { return false; }
3109          virtual bool join(const token&, const token&, const token&, token&) { return false; }
3110
3111       private:
3112
3113          inline std::size_t process_stride_2(generator& g)
3114          {
3115             typedef std::iterator_traits<generator::token_list_t::iterator>::difference_type diff_t;
3116
3117             if (g.token_list_.size() < 2)
3118                return 0;
3119
3120             std::size_t changes = 0;
3121
3122             for (int i = 0;  i < static_cast<int>(g.token_list_.size() - 1); ++i)
3123             {
3124                token t;
3125
3126                while (join(g[i], g[i + 1], t))
3127                {
3128                   g.token_list_[i] = t;
3129
3130                   g.token_list_.erase(g.token_list_.begin() + static_cast<diff_t>(i + 1));
3131
3132                   ++changes;
3133
3134                   if (static_cast<std::size_t>(i + 1) >= g.token_list_.size())
3135                      break;
3136                }
3137             }
3138
3139             return changes;
3140          }
3141
3142          inline std::size_t process_stride_3(generator& g)
3143          {
3144             typedef std::iterator_traits<generator::token_list_t::iterator>::difference_type diff_t;
3145
3146             if (g.token_list_.size() < 3)
3147                return 0;
3148
3149             std::size_t changes = 0;
3150
3151             for (int i = 0;  i < static_cast<int>(g.token_list_.size() - 2); ++i)
3152             {
3153                token t;
3154
3155                while (join(g[i], g[i + 1], g[i + 2], t))
3156                {
3157                   g.token_list_[i] = t;
3158
3159                   g.token_list_.erase(g.token_list_.begin() + static_cast<diff_t>(i + 1),
3160                                       g.token_list_.begin() + static_cast<diff_t>(i + 3));
3161                   ++changes;
3162
3163                   if (static_cast<std::size_t>(i + 2) >= g.token_list_.size())
3164                      break;
3165                }
3166             }
3167
3168             return changes;
3169          }
3170
3171          const std::size_t stride_;
3172       };
3173
3174       namespace helper
3175       {
3176
3177          inline void dump(lexer::generator& generator)
3178          {
3179             for (std::size_t i = 0; i < generator.size(); ++i)
3180             {
3181                lexer::token t = generator[i];
3182                printf("Token[%02d] @ %03d  %6s  -->  '%s'\n",
3183                       static_cast<int>(i),
3184                       static_cast<int>(t.position),
3185                       t.to_str(t.type).c_str(),
3186                       t.value.c_str());
3187             }
3188          }
3189
3190          class commutative_inserter : public lexer::token_inserter
3191          {
3192          public:
3193
3194             using lexer::token_inserter::insert;
3195
3196             commutative_inserter()
3197             : lexer::token_inserter(2)
3198             {}
3199
3200             inline void ignore_symbol(const std::string& symbol)
3201             {
3202                ignore_set_.insert(symbol);
3203             }
3204
3205             inline int insert(const lexer::token& t0, const lexer::token& t1, lexer::token& new_token)
3206             {
3207                bool match         = false;
3208                new_token.type     = lexer::token::e_mul;
3209                new_token.value    = "*";
3210                new_token.position = t1.position;
3211
3212                if (t0.type == lexer::token::e_symbol)
3213                {
3214                   if (ignore_set_.end() != ignore_set_.find(t0.value))
3215                   {
3216                      return -1;
3217                   }
3218                   else if (!t0.value.empty() && ('$' == t0.value[0]))
3219                   {
3220                      return -1;
3221                   }
3222                }
3223
3224                if (t1.type == lexer::token::e_symbol)
3225                {
3226                   if (ignore_set_.end() != ignore_set_.find(t1.value))
3227                   {
3228                      return -1;
3229                   }
3230                }
3231                     if ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_symbol     )) match = true;
3232                else if ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_lbracket   )) match = true;
3233                else if ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_lcrlbracket)) match = true;
3234                else if ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_lsqrbracket)) match = true;
3235                else if ((t0.type == lexer::token::e_symbol     ) && (t1.type == lexer::token::e_number     )) match = true;
3236                else if ((t0.type == lexer::token::e_rbracket   ) && (t1.type == lexer::token::e_number     )) match = true;
3237                else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_number     )) match = true;
3238                else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_number     )) match = true;
3239                else if ((t0.type == lexer::token::e_rbracket   ) && (t1.type == lexer::token::e_symbol     )) match = true;
3240                else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_symbol     )) match = true;
3241                else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_symbol     )) match = true;
3242                else if ((t0.type == lexer::token::e_symbol     ) && (t1.type == lexer::token::e_symbol     )) match = true;
3243
3244                return (match) ? 1 : -1;
3245             }
3246
3247          private:
3248
3249             std::set<std::string,details::ilesscompare> ignore_set_;
3250          };
3251
3252          class operator_joiner : public token_joiner
3253          {
3254          public:
3255
3256             explicit operator_joiner(const std::size_t& stride)
3257             : token_joiner(stride)
3258             {}
3259
3260             inline bool join(const lexer::token& t0, const lexer::token& t1, lexer::token& t)
3261             {
3262                // ': =' --> ':='
3263                if ((t0.type == lexer::token::e_colon) && (t1.type == lexer::token::e_eq))
3264                {
3265                   t.type     = lexer::token::e_assign;
3266                   t.value    = ":=";
3267                   t.position = t0.position;
3268
3269                   return true;
3270                }
3271                // '+ =' --> '+='
3272                else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_eq))
3273                {
3274                   t.type     = lexer::token::e_addass;
3275                   t.value    = "+=";
3276                   t.position = t0.position;
3277
3278                   return true;
3279                }
3280                // '- =' --> '-='
3281                else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_eq))
3282                {
3283                   t.type     = lexer::token::e_subass;
3284                   t.value    = "-=";
3285                   t.position = t0.position;
3286
3287                   return true;
3288                }
3289                // '* =' --> '*='
3290                else if ((t0.type == lexer::token::e_mul) && (t1.type == lexer::token::e_eq))
3291                {
3292                   t.type     = lexer::token::e_mulass;
3293                   t.value    = "*=";
3294                   t.position = t0.position;
3295
3296                   return true;
3297                }
3298                // '/ =' --> '/='
3299                else if ((t0.type == lexer::token::e_div) && (t1.type == lexer::token::e_eq))
3300                {
3301                   t.type     = lexer::token::e_divass;
3302                   t.value    = "/=";
3303                   t.position = t0.position;
3304
3305                   return true;
3306                }
3307                // '% =' --> '%='
3308                else if ((t0.type == lexer::token::e_mod) && (t1.type == lexer::token::e_eq))
3309                {
3310                   t.type     = lexer::token::e_modass;
3311                   t.value    = "%=";
3312                   t.position = t0.position;
3313
3314                   return true;
3315                }
3316                // '> =' --> '>='
3317                else if ((t0.type == lexer::token::e_gt) && (t1.type == lexer::token::e_eq))
3318                {
3319                   t.type     = lexer::token::e_gte;
3320                   t.value    = ">=";
3321                   t.position = t0.position;
3322
3323                   return true;
3324                }
3325                // '< =' --> '<='
3326                else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_eq))
3327                {
3328                   t.type     = lexer::token::e_lte;
3329                   t.value    = "<=";
3330                   t.position = t0.position;
3331
3332                   return true;
3333                }
3334                // '= =' --> '=='
3335                else if ((t0.type == lexer::token::e_eq) && (t1.type == lexer::token::e_eq))
3336                {
3337                   t.type     = lexer::token::e_eq;
3338                   t.value    = "==";
3339                   t.position = t0.position;
3340
3341                   return true;
3342                }
3343                // '! =' --> '!='
3344                else if ((static_cast<char>(t0.type) == '!') && (t1.type == lexer::token::e_eq))
3345                {
3346                   t.type     = lexer::token::e_ne;
3347                   t.value    = "!=";
3348                   t.position = t0.position;
3349
3350                   return true;
3351                }
3352                // '< >' --> '<>'
3353                else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_gt))
3354                {
3355                   t.type     = lexer::token::e_ne;
3356                   t.value    = "<>";
3357                   t.position = t0.position;
3358
3359                   return true;
3360                }
3361                // '<= >' --> '<=>'
3362                else if ((t0.type == lexer::token::e_lte) && (t1.type == lexer::token::e_gt))
3363                {
3364                   t.type     = lexer::token::e_swap;
3365                   t.value    = "<=>";
3366                   t.position = t0.position;
3367
3368                   return true;
3369                }
3370                // '+ -' --> '-'
3371                else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_sub))
3372                {
3373                   t.type     = lexer::token::e_sub;
3374                   t.value    = "-";
3375                   t.position = t0.position;
3376
3377                   return true;
3378                }
3379                // '- +' --> '-'
3380                else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_add))
3381                {
3382                   t.type     = lexer::token::e_sub;
3383                   t.value    = "-";
3384                   t.position = t0.position;
3385
3386                   return true;
3387                }
3388                // '- -' --> '+'
3389                else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_sub))
3390                {
3391                   /*
3392                      Note: May need to reconsider this when wanting to implement
3393                      pre/postfix decrement operator
3394                   */
3395                   t.type     = lexer::token::e_add;
3396                   t.value    = "+";
3397                   t.position = t0.position;
3398
3399                   return true;
3400                }
3401                else
3402                   return false;
3403             }
3404
3405             inline bool join(const lexer::token& t0, const lexer::token& t1, const lexer::token& t2, lexer::token& t)
3406             {
3407                // '[ * ]' --> '[*]'
3408                if (
3409                     (t0.type == lexer::token::e_lsqrbracket) &&
3410                     (t1.type == lexer::token::e_mul        ) &&
3411                     (t2.type == lexer::token::e_rsqrbracket)
3412                   )
3413                {
3414                   t.type     = lexer::token::e_symbol;
3415                   t.value    = "[*]";
3416                   t.position = t0.position;
3417
3418                   return true;
3419                }
3420                else
3421                   return false;
3422             }
3423          };
3424
3425          class bracket_checker : public lexer::token_scanner
3426          {
3427          public:
3428
3429             using lexer::token_scanner::operator();
3430
3431             bracket_checker()
3432             : token_scanner(1),
3433               state_(true)
3434             {}
3435
3436             bool result()
3437             {
3438                if (!stack_.empty())
3439                {
3440                   lexer::token t;
3441                   t.value      = stack_.top().first;
3442                   t.position   = stack_.top().second;
3443                   error_token_ = t;
3444                   state_       = false;
3445
3446                   return false;
3447                }
3448                else
3449                   return state_;
3450             }
3451
3452             lexer::token error_token()
3453             {
3454                return error_token_;
3455             }
3456
3457             void reset()
3458             {
3459                // Why? because msvc doesn't support swap properly.
3460                stack_ = std::stack<std::pair<char,std::size_t> >();
3461                state_ = true;
3462                error_token_.clear();
3463             }
3464
3465             bool operator() (const lexer::token& t)
3466             {
3467                if (
3468                     !t.value.empty()                       &&
3469                     (lexer::token::e_string != t.type)     &&
3470                     (lexer::token::e_symbol != t.type)     &&
3471                     exprtk::details::is_bracket(t.value[0])
3472                   )
3473                {
3474                   details::char_t c = t.value[0];
3475
3476                        if (t.type == lexer::token::e_lbracket   ) stack_.push(std::make_pair(')',t.position));
3477                   else if (t.type == lexer::token::e_lcrlbracket) stack_.push(std::make_pair('}',t.position));
3478                   else if (t.type == lexer::token::e_lsqrbracket) stack_.push(std::make_pair(']',t.position));
3479                   else if (exprtk::details::is_right_bracket(c))
3480                   {
3481                      if (stack_.empty())
3482                      {
3483                         state_       = false;
3484                         error_token_ = t;
3485
3486                         return false;
3487                      }
3488                      else if (c != stack_.top().first)
3489                      {
3490                         state_       = false;
3491                         error_token_ = t;
3492
3493                         return false;
3494                      }
3495                      else
3496                         stack_.pop();
3497                   }
3498                }
3499
3500                return true;
3501             }
3502
3503          private:
3504
3505             bool state_;
3506             std::stack<std::pair<char,std::size_t> > stack_;
3507             lexer::token error_token_;
3508          };
3509
3510          class numeric_checker : public lexer::token_scanner
3511          {
3512          public:
3513
3514             using lexer::token_scanner::operator();
3515
3516             numeric_checker()
3517             : token_scanner (1),
3518               current_index_(0)
3519             {}
3520
3521             bool result()
3522             {
3523                return error_list_.empty();
3524             }
3525
3526             void reset()
3527             {
3528                error_list_.clear();
3529                current_index_ = 0;
3530             }
3531
3532             bool operator() (const lexer::token& t)
3533             {
3534                if (token::e_number == t.type)
3535                {
3536                   double v;
3537
3538                   if (!exprtk::details::string_to_real(t.value,v))
3539                   {
3540                      error_list_.push_back(current_index_);
3541                   }
3542                }
3543
3544                ++current_index_;
3545
3546                return true;
3547             }
3548
3549             std::size_t error_count() const
3550             {
3551                return error_list_.size();
3552             }
3553
3554             std::size_t error_index(const std::size_t& i)
3555             {
3556                if (i < error_list_.size())
3557                   return error_list_[i];
3558                else
3559                   return std::numeric_limits<std::size_t>::max();
3560             }
3561
3562             void clear_errors()
3563             {
3564                error_list_.clear();
3565             }
3566
3567          private:
3568
3569             std::size_t current_index_;
3570             std::vector<std::size_t> error_list_;
3571          };
3572
3573          class symbol_replacer : public lexer::token_modifier
3574          {
3575          private:
3576
3577             typedef std::map<std::string,std::pair<std::string,token::token_type>,details::ilesscompare> replace_map_t;
3578
3579          public:
3580
3581             bool remove(const std::string& target_symbol)
3582             {
3583                const replace_map_t::iterator itr = replace_map_.find(target_symbol);
3584
3585                if (replace_map_.end() == itr)
3586                   return false;
3587
3588                replace_map_.erase(itr);
3589
3590                return true;
3591             }
3592
3593             bool add_replace(const std::string& target_symbol,
3594                              const std::string& replace_symbol,
3595                              const lexer::token::token_type token_type = lexer::token::e_symbol)
3596             {
3597                const replace_map_t::iterator itr = replace_map_.find(target_symbol);
3598
3599                if (replace_map_.end() != itr)
3600                {
3601                   return false;
3602                }
3603
3604                replace_map_[target_symbol] = std::make_pair(replace_symbol,token_type);
3605
3606                return true;
3607             }
3608
3609             void clear()
3610             {
3611                replace_map_.clear();
3612             }
3613
3614          private:
3615
3616             bool modify(lexer::token& t)
3617             {
3618                if (lexer::token::e_symbol == t.type)
3619                {
3620                   if (replace_map_.empty())
3621                      return false;
3622
3623                   const replace_map_t::iterator itr = replace_map_.find(t.value);
3624
3625                   if (replace_map_.end() != itr)
3626                   {
3627                      t.value = itr->second.first;
3628                      t.type  = itr->second.second;
3629
3630                      return true;
3631                   }
3632                }
3633
3634                return false;
3635             }
3636
3637             replace_map_t replace_map_;
3638          };
3639
3640          class sequence_validator : public lexer::token_scanner
3641          {
3642          private:
3643
3644             typedef std::pair<lexer::token::token_type,lexer::token::token_type> token_pair_t;
3645             typedef std::set<token_pair_t> set_t;
3646
3647          public:
3648
3649             using lexer::token_scanner::operator();
3650
3651             sequence_validator()
3652             : lexer::token_scanner(2)
3653             {
3654                add_invalid(lexer::token::e_number, lexer::token::e_number);
3655                add_invalid(lexer::token::e_string, lexer::token::e_string);
3656                add_invalid(lexer::token::e_number, lexer::token::e_string);
3657                add_invalid(lexer::token::e_string, lexer::token::e_number);
3658
3659                add_invalid_set1(lexer::token::e_assign );
3660                add_invalid_set1(lexer::token::e_shr    );
3661                add_invalid_set1(lexer::token::e_shl    );
3662                add_invalid_set1(lexer::token::e_lte    );
3663                add_invalid_set1(lexer::token::e_ne     );
3664                add_invalid_set1(lexer::token::e_gte    );
3665                add_invalid_set1(lexer::token::e_lt     );
3666                add_invalid_set1(lexer::token::e_gt     );
3667                add_invalid_set1(lexer::token::e_eq     );
3668                add_invalid_set1(lexer::token::e_comma  );
3669                add_invalid_set1(lexer::token::e_add    );
3670                add_invalid_set1(lexer::token::e_sub    );
3671                add_invalid_set1(lexer::token::e_div    );
3672                add_invalid_set1(lexer::token::e_mul    );
3673                add_invalid_set1(lexer::token::e_mod    );
3674                add_invalid_set1(lexer::token::e_pow    );
3675                add_invalid_set1(lexer::token::e_colon  );
3676                add_invalid_set1(lexer::token::e_ternary);
3677             }
3678
3679             bool result()
3680             {
3681                return error_list_.empty();
3682             }
3683
3684             bool operator() (const lexer::token& t0, const lexer::token& t1)
3685             {
3686                const set_t::value_type p = std::make_pair(t0.type,t1.type);
3687
3688                if (invalid_bracket_check(t0.type,t1.type))
3689                {
3690                   error_list_.push_back(std::make_pair(t0,t1));
3691                }
3692                else if (invalid_comb_.find(p) != invalid_comb_.end())
3693                {
3694                   error_list_.push_back(std::make_pair(t0,t1));
3695                }
3696
3697                return true;
3698             }
3699
3700             std::size_t error_count() const
3701             {
3702                return error_list_.size();
3703             }
3704
3705             std::pair<lexer::token,lexer::token> error(const std::size_t index)
3706             {
3707                if (index < error_list_.size())
3708                {
3709                   return error_list_[index];
3710                }
3711                else
3712                {
3713                   static const lexer::token error_token;
3714                   return std::make_pair(error_token,error_token);
3715                }
3716             }
3717
3718             void clear_errors()
3719             {
3720                error_list_.clear();
3721             }
3722
3723          private:
3724
3725             void add_invalid(lexer::token::token_type base, lexer::token::token_type t)
3726             {
3727                invalid_comb_.insert(std::make_pair(base,t));
3728             }
3729
3730             void add_invalid_set1(lexer::token::token_type t)
3731             {
3732                add_invalid(t, lexer::token::e_assign);
3733                add_invalid(t, lexer::token::e_shr   );
3734                add_invalid(t, lexer::token::e_shl   );
3735                add_invalid(t, lexer::token::e_lte   );
3736                add_invalid(t, lexer::token::e_ne    );
3737                add_invalid(t, lexer::token::e_gte   );
3738                add_invalid(t, lexer::token::e_lt    );
3739                add_invalid(t, lexer::token::e_gt    );
3740                add_invalid(t, lexer::token::e_eq    );
3741                add_invalid(t, lexer::token::e_comma );
3742                add_invalid(t, lexer::token::e_div   );
3743                add_invalid(t, lexer::token::e_mul   );
3744                add_invalid(t, lexer::token::e_mod   );
3745                add_invalid(t, lexer::token::e_pow   );
3746                add_invalid(t, lexer::token::e_colon );
3747             }
3748
3749             bool invalid_bracket_check(lexer::token::token_type base, lexer::token::token_type t)
3750             {
3751                if (details::is_right_bracket(static_cast<char>(base)))
3752                {
3753                   switch (t)
3754                   {
3755                      case lexer::token::e_assign : return (']' != base);
3756                      case lexer::token::e_string : return (')' != base);
3757                      default                     : return false;
3758                   }
3759                }
3760                else if (details::is_left_bracket(static_cast<char>(base)))
3761                {
3762                   if (details::is_right_bracket(static_cast<char>(t)))
3763                      return false;
3764                   else if (details::is_left_bracket(static_cast<char>(t)))
3765                      return false;
3766                   else
3767                   {
3768                      switch (t)
3769                      {
3770                         case lexer::token::e_number  : return false;
3771                         case lexer::token::e_symbol  : return false;
3772                         case lexer::token::e_string  : return false;
3773                         case lexer::token::e_add     : return false;
3774                         case lexer::token::e_sub     : return false;
3775                         case lexer::token::e_colon   : return false;
3776                         case lexer::token::e_ternary : return false;
3777                         default                      : return true ;
3778                      }
3779                   }
3780                }
3781                else if (details::is_right_bracket(static_cast<char>(t)))
3782                {
3783                   switch (base)
3784                   {
3785                      case lexer::token::e_number  : return false;
3786                      case lexer::token::e_symbol  : return false;
3787                      case lexer::token::e_string  : return false;
3788                      case lexer::token::e_eof     : return false;
3789                      case lexer::token::e_colon   : return false;
3790                      case lexer::token::e_ternary : return false;
3791                      default                      : return true ;
3792                   }
3793                }
3794                else if (details::is_left_bracket(static_cast<char>(t)))
3795                {
3796                   switch (base)
3797                   {
3798                      case lexer::token::e_rbracket    : return true;
3799                      case lexer::token::e_rsqrbracket : return true;
3800                      case lexer::token::e_rcrlbracket : return true;
3801                      default                          : return false;
3802                   }
3803                }
3804
3805                return false;
3806             }
3807
3808             set_t invalid_comb_;
3809             std::vector<std::pair<lexer::token,lexer::token> > error_list_;
3810          };
3811
3812          class sequence_validator_3tokens : public lexer::token_scanner
3813          {
3814          private:
3815
3816             typedef lexer::token::token_type token_t;
3817             typedef std::pair<token_t,std::pair<token_t,token_t> > token_triplet_t;
3818             typedef std::set<token_triplet_t> set_t;
3819
3820          public:
3821
3822             using lexer::token_scanner::operator();
3823
3824             sequence_validator_3tokens()
3825             : lexer::token_scanner(3)
3826             {
3827                add_invalid(lexer::token::e_number, lexer::token::e_number, lexer::token::e_number);
3828                add_invalid(lexer::token::e_string, lexer::token::e_string, lexer::token::e_string);
3829                add_invalid(lexer::token::e_comma , lexer::token::e_comma , lexer::token::e_comma );
3830
3831                add_invalid(lexer::token::e_add   , lexer::token::e_add   , lexer::token::e_add   );
3832                add_invalid(lexer::token::e_sub   , lexer::token::e_sub   , lexer::token::e_sub   );
3833                add_invalid(lexer::token::e_div   , lexer::token::e_div   , lexer::token::e_div   );
3834                add_invalid(lexer::token::e_mul   , lexer::token::e_mul   , lexer::token::e_mul   );
3835                add_invalid(lexer::token::e_mod   , lexer::token::e_mod   , lexer::token::e_mod   );
3836                add_invalid(lexer::token::e_pow   , lexer::token::e_pow   , lexer::token::e_pow   );
3837
3838                add_invalid(lexer::token::e_add   , lexer::token::e_sub   , lexer::token::e_add   );
3839                add_invalid(lexer::token::e_sub   , lexer::token::e_add   , lexer::token::e_sub   );
3840                add_invalid(lexer::token::e_div   , lexer::token::e_mul   , lexer::token::e_div   );
3841                add_invalid(lexer::token::e_mul   , lexer::token::e_div   , lexer::token::e_mul   );
3842                add_invalid(lexer::token::e_mod   , lexer::token::e_pow   , lexer::token::e_mod   );
3843                add_invalid(lexer::token::e_pow   , lexer::token::e_mod   , lexer::token::e_pow   );
3844             }
3845
3846             bool result()
3847             {
3848                return error_list_.empty();
3849             }
3850
3851             bool operator() (const lexer::token& t0, const lexer::token& t1, const lexer::token& t2)
3852             {
3853                const set_t::value_type p = std::make_pair(t0.type,std::make_pair(t1.type,t2.type));
3854
3855                if (invalid_comb_.find(p) != invalid_comb_.end())
3856                {
3857                   error_list_.push_back(std::make_pair(t0,t1));
3858                }
3859
3860                return true;
3861             }
3862
3863             std::size_t error_count() const
3864             {
3865                return error_list_.size();
3866             }
3867
3868             std::pair<lexer::token,lexer::token> error(const std::size_t index)
3869             {
3870                if (index < error_list_.size())
3871                {
3872                   return error_list_[index];
3873                }
3874                else
3875                {
3876                   static const lexer::token error_token;
3877                   return std::make_pair(error_token,error_token);
3878                }
3879             }
3880
3881             void clear_errors()
3882             {
3883                error_list_.clear();
3884             }
3885
3886          private:
3887
3888             void add_invalid(token_t t0, token_t t1, token_t t2)
3889             {
3890                invalid_comb_.insert(std::make_pair(t0,std::make_pair(t1,t2)));
3891             }
3892
3893             set_t invalid_comb_;
3894             std::vector<std::pair<lexer::token,lexer::token> > error_list_;
3895          };
3896
3897          struct helper_assembly
3898          {
3899             inline bool register_scanner(lexer::token_scanner* scanner)
3900             {
3901                if (token_scanner_list.end() != std::find(token_scanner_list.begin(),
3902                                                          token_scanner_list.end  (),
3903                                                          scanner))
3904                {
3905                   return false;
3906                }
3907
3908                token_scanner_list.push_back(scanner);
3909
3910                return true;
3911             }
3912
3913             inline bool register_modifier(lexer::token_modifier* modifier)
3914             {
3915                if (token_modifier_list.end() != std::find(token_modifier_list.begin(),
3916                                                           token_modifier_list.end  (),
3917                                                           modifier))
3918                {
3919                   return false;
3920                }
3921
3922                token_modifier_list.push_back(modifier);
3923
3924                return true;
3925             }
3926
3927             inline bool register_joiner(lexer::token_joiner* joiner)
3928             {
3929                if (token_joiner_list.end() != std::find(token_joiner_list.begin(),
3930                                                         token_joiner_list.end  (),
3931                                                         joiner))
3932                {
3933                   return false;
3934                }
3935
3936                token_joiner_list.push_back(joiner);
3937
3938                return true;
3939             }
3940
3941             inline bool register_inserter(lexer::token_inserter* inserter)
3942             {
3943                if (token_inserter_list.end() != std::find(token_inserter_list.begin(),
3944                                                           token_inserter_list.end  (),
3945                                                           inserter))
3946                {
3947                   return false;
3948                }
3949
3950                token_inserter_list.push_back(inserter);
3951
3952                return true;
3953             }
3954
3955             inline bool run_modifiers(lexer::generator& g)
3956             {
3957                error_token_modifier = reinterpret_cast<lexer::token_modifier*>(0);
3958
3959                for (std::size_t i = 0; i < token_modifier_list.size(); ++i)
3960                {
3961                   lexer::token_modifier& modifier = (*token_modifier_list[i]);
3962
3963                   modifier.reset();
3964                   modifier.process(g);
3965
3966                   if (!modifier.result())
3967                   {
3968                      error_token_modifier = token_modifier_list[i];
3969
3970                      return false;
3971                   }
3972                }
3973
3974                return true;
3975             }
3976
3977             inline bool run_joiners(lexer::generator& g)
3978             {
3979                error_token_joiner = reinterpret_cast<lexer::token_joiner*>(0);
3980
3981                for (std::size_t i = 0; i < token_joiner_list.size(); ++i)
3982                {
3983                   lexer::token_joiner& joiner = (*token_joiner_list[i]);
3984
3985                   joiner.reset();
3986                   joiner.process(g);
3987
3988                   if (!joiner.result())
3989                   {
3990                      error_token_joiner = token_joiner_list[i];
3991
3992                      return false;
3993                   }
3994                }
3995
3996                return true;
3997             }
3998
3999             inline bool run_inserters(lexer::generator& g)
4000             {
4001                error_token_inserter = reinterpret_cast<lexer::token_inserter*>(0);
4002
4003                for (std::size_t i = 0; i < token_inserter_list.size(); ++i)
4004                {
4005                   lexer::token_inserter& inserter = (*token_inserter_list[i]);
4006
4007                   inserter.reset();
4008                   inserter.process(g);
4009
4010                   if (!inserter.result())
4011                   {
4012                      error_token_inserter = token_inserter_list[i];
4013
4014                      return false;
4015                   }
4016                }
4017
4018                return true;
4019             }
4020
4021             inline bool run_scanners(lexer::generator& g)
4022             {
4023                error_token_scanner = reinterpret_cast<lexer::token_scanner*>(0);
4024
4025                for (std::size_t i = 0; i < token_scanner_list.size(); ++i)
4026                {
4027                   lexer::token_scanner& scanner = (*token_scanner_list[i]);
4028
4029                   scanner.reset();
4030                   scanner.process(g);
4031
4032                   if (!scanner.result())
4033                   {
4034                      error_token_scanner = token_scanner_list[i];
4035
4036                      return false;
4037                   }
4038                }
4039
4040                return true;
4041             }
4042
4043             std::vector<lexer::token_scanner*>  token_scanner_list;
4044             std::vector<lexer::token_modifier*> token_modifier_list;
4045             std::vector<lexer::token_joiner*>   token_joiner_list;
4046             std::vector<lexer::token_inserter*> token_inserter_list;
4047
4048             lexer::token_scanner*  error_token_scanner;
4049             lexer::token_modifier* error_token_modifier;
4050             lexer::token_joiner*   error_token_joiner;
4051             lexer::token_inserter* error_token_inserter;
4052          };
4053       }
4054
4055       class parser_helper
4056       {
4057       public:
4058
4059          typedef token         token_t;
4060          typedef generator generator_t;
4061
4062          inline bool init(const std::string& str)
4063          {
4064             if (!lexer_.process(str))
4065             {
4066                return false;
4067             }
4068
4069             lexer_.begin();
4070
4071             next_token();
4072
4073             return true;
4074          }
4075
4076          inline generator_t& lexer()
4077          {
4078             return lexer_;
4079          }
4080
4081          inline const generator_t& lexer() const
4082          {
4083             return lexer_;
4084          }
4085
4086          inline void store_token()
4087          {
4088             lexer_.store();
4089             store_current_token_ = current_token_;
4090          }
4091
4092          inline void restore_token()
4093          {
4094             lexer_.restore();
4095             current_token_ = store_current_token_;
4096          }
4097
4098          inline void next_token()
4099          {
4100             current_token_ = lexer_.next_token();
4101          }
4102
4103          inline const token_t& current_token() const
4104          {
4105             return current_token_;
4106          }
4107
4108          enum token_advance_mode
4109          {
4110             e_hold    = 0,
4111             e_advance = 1
4112          };
4113
4114          inline void advance_token(const token_advance_mode mode)
4115          {
4116             if (e_advance == mode)
4117             {
4118                next_token();
4119             }
4120          }
4121
4122          inline bool token_is(const token_t::token_type& ttype, const token_advance_mode mode = e_advance)
4123          {
4124             if (current_token().type != ttype)
4125             {
4126                return false;
4127             }
4128
4129             advance_token(mode);
4130
4131             return true;
4132          }
4133
4134          inline bool token_is(const token_t::token_type& ttype,
4135                               const std::string& value,
4136                               const token_advance_mode mode = e_advance)
4137          {
4138             if (
4139                  (current_token().type != ttype) ||
4140                  !exprtk::details::imatch(value,current_token().value)
4141                )
4142             {
4143                return false;
4144             }
4145
4146             advance_token(mode);
4147
4148             return true;
4149          }
4150
4151          inline bool peek_token_is(const token_t::token_type& ttype)
4152          {
4153             return (lexer_.peek_next_token().type == ttype);
4154          }
4155
4156          inline bool peek_token_is(const std::string& s)
4157          {
4158             return (exprtk::details::imatch(lexer_.peek_next_token().value,s));
4159          }
4160
4161       private:
4162
4163          generator_t lexer_;
4164          token_t     current_token_;
4165          token_t     store_current_token_;
4166       };
4167    }
4168
4169    template <typename T>
4170    class vector_view
4171    {
4172    public:
4173
4174       typedef T* data_ptr_t;
4175
4176       vector_view(data_ptr_t data, const std::size_t& size)
4177       : size_(size),
4178         data_(data),
4179         data_ref_(0)
4180       {}
4181
4182       vector_view(const vector_view<T>& vv)
4183       : size_(vv.size_),
4184         data_(vv.data_),
4185         data_ref_(0)
4186       {}
4187
4188       inline void rebase(data_ptr_t data)
4189       {
4190          data_ = data;
4191
4192          if (!data_ref_.empty())
4193          {
4194             for (std::size_t i = 0; i < data_ref_.size(); ++i)
4195             {
4196                (*data_ref_[i]) = data;
4197             }
4198          }
4199       }
4200
4201       inline data_ptr_t data() const
4202       {
4203          return data_;
4204       }
4205
4206       inline std::size_t size() const
4207       {
4208          return size_;
4209       }
4210
4211       inline const T& operator[](const std::size_t index) const
4212       {
4213          return data_[index];
4214       }
4215
4216       inline T& operator[](const std::size_t index)
4217       {
4218          return data_[index];
4219       }
4220
4221       void set_ref(data_ptr_t* data_ref)
4222       {
4223          data_ref_.push_back(data_ref);
4224       }
4225
4226    private:
4227
4228       const std::size_t size_;
4229       data_ptr_t  data_;
4230       std::vector<data_ptr_t*> data_ref_;
4231    };
4232
4233    template <typename T>
4234    inline vector_view<T> make_vector_view(T* data,
4235                                           const std::size_t size, const std::size_t offset = 0)
4236    {
4237       return vector_view<T>(data + offset, size);
4238    }
4239
4240    template <typename T>
4241    inline vector_view<T> make_vector_view(std::vector<T>& v,
4242                                           const std::size_t size, const std::size_t offset = 0)
4243    {
4244       return vector_view<T>(v.data() + offset, size);
4245    }
4246
4247    template <typename T> class results_context;
4248
4249    template <typename T>
4250    struct type_store
4251    {
4252       enum store_type
4253       {
4254          e_unknown,
4255          e_scalar ,
4256          e_vector ,
4257          e_string
4258       };
4259
4260       type_store()
4261       : data(0),
4262         size(0),
4263         type(e_unknown)
4264       {}
4265
4266       union
4267       {
4268           void*  data;
4269           T*     vec_data;
4270       };
4271
4272       std::size_t size;
4273       store_type  type;
4274
4275       class parameter_list
4276       {
4277       public:
4278
4279          parameter_list(std::vector<type_store>& pl)
4280          : parameter_list_(pl)
4281          {}
4282
4283          inline bool empty() const
4284          {
4285             return parameter_list_.empty();
4286          }
4287
4288          inline std::size_t size() const
4289          {
4290             return parameter_list_.size();
4291          }
4292
4293          inline type_store& operator[](const std::size_t& index)
4294          {
4295             return parameter_list_[index];
4296          }
4297
4298          inline const type_store& operator[](const std::size_t& index) const
4299          {
4300             return parameter_list_[index];
4301          }
4302
4303          inline type_store& front()
4304          {
4305             return parameter_list_[0];
4306          }
4307
4308          inline const type_store& front() const
4309          {
4310             return parameter_list_[0];
4311          }
4312
4313          inline type_store& back()
4314          {
4315             return parameter_list_.back();
4316          }
4317
4318          inline const type_store& back() const
4319          {
4320             return parameter_list_.back();
4321          }
4322
4323       private:
4324
4325          std::vector<type_store>& parameter_list_;
4326
4327          friend class results_context<T>;
4328       };
4329
4330       template <typename ViewType>
4331       struct type_view
4332       {
4333          typedef type_store<T> type_store_t;
4334          typedef ViewType      value_t;
4335
4336          type_view(type_store_t& ts)
4337          : ts_(ts),
4338            data_(reinterpret_cast<value_t*>(ts_.data))
4339          {}
4340
4341          type_view(const type_store_t& ts)
4342          : ts_(const_cast<type_store_t&>(ts)),
4343            data_(reinterpret_cast<value_t*>(ts_.data))
4344          {}
4345
4346          inline std::size_t size() const
4347          {
4348             return ts_.size;
4349          }
4350
4351          inline value_t& operator[](const std::size_t& i)
4352          {
4353             return data_[i];
4354          }
4355
4356          inline const value_t& operator[](const std::size_t& i) const
4357          {
4358             return data_[i];
4359          }
4360
4361          inline const value_t* begin() const { return data_; }
4362          inline       value_t* begin()       { return data_; }
4363
4364          inline const value_t* end() const
4365          {
4366             return static_cast<value_t*>(data_ + ts_.size);
4367          }
4368
4369          inline value_t* end()
4370          {
4371             return static_cast<value_t*>(data_ + ts_.size);
4372          }
4373
4374          type_store_t& ts_;
4375          value_t* data_;
4376       };
4377
4378       typedef type_view<T>    vector_view;
4379       typedef type_view<char> string_view;
4380
4381       struct scalar_view
4382       {
4383          typedef type_store<T> type_store_t;
4384          typedef T value_t;
4385
4386          scalar_view(type_store_t& ts)
4387          : v_(*reinterpret_cast<value_t*>(ts.data))
4388          {}
4389
4390          scalar_view(const type_store_t& ts)
4391          : v_(*reinterpret_cast<value_t*>(const_cast<type_store_t&>(ts).data))
4392          {}
4393
4394          inline value_t& operator() ()
4395          {
4396             return v_;
4397          }
4398
4399          inline const value_t& operator() () const
4400          {
4401             return v_;
4402          }
4403
4404          template <typename IntType>
4405          inline bool to_int(IntType& i) const
4406          {
4407             if (!exprtk::details::numeric::is_integer(v_))
4408                return false;
4409
4410             i = static_cast<IntType>(v_);
4411
4412             return true;
4413          }
4414
4415          template <typename UIntType>
4416          inline bool to_uint(UIntType& u) const
4417          {
4418             if (v_ < T(0))
4419                return false;
4420             else if (!exprtk::details::numeric::is_integer(v_))
4421                return false;
4422
4423             u = static_cast<UIntType>(v_);
4424
4425             return true;
4426          }
4427
4428          T& v_;
4429       };
4430    };
4431
4432    template <typename StringView>
4433    inline std::string to_str(const StringView& view)
4434    {
4435       return std::string(view.begin(),view.size());
4436    }
4437
4438    #ifndef exprtk_disable_return_statement
4439    namespace details
4440    {
4441       template <typename T> class return_node;
4442       template <typename T> class return_envelope_node;
4443    }
4444    #endif
4445
4446    template <typename T>
4447    class results_context
4448    {
4449    public:
4450
4451       typedef type_store<T> type_store_t;
4452
4453       results_context()
4454       : results_available_(false)
4455       {}
4456
4457       inline std::size_t count() const
4458       {
4459          if (results_available_)
4460             return parameter_list_.size();
4461          else
4462             return 0;
4463       }
4464
4465       inline type_store_t& operator[](const std::size_t& index)
4466       {
4467          return parameter_list_[index];
4468       }
4469
4470       inline const type_store_t& operator[](const std::size_t& index) const
4471       {
4472          return parameter_list_[index];
4473       }
4474
4475    private:
4476
4477       inline void clear()
4478       {
4479          results_available_ = false;
4480       }
4481
4482       typedef std::vector<type_store_t> ts_list_t;
4483       typedef typename type_store_t::parameter_list parameter_list_t;
4484
4485       inline void assign(const parameter_list_t& pl)
4486       {
4487          parameter_list_    = pl.parameter_list_;
4488          results_available_ = true;
4489       }
4490
4491       bool results_available_;
4492       ts_list_t parameter_list_;
4493
4494       #ifndef exprtk_disable_return_statement
4495       friend class details::return_node<T>;
4496       friend class details::return_envelope_node<T>;
4497       #endif
4498    };
4499
4500    namespace details
4501    {
4502       enum operator_type
4503       {
4504          e_default , e_null    , e_add     , e_sub     ,
4505          e_mul     , e_div     , e_mod     , e_pow     ,
4506          e_atan2   , e_min     , e_max     , e_avg     ,
4507          e_sum     , e_prod    , e_lt      , e_lte     ,
4508          e_eq      , e_equal   , e_ne      , e_nequal  ,
4509          e_gte     , e_gt      , e_and     , e_nand    ,
4510          e_or      , e_nor     , e_xor     , e_xnor    ,
4511          e_mand    , e_mor     , e_scand   , e_scor    ,
4512          e_shr     , e_shl     , e_abs     , e_acos    ,
4513          e_acosh   , e_asin    , e_asinh   , e_atan    ,
4514          e_atanh   , e_ceil    , e_cos     , e_cosh    ,
4515          e_exp     , e_expm1   , e_floor   , e_log     ,
4516          e_log10   , e_log2    , e_log1p   , e_logn    ,
4517          e_neg     , e_pos     , e_round   , e_roundn  ,
4518          e_root    , e_sqrt    , e_sin     , e_sinc    ,
4519          e_sinh    , e_sec     , e_csc     , e_tan     ,
4520          e_tanh    , e_cot     , e_clamp   , e_iclamp  ,
4521          e_inrange , e_sgn     , e_r2d     , e_d2r     ,
4522          e_d2g     , e_g2d     , e_hypot   , e_notl    ,
4523          e_erf     , e_erfc    , e_ncdf    , e_frac    ,
4524          e_trunc   , e_assign  , e_addass  , e_subass  ,
4525          e_mulass  , e_divass  , e_modass  , e_in      ,
4526          e_like    , e_ilike   , e_multi   , e_smulti  ,
4527          e_swap    ,
4528
4529          // Do not add new functions/operators after this point.
4530          e_sf00 = 1000, e_sf01 = 1001, e_sf02 = 1002, e_sf03 = 1003,
4531          e_sf04 = 1004, e_sf05 = 1005, e_sf06 = 1006, e_sf07 = 1007,
4532          e_sf08 = 1008, e_sf09 = 1009, e_sf10 = 1010, e_sf11 = 1011,
4533          e_sf12 = 1012, e_sf13 = 1013, e_sf14 = 1014, e_sf15 = 1015,
4534          e_sf16 = 1016, e_sf17 = 1017, e_sf18 = 1018, e_sf19 = 1019,
4535          e_sf20 = 1020, e_sf21 = 1021, e_sf22 = 1022, e_sf23 = 1023,
4536          e_sf24 = 1024, e_sf25 = 1025, e_sf26 = 1026, e_sf27 = 1027,
4537          e_sf28 = 1028, e_sf29 = 1029, e_sf30 = 1030, e_sf31 = 1031,
4538          e_sf32 = 1032, e_sf33 = 1033, e_sf34 = 1034, e_sf35 = 1035,
4539          e_sf36 = 1036, e_sf37 = 1037, e_sf38 = 1038, e_sf39 = 1039,
4540          e_sf40 = 1040, e_sf41 = 1041, e_sf42 = 1042, e_sf43 = 1043,
4541          e_sf44 = 1044, e_sf45 = 1045, e_sf46 = 1046, e_sf47 = 1047,
4542          e_sf48 = 1048, e_sf49 = 1049, e_sf50 = 1050, e_sf51 = 1051,
4543          e_sf52 = 1052, e_sf53 = 1053, e_sf54 = 1054, e_sf55 = 1055,
4544          e_sf56 = 1056, e_sf57 = 1057, e_sf58 = 1058, e_sf59 = 1059,
4545          e_sf60 = 1060, e_sf61 = 1061, e_sf62 = 1062, e_sf63 = 1063,
4546          e_sf64 = 1064, e_sf65 = 1065, e_sf66 = 1066, e_sf67 = 1067,
4547          e_sf68 = 1068, e_sf69 = 1069, e_sf70 = 1070, e_sf71 = 1071,
4548          e_sf72 = 1072, e_sf73 = 1073, e_sf74 = 1074, e_sf75 = 1075,
4549          e_sf76 = 1076, e_sf77 = 1077, e_sf78 = 1078, e_sf79 = 1079,
4550          e_sf80 = 1080, e_sf81 = 1081, e_sf82 = 1082, e_sf83 = 1083,
4551          e_sf84 = 1084, e_sf85 = 1085, e_sf86 = 1086, e_sf87 = 1087,
4552          e_sf88 = 1088, e_sf89 = 1089, e_sf90 = 1090, e_sf91 = 1091,
4553          e_sf92 = 1092, e_sf93 = 1093, e_sf94 = 1094, e_sf95 = 1095,
4554          e_sf96 = 1096, e_sf97 = 1097, e_sf98 = 1098, e_sf99 = 1099,
4555          e_sffinal  = 1100,
4556          e_sf4ext00 = 2000, e_sf4ext01 = 2001, e_sf4ext02 = 2002, e_sf4ext03 = 2003,
4557          e_sf4ext04 = 2004, e_sf4ext05 = 2005, e_sf4ext06 = 2006, e_sf4ext07 = 2007,
4558          e_sf4ext08 = 2008, e_sf4ext09 = 2009, e_sf4ext10 = 2010, e_sf4ext11 = 2011,
4559          e_sf4ext12 = 2012, e_sf4ext13 = 2013, e_sf4ext14 = 2014, e_sf4ext15 = 2015,
4560          e_sf4ext16 = 2016, e_sf4ext17 = 2017, e_sf4ext18 = 2018, e_sf4ext19 = 2019,
4561          e_sf4ext20 = 2020, e_sf4ext21 = 2021, e_sf4ext22 = 2022, e_sf4ext23 = 2023,
4562          e_sf4ext24 = 2024, e_sf4ext25 = 2025, e_sf4ext26 = 2026, e_sf4ext27 = 2027,
4563          e_sf4ext28 = 2028, e_sf4ext29 = 2029, e_sf4ext30 = 2030, e_sf4ext31 = 2031,
4564          e_sf4ext32 = 2032, e_sf4ext33 = 2033, e_sf4ext34 = 2034, e_sf4ext35 = 2035,
4565          e_sf4ext36 = 2036, e_sf4ext37 = 2037, e_sf4ext38 = 2038, e_sf4ext39 = 2039,
4566          e_sf4ext40 = 2040, e_sf4ext41 = 2041, e_sf4ext42 = 2042, e_sf4ext43 = 2043,
4567          e_sf4ext44 = 2044, e_sf4ext45 = 2045, e_sf4ext46 = 2046, e_sf4ext47 = 2047,
4568          e_sf4ext48 = 2048, e_sf4ext49 = 2049, e_sf4ext50 = 2050, e_sf4ext51 = 2051,
4569          e_sf4ext52 = 2052, e_sf4ext53 = 2053, e_sf4ext54 = 2054, e_sf4ext55 = 2055,
4570          e_sf4ext56 = 2056, e_sf4ext57 = 2057, e_sf4ext58 = 2058, e_sf4ext59 = 2059,
4571          e_sf4ext60 = 2060, e_sf4ext61 = 2061
4572       };
4573
4574       inline std::string to_str(const operator_type opr)
4575       {
4576          switch (opr)
4577          {
4578             case e_add    : return  "+"  ;
4579             case e_sub    : return  "-"  ;
4580             case e_mul    : return  "*"  ;
4581             case e_div    : return  "/"  ;
4582             case e_mod    : return  "%"  ;
4583             case e_pow    : return  "^"  ;
4584             case e_assign : return ":="  ;
4585             case e_addass : return "+="  ;
4586             case e_subass : return "-="  ;
4587             case e_mulass : return "*="  ;
4588             case e_divass : return "/="  ;
4589             case e_modass : return "%="  ;
4590             case e_lt     : return  "<"  ;
4591             case e_lte    : return "<="  ;
4592             case e_eq     : return "=="  ;
4593             case e_equal  : return  "="  ;
4594             case e_ne     : return "!="  ;
4595             case e_nequal : return "<>"  ;
4596             case e_gte    : return ">="  ;
4597             case e_gt     : return  ">"  ;
4598             case e_and    : return "and" ;
4599             case e_or     : return "or"  ;
4600             case e_xor    : return "xor" ;
4601             case e_nand   : return "nand";
4602             case e_nor    : return "nor" ;
4603             case e_xnor   : return "xnor";
4604             default       : return "N/A" ;
4605          }
4606       }
4607
4608       struct base_operation_t
4609       {
4610          base_operation_t(const operator_type t, const unsigned int& np)
4611          : type(t),
4612            num_params(np)
4613          {}
4614
4615          operator_type type;
4616          unsigned int num_params;
4617       };
4618
4619       namespace loop_unroll
4620       {
4621          #ifndef exprtk_disable_superscalar_unroll
4622          const unsigned int global_loop_batch_size = 16;
4623          #else
4624          const unsigned int global_loop_batch_size = 4;
4625          #endif
4626
4627          struct details
4628          {
4629             details(const std::size_t& vsize,
4630                     const unsigned int loop_batch_size = global_loop_batch_size)
4631             : batch_size(loop_batch_size   ),
4632               remainder (vsize % batch_size),
4633               upper_bound(static_cast<int>(vsize - (remainder ? loop_batch_size : 0)))
4634             {}
4635
4636             unsigned int batch_size;
4637             int   remainder;
4638             int upper_bound;
4639          };
4640       }
4641
4642       #ifdef exprtk_enable_debugging
4643       inline void dump_ptr(const std::string& s, const void* ptr, const std::size_t size = 0)
4644       {
4645          if (size)
4646             exprtk_debug(("%s - addr: %p\n",s.c_str(),ptr));
4647          else
4648             exprtk_debug(("%s - addr: %p size: %d\n",
4649                           s.c_str(),
4650                           ptr,
4651                           static_cast<unsigned int>(size)));
4652       }
4653       #else
4654       inline void dump_ptr(const std::string&, const void*) {}
4655       inline void dump_ptr(const std::string&, const void*, const std::size_t) {}
4656       #endif
4657
4658       template <typename T>
4659       class vec_data_store
4660       {
4661       public:
4662
4663          typedef vec_data_store<T> type;
4664          typedef T* data_t;
4665
4666       private:
4667
4668          struct control_block
4669          {
4670             control_block()
4671             : ref_count(1),
4672               size     (0),
4673               data     (0),
4674               destruct (true)
4675             {}
4676
4677             control_block(const std::size_t& dsize)
4678             : ref_count(1    ),
4679               size     (dsize),
4680               data     (0    ),
4681               destruct (true )
4682             { create_data(); }
4683
4684             control_block(const std::size_t& dsize, data_t dptr, bool dstrct = false)
4685             : ref_count(1     ),
4686               size     (dsize ),
4687               data     (dptr  ),
4688               destruct (dstrct)
4689             {}
4690
4691            ~control_block()
4692             {
4693                if (data && destruct && (0 == ref_count))
4694                {
4695                   dump_ptr("~control_block() data",data);
4696                   delete[] data;
4697                   data = reinterpret_cast<data_t>(0);
4698                }
4699             }
4700
4701             static inline control_block* create(const std::size_t& dsize, data_t data_ptr = data_t(0), bool dstrct = false)
4702             {
4703                if (dsize)
4704                {
4705                   if (0 == data_ptr)
4706                      return (new control_block(dsize));
4707                   else
4708                      return (new control_block(dsize, data_ptr, dstrct));
4709                }
4710                else
4711                   return (new control_block);
4712             }
4713
4714             static inline void destroy(control_block*& cntrl_blck)
4715             {
4716                if (cntrl_blck)
4717                {
4718                   if (
4719                        (0 !=   cntrl_blck->ref_count) &&
4720                        (0 == --cntrl_blck->ref_count)
4721                      )
4722                   {
4723                      delete cntrl_blck;
4724                   }
4725
4726                   cntrl_blck = 0;
4727                }
4728             }
4729
4730             std::size_t ref_count;
4731             std::size_t size;
4732             data_t      data;
4733             bool        destruct;
4734
4735          private:
4736
4737             control_block(const control_block&);
4738             control_block& operator=(const control_block&);
4739
4740             inline void create_data()
4741             {
4742                destruct = true;
4743                data     = new T[size];
4744                std::fill_n(data,size,T(0));
4745                dump_ptr("control_block::create_data() - data",data,size);
4746             }
4747          };
4748
4749       public:
4750
4751          vec_data_store()
4752          : control_block_(control_block::create(0))
4753          {}
4754
4755          vec_data_store(const std::size_t& size)
4756          : control_block_(control_block::create(size,(data_t)(0),true))
4757          {}
4758
4759          vec_data_store(const std::size_t& size, data_t data, bool dstrct = false)
4760          : control_block_(control_block::create(size, data, dstrct))
4761          {}
4762
4763          vec_data_store(const type& vds)
4764          {
4765             control_block_ = vds.control_block_;
4766             control_block_->ref_count++;
4767          }
4768
4769         ~vec_data_store()
4770          {
4771             control_block::destroy(control_block_);
4772          }
4773
4774          type& operator=(const type& vds)
4775          {
4776             if (this != &vds)
4777             {
4778                std::size_t final_size = min_size(control_block_, vds.control_block_);
4779
4780                vds.control_block_->size = final_size;
4781                    control_block_->size = final_size;
4782
4783                if (control_block_->destruct || (0 == control_block_->data))
4784                {
4785                   control_block::destroy(control_block_);
4786
4787                   control_block_ = vds.control_block_;
4788                   control_block_->ref_count++;
4789                }
4790             }
4791
4792             return (*this);
4793          }
4794
4795          inline data_t data()
4796          {
4797             return control_block_->data;
4798          }
4799
4800          inline data_t data() const
4801          {
4802             return control_block_->data;
4803          }
4804
4805          inline std::size_t size()
4806          {
4807             return control_block_->size;
4808          }
4809
4810          inline std::size_t size() const
4811          {
4812             return control_block_->size;
4813          }
4814
4815          inline data_t& ref()
4816          {
4817             return control_block_->data;
4818          }
4819
4820          inline void dump() const
4821          {
4822             #ifdef exprtk_enable_debugging
4823             exprtk_debug(("size: %d\taddress:%p\tdestruct:%c\n",
4824                           size(),
4825                           data(),
4826                           (control_block_->destruct ? 'T' : 'F')));
4827
4828             for (std::size_t i = 0; i < size(); ++i)
4829             {
4830                if (5 == i)
4831                   exprtk_debug(("\n"));
4832
4833                exprtk_debug(("%15.10f ",data()[i]));
4834             }
4835             exprtk_debug(("\n"));
4836             #endif
4837          }
4838
4839          static inline void match_sizes(type& vds0, type& vds1)
4840          {
4841             std::size_t size = min_size(vds0.control_block_,vds1.control_block_);
4842             vds0.control_block_->size = size;
4843             vds1.control_block_->size = size;
4844          }
4845
4846       private:
4847
4848          static inline std::size_t min_size(control_block* cb0, control_block* cb1)
4849          {
4850             const std::size_t size0 = cb0->size;
4851             const std::size_t size1 = cb1->size;
4852
4853             if (size0 && size1)
4854                return std::min(size0,size1);
4855             else
4856                return (size0) ? size0 : size1;
4857          }
4858
4859          control_block* control_block_;
4860       };
4861
4862       namespace numeric
4863       {
4864          namespace details
4865          {
4866             template <typename T>
4867             inline T process_impl(const operator_type operation, const T arg)
4868             {
4869                switch (operation)
4870                {
4871                   case e_abs   : return numeric::abs  (arg);
4872                   case e_acos  : return numeric::acos (arg);
4873                   case e_acosh : return numeric::acosh(arg);
4874                   case e_asin  : return numeric::asin (arg);
4875                   case e_asinh : return numeric::asinh(arg);
4876                   case e_atan  : return numeric::atan (arg);
4877                   case e_atanh : return numeric::atanh(arg);
4878                   case e_ceil  : return numeric::ceil (arg);
4879                   case e_cos   : return numeric::cos  (arg);
4880                   case e_cosh  : return numeric::cosh (arg);
4881                   case e_exp   : return numeric::exp  (arg);
4882                   case e_expm1 : return numeric::expm1(arg);
4883                   case e_floor : return numeric::floor(arg);
4884                   case e_log   : return numeric::log  (arg);
4885                   case e_log10 : return numeric::log10(arg);
4886                   case e_log2  : return numeric::log2 (arg);
4887                   case e_log1p : return numeric::log1p(arg);
4888                   case e_neg   : return numeric::neg  (arg);
4889                   case e_pos   : return numeric::pos  (arg);
4890                   case e_round : return numeric::round(arg);
4891                   case e_sin   : return numeric::sin  (arg);
4892                   case e_sinc  : return numeric::sinc (arg);
4893                   case e_sinh  : return numeric::sinh (arg);
4894                   case e_sqrt  : return numeric::sqrt (arg);
4895                   case e_tan   : return numeric::tan  (arg);
4896                   case e_tanh  : return numeric::tanh (arg);
4897                   case e_cot   : return numeric::cot  (arg);
4898                   case e_sec   : return numeric::sec  (arg);
4899                   case e_csc   : return numeric::csc  (arg);
4900                   case e_r2d   : return numeric::r2d  (arg);
4901                   case e_d2r   : return numeric::d2r  (arg);
4902                   case e_d2g   : return numeric::d2g  (arg);
4903                   case e_g2d   : return numeric::g2d  (arg);
4904                   case e_notl  : return numeric::notl (arg);
4905                   case e_sgn   : return numeric::sgn  (arg);
4906                   case e_erf   : return numeric::erf  (arg);
4907                   case e_erfc  : return numeric::erfc (arg);
4908                   case e_ncdf  : return numeric::ncdf (arg);
4909                   case e_frac  : return numeric::frac (arg);
4910                   case e_trunc : return numeric::trunc(arg);
4911
4912                   default      : exprtk_debug(("numeric::details::process_impl<T> - Invalid unary operation.\n"));
4913                                  return std::numeric_limits<T>::quiet_NaN();
4914                }
4915             }
4916
4917             template <typename T>
4918             inline T process_impl(const operator_type operation, const T arg0, const T arg1)
4919             {
4920                switch (operation)
4921                {
4922                   case e_add    : return (arg0 + arg1);
4923                   case e_sub    : return (arg0 - arg1);
4924                   case e_mul    : return (arg0 * arg1);
4925                   case e_div    : return (arg0 / arg1);
4926                   case e_mod    : return modulus<T>(arg0,arg1);
4927                   case e_pow    : return pow<T>(arg0,arg1);
4928                   case e_atan2  : return atan2<T>(arg0,arg1);
4929                   case e_min    : return std::min<T>(arg0,arg1);
4930                   case e_max    : return std::max<T>(arg0,arg1);
4931                   case e_logn   : return logn<T>(arg0,arg1);
4932                   case e_lt     : return (arg0 <  arg1) ? T(1) : T(0);
4933                   case e_lte    : return (arg0 <= arg1) ? T(1) : T(0);
4934                   case e_eq     : return std::equal_to<T>()(arg0,arg1) ? T(1) : T(0);
4935                   case e_ne     : return std::not_equal_to<T>()(arg0,arg1) ? T(1) : T(0);
4936                   case e_gte    : return (arg0 >= arg1) ? T(1) : T(0);
4937                   case e_gt     : return (arg0 >  arg1) ? T(1) : T(0);
4938                   case e_and    : return and_opr <T>(arg0,arg1);
4939                   case e_nand   : return nand_opr<T>(arg0,arg1);
4940                   case e_or     : return or_opr  <T>(arg0,arg1);
4941                   case e_nor    : return nor_opr <T>(arg0,arg1);
4942                   case e_xor    : return xor_opr <T>(arg0,arg1);
4943                   case e_xnor   : return xnor_opr<T>(arg0,arg1);
4944                   case e_root   : return root    <T>(arg0,arg1);
4945                   case e_roundn : return roundn  <T>(arg0,arg1);
4946                   case e_equal  : return equal      (arg0,arg1);
4947                   case e_nequal : return nequal     (arg0,arg1);
4948                   case e_hypot  : return hypot   <T>(arg0,arg1);
4949                   case e_shr    : return shr     <T>(arg0,arg1);
4950                   case e_shl    : return shl     <T>(arg0,arg1);
4951
4952                   default       : exprtk_debug(("numeric::details::process_impl<T> - Invalid binary operation.\n"));
4953                                   return std::numeric_limits<T>::quiet_NaN();
4954                }
4955             }
4956
4957             template <typename T>
4958             inline T process_impl(const operator_type operation, const T arg0, const T arg1, int_type_tag)
4959             {
4960                switch (operation)
4961                {
4962                   case e_add    : return (arg0 + arg1);
4963                   case e_sub    : return (arg0 - arg1);
4964                   case e_mul    : return (arg0 * arg1);
4965                   case e_div    : return (arg0 / arg1);
4966                   case e_mod    : return arg0 % arg1;
4967                   case e_pow    : return pow<T>(arg0,arg1);
4968                   case e_min    : return std::min<T>(arg0,arg1);
4969                   case e_max    : return std::max<T>(arg0,arg1);
4970                   case e_logn   : return logn<T>(arg0,arg1);
4971                   case e_lt     : return (arg0 <  arg1) ? T(1) : T(0);
4972                   case e_lte    : return (arg0 <= arg1) ? T(1) : T(0);
4973                   case e_eq     : return (arg0 == arg1) ? T(1) : T(0);
4974                   case e_ne     : return (arg0 != arg1) ? T(1) : T(0);
4975                   case e_gte    : return (arg0 >= arg1) ? T(1) : T(0);
4976                   case e_gt     : return (arg0 >  arg1) ? T(1) : T(0);
4977                   case e_and    : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(1) : T(0);
4978                   case e_nand   : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(0) : T(1);
4979                   case e_or     : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(1) : T(0);
4980                   case e_nor    : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(0) : T(1);
4981                   case e_xor    : return arg0 ^ arg1;
4982                   case e_xnor   : return !(arg0 ^ arg1);
4983                   case e_root   : return root<T>(arg0,arg1);
4984                   case e_equal  : return arg0 == arg1;
4985                   case e_nequal : return arg0 != arg1;
4986                   case e_hypot  : return hypot<T>(arg0,arg1);
4987                   case e_shr    : return arg0 >> arg1;
4988                   case e_shl    : return arg0 << arg1;
4989
4990                   default       : exprtk_debug(("numeric::details::process_impl<IntType> - Invalid binary operation.\n"));
4991                                   return std::numeric_limits<T>::quiet_NaN();
4992                }
4993             }
4994          }
4995
4996          template <typename T>
4997          inline T process(const operator_type operation, const T arg)
4998          {
4999             return exprtk::details::numeric::details::process_impl(operation,arg);
5000          }
5001
5002          template <typename T>
5003          inline T process(const operator_type operation, const T arg0, const T arg1)
5004          {
5005             return exprtk::details::numeric::details::process_impl(operation, arg0, arg1);
5006          }
5007       }
5008
5009       template <typename T>
5010       class expression_node
5011       {
5012       public:
5013
5014          enum node_type
5015          {
5016             e_none          , e_null          , e_constant    , e_unary        ,
5017             e_binary        , e_binary_ext    , e_trinary     , e_quaternary   ,
5018             e_vararg        , e_conditional   , e_while       , e_repeat       ,
5019             e_for           , e_switch        , e_mswitch     , e_return       ,
5020             e_retenv        , e_variable      , e_stringvar   , e_stringconst  ,
5021             e_stringvarrng  , e_cstringvarrng , e_strgenrange , e_strconcat    ,
5022             e_stringvarsize , e_strswap       , e_stringsize  , e_stringvararg ,
5023             e_function      , e_vafunction    , e_genfunction , e_strfunction  ,
5024             e_strcondition  , e_strccondition , e_add         , e_sub          ,
5025             e_mul           , e_div           , e_mod         , e_pow          ,
5026             e_lt            , e_lte           , e_gt          , e_gte          ,
5027             e_eq            , e_ne            , e_and         , e_nand         ,
5028             e_or            , e_nor           , e_xor         , e_xnor         ,
5029             e_in            , e_like          , e_ilike       , e_inranges     ,
5030             e_ipow          , e_ipowinv       , e_abs         , e_acos         ,
5031             e_acosh         , e_asin          , e_asinh       , e_atan         ,
5032             e_atanh         , e_ceil          , e_cos         , e_cosh         ,
5033             e_exp           , e_expm1         , e_floor       , e_log          ,
5034             e_log10         , e_log2          , e_log1p       , e_neg          ,
5035             e_pos           , e_round         , e_sin         , e_sinc         ,
5036             e_sinh          , e_sqrt          , e_tan         , e_tanh         ,
5037             e_cot           , e_sec           , e_csc         , e_r2d          ,
5038             e_d2r           , e_d2g           , e_g2d         , e_notl         ,
5039             e_sgn           , e_erf           , e_erfc        , e_ncdf         ,
5040             e_frac          , e_trunc         , e_uvouv       , e_vov          ,
5041             e_cov           , e_voc           , e_vob         , e_bov          ,
5042             e_cob           , e_boc           , e_vovov       , e_vovoc        ,
5043             e_vocov         , e_covov         , e_covoc       , e_vovovov      ,
5044             e_vovovoc       , e_vovocov       , e_vocovov     , e_covovov      ,
5045             e_covocov       , e_vocovoc       , e_covovoc     , e_vococov      ,
5046             e_sf3ext        , e_sf4ext        , e_nulleq      , e_strass       ,
5047             e_vector        , e_vecelem       , e_rbvecelem   , e_rbveccelem   ,
5048             e_vecdefass     , e_vecvalass     , e_vecvecass   , e_vecopvalass  ,
5049             e_vecopvecass   , e_vecfunc       , e_vecvecswap  , e_vecvecineq   ,
5050             e_vecvalineq    , e_valvecineq    , e_vecvecarith , e_vecvalarith  ,
5051             e_valvecarith   , e_vecunaryop    , e_break       , e_continue     ,
5052             e_swap
5053          };
5054
5055          typedef T value_type;
5056          typedef expression_node<T>* expression_ptr;
5057
5058          virtual ~expression_node()
5059          {}
5060
5061          inline virtual T value() const
5062          {
5063             return std::numeric_limits<T>::quiet_NaN();
5064          }
5065
5066          inline virtual expression_node<T>* branch(const std::size_t& index = 0) const
5067          {
5068             return reinterpret_cast<expression_ptr>(index * 0);
5069          }
5070
5071          inline virtual node_type type() const
5072          {
5073             return e_none;
5074          }
5075       };
5076
5077       template <typename T>
5078       inline bool is_generally_string_node(const expression_node<T>* node);
5079
5080       inline bool is_true(const double v)
5081       {
5082          return std::not_equal_to<double>()(0.0,v);
5083       }
5084
5085       inline bool is_true(const long double v)
5086       {
5087          return std::not_equal_to<long double>()(0.0L,v);
5088       }
5089
5090       inline bool is_true(const float v)
5091       {
5092          return std::not_equal_to<float>()(0.0f,v);
5093       }
5094
5095       template <typename T>
5096       inline bool is_true(const std::complex<T>& v)
5097       {
5098          return std::not_equal_to<std::complex<T> >()(std::complex<T>(0),v);
5099       }
5100
5101       template <typename T>
5102       inline bool is_true(const expression_node<T>* node)
5103       {
5104          return std::not_equal_to<T>()(T(0),node->value());
5105       }
5106
5107       template <typename T>
5108       inline bool is_false(const expression_node<T>* node)
5109       {
5110          return std::equal_to<T>()(T(0),node->value());
5111       }
5112
5113       template <typename T>
5114       inline bool is_unary_node(const expression_node<T>* node)
5115       {
5116          return node && (details::expression_node<T>::e_unary == node->type());
5117       }
5118
5119       template <typename T>
5120       inline bool is_neg_unary_node(const expression_node<T>* node)
5121       {
5122          return node && (details::expression_node<T>::e_neg == node->type());
5123       }
5124
5125       template <typename T>
5126       inline bool is_binary_node(const expression_node<T>* node)
5127       {
5128          return node && (details::expression_node<T>::e_binary == node->type());
5129       }
5130
5131       template <typename T>
5132       inline bool is_variable_node(const expression_node<T>* node)
5133       {
5134          return node && (details::expression_node<T>::e_variable == node->type());
5135       }
5136
5137       template <typename T>
5138       inline bool is_ivariable_node(const expression_node<T>* node)
5139       {
5140          return node &&
5141                 (
5142                   details::expression_node<T>::e_variable   == node->type() ||
5143                   details::expression_node<T>::e_vecelem    == node->type() ||
5144                   details::expression_node<T>::e_rbvecelem  == node->type() ||
5145                   details::expression_node<T>::e_rbveccelem == node->type()
5146                 );
5147       }
5148
5149       template <typename T>
5150       inline bool is_vector_elem_node(const expression_node<T>* node)
5151       {
5152          return node && (details::expression_node<T>::e_vecelem == node->type());
5153       }
5154
5155       template <typename T>
5156       inline bool is_rebasevector_elem_node(const expression_node<T>* node)
5157       {
5158          return node && (details::expression_node<T>::e_rbvecelem == node->type());
5159       }
5160
5161       template <typename T>
5162       inline bool is_rebasevector_celem_node(const expression_node<T>* node)
5163       {
5164          return node && (details::expression_node<T>::e_rbveccelem == node->type());
5165       }
5166
5167       template <typename T>
5168       inline bool is_vector_node(const expression_node<T>* node)
5169       {
5170          return node && (details::expression_node<T>::e_vector == node->type());
5171       }
5172
5173       template <typename T>
5174       inline bool is_ivector_node(const expression_node<T>* node)
5175       {
5176          if (node)
5177          {
5178             switch (node->type())
5179             {
5180                case details::expression_node<T>::e_vector      :
5181                case details::expression_node<T>::e_vecvalass   :
5182                case details::expression_node<T>::e_vecvecass   :
5183                case details::expression_node<T>::e_vecopvalass :
5184                case details::expression_node<T>::e_vecopvecass :
5185                case details::expression_node<T>::e_vecvecswap  :
5186                case details::expression_node<T>::e_vecvecarith :
5187                case details::expression_node<T>::e_vecvalarith :
5188                case details::expression_node<T>::e_valvecarith :
5189                case details::expression_node<T>::e_vecunaryop  : return true;
5190                default                                         : return false;
5191             }
5192          }
5193          else
5194             return false;
5195       }
5196
5197       template <typename T>
5198       inline bool is_constant_node(const expression_node<T>* node)
5199       {
5200          return node && (details::expression_node<T>::e_constant == node->type());
5201       }
5202
5203       template <typename T>
5204       inline bool is_null_node(const expression_node<T>* node)
5205       {
5206          return node && (details::expression_node<T>::e_null == node->type());
5207       }
5208
5209       template <typename T>
5210       inline bool is_break_node(const expression_node<T>* node)
5211       {
5212          return node && (details::expression_node<T>::e_break == node->type());
5213       }
5214
5215       template <typename T>
5216       inline bool is_continue_node(const expression_node<T>* node)
5217       {
5218          return node && (details::expression_node<T>::e_continue == node->type());
5219       }
5220
5221       template <typename T>
5222       inline bool is_swap_node(const expression_node<T>* node)
5223       {
5224          return node && (details::expression_node<T>::e_swap == node->type());
5225       }
5226
5227       template <typename T>
5228       inline bool is_function(const expression_node<T>* node)
5229       {
5230          return node && (details::expression_node<T>::e_function == node->type());
5231       }
5232
5233       template <typename T>
5234       inline bool is_return_node(const expression_node<T>* node)
5235       {
5236          return node && (details::expression_node<T>::e_return == node->type());
5237       }
5238
5239       template <typename T> class unary_node;
5240
5241       template <typename T>
5242       inline bool is_negate_node(const expression_node<T>* node)
5243       {
5244          if (node && is_unary_node(node))
5245          {
5246             return (details::e_neg == static_cast<const unary_node<T>*>(node)->operation());
5247          }
5248          else
5249             return false;
5250       }
5251
5252       template <typename T>
5253       inline bool branch_deletable(expression_node<T>* node)
5254       {
5255          return !is_variable_node(node) &&
5256                 !is_string_node  (node) ;
5257       }
5258
5259       template <std::size_t N, typename T>
5260       inline bool all_nodes_valid(expression_node<T>* (&b)[N])
5261       {
5262          for (std::size_t i = 0; i < N; ++i)
5263          {
5264             if (0 == b[i]) return false;
5265          }
5266
5267          return true;
5268       }
5269
5270       template <typename T,
5271                 typename Allocator,
5272                 template <typename, typename> class Sequence>
5273       inline bool all_nodes_valid(const Sequence<expression_node<T>*,Allocator>& b)
5274       {
5275          for (std::size_t i = 0; i < b.size(); ++i)
5276          {
5277             if (0 == b[i]) return false;
5278          }
5279
5280          return true;
5281       }
5282
5283       template <std::size_t N, typename T>
5284       inline bool all_nodes_variables(expression_node<T>* (&b)[N])
5285       {
5286          for (std::size_t i = 0; i < N; ++i)
5287          {
5288             if (0 == b[i])
5289                return false;
5290             else if (!is_variable_node(b[i]))
5291                return false;
5292          }
5293
5294          return true;
5295       }
5296
5297       template <typename T,
5298                 typename Allocator,
5299                 template <typename, typename> class Sequence>
5300       inline bool all_nodes_variables(Sequence<expression_node<T>*,Allocator>& b)
5301       {
5302          for (std::size_t i = 0; i < b.size(); ++i)
5303          {
5304             if (0 == b[i])
5305                return false;
5306             else if (!is_variable_node(b[i]))
5307                return false;
5308          }
5309
5310          return true;
5311       }
5312
5313       template <typename NodeAllocator, typename T, std::size_t N>
5314       inline void free_all_nodes(NodeAllocator& node_allocator, expression_node<T>* (&b)[N])
5315       {
5316          for (std::size_t i = 0; i < N; ++i)
5317          {
5318             free_node(node_allocator,b[i]);
5319          }
5320       }
5321
5322       template <typename NodeAllocator,
5323                 typename T,
5324                 typename Allocator,
5325                 template <typename, typename> class Sequence>
5326       inline void free_all_nodes(NodeAllocator& node_allocator, Sequence<expression_node<T>*,Allocator>& b)
5327       {
5328          for (std::size_t i = 0; i < b.size(); ++i)
5329          {
5330             free_node(node_allocator,b[i]);
5331          }
5332
5333          b.clear();
5334       }
5335
5336       template <typename NodeAllocator, typename T>
5337       inline void free_node(NodeAllocator& node_allocator, expression_node<T>*& node, const bool force_delete = false)
5338       {
5339          if (0 != node)
5340          {
5341             if (
5342                  (is_variable_node(node) || is_string_node(node)) ||
5343                  force_delete
5344                )
5345                return;
5346
5347             node_allocator.free(node);
5348             node = reinterpret_cast<expression_node<T>*>(0);
5349          }
5350       }
5351
5352       template <typename T>
5353       inline void destroy_node(expression_node<T>*& node)
5354       {
5355          delete node;
5356          node = reinterpret_cast<expression_node<T>*>(0);
5357       }
5358
5359       template <typename Type>
5360       class vector_holder
5361       {
5362       private:
5363
5364          typedef Type value_type;
5365          typedef value_type* value_ptr;
5366          typedef const value_ptr const_value_ptr;
5367
5368          class vector_holder_base
5369          {
5370          public:
5371
5372             virtual ~vector_holder_base() {}
5373
5374             inline value_ptr operator[](const std::size_t& index) const
5375             {
5376                return value_at(index);
5377             }
5378
5379             inline std::size_t size() const
5380             {
5381                return vector_size();
5382             }
5383
5384             inline value_ptr data() const
5385             {
5386                return value_at(0);
5387             }
5388
5389             virtual inline bool rebaseable() const
5390             {
5391                return false;
5392             }
5393
5394             virtual void set_ref(value_ptr*) {}
5395
5396          protected:
5397
5398             virtual value_ptr value_at(const std::size_t&) const = 0;
5399             virtual std::size_t vector_size()              const = 0;
5400          };
5401
5402          class array_vector_impl : public vector_holder_base
5403          {
5404          public:
5405
5406             array_vector_impl(const Type* vec, const std::size_t& vec_size)
5407             : vec_(vec),
5408               size_(vec_size)
5409             {}
5410
5411          protected:
5412
5413             value_ptr value_at(const std::size_t& index) const
5414             {
5415                if (index < size_)
5416                   return const_cast<const_value_ptr>(vec_ + index);
5417                else
5418                   return const_value_ptr(0);
5419             }
5420
5421             std::size_t vector_size() const
5422             {
5423                return size_;
5424             }
5425
5426          private:
5427
5428             array_vector_impl operator=(const array_vector_impl&);
5429
5430             const Type* vec_;
5431             const std::size_t size_;
5432          };
5433
5434          template <typename Allocator,
5435                    template <typename, typename> class Sequence>
5436          class sequence_vector_impl : public vector_holder_base
5437          {
5438          public:
5439
5440             typedef Sequence<Type,Allocator> sequence_t;
5441
5442             sequence_vector_impl(sequence_t& seq)
5443             : sequence_(seq)
5444             {}
5445
5446          protected:
5447
5448             value_ptr value_at(const std::size_t& index) const
5449             {
5450                return (index < sequence_.size()) ? (&sequence_[index]) : const_value_ptr(0);
5451             }
5452
5453             std::size_t vector_size() const
5454             {
5455                return sequence_.size();
5456             }
5457
5458          private:
5459
5460             sequence_vector_impl operator=(const sequence_vector_impl&);
5461
5462             sequence_t& sequence_;
5463          };
5464
5465          class vector_view_impl : public vector_holder_base
5466          {
5467          public:
5468
5469             typedef exprtk::vector_view<Type> vector_view_t;
5470
5471             vector_view_impl(vector_view_t& vec_view)
5472             : vec_view_(vec_view)
5473             {}
5474
5475             void set_ref(value_ptr* ref)
5476             {
5477                vec_view_.set_ref(ref);
5478             }
5479
5480             virtual inline bool rebaseable() const
5481             {
5482                return true;
5483             }
5484
5485          protected:
5486
5487             value_ptr value_at(const std::size_t& index) const
5488             {
5489                return (index < vec_view_.size()) ? (&vec_view_[index]) : const_value_ptr(0);
5490             }
5491
5492             std::size_t vector_size() const
5493             {
5494                return vec_view_.size();
5495             }
5496
5497          private:
5498
5499             vector_view_impl operator=(const vector_view_impl&);
5500
5501             vector_view_t& vec_view_;
5502          };
5503
5504       public:
5505
5506          typedef typename details::vec_data_store<Type> vds_t;
5507
5508          vector_holder(Type* vec, const std::size_t& vec_size)
5509          : vector_holder_base_(new(buffer)array_vector_impl(vec,vec_size))
5510          {}
5511
5512          vector_holder(const vds_t& vds)
5513          : vector_holder_base_(new(buffer)array_vector_impl(vds.data(),vds.size()))
5514          {}
5515
5516          template <typename Allocator>
5517          vector_holder(std::vector<Type,Allocator>& vec)
5518          : vector_holder_base_(new(buffer)sequence_vector_impl<Allocator,std::vector>(vec))
5519          {}
5520
5521          vector_holder(exprtk::vector_view<Type>& vec)
5522          : vector_holder_base_(new(buffer)vector_view_impl(vec))
5523          {}
5524
5525          inline value_ptr operator[](const std::size_t& index) const
5526          {
5527             return (*vector_holder_base_)[index];
5528          }
5529
5530          inline std::size_t size() const
5531          {
5532             return vector_holder_base_->size();
5533          }
5534
5535          inline value_ptr data() const
5536          {
5537             return vector_holder_base_->data();
5538          }
5539
5540          void set_ref(value_ptr* ref)
5541          {
5542             vector_holder_base_->set_ref(ref);
5543          }
5544
5545          bool rebaseable() const
5546          {
5547             return vector_holder_base_->rebaseable();
5548          }
5549
5550       private:
5551
5552          mutable vector_holder_base* vector_holder_base_;
5553          uchar_t buffer[64];
5554       };
5555
5556       template <typename T>
5557       class null_node : public expression_node<T>
5558       {
5559       public:
5560
5561          inline T value() const
5562          {
5563             return std::numeric_limits<T>::quiet_NaN();
5564          }
5565
5566          inline typename expression_node<T>::node_type type() const
5567          {
5568             return expression_node<T>::e_null;
5569          }
5570       };
5571
5572       template <typename T>
5573       class null_eq_node : public expression_node<T>
5574       {
5575       public:
5576
5577          typedef expression_node<T>* expression_ptr;
5578
5579          null_eq_node(expression_ptr brnch, const bool equality = true)
5580          : branch_(brnch),
5581            branch_deletable_(branch_deletable(branch_)),
5582            equality_(equality)
5583          {}
5584
5585         ~null_eq_node()
5586          {
5587             if (branch_ && branch_deletable_)
5588             {
5589                destroy_node(branch_);
5590             }
5591          }
5592
5593          inline T value() const
5594          {
5595             const T v = branch_->value();
5596             const bool result = details::numeric::is_nan(v);
5597
5598             if (result)
5599                return (equality_) ? T(1) : T(0);
5600             else
5601                return (equality_) ? T(0) : T(1);
5602          }
5603
5604          inline typename expression_node<T>::node_type type() const
5605          {
5606             return expression_node<T>::e_nulleq;
5607          }
5608
5609          inline operator_type operation() const
5610          {
5611             return details::e_eq;
5612          }
5613
5614          inline expression_node<T>* branch(const std::size_t&) const
5615          {
5616             return branch_;
5617          }
5618
5619       private:
5620
5621          expression_ptr branch_;
5622          const bool branch_deletable_;
5623          bool equality_;
5624       };
5625
5626       template <typename T>
5627       class literal_node : public expression_node<T>
5628       {
5629       public:
5630
5631          explicit literal_node(const T& v)
5632          : value_(v)
5633          {}
5634
5635          inline T value() const
5636          {
5637             return value_;
5638          }
5639
5640          inline typename expression_node<T>::node_type type() const
5641          {
5642             return expression_node<T>::e_constant;
5643          }
5644
5645          inline expression_node<T>* branch(const std::size_t&) const
5646          {
5647             return reinterpret_cast<expression_node<T>*>(0);
5648          }
5649
5650       private:
5651
5652          literal_node(literal_node<T>&) {}
5653          literal_node<T>& operator=(literal_node<T>&) { return (*this); }
5654
5655          const T value_;
5656       };
5657
5658       template <typename T>
5659       struct range_pack;
5660
5661       template <typename T>
5662       struct range_data_type;
5663
5664       template <typename T>
5665       class range_interface
5666       {
5667       public:
5668
5669          typedef range_pack<T> range_t;
5670
5671          virtual ~range_interface()
5672          {}
5673
5674          virtual range_t& range_ref() = 0;
5675
5676          virtual const range_t& range_ref() const = 0;
5677       };
5678
5679       #ifndef exprtk_disable_string_capabilities
5680       template <typename T>
5681       class string_base_node
5682       {
5683       public:
5684
5685          typedef range_data_type<T> range_data_type_t;
5686
5687          virtual ~string_base_node()
5688          {}
5689
5690          virtual std::string str () const = 0;
5691
5692          virtual char_cptr   base() const = 0;
5693
5694          virtual std::size_t size() const = 0;
5695       };
5696
5697       template <typename T>
5698       class string_literal_node : public expression_node <T>,
5699                                   public string_base_node<T>,
5700                                   public range_interface <T>
5701       {
5702       public:
5703
5704          typedef range_pack<T> range_t;
5705
5706          explicit string_literal_node(const std::string& v)
5707          : value_(v)
5708          {
5709             rp_.n0_c = std::make_pair<bool,std::size_t>(true,0);
5710             rp_.n1_c = std::make_pair<bool,std::size_t>(true,v.size() - 1);
5711             rp_.cache.first  = rp_.n0_c.second;
5712             rp_.cache.second = rp_.n1_c.second;
5713          }
5714
5715          inline T value() const
5716          {
5717             return std::numeric_limits<T>::quiet_NaN();
5718          }
5719
5720          inline typename expression_node<T>::node_type type() const
5721          {
5722             return expression_node<T>::e_stringconst;
5723          }
5724
5725          inline expression_node<T>* branch(const std::size_t&) const
5726          {
5727             return reinterpret_cast<expression_node<T>*>(0);
5728          }
5729
5730          std::string str() const
5731          {
5732             return value_;
5733          }
5734
5735          char_cptr base() const
5736          {
5737             return value_.data();
5738          }
5739
5740          std::size_t size() const
5741          {
5742             return value_.size();
5743          }
5744
5745          range_t& range_ref()
5746          {
5747             return rp_;
5748          }
5749
5750          const range_t& range_ref() const
5751          {
5752             return rp_;
5753          }
5754
5755       private:
5756
5757          string_literal_node(const string_literal_node<T>&);
5758          string_literal_node<T>& operator=(const string_literal_node<T>&);
5759
5760          const std::string value_;
5761          range_t rp_;
5762       };
5763       #endif
5764
5765       template <typename T>
5766       class unary_node : public expression_node<T>
5767       {
5768       public:
5769
5770          typedef expression_node<T>* expression_ptr;
5771
5772          unary_node(const operator_type& opr,
5773                     expression_ptr brnch)
5774          : operation_(opr),
5775            branch_(brnch),
5776            branch_deletable_(branch_deletable(branch_))
5777          {}
5778
5779         ~unary_node()
5780          {
5781             if (branch_ && branch_deletable_)
5782             {
5783                destroy_node(branch_);
5784             }
5785          }
5786
5787          inline T value() const
5788          {
5789             const T arg = branch_->value();
5790
5791             return numeric::process<T>(operation_,arg);
5792          }
5793
5794          inline typename expression_node<T>::node_type type() const
5795          {
5796             return expression_node<T>::e_unary;
5797          }
5798
5799          inline operator_type operation() const
5800          {
5801             return operation_;
5802          }
5803
5804          inline expression_node<T>* branch(const std::size_t&) const
5805          {
5806             return branch_;
5807          }
5808
5809          inline void release()
5810          {
5811             branch_deletable_ = false;
5812          }
5813
5814       protected:
5815
5816          operator_type operation_;
5817          expression_ptr branch_;
5818          bool branch_deletable_;
5819       };
5820
5821       template <typename T, std::size_t D, bool B>
5822       struct construct_branch_pair
5823       {
5824          template <std::size_t N>
5825          static inline void process(std::pair<expression_node<T>*,bool> (&)[N], expression_node<T>*)
5826          {}
5827       };
5828
5829       template <typename T, std::size_t D>
5830       struct construct_branch_pair<T,D,true>
5831       {
5832          template <std::size_t N>
5833          static inline void process(std::pair<expression_node<T>*,bool> (&branch)[N], expression_node<T>* b)
5834          {
5835             if (b)
5836             {
5837                branch[D] = std::make_pair(b,branch_deletable(b));
5838             }
5839          }
5840       };
5841
5842       template <std::size_t N, typename T>
5843       inline void init_branches(std::pair<expression_node<T>*,bool> (&branch)[N],
5844                                 expression_node<T>* b0,
5845                                 expression_node<T>* b1 = reinterpret_cast<expression_node<T>*>(0),
5846                                 expression_node<T>* b2 = reinterpret_cast<expression_node<T>*>(0),
5847                                 expression_node<T>* b3 = reinterpret_cast<expression_node<T>*>(0),
5848                                 expression_node<T>* b4 = reinterpret_cast<expression_node<T>*>(0),
5849                                 expression_node<T>* b5 = reinterpret_cast<expression_node<T>*>(0),
5850                                 expression_node<T>* b6 = reinterpret_cast<expression_node<T>*>(0),
5851                                 expression_node<T>* b7 = reinterpret_cast<expression_node<T>*>(0),
5852                                 expression_node<T>* b8 = reinterpret_cast<expression_node<T>*>(0),
5853                                 expression_node<T>* b9 = reinterpret_cast<expression_node<T>*>(0))
5854       {
5855          construct_branch_pair<T,0,(N > 0)>::process(branch,b0);
5856          construct_branch_pair<T,1,(N > 1)>::process(branch,b1);
5857          construct_branch_pair<T,2,(N > 2)>::process(branch,b2);
5858          construct_branch_pair<T,3,(N > 3)>::process(branch,b3);
5859          construct_branch_pair<T,4,(N > 4)>::process(branch,b4);
5860          construct_branch_pair<T,5,(N > 5)>::process(branch,b5);
5861          construct_branch_pair<T,6,(N > 6)>::process(branch,b6);
5862          construct_branch_pair<T,7,(N > 7)>::process(branch,b7);
5863          construct_branch_pair<T,8,(N > 8)>::process(branch,b8);
5864          construct_branch_pair<T,9,(N > 9)>::process(branch,b9);
5865       }
5866
5867       struct cleanup_branches
5868       {
5869          template <typename T, std::size_t N>
5870          static inline void execute(std::pair<expression_node<T>*,bool> (&branch)[N])
5871          {
5872             for (std::size_t i = 0; i < N; ++i)
5873             {
5874                if (branch[i].first && branch[i].second)
5875                {
5876                   destroy_node(branch[i].first);
5877                }
5878             }
5879          }
5880
5881          template <typename T,
5882                    typename Allocator,
5883                    template <typename, typename> class Sequence>
5884          static inline void execute(Sequence<std::pair<expression_node<T>*,bool>,Allocator>& branch)
5885          {
5886             for (std::size_t i = 0; i < branch.size(); ++i)
5887             {
5888                if (branch[i].first && branch[i].second)
5889                {
5890                   destroy_node(branch[i].first);
5891                }
5892             }
5893          }
5894       };
5895
5896       template <typename T>
5897       class binary_node : public expression_node<T>
5898       {
5899       public:
5900
5901          typedef expression_node<T>* expression_ptr;
5902          typedef std::pair<expression_ptr,bool> branch_t;
5903
5904          binary_node(const operator_type& opr,
5905                      expression_ptr branch0,
5906                      expression_ptr branch1)
5907          : operation_(opr)
5908          {
5909             init_branches<2>(branch_, branch0, branch1);
5910          }
5911
5912         ~binary_node()
5913          {
5914             cleanup_branches::execute<T,2>(branch_);
5915          }
5916
5917          inline T value() const
5918          {
5919             const T arg0 = branch_[0].first->value();
5920             const T arg1 = branch_[1].first->value();
5921
5922             return numeric::process<T>(operation_,arg0,arg1);
5923          }
5924
5925          inline typename expression_node<T>::node_type type() const
5926          {
5927             return expression_node<T>::e_binary;
5928          }
5929
5930          inline operator_type operation()
5931          {
5932             return operation_;
5933          }
5934
5935          inline expression_node<T>* branch(const std::size_t& index = 0) const
5936          {
5937             if (0 == index)
5938                return branch_[0].first;
5939             else if (1 == index)
5940                return branch_[1].first;
5941             else
5942                return reinterpret_cast<expression_ptr>(0);
5943          }
5944
5945       protected:
5946
5947          operator_type operation_;
5948          branch_t branch_[2];
5949       };
5950
5951       template <typename T, typename Operation>
5952       class binary_ext_node : public expression_node<T>
5953       {
5954       public:
5955
5956          typedef expression_node<T>* expression_ptr;
5957          typedef std::pair<expression_ptr,bool> branch_t;
5958
5959          binary_ext_node(expression_ptr branch0, expression_ptr branch1)
5960          {
5961             init_branches<2>(branch_, branch0, branch1);
5962          }
5963
5964         ~binary_ext_node()
5965          {
5966             cleanup_branches::execute<T,2>(branch_);
5967          }
5968
5969          inline T value() const
5970          {
5971             const T arg0 = branch_[0].first->value();
5972             const T arg1 = branch_[1].first->value();
5973
5974             return Operation::process(arg0,arg1);
5975          }
5976
5977          inline typename expression_node<T>::node_type type() const
5978          {
5979             return expression_node<T>::e_binary_ext;
5980          }
5981
5982          inline operator_type operation()
5983          {
5984             return Operation::operation();
5985          }
5986
5987          inline expression_node<T>* branch(const std::size_t& index = 0) const
5988          {
5989             if (0 == index)
5990                return branch_[0].first;
5991             else if (1 == index)
5992                return branch_[1].first;
5993             else
5994                return reinterpret_cast<expression_ptr>(0);
5995          }
5996
5997       protected:
5998
5999          branch_t branch_[2];
6000       };
6001
6002       template <typename T>
6003       class trinary_node : public expression_node<T>
6004       {
6005       public:
6006
6007          typedef expression_node<T>* expression_ptr;
6008          typedef std::pair<expression_ptr,bool> branch_t;
6009
6010          trinary_node(const operator_type& opr,
6011                       expression_ptr branch0,
6012                       expression_ptr branch1,
6013                       expression_ptr branch2)
6014          : operation_(opr)
6015          {
6016             init_branches<3>(branch_, branch0, branch1, branch2);
6017          }
6018
6019         ~trinary_node()
6020          {
6021             cleanup_branches::execute<T,3>(branch_);
6022          }
6023
6024          inline T value() const
6025          {
6026             const T arg0 = branch_[0].first->value();
6027             const T arg1 = branch_[1].first->value();
6028             const T arg2 = branch_[2].first->value();
6029
6030             switch (operation_)
6031             {
6032                case e_inrange : return (arg1 < arg0) ? T(0) : ((arg1 > arg2) ? T(0) : T(1));
6033
6034                case e_clamp   : return (arg1 < arg0) ? arg0 : (arg1 > arg2 ? arg2 : arg1);
6035
6036                case e_iclamp  : if ((arg1 <= arg0) || (arg1 >= arg2))
6037                                    return arg1;
6038                                 else
6039                                    return ((T(2) * arg1  <= (arg2 + arg0)) ? arg0 : arg2);
6040
6041                default        : exprtk_debug(("trinary_node::value() - Error: Invalid operation\n"));
6042                                 return std::numeric_limits<T>::quiet_NaN();
6043             }
6044          }
6045
6046          inline typename expression_node<T>::node_type type() const
6047          {
6048             return expression_node<T>::e_trinary;
6049          }
6050
6051       protected:
6052
6053          operator_type operation_;
6054          branch_t branch_[3];
6055       };
6056
6057       template <typename T>
6058       class quaternary_node : public expression_node<T>
6059       {
6060       public:
6061
6062          typedef expression_node<T>* expression_ptr;
6063          typedef std::pair<expression_ptr,bool> branch_t;
6064
6065          quaternary_node(const operator_type& opr,
6066                          expression_ptr branch0,
6067                          expression_ptr branch1,
6068                          expression_ptr branch2,
6069                          expression_ptr branch3)
6070          : operation_(opr)
6071          {
6072             init_branches<4>(branch_, branch0, branch1, branch2, branch3);
6073          }
6074
6075         ~quaternary_node()
6076          {
6077             cleanup_branches::execute<T,4>(branch_);
6078          }
6079
6080          inline T value() const
6081          {
6082             return std::numeric_limits<T>::quiet_NaN();
6083          }
6084
6085          inline typename expression_node<T>::node_type type() const
6086          {
6087             return expression_node<T>::e_quaternary;
6088          }
6089
6090       protected:
6091
6092          operator_type operation_;
6093          branch_t branch_[4];
6094       };
6095
6096       template <typename T>
6097       class conditional_node : public expression_node<T>
6098       {
6099       public:
6100
6101          typedef expression_node<T>* expression_ptr;
6102
6103          conditional_node(expression_ptr test,
6104                           expression_ptr consequent,
6105                           expression_ptr alternative)
6106          : test_(test),
6107            consequent_(consequent),
6108            alternative_(alternative),
6109            test_deletable_(branch_deletable(test_)),
6110            consequent_deletable_(branch_deletable(consequent_)),
6111            alternative_deletable_(branch_deletable(alternative_))
6112          {}
6113
6114         ~conditional_node()
6115          {
6116             if (test_ && test_deletable_)
6117             {
6118                destroy_node(test_);
6119             }
6120
6121             if (consequent_ && consequent_deletable_ )
6122             {
6123                destroy_node(consequent_);
6124             }
6125
6126             if (alternative_ && alternative_deletable_)
6127             {
6128                destroy_node(alternative_);
6129             }
6130          }
6131
6132          inline T value() const
6133          {
6134             if (is_true(test_))
6135                return consequent_->value();
6136             else
6137                return alternative_->value();
6138          }
6139
6140          inline typename expression_node<T>::node_type type() const
6141          {
6142             return expression_node<T>::e_conditional;
6143          }
6144
6145       private:
6146
6147          expression_ptr test_;
6148          expression_ptr consequent_;
6149          expression_ptr alternative_;
6150          const bool test_deletable_;
6151          const bool consequent_deletable_;
6152          const bool alternative_deletable_;
6153       };
6154
6155       template <typename T>
6156       class cons_conditional_node : public expression_node<T>
6157       {
6158       public:
6159
6160          // Consequent only conditional statement node
6161          typedef expression_node<T>* expression_ptr;
6162
6163          cons_conditional_node(expression_ptr test,
6164                                expression_ptr consequent)
6165          : test_(test),
6166            consequent_(consequent),
6167            test_deletable_(branch_deletable(test_)),
6168            consequent_deletable_(branch_deletable(consequent_))
6169          {}
6170
6171         ~cons_conditional_node()
6172          {
6173             if (test_ && test_deletable_)
6174             {
6175                destroy_node(test_);
6176             }
6177
6178             if (consequent_ && consequent_deletable_)
6179             {
6180                destroy_node(consequent_);
6181             }
6182          }
6183
6184          inline T value() const
6185          {
6186             if (is_true(test_))
6187                return consequent_->value();
6188             else
6189                return std::numeric_limits<T>::quiet_NaN();
6190          }
6191
6192          inline typename expression_node<T>::node_type type() const
6193          {
6194             return expression_node<T>::e_conditional;
6195          }
6196
6197       private:
6198
6199          expression_ptr test_;
6200          expression_ptr consequent_;
6201          const bool test_deletable_;
6202          const bool consequent_deletable_;
6203       };
6204
6205       #ifndef exprtk_disable_break_continue
6206       template <typename T>
6207       class break_exception
6208       {
6209       public:
6210
6211          break_exception(const T& v)
6212          : value(v)
6213          {}
6214
6215          T value;
6216       };
6217
6218       class continue_exception
6219       {};
6220
6221       template <typename T>
6222       class break_node : public expression_node<T>
6223       {
6224       public:
6225
6226          typedef expression_node<T>* expression_ptr;
6227
6228          break_node(expression_ptr ret = expression_ptr(0))
6229          : return_(ret),
6230            return_deletable_(branch_deletable(return_))
6231          {}
6232
6233         ~break_node()
6234          {
6235             if (return_deletable_)
6236             {
6237                destroy_node(return_);
6238             }
6239          }
6240
6241          inline T value() const
6242          {
6243             throw break_exception<T>(return_ ? return_->value() : std::numeric_limits<T>::quiet_NaN());
6244             #ifndef _MSC_VER
6245             return std::numeric_limits<T>::quiet_NaN();
6246             #endif
6247          }
6248
6249          inline typename expression_node<T>::node_type type() const
6250          {
6251             return expression_node<T>::e_break;
6252          }
6253
6254       private:
6255
6256          expression_ptr return_;
6257          const bool return_deletable_;
6258       };
6259
6260       template <typename T>
6261       class continue_node : public expression_node<T>
6262       {
6263       public:
6264
6265          inline T value() const
6266          {
6267             throw continue_exception();
6268             #ifndef _MSC_VER
6269             return std::numeric_limits<T>::quiet_NaN();
6270             #endif
6271          }
6272
6273          inline typename expression_node<T>::node_type type() const
6274          {
6275             return expression_node<T>::e_break;
6276          }
6277       };
6278       #endif
6279
6280       template <typename T>
6281       class while_loop_node : public expression_node<T>
6282       {
6283       public:
6284
6285          typedef expression_node<T>* expression_ptr;
6286
6287          while_loop_node(expression_ptr condition, expression_ptr loop_body)
6288          : condition_(condition),
6289            loop_body_(loop_body),
6290            condition_deletable_(branch_deletable(condition_)),
6291            loop_body_deletable_(branch_deletable(loop_body_))
6292          {}
6293
6294         ~while_loop_node()
6295          {
6296             if (condition_ && condition_deletable_)
6297             {
6298                destroy_node(condition_);
6299             }
6300
6301             if (loop_body_ && loop_body_deletable_)
6302             {
6303                destroy_node(loop_body_);
6304             }
6305          }
6306
6307          inline T value() const
6308          {
6309             T result = T(0);
6310
6311             while (is_true(condition_))
6312             {
6313                result = loop_body_->value();
6314             }
6315
6316             return result;
6317          }
6318
6319          inline typename expression_node<T>::node_type type() const
6320          {
6321             return expression_node<T>::e_while;
6322          }
6323
6324       private:
6325
6326          expression_ptr condition_;
6327          expression_ptr loop_body_;
6328          const bool condition_deletable_;
6329          const bool loop_body_deletable_;
6330       };
6331
6332       template <typename T>
6333       class repeat_until_loop_node : public expression_node<T>
6334       {
6335       public:
6336
6337          typedef expression_node<T>* expression_ptr;
6338
6339          repeat_until_loop_node(expression_ptr condition, expression_ptr loop_body)
6340          : condition_(condition),
6341            loop_body_(loop_body),
6342            condition_deletable_(branch_deletable(condition_)),
6343            loop_body_deletable_(branch_deletable(loop_body_))
6344          {}
6345
6346         ~repeat_until_loop_node()
6347          {
6348             if (condition_ && condition_deletable_)
6349             {
6350                destroy_node(condition_);
6351             }
6352
6353             if (loop_body_ && loop_body_deletable_)
6354             {
6355                destroy_node(loop_body_);
6356             }
6357          }
6358
6359          inline T value() const
6360          {
6361             T result = T(0);
6362
6363             do
6364             {
6365                result = loop_body_->value();
6366             }
6367             while (is_false(condition_));
6368
6369             return result;
6370          }
6371
6372          inline typename expression_node<T>::node_type type() const
6373          {
6374             return expression_node<T>::e_repeat;
6375          }
6376
6377       private:
6378
6379          expression_ptr condition_;
6380          expression_ptr loop_body_;
6381          const bool condition_deletable_;
6382          const bool loop_body_deletable_;
6383       };
6384
6385       template <typename T>
6386       class for_loop_node : public expression_node<T>
6387       {
6388       public:
6389
6390          typedef expression_node<T>* expression_ptr;
6391
6392          for_loop_node(expression_ptr initialiser,
6393                        expression_ptr condition,
6394                        expression_ptr incrementor,
6395                        expression_ptr loop_body)
6396          : initialiser_(initialiser),
6397            condition_  (condition  ),
6398            incrementor_(incrementor),
6399            loop_body_  (loop_body  ),
6400            initialiser_deletable_(branch_deletable(initialiser_)),
6401            condition_deletable_  (branch_deletable(condition_  )),
6402            incrementor_deletable_(branch_deletable(incrementor_)),
6403            loop_body_deletable_  (branch_deletable(loop_body_  ))
6404          {}
6405
6406         ~for_loop_node()
6407          {
6408             if (initialiser_ && initialiser_deletable_)
6409             {
6410                destroy_node(initialiser_);
6411             }
6412
6413             if (condition_ && condition_deletable_)
6414             {
6415                destroy_node(condition_);
6416             }
6417
6418             if (incrementor_ && incrementor_deletable_)
6419             {
6420                destroy_node(incrementor_);
6421             }
6422
6423             if (loop_body_ && loop_body_deletable_)
6424             {
6425                destroy_node(loop_body_);
6426             }
6427          }
6428
6429          inline T value() const
6430          {
6431             T result = T(0);
6432
6433             if (initialiser_)
6434                initialiser_->value();
6435
6436             if (incrementor_)
6437             {
6438                while (is_true(condition_))
6439                {
6440                   result = loop_body_->value();
6441                   incrementor_->value();
6442                }
6443             }
6444             else
6445             {
6446                while (is_true(condition_))
6447                {
6448                   result = loop_body_->value();
6449                }
6450             }
6451
6452             return result;
6453          }
6454
6455          inline typename expression_node<T>::node_type type() const
6456          {
6457             return expression_node<T>::e_for;
6458          }
6459
6460       private:
6461
6462          expression_ptr initialiser_      ;
6463          expression_ptr condition_        ;
6464          expression_ptr incrementor_      ;
6465          expression_ptr loop_body_        ;
6466          const bool initialiser_deletable_;
6467          const bool condition_deletable_  ;
6468          const bool incrementor_deletable_;
6469          const bool loop_body_deletable_  ;
6470       };
6471
6472       #ifndef exprtk_disable_break_continue
6473       template <typename T>
6474       class while_loop_bc_node : public expression_node<T>
6475       {
6476       public:
6477
6478          typedef expression_node<T>* expression_ptr;
6479
6480          while_loop_bc_node(expression_ptr condition, expression_ptr loop_body)
6481          : condition_(condition),
6482            loop_body_(loop_body),
6483            condition_deletable_(branch_deletable(condition_)),
6484            loop_body_deletable_(branch_deletable(loop_body_))
6485          {}
6486
6487         ~while_loop_bc_node()
6488          {
6489             if (condition_ && condition_deletable_)
6490             {
6491                destroy_node(condition_);
6492             }
6493
6494             if (loop_body_ && loop_body_deletable_)
6495             {
6496                destroy_node(loop_body_);
6497             }
6498          }
6499
6500          inline T value() const
6501          {
6502             T result = T(0);
6503
6504             while (is_true(condition_))
6505             {
6506                try
6507                {
6508                   result = loop_body_->value();
6509                }
6510                catch(const break_exception<T>& e)
6511                {
6512                   return e.value;
6513                }
6514                catch(const continue_exception&)
6515                {}
6516             }
6517
6518             return result;
6519          }
6520
6521          inline typename expression_node<T>::node_type type() const
6522          {
6523             return expression_node<T>::e_while;
6524          }
6525
6526       private:
6527
6528          expression_ptr condition_;
6529          expression_ptr loop_body_;
6530          const bool condition_deletable_;
6531          const bool loop_body_deletable_;
6532       };
6533
6534       template <typename T>
6535       class repeat_until_loop_bc_node : public expression_node<T>
6536       {
6537       public:
6538
6539          typedef expression_node<T>* expression_ptr;
6540
6541          repeat_until_loop_bc_node(expression_ptr condition, expression_ptr loop_body)
6542          : condition_(condition),
6543            loop_body_(loop_body),
6544            condition_deletable_(branch_deletable(condition_)),
6545            loop_body_deletable_(branch_deletable(loop_body_))
6546          {}
6547
6548         ~repeat_until_loop_bc_node()
6549          {
6550             if (condition_ && condition_deletable_)
6551             {
6552                destroy_node(condition_);
6553             }
6554
6555             if (loop_body_ && loop_body_deletable_)
6556             {
6557                destroy_node(loop_body_);
6558             }
6559          }
6560
6561          inline T value() const
6562          {
6563             T result = T(0);
6564
6565             do
6566             {
6567                try
6568                {
6569                   result = loop_body_->value();
6570                }
6571                catch(const break_exception<T>& e)
6572                {
6573                   return e.value;
6574                }
6575                catch(const continue_exception&)
6576                {}
6577             }
6578             while (is_false(condition_));
6579
6580             return result;
6581          }
6582
6583          inline typename expression_node<T>::node_type type() const
6584          {
6585             return expression_node<T>::e_repeat;
6586          }
6587
6588       private:
6589
6590          expression_ptr condition_;
6591          expression_ptr loop_body_;
6592          const bool condition_deletable_;
6593          const bool loop_body_deletable_;
6594       };
6595
6596       template <typename T>
6597       class for_loop_bc_node : public expression_node<T>
6598       {
6599       public:
6600
6601          typedef expression_node<T>* expression_ptr;
6602
6603          for_loop_bc_node(expression_ptr initialiser,
6604                        expression_ptr condition,
6605                        expression_ptr incrementor,
6606                        expression_ptr loop_body)
6607          : initialiser_(initialiser),
6608            condition_  (condition  ),
6609            incrementor_(incrementor),
6610            loop_body_  (loop_body  ),
6611            initialiser_deletable_(branch_deletable(initialiser_)),
6612            condition_deletable_  (branch_deletable(condition_  )),
6613            incrementor_deletable_(branch_deletable(incrementor_)),
6614            loop_body_deletable_  (branch_deletable(loop_body_  ))
6615          {}
6616
6617         ~for_loop_bc_node()
6618          {
6619             if (initialiser_ && initialiser_deletable_)
6620             {
6621                destroy_node(initialiser_);
6622             }
6623
6624             if (condition_ && condition_deletable_)
6625             {
6626                destroy_node(condition_);
6627             }
6628
6629             if (incrementor_ && incrementor_deletable_)
6630             {
6631                destroy_node(incrementor_);
6632             }
6633
6634             if (loop_body_ && loop_body_deletable_)
6635             {
6636                destroy_node(loop_body_);
6637             }
6638          }
6639
6640          inline T value() const
6641          {
6642             T result = T(0);
6643
6644             if (initialiser_)
6645                initialiser_->value();
6646
6647             if (incrementor_)
6648             {
6649                while (is_true(condition_))
6650                {
6651                   try
6652                   {
6653                      result = loop_body_->value();
6654                   }
6655                   catch(const break_exception<T>& e)
6656                   {
6657                      return e.value;
6658                   }
6659                   catch(const continue_exception&)
6660                   {}
6661
6662                   incrementor_->value();
6663                }
6664             }
6665             else
6666             {
6667                while (is_true(condition_))
6668                {
6669                   try
6670                   {
6671                      result = loop_body_->value();
6672                   }
6673                   catch(const break_exception<T>& e)
6674                   {
6675                      return e.value;
6676                   }
6677                   catch(const continue_exception&)
6678                   {}
6679                }
6680             }
6681
6682             return result;
6683          }
6684
6685          inline typename expression_node<T>::node_type type() const
6686          {
6687             return expression_node<T>::e_for;
6688          }
6689
6690       private:
6691
6692          expression_ptr initialiser_;
6693          expression_ptr condition_  ;
6694          expression_ptr incrementor_;
6695          expression_ptr loop_body_  ;
6696          const bool initialiser_deletable_;
6697          const bool condition_deletable_  ;
6698          const bool incrementor_deletable_;
6699          const bool loop_body_deletable_  ;
6700       };
6701       #endif
6702
6703       template <typename T>
6704       class switch_node : public expression_node<T>
6705       {
6706       public:
6707
6708          typedef expression_node<T>* expression_ptr;
6709
6710          template <typename Allocator,
6711                    template <typename, typename> class Sequence>
6712          explicit switch_node(const Sequence<expression_ptr,Allocator>& arg_list)
6713          {
6714             if (1 != (arg_list.size() & 1))
6715                return;
6716
6717             arg_list_.resize(arg_list.size());
6718             delete_branch_.resize(arg_list.size());
6719
6720             for (std::size_t i = 0; i < arg_list.size(); ++i)
6721             {
6722                if (arg_list[i])
6723                {
6724                        arg_list_[i] = arg_list[i];
6725                   delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0);
6726                }
6727                else
6728                {
6729                   arg_list_.clear();
6730                   delete_branch_.clear();
6731                   return;
6732                }
6733             }
6734          }
6735
6736         ~switch_node()
6737          {
6738             for (std::size_t i = 0; i < arg_list_.size(); ++i)
6739             {
6740                if (arg_list_[i] && delete_branch_[i])
6741                {
6742                   destroy_node(arg_list_[i]);
6743                }
6744             }
6745          }
6746
6747          inline T value() const
6748          {
6749             if (!arg_list_.empty())
6750             {
6751                const std::size_t upper_bound = (arg_list_.size() - 1);
6752
6753                for (std::size_t i = 0; i < upper_bound; i += 2)
6754                {
6755                   expression_ptr condition  = arg_list_[i    ];
6756                   expression_ptr consequent = arg_list_[i + 1];
6757
6758                   if (is_true(condition))
6759                   {
6760                      return consequent->value();
6761                   }
6762                }
6763
6764                return arg_list_[upper_bound]->value();
6765             }
6766             else
6767                return std::numeric_limits<T>::quiet_NaN();
6768          }
6769
6770          inline typename expression_node<T>::node_type type() const
6771          {
6772             return expression_node<T>::e_switch;
6773          }
6774
6775       protected:
6776
6777          std::vector<expression_ptr> arg_list_;
6778          std::vector<unsigned char> delete_branch_;
6779       };
6780
6781       template <typename T, typename Switch_N>
6782       class switch_n_node : public switch_node<T>
6783       {
6784       public:
6785
6786          typedef expression_node<T>* expression_ptr;
6787
6788          template <typename Allocator,
6789                    template <typename, typename> class Sequence>
6790          explicit switch_n_node(const Sequence<expression_ptr,Allocator>& arg_list)
6791          : switch_node<T>(arg_list)
6792          {}
6793
6794          inline T value() const
6795          {
6796             return Switch_N::process(switch_node<T>::arg_list_);
6797          }
6798       };
6799
6800       template <typename T>
6801       class multi_switch_node : public expression_node<T>
6802       {
6803       public:
6804
6805          typedef expression_node<T>* expression_ptr;
6806
6807          template <typename Allocator,
6808                    template <typename, typename> class Sequence>
6809          explicit multi_switch_node(const Sequence<expression_ptr,Allocator>& arg_list)
6810          {
6811             if (0 != (arg_list.size() & 1))
6812                return;
6813
6814             arg_list_.resize(arg_list.size());
6815             delete_branch_.resize(arg_list.size());
6816
6817             for (std::size_t i = 0; i < arg_list.size(); ++i)
6818             {
6819                if (arg_list[i])
6820                {
6821                        arg_list_[i] = arg_list[i];
6822                   delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0);
6823                }
6824                else
6825                {
6826                   arg_list_.clear();
6827                   delete_branch_.clear();
6828                   return;
6829                }
6830             }
6831          }
6832
6833         ~multi_switch_node()
6834          {
6835             for (std::size_t i = 0; i < arg_list_.size(); ++i)
6836             {
6837                if (arg_list_[i] && delete_branch_[i])
6838                {
6839                   destroy_node(arg_list_[i]);
6840                }
6841             }
6842          }
6843
6844          inline T value() const
6845          {
6846             T result = T(0);
6847
6848             if (arg_list_.empty())
6849             {
6850                return std::numeric_limits<T>::quiet_NaN();
6851             }
6852
6853             const std::size_t upper_bound = (arg_list_.size() - 1);
6854
6855             for (std::size_t i = 0; i < upper_bound; i += 2)
6856             {
6857                expression_ptr condition  = arg_list_[i    ];
6858                expression_ptr consequent = arg_list_[i + 1];
6859
6860                if (is_true(condition))
6861                {
6862                   result = consequent->value();
6863                }
6864             }
6865
6866             return result;
6867          }
6868
6869          inline typename expression_node<T>::node_type type() const
6870          {
6871             return expression_node<T>::e_mswitch;
6872          }
6873
6874       private:
6875
6876          std::vector<expression_ptr> arg_list_;
6877          std::vector<unsigned char> delete_branch_;
6878       };
6879
6880       template <typename T>
6881       class ivariable
6882       {
6883       public:
6884
6885          virtual ~ivariable()
6886          {}
6887
6888          virtual T& ref() = 0;
6889          virtual const T& ref() const = 0;
6890       };
6891
6892       template <typename T>
6893       class variable_node : public expression_node<T>,
6894                             public ivariable      <T>
6895       {
6896       public:
6897
6898          static T null_value;
6899
6900          explicit variable_node()
6901          : value_(&null_value)
6902          {}
6903
6904          explicit variable_node(T& v)
6905          : value_(&v)
6906          {}
6907
6908          inline bool operator <(const variable_node<T>& v) const
6909          {
6910             return this < (&v);
6911          }
6912
6913          inline T value() const
6914          {
6915             return (*value_);
6916          }
6917
6918          inline T& ref()
6919          {
6920             return (*value_);
6921          }
6922
6923          inline const T& ref() const
6924          {
6925             return (*value_);
6926          }
6927
6928          inline typename expression_node<T>::node_type type() const
6929          {
6930             return expression_node<T>::e_variable;
6931          }
6932
6933       private:
6934
6935          T* value_;
6936       };
6937
6938       template <typename T>
6939       T variable_node<T>::null_value = T(std::numeric_limits<T>::quiet_NaN());
6940
6941       template <typename T>
6942       struct range_pack
6943       {
6944          typedef expression_node<T>*           expression_node_ptr;
6945          typedef std::pair<std::size_t,std::size_t> cached_range_t;
6946
6947          range_pack()
6948          : n0_e (std::make_pair(false,expression_node_ptr(0))),
6949            n1_e (std::make_pair(false,expression_node_ptr(0))),
6950            n0_c (std::make_pair(false,0)),
6951            n1_c (std::make_pair(false,0)),
6952            cache(std::make_pair(0,0))
6953          {}
6954
6955          void clear()
6956          {
6957             n0_e  = std::make_pair(false,expression_node_ptr(0));
6958             n1_e  = std::make_pair(false,expression_node_ptr(0));
6959             n0_c  = std::make_pair(false,0);
6960             n1_c  = std::make_pair(false,0);
6961             cache = std::make_pair(0,0);
6962          }
6963
6964          void free()
6965          {
6966             if (n0_e.first && n0_e.second)
6967             {
6968                n0_e.first = false;
6969
6970                if (
6971                     !is_variable_node(n0_e.second) &&
6972                     !is_string_node  (n0_e.second)
6973                   )
6974                {
6975                   destroy_node(n0_e.second);
6976                }
6977             }
6978
6979             if (n1_e.first && n1_e.second)
6980             {
6981                n1_e.first = false;
6982
6983                if (
6984                     !is_variable_node(n1_e.second) &&
6985                     !is_string_node  (n1_e.second)
6986                   )
6987                {
6988                   destroy_node(n1_e.second);
6989                }
6990             }
6991          }
6992
6993          bool const_range()
6994          {
6995            return ( n0_c.first &&  n1_c.first) &&
6996                   (!n0_e.first && !n1_e.first);
6997          }
6998
6999          bool var_range()
7000          {
7001            return ( n0_e.first &&  n1_e.first) &&
7002                   (!n0_c.first && !n1_c.first);
7003          }
7004
7005          bool operator() (std::size_t& r0, std::size_t& r1,
7006                           const std::size_t& size = std::numeric_limits<std::size_t>::max()) const
7007          {
7008             if (n0_c.first)
7009                r0 = n0_c.second;
7010             else if (n0_e.first)
7011             {
7012                const T r0_value = n0_e.second->value();
7013
7014                if (r0_value < 0)
7015                   return false;
7016                else
7017                   r0 = static_cast<std::size_t>(details::numeric::to_int64(r0_value));
7018             }
7019             else
7020                return false;
7021
7022             if (n1_c.first)
7023                r1 = n1_c.second;
7024             else if (n1_e.first)
7025             {
7026                const T r1_value = n1_e.second->value();
7027
7028                if (r1_value < 0)
7029                   return false;
7030                else
7031                   r1 = static_cast<std::size_t>(details::numeric::to_int64(r1_value));
7032             }
7033             else
7034                return false;
7035
7036             if (
7037                  (std::numeric_limits<std::size_t>::max() != size) &&
7038                  (std::numeric_limits<std::size_t>::max() == r1  )
7039                )
7040             {
7041                r1 = size - 1;
7042             }
7043
7044             cache.first  = r0;
7045             cache.second = r1;
7046
7047             return (r0 <= r1);
7048          }
7049
7050          inline std::size_t const_size() const
7051          {
7052             return (n1_c.second - n0_c.second + 1);
7053          }
7054
7055          inline std::size_t cache_size() const
7056          {
7057             return (cache.second - cache.first + 1);
7058          }
7059
7060          std::pair<bool,expression_node_ptr> n0_e;
7061          std::pair<bool,expression_node_ptr> n1_e;
7062          std::pair<bool,std::size_t        > n0_c;
7063          std::pair<bool,std::size_t        > n1_c;
7064          mutable cached_range_t             cache;
7065       };
7066
7067       template <typename T>
7068       class string_base_node;
7069
7070       template <typename T>
7071       struct range_data_type
7072       {
7073          typedef range_pack<T> range_t;
7074          typedef string_base_node<T>* strbase_ptr_t;
7075
7076          range_data_type()
7077          : range(0),
7078            data (0),
7079            size (0),
7080            type_size(0),
7081            str_node (0)
7082          {}
7083
7084          range_t*      range;
7085          void*         data;
7086          std::size_t   size;
7087          std::size_t   type_size;
7088          strbase_ptr_t str_node;
7089       };
7090
7091       template <typename T> class vector_node;
7092
7093       template <typename T>
7094       class vector_interface
7095       {
7096       public:
7097
7098          typedef vector_node<T>*   vector_node_ptr;
7099          typedef vec_data_store<T>           vds_t;
7100
7101          virtual ~vector_interface()
7102          {}
7103
7104          virtual std::size_t size   () const = 0;
7105
7106          virtual vector_node_ptr vec() const = 0;
7107
7108          virtual vector_node_ptr vec()       = 0;
7109
7110          virtual       vds_t& vds   ()       = 0;
7111
7112          virtual const vds_t& vds   () const = 0;
7113
7114          virtual bool side_effect   () const { return false; }
7115       };
7116
7117       template <typename T>
7118       class vector_node : public expression_node <T>,
7119                           public vector_interface<T>
7120       {
7121       public:
7122
7123          typedef expression_node<T>*  expression_ptr;
7124          typedef vector_holder<T>    vector_holder_t;
7125          typedef vector_node<T>*     vector_node_ptr;
7126          typedef vec_data_store<T>             vds_t;
7127
7128          explicit vector_node(vector_holder_t* vh)
7129          : vector_holder_(vh),
7130            vds_((*vector_holder_).size(),(*vector_holder_)[0])
7131          {
7132             vector_holder_->set_ref(&vds_.ref());
7133          }
7134
7135          vector_node(const vds_t& vds, vector_holder_t* vh)
7136          : vector_holder_(vh),
7137            vds_(vds)
7138          {}
7139
7140          inline T value() const
7141          {
7142             return vds().data()[0];
7143          }
7144
7145          vector_node_ptr vec() const
7146          {
7147             return const_cast<vector_node_ptr>(this);
7148          }
7149
7150          vector_node_ptr vec()
7151          {
7152             return this;
7153          }
7154
7155          inline typename expression_node<T>::node_type type() const
7156          {
7157             return expression_node<T>::e_vector;
7158          }
7159
7160          std::size_t size() const
7161          {
7162             return vds().size();
7163          }
7164
7165          vds_t& vds()
7166          {
7167             return vds_;
7168          }
7169
7170          const vds_t& vds() const
7171          {
7172             return vds_;
7173          }
7174
7175          inline vector_holder_t& vec_holder()
7176          {
7177             return (*vector_holder_);
7178          }
7179
7180       private:
7181
7182          vector_holder_t* vector_holder_;
7183          vds_t                      vds_;
7184       };
7185
7186       template <typename T>
7187       class vector_elem_node : public expression_node<T>,
7188                                public ivariable      <T>
7189       {
7190       public:
7191
7192          typedef expression_node<T>* expression_ptr;
7193          typedef vector_holder<T>    vector_holder_t;
7194          typedef vector_holder_t*    vector_holder_ptr;
7195
7196          vector_elem_node(expression_ptr index, vector_holder_ptr vec_holder)
7197          : index_(index),
7198            vec_holder_(vec_holder),
7199            vector_base_((*vec_holder)[0]),
7200            index_deletable_(branch_deletable(index_))
7201          {}
7202
7203         ~vector_elem_node()
7204          {
7205             if (index_ && index_deletable_)
7206             {
7207                destroy_node(index_);
7208             }
7209          }
7210
7211          inline T value() const
7212          {
7213             return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
7214          }
7215
7216          inline T& ref()
7217          {
7218             return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
7219          }
7220
7221          inline const T& ref() const
7222          {
7223             return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
7224          }
7225
7226          inline typename expression_node<T>::node_type type() const
7227          {
7228             return expression_node<T>::e_vecelem;
7229          }
7230
7231          inline vector_holder_t& vec_holder()
7232          {
7233             return (*vec_holder_);
7234          }
7235
7236       private:
7237
7238          expression_ptr index_;
7239          vector_holder_ptr vec_holder_;
7240          T* vector_base_;
7241          const bool index_deletable_;
7242       };
7243
7244       template <typename T>
7245       class rebasevector_elem_node : public expression_node<T>,
7246                                      public ivariable      <T>
7247       {
7248       public:
7249
7250          typedef expression_node<T>* expression_ptr;
7251          typedef vector_holder<T>    vector_holder_t;
7252          typedef vector_holder_t*    vector_holder_ptr;
7253          typedef vec_data_store<T>   vds_t;
7254
7255          rebasevector_elem_node(expression_ptr index, vector_holder_ptr vec_holder)
7256          : index_(index),
7257            index_deletable_(branch_deletable(index_)),
7258            vector_holder_(vec_holder),
7259            vds_((*vector_holder_).size(),(*vector_holder_)[0])
7260          {
7261             vector_holder_->set_ref(&vds_.ref());
7262          }
7263
7264         ~rebasevector_elem_node()
7265          {
7266             if (index_ && index_deletable_)
7267             {
7268                destroy_node(index_);
7269             }
7270          }
7271
7272          inline T value() const
7273          {
7274             return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
7275          }
7276
7277          inline T& ref()
7278          {
7279             return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
7280          }
7281
7282          inline const T& ref() const
7283          {
7284             return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
7285          }
7286
7287          inline typename expression_node<T>::node_type type() const
7288          {
7289             return expression_node<T>::e_rbvecelem;
7290          }
7291
7292          inline vector_holder_t& vec_holder()
7293          {
7294             return (*vector_holder_);
7295          }
7296
7297       private:
7298
7299          expression_ptr index_;
7300          const bool index_deletable_;
7301          vector_holder_ptr vector_holder_;
7302          vds_t             vds_;
7303       };
7304
7305       template <typename T>
7306       class rebasevector_celem_node : public expression_node<T>,
7307                                       public ivariable      <T>
7308       {
7309       public:
7310
7311          typedef expression_node<T>* expression_ptr;
7312          typedef vector_holder<T>    vector_holder_t;
7313          typedef vector_holder_t*    vector_holder_ptr;
7314          typedef vec_data_store<T>   vds_t;
7315
7316          rebasevector_celem_node(const std::size_t index, vector_holder_ptr vec_holder)
7317          : index_(index),
7318            vector_holder_(vec_holder),
7319            vds_((*vector_holder_).size(),(*vector_holder_)[0])
7320          {
7321             vector_holder_->set_ref(&vds_.ref());
7322          }
7323
7324          inline T value() const
7325          {
7326             return *(vds_.data() + index_);
7327          }
7328
7329          inline T& ref()
7330          {
7331             return *(vds_.data() + index_);
7332          }
7333
7334          inline const T& ref() const
7335          {
7336             return *(vds_.data() + index_);
7337          }
7338
7339          inline typename expression_node<T>::node_type type() const
7340          {
7341             return expression_node<T>::e_rbveccelem;
7342          }
7343
7344          inline vector_holder_t& vec_holder()
7345          {
7346             return (*vector_holder_);
7347          }
7348
7349       private:
7350
7351          const std::size_t index_;
7352          vector_holder_ptr vector_holder_;
7353          vds_t vds_;
7354       };
7355
7356       template <typename T>
7357       class vector_assignment_node : public expression_node<T>
7358       {
7359       public:
7360
7361          typedef expression_node<T>* expression_ptr;
7362
7363          vector_assignment_node(T* vector_base,
7364                                 const std::size_t& size,
7365                                 const std::vector<expression_ptr>& initialiser_list,
7366                                 const bool single_value_initialse)
7367          : vector_base_(vector_base),
7368            initialiser_list_(initialiser_list),
7369            size_(size),
7370            single_value_initialse_(single_value_initialse)
7371          {}
7372
7373         ~vector_assignment_node()
7374          {
7375             for (std::size_t i = 0; i < initialiser_list_.size(); ++i)
7376             {
7377                if (branch_deletable(initialiser_list_[i]))
7378                {
7379                   destroy_node(initialiser_list_[i]);
7380                }
7381             }
7382          }
7383
7384          inline T value() const
7385          {
7386             if (single_value_initialse_)
7387             {
7388                for (std::size_t i = 0; i < size_; ++i)
7389                {
7390                   *(vector_base_ + i) = initialiser_list_[0]->value();
7391                }
7392             }
7393             else
7394             {
7395                std::size_t il_size = initialiser_list_.size();
7396
7397                for (std::size_t i = 0; i < il_size; ++i)
7398                {
7399                   *(vector_base_ + i) = initialiser_list_[i]->value();
7400                }
7401
7402                if (il_size < size_)
7403                {
7404                   for (std::size_t i = il_size; i < size_; ++i)
7405                   {
7406                      *(vector_base_ + i) = T(0);
7407                   }
7408                }
7409             }
7410
7411             return *(vector_base_);
7412          }
7413
7414          inline typename expression_node<T>::node_type type() const
7415          {
7416             return expression_node<T>::e_vecdefass;
7417          }
7418
7419       private:
7420
7421          vector_assignment_node<T>& operator=(const vector_assignment_node<T>&);
7422
7423          mutable T* vector_base_;
7424          std::vector<expression_ptr> initialiser_list_;
7425          const std::size_t size_;
7426          const bool single_value_initialse_;
7427       };
7428
7429       template <typename T>
7430       class swap_node : public expression_node<T>
7431       {
7432       public:
7433
7434          typedef expression_node<T>* expression_ptr;
7435          typedef variable_node<T>*   variable_node_ptr;
7436
7437          swap_node(variable_node_ptr var0, variable_node_ptr var1)
7438          : var0_(var0),
7439            var1_(var1)
7440          {}
7441
7442          inline T value() const
7443          {
7444             std::swap(var0_->ref(),var1_->ref());
7445             return var1_->ref();
7446          }
7447
7448          inline typename expression_node<T>::node_type type() const
7449          {
7450             return expression_node<T>::e_swap;
7451          }
7452
7453       private:
7454
7455          variable_node_ptr var0_;
7456          variable_node_ptr var1_;
7457       };
7458
7459       template <typename T>
7460       class swap_generic_node : public binary_node<T>
7461       {
7462       public:
7463
7464          typedef expression_node<T>* expression_ptr;
7465          typedef ivariable<T>* ivariable_ptr;
7466
7467          swap_generic_node(expression_ptr var0, expression_ptr var1)
7468          : binary_node<T>(details::e_swap, var0, var1),
7469            var0_(dynamic_cast<ivariable_ptr>(var0)),
7470            var1_(dynamic_cast<ivariable_ptr>(var1))
7471          {}
7472
7473          inline T value() const
7474          {
7475             std::swap(var0_->ref(),var1_->ref());
7476             return var1_->ref();
7477          }
7478
7479          inline typename expression_node<T>::node_type type() const
7480          {
7481             return expression_node<T>::e_swap;
7482          }
7483
7484       private:
7485
7486          ivariable_ptr var0_;
7487          ivariable_ptr var1_;
7488       };
7489
7490       template <typename T>
7491       class swap_vecvec_node : public binary_node     <T>,
7492                                public vector_interface<T>
7493       {
7494       public:
7495
7496          typedef expression_node<T>*  expression_ptr;
7497          typedef vector_node<T>*     vector_node_ptr;
7498          typedef vec_data_store<T>             vds_t;
7499
7500          swap_vecvec_node(expression_ptr branch0,
7501                           expression_ptr branch1)
7502          : binary_node<T>(details::e_swap, branch0, branch1),
7503            vec0_node_ptr_(0),
7504            vec1_node_ptr_(0),
7505            vec_size_     (0),
7506            initialised_  (false)
7507          {
7508             if (is_ivector_node(binary_node<T>::branch_[0].first))
7509             {
7510                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
7511
7512                if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
7513                {
7514                   vec0_node_ptr_ = vi->vec();
7515                   vds()          = vi->vds();
7516                }
7517             }
7518
7519             if (is_ivector_node(binary_node<T>::branch_[1].first))
7520             {
7521                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
7522
7523                if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
7524                {
7525                   vec1_node_ptr_ = vi->vec();
7526                }
7527             }
7528
7529             if (vec0_node_ptr_ && vec1_node_ptr_)
7530             {
7531                vec_size_ = std::min(vec0_node_ptr_->vds().size(),
7532                                     vec1_node_ptr_->vds().size());
7533
7534                initialised_ = true;
7535             }
7536          }
7537
7538          inline T value() const
7539          {
7540             if (initialised_)
7541             {
7542                binary_node<T>::branch_[0].first->value();
7543                binary_node<T>::branch_[1].first->value();
7544
7545                T* vec0 = vec0_node_ptr_->vds().data();
7546                T* vec1 = vec1_node_ptr_->vds().data();
7547
7548                for (std::size_t i = 0; i < vec_size_; ++i)
7549                {
7550                   std::swap(vec0[i],vec1[i]);
7551                }
7552
7553                return vec1_node_ptr_->value();
7554             }
7555             else
7556                return std::numeric_limits<T>::quiet_NaN();
7557          }
7558
7559          vector_node_ptr vec() const
7560          {
7561             return vec0_node_ptr_;
7562          }
7563
7564          vector_node_ptr vec()
7565          {
7566             return vec0_node_ptr_;
7567          }
7568
7569          inline typename expression_node<T>::node_type type() const
7570          {
7571             return expression_node<T>::e_vecvecswap;
7572          }
7573
7574          std::size_t size() const
7575          {
7576             return vec_size_;
7577          }
7578
7579          vds_t& vds()
7580          {
7581             return vds_;
7582          }
7583
7584          const vds_t& vds() const
7585          {
7586             return vds_;
7587          }
7588
7589       private:
7590
7591          vector_node<T>* vec0_node_ptr_;
7592          vector_node<T>* vec1_node_ptr_;
7593          std::size_t     vec_size_;
7594          bool            initialised_;
7595          vds_t           vds_;
7596       };
7597
7598       #ifndef exprtk_disable_string_capabilities
7599       template <typename T>
7600       class stringvar_node : public expression_node <T>,
7601                              public string_base_node<T>,
7602                              public range_interface <T>
7603       {
7604       public:
7605
7606          typedef range_pack<T> range_t;
7607
7608          static std::string null_value;
7609
7610          explicit stringvar_node()
7611          : value_(&null_value)
7612          {}
7613
7614          explicit stringvar_node(std::string& v)
7615          : value_(&v)
7616          {
7617             rp_.n0_c = std::make_pair<bool,std::size_t>(true,0);
7618             rp_.n1_c = std::make_pair<bool,std::size_t>(true,v.size() - 1);
7619             rp_.cache.first  = rp_.n0_c.second;
7620             rp_.cache.second = rp_.n1_c.second;
7621          }
7622
7623          inline bool operator <(const stringvar_node<T>& v) const
7624          {
7625             return this < (&v);
7626          }
7627
7628          inline T value() const
7629          {
7630             rp_.n1_c.second  = (*value_).size() - 1;
7631             rp_.cache.second = rp_.n1_c.second;
7632
7633             return std::numeric_limits<T>::quiet_NaN();
7634          }
7635
7636          std::string str() const
7637          {
7638             return ref();
7639          }
7640
7641          char_cptr base() const
7642          {
7643             return &(*value_)[0];
7644          }
7645
7646          std::size_t size() const
7647          {
7648             return ref().size();
7649          }
7650
7651          std::string& ref()
7652          {
7653             return (*value_);
7654          }
7655
7656          const std::string& ref() const
7657          {
7658             return (*value_);
7659          }
7660
7661          range_t& range_ref()
7662          {
7663             return rp_;
7664          }
7665
7666          const range_t& range_ref() const
7667          {
7668             return rp_;
7669          }
7670
7671          inline typename expression_node<T>::node_type type() const
7672          {
7673             return expression_node<T>::e_stringvar;
7674          }
7675
7676       private:
7677
7678          std::string* value_;
7679          mutable range_t rp_;
7680       };
7681
7682       template <typename T>
7683       std::string stringvar_node<T>::null_value = std::string("");
7684
7685       template <typename T>
7686       class string_range_node : public expression_node <T>,
7687                                 public string_base_node<T>,
7688                                 public range_interface <T>
7689       {
7690       public:
7691
7692          typedef range_pack<T> range_t;
7693
7694          static std::string null_value;
7695
7696          explicit string_range_node(std::string& v, const range_t& rp)
7697          : value_(&v),
7698            rp_(rp)
7699          {}
7700
7701          virtual ~string_range_node()
7702          {
7703             rp_.free();
7704          }
7705
7706          inline bool operator <(const string_range_node<T>& v) const
7707          {
7708             return this < (&v);
7709          }
7710
7711          inline T value() const
7712          {
7713             return std::numeric_limits<T>::quiet_NaN();
7714          }
7715
7716          inline std::string str() const
7717          {
7718             return (*value_);
7719          }
7720
7721          char_cptr base() const
7722          {
7723             return &(*value_)[0];
7724          }
7725
7726          std::size_t size() const
7727          {
7728             return ref().size();
7729          }
7730
7731          inline range_t range() const
7732          {
7733             return rp_;
7734          }
7735
7736          inline virtual std::string& ref()
7737          {
7738             return (*value_);
7739          }
7740
7741          inline virtual const std::string& ref() const
7742          {
7743             return (*value_);
7744          }
7745
7746          inline range_t& range_ref()
7747          {
7748             return rp_;
7749          }
7750
7751          inline const range_t& range_ref() const
7752          {
7753             return rp_;
7754          }
7755
7756          inline typename expression_node<T>::node_type type() const
7757          {
7758             return expression_node<T>::e_stringvarrng;
7759          }
7760
7761       private:
7762
7763          std::string* value_;
7764          range_t      rp_;
7765       };
7766
7767       template <typename T>
7768       std::string string_range_node<T>::null_value = std::string("");
7769
7770       template <typename T>
7771       class const_string_range_node : public expression_node <T>,
7772                                       public string_base_node<T>,
7773                                       public range_interface <T>
7774       {
7775       public:
7776
7777          typedef range_pack<T> range_t;
7778
7779          explicit const_string_range_node(const std::string& v, const range_t& rp)
7780          : value_(v),
7781            rp_(rp)
7782          {}
7783
7784         ~const_string_range_node()
7785          {
7786             rp_.free();
7787          }
7788
7789          inline T value() const
7790          {
7791             return std::numeric_limits<T>::quiet_NaN();
7792          }
7793
7794          std::string str() const
7795          {
7796             return value_;
7797          }
7798
7799          char_cptr base() const
7800          {
7801             return value_.data();
7802          }
7803
7804          std::size_t size() const
7805          {
7806             return value_.size();
7807          }
7808
7809          range_t range() const
7810          {
7811             return rp_;
7812          }
7813
7814          range_t& range_ref()
7815          {
7816             return rp_;
7817          }
7818
7819          const range_t& range_ref() const
7820          {
7821             return rp_;
7822          }
7823
7824          inline typename expression_node<T>::node_type type() const
7825          {
7826             return expression_node<T>::e_cstringvarrng;
7827          }
7828
7829       private:
7830
7831          const_string_range_node<T>& operator=(const const_string_range_node<T>&);
7832
7833          const std::string value_;
7834          range_t rp_;
7835       };
7836
7837       template <typename T>
7838       class generic_string_range_node : public expression_node <T>,
7839                                         public string_base_node<T>,
7840                                         public range_interface <T>
7841       {
7842       public:
7843
7844          typedef expression_node <T>*  expression_ptr;
7845          typedef stringvar_node  <T>* strvar_node_ptr;
7846          typedef string_base_node<T>*    str_base_ptr;
7847          typedef range_pack      <T>          range_t;
7848          typedef range_t*                   range_ptr;
7849          typedef range_interface<T>          irange_t;
7850          typedef irange_t*                 irange_ptr;
7851
7852          generic_string_range_node(expression_ptr str_branch, const range_t& brange)
7853          : initialised_(false),
7854            branch_(str_branch),
7855            branch_deletable_(branch_deletable(branch_)),
7856            str_base_ptr_ (0),
7857            str_range_ptr_(0),
7858            base_range_(brange)
7859          {
7860             range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
7861             range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
7862             range_.cache.first  = range_.n0_c.second;
7863             range_.cache.second = range_.n1_c.second;
7864
7865             if (is_generally_string_node(branch_))
7866             {
7867                str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_);
7868
7869                if (0 == str_base_ptr_)
7870                   return;
7871
7872                str_range_ptr_ = dynamic_cast<irange_ptr>(branch_);
7873
7874                if (0 == str_range_ptr_)
7875                   return;
7876             }
7877
7878             initialised_ = (str_base_ptr_ && str_range_ptr_);
7879          }
7880
7881         ~generic_string_range_node()
7882          {
7883             base_range_.free();
7884
7885             if (branch_ && branch_deletable_)
7886             {
7887                destroy_node(branch_);
7888             }
7889          }
7890
7891          inline T value() const
7892          {
7893             if (initialised_)
7894             {
7895                branch_->value();
7896
7897                std::size_t str_r0 = 0;
7898                std::size_t str_r1 = 0;
7899
7900                std::size_t r0 = 0;
7901                std::size_t r1 = 0;
7902
7903                range_t& range = str_range_ptr_->range_ref();
7904
7905                const std::size_t base_str_size = str_base_ptr_->size();
7906
7907                if (
7908                     range      (str_r0, str_r1, base_str_size) &&
7909                     base_range_(    r0,     r1, base_str_size)
7910                   )
7911                {
7912                   const std::size_t size = (r1 - r0) + 1;
7913
7914                   range_.n1_c.second  = size - 1;
7915                   range_.cache.second = range_.n1_c.second;
7916
7917                   value_.assign(str_base_ptr_->base() + str_r0 + r0, size);
7918                }
7919             }
7920
7921             return std::numeric_limits<T>::quiet_NaN();
7922          }
7923
7924          std::string str() const
7925          {
7926             return value_;
7927          }
7928
7929          char_cptr base() const
7930          {
7931             return &value_[0];
7932          }
7933
7934          std::size_t size() const
7935          {
7936             return value_.size();
7937          }
7938
7939          range_t& range_ref()
7940          {
7941             return range_;
7942          }
7943
7944          const range_t& range_ref() const
7945          {
7946             return range_;
7947          }
7948
7949          inline typename expression_node<T>::node_type type() const
7950          {
7951             return expression_node<T>::e_strgenrange;
7952          }
7953
7954       private:
7955
7956          bool                initialised_;
7957          expression_ptr           branch_;
7958          const bool     branch_deletable_;
7959          str_base_ptr       str_base_ptr_;
7960          irange_ptr        str_range_ptr_;
7961          mutable range_t      base_range_;
7962          mutable range_t           range_;
7963          mutable std::string       value_;
7964       };
7965
7966       template <typename T>
7967       class string_concat_node : public binary_node     <T>,
7968                                  public string_base_node<T>,
7969                                  public range_interface <T>
7970       {
7971       public:
7972
7973          typedef expression_node <T>*  expression_ptr;
7974          typedef string_base_node<T>*    str_base_ptr;
7975          typedef range_pack      <T>          range_t;
7976          typedef range_t*                   range_ptr;
7977          typedef range_interface<T>          irange_t;
7978          typedef irange_t*                 irange_ptr;
7979
7980          string_concat_node(const operator_type& opr,
7981                             expression_ptr branch0,
7982                             expression_ptr branch1)
7983          : binary_node<T>(opr, branch0, branch1),
7984            initialised_(false),
7985            str0_base_ptr_ (0),
7986            str1_base_ptr_ (0),
7987            str0_range_ptr_(0),
7988            str1_range_ptr_(0)
7989          {
7990             range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
7991             range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
7992
7993             range_.cache.first  = range_.n0_c.second;
7994             range_.cache.second = range_.n1_c.second;
7995
7996             if (is_generally_string_node(binary_node<T>::branch_[0].first))
7997             {
7998                str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
7999
8000                if (0 == str0_base_ptr_)
8001                   return;
8002
8003                str0_range_ptr_ = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
8004
8005                if (0 == str0_range_ptr_)
8006                   return;
8007             }
8008
8009             if (is_generally_string_node(binary_node<T>::branch_[1].first))
8010             {
8011                str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
8012
8013                if (0 == str1_base_ptr_)
8014                   return;
8015
8016                str1_range_ptr_ = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
8017
8018                if (0 == str1_range_ptr_)
8019                   return;
8020             }
8021
8022             initialised_ = str0_base_ptr_  &&
8023                            str1_base_ptr_  &&
8024                            str0_range_ptr_ &&
8025                            str1_range_ptr_ ;
8026          }
8027
8028          inline T value() const
8029          {
8030             if (initialised_)
8031             {
8032                binary_node<T>::branch_[0].first->value();
8033                binary_node<T>::branch_[1].first->value();
8034
8035                std::size_t str0_r0 = 0;
8036                std::size_t str0_r1 = 0;
8037
8038                std::size_t str1_r0 = 0;
8039                std::size_t str1_r1 = 0;
8040
8041                range_t& range0 = str0_range_ptr_->range_ref();
8042                range_t& range1 = str1_range_ptr_->range_ref();
8043
8044                if (
8045                     range0(str0_r0, str0_r1, str0_base_ptr_->size()) &&
8046                     range1(str1_r0, str1_r1, str1_base_ptr_->size())
8047                   )
8048                {
8049                   const std::size_t size0 = (str0_r1 - str0_r0) + 1;
8050                   const std::size_t size1 = (str1_r1 - str1_r0) + 1;
8051
8052                   value_.assign(str0_base_ptr_->base() + str0_r0, size0);
8053                   value_.append(str1_base_ptr_->base() + str1_r0, size1);
8054
8055                   range_.n1_c.second  = value_.size() - 1;
8056                   range_.cache.second = range_.n1_c.second;
8057                }
8058             }
8059
8060             return std::numeric_limits<T>::quiet_NaN();
8061          }
8062
8063          std::string str() const
8064          {
8065             return value_;
8066          }
8067
8068          char_cptr base() const
8069          {
8070             return &value_[0];
8071          }
8072
8073          std::size_t size() const
8074          {
8075             return value_.size();
8076          }
8077
8078          range_t& range_ref()
8079          {
8080             return range_;
8081          }
8082
8083          const range_t& range_ref() const
8084          {
8085             return range_;
8086          }
8087
8088          inline typename expression_node<T>::node_type type() const
8089          {
8090             return expression_node<T>::e_strconcat;
8091          }
8092
8093       private:
8094
8095          bool initialised_;
8096          str_base_ptr str0_base_ptr_;
8097          str_base_ptr str1_base_ptr_;
8098          irange_ptr   str0_range_ptr_;
8099          irange_ptr   str1_range_ptr_;
8100          mutable range_t     range_;
8101          mutable std::string value_;
8102       };
8103
8104       template <typename T>
8105       class swap_string_node : public binary_node     <T>,
8106                                public string_base_node<T>,
8107                                public range_interface <T>
8108       {
8109       public:
8110
8111          typedef expression_node <T>*  expression_ptr;
8112          typedef stringvar_node  <T>* strvar_node_ptr;
8113          typedef string_base_node<T>*    str_base_ptr;
8114          typedef range_pack      <T>          range_t;
8115          typedef range_t*                   range_ptr;
8116          typedef range_interface<T>          irange_t;
8117          typedef irange_t*                 irange_ptr;
8118
8119          swap_string_node(expression_ptr branch0, expression_ptr branch1)
8120          : binary_node<T>(details::e_swap, branch0, branch1),
8121            initialised_(false),
8122            str0_node_ptr_(0),
8123            str1_node_ptr_(0)
8124          {
8125             if (is_string_node(binary_node<T>::branch_[0].first))
8126             {
8127                str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first);
8128             }
8129
8130             if (is_string_node(binary_node<T>::branch_[1].first))
8131             {
8132                str1_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[1].first);
8133             }
8134
8135             initialised_ = (str0_node_ptr_ && str1_node_ptr_);
8136          }
8137
8138          inline T value() const
8139          {
8140             if (initialised_)
8141             {
8142                binary_node<T>::branch_[0].first->value();
8143                binary_node<T>::branch_[1].first->value();
8144
8145                std::swap(str0_node_ptr_->ref(), str1_node_ptr_->ref());
8146             }
8147
8148             return std::numeric_limits<T>::quiet_NaN();
8149          }
8150
8151          std::string str() const
8152          {
8153             return str0_node_ptr_->str();
8154          }
8155
8156          char_cptr base() const
8157          {
8158            return str0_node_ptr_->base();
8159          }
8160
8161          std::size_t size() const
8162          {
8163             return str0_node_ptr_->size();
8164          }
8165
8166          range_t& range_ref()
8167          {
8168             return str0_node_ptr_->range_ref();
8169          }
8170
8171          const range_t& range_ref() const
8172          {
8173             return str0_node_ptr_->range_ref();
8174          }
8175
8176          inline typename expression_node<T>::node_type type() const
8177          {
8178             return expression_node<T>::e_strswap;
8179          }
8180
8181       private:
8182
8183          bool initialised_;
8184          strvar_node_ptr str0_node_ptr_;
8185          strvar_node_ptr str1_node_ptr_;
8186       };
8187
8188       template <typename T>
8189       class swap_genstrings_node : public binary_node<T>
8190       {
8191       public:
8192
8193          typedef expression_node <T>* expression_ptr;
8194          typedef string_base_node<T>*   str_base_ptr;
8195          typedef range_pack      <T>         range_t;
8196          typedef range_t*                  range_ptr;
8197          typedef range_interface<T>         irange_t;
8198          typedef irange_t*                irange_ptr;
8199
8200          swap_genstrings_node(expression_ptr branch0,
8201                               expression_ptr branch1)
8202          : binary_node<T>(details::e_default, branch0, branch1),
8203            str0_base_ptr_ (0),
8204            str1_base_ptr_ (0),
8205            str0_range_ptr_(0),
8206            str1_range_ptr_(0),
8207            initialised_(false)
8208          {
8209             if (is_generally_string_node(binary_node<T>::branch_[0].first))
8210             {
8211                str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
8212
8213                if (0 == str0_base_ptr_)
8214                   return;
8215
8216                irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
8217
8218                if (0 == range)
8219                   return;
8220
8221                str0_range_ptr_ = &(range->range_ref());
8222             }
8223
8224             if (is_generally_string_node(binary_node<T>::branch_[1].first))
8225             {
8226                str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
8227
8228                if (0 == str1_base_ptr_)
8229                   return;
8230
8231                irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
8232
8233                if (0 == range)
8234                   return;
8235
8236                str1_range_ptr_ = &(range->range_ref());
8237             }
8238
8239             initialised_ = str0_base_ptr_  &&
8240                            str1_base_ptr_  &&
8241                            str0_range_ptr_ &&
8242                            str1_range_ptr_ ;
8243          }
8244
8245          inline T value() const
8246          {
8247             if (initialised_)
8248             {
8249                binary_node<T>::branch_[0].first->value();
8250                binary_node<T>::branch_[1].first->value();
8251
8252                std::size_t str0_r0 = 0;
8253                std::size_t str0_r1 = 0;
8254
8255                std::size_t str1_r0 = 0;
8256                std::size_t str1_r1 = 0;
8257
8258                range_t& range0 = (*str0_range_ptr_);
8259                range_t& range1 = (*str1_range_ptr_);
8260
8261                if (
8262                     range0(str0_r0, str0_r1, str0_base_ptr_->size()) &&
8263                     range1(str1_r0, str1_r1, str1_base_ptr_->size())
8264                   )
8265                {
8266                   const std::size_t size0    = range0.cache_size();
8267                   const std::size_t size1    = range1.cache_size();
8268                   const std::size_t max_size = std::min(size0,size1);
8269
8270                   char_ptr s0 = const_cast<char_ptr>(str0_base_ptr_->base() + str0_r0);
8271                   char_ptr s1 = const_cast<char_ptr>(str1_base_ptr_->base() + str1_r0);
8272
8273                   loop_unroll::details lud(max_size);
8274                   char_cptr upper_bound = s0 + lud.upper_bound;
8275
8276                   while (s0 < upper_bound)
8277                   {
8278                      #define exprtk_loop(N)   \
8279                      std::swap(s0[N], s1[N]); \
8280
8281                      exprtk_loop( 0) exprtk_loop( 1)
8282                      exprtk_loop( 2) exprtk_loop( 3)
8283                      #ifndef exprtk_disable_superscalar_unroll
8284                      exprtk_loop( 4) exprtk_loop( 5)
8285                      exprtk_loop( 6) exprtk_loop( 7)
8286                      exprtk_loop( 8) exprtk_loop( 9)
8287                      exprtk_loop(10) exprtk_loop(11)
8288                      exprtk_loop(12) exprtk_loop(13)
8289                      exprtk_loop(14) exprtk_loop(15)
8290                      #endif
8291
8292                      s0 += lud.batch_size;
8293                      s1 += lud.batch_size;
8294                   }
8295
8296                   int i = 0;
8297
8298                   exprtk_disable_fallthrough_begin
8299                   switch (lud.remainder)
8300                   {
8301                      #define case_stmt(N)                       \
8302                      case N : { std::swap(s0[i], s1[i]); ++i; } \
8303
8304                      #ifndef exprtk_disable_superscalar_unroll
8305                      case_stmt(15) case_stmt(14)
8306                      case_stmt(13) case_stmt(12)
8307                      case_stmt(11) case_stmt(10)
8308                      case_stmt( 9) case_stmt( 8)
8309                      case_stmt( 7) case_stmt( 6)
8310                      case_stmt( 5) case_stmt( 4)
8311                      #endif
8312                      case_stmt( 3) case_stmt( 2)
8313                      case_stmt( 1)
8314                   }
8315                   exprtk_disable_fallthrough_end
8316
8317                   #undef exprtk_loop
8318                   #undef case_stmt
8319                }
8320             }
8321
8322             return std::numeric_limits<T>::quiet_NaN();
8323          }
8324
8325          inline typename expression_node<T>::node_type type() const
8326          {
8327             return expression_node<T>::e_strswap;
8328          }
8329
8330       private:
8331
8332          swap_genstrings_node(swap_genstrings_node<T>&);
8333          swap_genstrings_node<T>& operator=(swap_genstrings_node<T>&);
8334
8335          str_base_ptr str0_base_ptr_;
8336          str_base_ptr str1_base_ptr_;
8337          range_ptr    str0_range_ptr_;
8338          range_ptr    str1_range_ptr_;
8339          bool         initialised_;
8340       };
8341
8342       template <typename T>
8343       class stringvar_size_node : public expression_node<T>
8344       {
8345       public:
8346
8347          static std::string null_value;
8348
8349          explicit stringvar_size_node()
8350          : value_(&null_value)
8351          {}
8352
8353          explicit stringvar_size_node(std::string& v)
8354          : value_(&v)
8355          {}
8356
8357          inline T value() const
8358          {
8359             return T((*value_).size());
8360          }
8361
8362          inline typename expression_node<T>::node_type type() const
8363          {
8364             return expression_node<T>::e_stringvarsize;
8365          }
8366
8367       private:
8368
8369          std::string* value_;
8370       };
8371
8372       template <typename T>
8373       std::string stringvar_size_node<T>::null_value = std::string("");
8374
8375       template <typename T>
8376       class string_size_node : public expression_node<T>
8377       {
8378       public:
8379
8380          typedef expression_node <T>* expression_ptr;
8381          typedef string_base_node<T>*   str_base_ptr;
8382
8383          explicit string_size_node(expression_ptr brnch)
8384          : branch_(brnch),
8385            branch_deletable_(branch_deletable(branch_)),
8386            str_base_ptr_(0)
8387          {
8388             if (is_generally_string_node(branch_))
8389             {
8390                str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_);
8391
8392                if (0 == str_base_ptr_)
8393                   return;
8394             }
8395          }
8396
8397         ~string_size_node()
8398          {
8399             if (branch_ && branch_deletable_)
8400             {
8401                destroy_node(branch_);
8402             }
8403          }
8404
8405          inline T value() const
8406          {
8407             T result = std::numeric_limits<T>::quiet_NaN();
8408
8409             if (str_base_ptr_)
8410             {
8411                branch_->value();
8412                result = T(str_base_ptr_->size());
8413             }
8414
8415             return result;
8416          }
8417
8418          inline typename expression_node<T>::node_type type() const
8419          {
8420             return expression_node<T>::e_stringsize;
8421          }
8422
8423       private:
8424
8425          expression_ptr           branch_;
8426          const bool     branch_deletable_;
8427          str_base_ptr       str_base_ptr_;
8428       };
8429
8430       struct asn_assignment
8431       {
8432          static inline void execute(std::string& s, char_cptr data, const std::size_t size)
8433          { s.assign(data,size); }
8434       };
8435
8436       struct asn_addassignment
8437       {
8438          static inline void execute(std::string& s, char_cptr data, const std::size_t size)
8439          { s.append(data,size); }
8440       };
8441
8442       template <typename T, typename AssignmentProcess = asn_assignment>
8443       class assignment_string_node : public binary_node     <T>,
8444                                      public string_base_node<T>,
8445                                      public range_interface <T>
8446       {
8447       public:
8448
8449          typedef expression_node <T>*  expression_ptr;
8450          typedef stringvar_node  <T>* strvar_node_ptr;
8451          typedef string_base_node<T>*    str_base_ptr;
8452          typedef range_pack      <T>          range_t;
8453          typedef range_t*                   range_ptr;
8454          typedef range_interface<T>          irange_t;
8455          typedef irange_t*                 irange_ptr;
8456
8457          assignment_string_node(const operator_type& opr,
8458                                 expression_ptr branch0,
8459                                 expression_ptr branch1)
8460          : binary_node<T>(opr, branch0, branch1),
8461            initialised_(false),
8462            str0_base_ptr_ (0),
8463            str1_base_ptr_ (0),
8464            str0_node_ptr_ (0),
8465            str1_range_ptr_(0)
8466          {
8467             if (is_string_node(binary_node<T>::branch_[0].first))
8468             {
8469                str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first);
8470
8471                str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
8472             }
8473
8474             if (is_generally_string_node(binary_node<T>::branch_[1].first))
8475             {
8476                str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
8477
8478                if (0 == str1_base_ptr_)
8479                   return;
8480
8481                irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
8482
8483                if (0 == range)
8484                   return;
8485
8486                str1_range_ptr_ = &(range->range_ref());
8487             }
8488
8489             initialised_ = str0_base_ptr_  &&
8490                            str1_base_ptr_  &&
8491                            str0_node_ptr_  &&
8492                            str1_range_ptr_ ;
8493          }
8494
8495          inline T value() const
8496          {
8497             if (initialised_)
8498             {
8499                binary_node<T>::branch_[1].first->value();
8500
8501                std::size_t r0 = 0;
8502                std::size_t r1 = 0;
8503
8504                range_t& range = (*str1_range_ptr_);
8505
8506                if (range(r0, r1, str1_base_ptr_->size()))
8507                {
8508                   AssignmentProcess::execute(str0_node_ptr_->ref(),
8509                                              str1_base_ptr_->base() + r0,
8510                                              (r1 - r0) + 1);
8511
8512                   binary_node<T>::branch_[0].first->value();
8513                }
8514             }
8515
8516             return std::numeric_limits<T>::quiet_NaN();
8517          }
8518
8519          std::string str() const
8520          {
8521             return str0_node_ptr_->str();
8522          }
8523
8524          char_cptr base() const
8525          {
8526            return str0_node_ptr_->base();
8527          }
8528
8529          std::size_t size() const
8530          {
8531             return str0_node_ptr_->size();
8532          }
8533
8534          range_t& range_ref()
8535          {
8536             return str0_node_ptr_->range_ref();
8537          }
8538
8539          const range_t& range_ref() const
8540          {
8541             return str0_node_ptr_->range_ref();
8542          }
8543
8544          inline typename expression_node<T>::node_type type() const
8545          {
8546             return expression_node<T>::e_strass;
8547          }
8548
8549       private:
8550
8551          bool            initialised_;
8552          str_base_ptr    str0_base_ptr_;
8553          str_base_ptr    str1_base_ptr_;
8554          strvar_node_ptr str0_node_ptr_;
8555          range_ptr       str1_range_ptr_;
8556       };
8557
8558       template <typename T, typename AssignmentProcess = asn_assignment>
8559       class assignment_string_range_node : public binary_node     <T>,
8560                                            public string_base_node<T>,
8561                                            public range_interface <T>
8562       {
8563       public:
8564
8565          typedef expression_node <T>*  expression_ptr;
8566          typedef stringvar_node  <T>* strvar_node_ptr;
8567          typedef string_base_node<T>*    str_base_ptr;
8568          typedef range_pack      <T>          range_t;
8569          typedef range_t*                   range_ptr;
8570          typedef range_interface<T>          irange_t;
8571          typedef irange_t*                 irange_ptr;
8572
8573          assignment_string_range_node(const operator_type& opr,
8574                                       expression_ptr branch0,
8575                                       expression_ptr branch1)
8576          : binary_node<T>(opr, branch0, branch1),
8577            initialised_(false),
8578            str0_base_ptr_ (0),
8579            str1_base_ptr_ (0),
8580            str0_node_ptr_ (0),
8581            str0_range_ptr_(0),
8582            str1_range_ptr_(0)
8583          {
8584             if (is_string_range_node(binary_node<T>::branch_[0].first))
8585             {
8586                str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first);
8587
8588                str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
8589
8590                irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
8591
8592                if (0 == range)
8593                   return;
8594
8595                str0_range_ptr_ = &(range->range_ref());
8596             }
8597
8598             if (is_generally_string_node(binary_node<T>::branch_[1].first))
8599             {
8600                str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
8601
8602                if (0 == str1_base_ptr_)
8603                   return;
8604
8605                irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
8606
8607                if (0 == range)
8608                   return;
8609
8610                str1_range_ptr_ = &(range->range_ref());
8611             }
8612
8613             initialised_ = str0_base_ptr_  &&
8614                            str1_base_ptr_  &&
8615                            str0_node_ptr_  &&
8616                            str0_range_ptr_ &&
8617                            str1_range_ptr_ ;
8618          }
8619
8620          inline T value() const
8621          {
8622             if (initialised_)
8623             {
8624                binary_node<T>::branch_[0].first->value();
8625                binary_node<T>::branch_[1].first->value();
8626
8627                std::size_t s0_r0 = 0;
8628                std::size_t s0_r1 = 0;
8629
8630                std::size_t s1_r0 = 0;
8631                std::size_t s1_r1 = 0;
8632
8633                range_t& range0 = (*str0_range_ptr_);
8634                range_t& range1 = (*str1_range_ptr_);
8635
8636                if (
8637                     range0(s0_r0, s0_r1, str0_base_ptr_->size()) &&
8638                     range1(s1_r0, s1_r1, str1_base_ptr_->size())
8639                   )
8640                {
8641                   std::size_t size = std::min((s0_r1 - s0_r0), (s1_r1 - s1_r0)) + 1;
8642
8643                   std::copy(str1_base_ptr_->base() + s1_r0,
8644                             str1_base_ptr_->base() + s1_r0 + size,
8645                             const_cast<char_ptr>(base() + s0_r0));
8646                }
8647             }
8648
8649             return std::numeric_limits<T>::quiet_NaN();
8650          }
8651
8652          std::string str() const
8653          {
8654             return str0_node_ptr_->str();
8655          }
8656
8657          char_cptr base() const
8658          {
8659            return str0_node_ptr_->base();
8660          }
8661
8662          std::size_t size() const
8663          {
8664             return str0_node_ptr_->size();
8665          }
8666
8667          range_t& range_ref()
8668          {
8669             return str0_node_ptr_->range_ref();
8670          }
8671
8672          const range_t& range_ref() const
8673          {
8674             return str0_node_ptr_->range_ref();
8675          }
8676
8677          inline typename expression_node<T>::node_type type() const
8678          {
8679             return expression_node<T>::e_strass;
8680          }
8681
8682       private:
8683
8684          bool            initialised_;
8685          str_base_ptr    str0_base_ptr_;
8686          str_base_ptr    str1_base_ptr_;
8687          strvar_node_ptr str0_node_ptr_;
8688          range_ptr       str0_range_ptr_;
8689          range_ptr       str1_range_ptr_;
8690       };
8691
8692       template <typename T>
8693       class conditional_string_node : public trinary_node    <T>,
8694                                       public string_base_node<T>,
8695                                       public range_interface <T>
8696       {
8697       public:
8698
8699          typedef expression_node <T>* expression_ptr;
8700          typedef string_base_node<T>*   str_base_ptr;
8701          typedef range_pack      <T>         range_t;
8702          typedef range_t*                  range_ptr;
8703          typedef range_interface<T>         irange_t;
8704          typedef irange_t*                irange_ptr;
8705
8706          conditional_string_node(expression_ptr test,
8707                                  expression_ptr consequent,
8708                                  expression_ptr alternative)
8709          : trinary_node<T>(details::e_default,consequent,alternative,test),
8710            initialised_(false),
8711            str0_base_ptr_ (0),
8712            str1_base_ptr_ (0),
8713            str0_range_ptr_(0),
8714            str1_range_ptr_(0),
8715            test_              (test),
8716            consequent_  (consequent),
8717            alternative_(alternative)
8718          {
8719             range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
8720             range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
8721
8722             range_.cache.first  = range_.n0_c.second;
8723             range_.cache.second = range_.n1_c.second;
8724
8725             if (is_generally_string_node(trinary_node<T>::branch_[0].first))
8726             {
8727                str0_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[0].first);
8728
8729                if (0 == str0_base_ptr_)
8730                   return;
8731
8732                str0_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[0].first);
8733
8734                if (0 == str0_range_ptr_)
8735                   return;
8736             }
8737
8738             if (is_generally_string_node(trinary_node<T>::branch_[1].first))
8739             {
8740                str1_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[1].first);
8741
8742                if (0 == str1_base_ptr_)
8743                   return;
8744
8745                str1_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[1].first);
8746
8747                if (0 == str1_range_ptr_)
8748                   return;
8749             }
8750
8751             initialised_ = str0_base_ptr_  &&
8752                            str1_base_ptr_  &&
8753                            str0_range_ptr_ &&
8754                            str1_range_ptr_ ;
8755
8756          }
8757
8758          inline T value() const
8759          {
8760             if (initialised_)
8761             {
8762                std::size_t r0 = 0;
8763                std::size_t r1 = 0;
8764
8765                if (is_true(test_))
8766                {
8767                   consequent_->value();
8768
8769                   range_t& range = str0_range_ptr_->range_ref();
8770
8771                   if (range(r0, r1, str0_base_ptr_->size()))
8772                   {
8773                      const std::size_t size = (r1 - r0) + 1;
8774
8775                      value_.assign(str0_base_ptr_->base() + r0, size);
8776
8777                      range_.n1_c.second  = value_.size() - 1;
8778                      range_.cache.second = range_.n1_c.second;
8779
8780                      return T(1);
8781                   }
8782                }
8783                else
8784                {
8785                   alternative_->value();
8786
8787                   range_t& range = str1_range_ptr_->range_ref();
8788
8789                   if (range(r0, r1, str1_base_ptr_->size()))
8790                   {
8791                      const std::size_t size = (r1 - r0) + 1;
8792
8793                      value_.assign(str1_base_ptr_->base() + r0, size);
8794
8795                      range_.n1_c.second  = value_.size() - 1;
8796                      range_.cache.second = range_.n1_c.second;
8797
8798                      return T(0);
8799                   }
8800                }
8801             }
8802
8803             return std::numeric_limits<T>::quiet_NaN();
8804          }
8805
8806          std::string str() const
8807          {
8808             return value_;
8809          }
8810
8811          char_cptr base() const
8812          {
8813             return &value_[0];
8814          }
8815
8816          std::size_t size() const
8817          {
8818             return value_.size();
8819          }
8820
8821          range_t& range_ref()
8822          {
8823             return range_;
8824          }
8825
8826          const range_t& range_ref() const
8827          {
8828             return range_;
8829          }
8830
8831          inline typename expression_node<T>::node_type type() const
8832          {
8833             return expression_node<T>::e_strcondition;
8834          }
8835
8836       private:
8837
8838          bool initialised_;
8839          str_base_ptr str0_base_ptr_;
8840          str_base_ptr str1_base_ptr_;
8841          irange_ptr   str0_range_ptr_;
8842          irange_ptr   str1_range_ptr_;
8843          mutable range_t     range_;
8844          mutable std::string value_;
8845
8846          expression_ptr test_;
8847          expression_ptr consequent_;
8848          expression_ptr alternative_;
8849       };
8850
8851       template <typename T>
8852       class cons_conditional_str_node : public binary_node     <T>,
8853                                         public string_base_node<T>,
8854                                         public range_interface <T>
8855       {
8856       public:
8857
8858          typedef expression_node <T>* expression_ptr;
8859          typedef string_base_node<T>*   str_base_ptr;
8860          typedef range_pack      <T>         range_t;
8861          typedef range_t*                  range_ptr;
8862          typedef range_interface<T>         irange_t;
8863          typedef irange_t*                irange_ptr;
8864
8865          cons_conditional_str_node(expression_ptr test,
8866                                    expression_ptr consequent)
8867          : binary_node<T>(details::e_default, consequent, test),
8868            initialised_(false),
8869            str0_base_ptr_ (0),
8870            str0_range_ptr_(0),
8871            test_      (test),
8872            consequent_(consequent)
8873          {
8874             range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
8875             range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
8876
8877             range_.cache.first  = range_.n0_c.second;
8878             range_.cache.second = range_.n1_c.second;
8879
8880             if (is_generally_string_node(binary_node<T>::branch_[0].first))
8881             {
8882                str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
8883
8884                if (0 == str0_base_ptr_)
8885                   return;
8886
8887                str0_range_ptr_ = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
8888
8889                if (0 == str0_range_ptr_)
8890                   return;
8891             }
8892
8893             initialised_ = str0_base_ptr_ && str0_range_ptr_ ;
8894          }
8895
8896          inline T value() const
8897          {
8898             if (initialised_)
8899             {
8900                if (is_true(test_))
8901                {
8902                   consequent_->value();
8903
8904                   range_t& range = str0_range_ptr_->range_ref();
8905
8906                   std::size_t r0 = 0;
8907                   std::size_t r1 = 0;
8908
8909                   if (range(r0, r1, str0_base_ptr_->size()))
8910                   {
8911                      const std::size_t size = (r1 - r0) + 1;
8912
8913                      value_.assign(str0_base_ptr_->base() + r0, size);
8914
8915                      range_.n1_c.second  = value_.size() - 1;
8916                      range_.cache.second = range_.n1_c.second;
8917
8918                      return T(1);
8919                   }
8920                }
8921             }
8922
8923             return std::numeric_limits<T>::quiet_NaN();
8924          }
8925
8926          std::string str() const
8927          {
8928             return value_;
8929          }
8930
8931          char_cptr base() const
8932          {
8933             return &value_[0];
8934          }
8935
8936          std::size_t size() const
8937          {
8938             return value_.size();
8939          }
8940
8941          range_t& range_ref()
8942          {
8943             return range_;
8944          }
8945
8946          const range_t& range_ref() const
8947          {
8948             return range_;
8949          }
8950
8951          inline typename expression_node<T>::node_type type() const
8952          {
8953             return expression_node<T>::e_strccondition;
8954          }
8955
8956       private:
8957
8958          bool initialised_;
8959          str_base_ptr str0_base_ptr_;
8960          irange_ptr   str0_range_ptr_;
8961          mutable range_t     range_;
8962          mutable std::string value_;
8963
8964          expression_ptr test_;
8965          expression_ptr consequent_;
8966       };
8967
8968       template <typename T, typename VarArgFunction>
8969       class str_vararg_node  : public expression_node <T>,
8970                                public string_base_node<T>,
8971                                public range_interface <T>
8972       {
8973       public:
8974
8975          typedef expression_node <T>*  expression_ptr;
8976          typedef string_base_node<T>*    str_base_ptr;
8977          typedef range_pack      <T>          range_t;
8978          typedef range_t*                   range_ptr;
8979          typedef range_interface<T>          irange_t;
8980          typedef irange_t*                 irange_ptr;
8981
8982          template <typename Allocator,
8983                    template <typename, typename> class Sequence>
8984          explicit str_vararg_node(const Sequence<expression_ptr,Allocator>& arg_list)
8985          : final_node_(arg_list.back()),
8986            final_deletable_(branch_deletable(final_node_)),
8987            initialised_(false),
8988            str_base_ptr_ (0),
8989            str_range_ptr_(0)
8990          {
8991             if (0 == final_node_)
8992                return;
8993             else if (!is_generally_string_node(final_node_))
8994                return;
8995
8996             str_base_ptr_ = dynamic_cast<str_base_ptr>(final_node_);
8997
8998             if (0 == str_base_ptr_)
8999                return;
9000
9001             str_range_ptr_ = dynamic_cast<irange_ptr>(final_node_);
9002
9003             if (0 == str_range_ptr_)
9004                return;
9005
9006             initialised_ = str_base_ptr_  && str_range_ptr_;
9007
9008             if (arg_list.size() > 1)
9009             {
9010                const std::size_t arg_list_size = arg_list.size() - 1;
9011
9012                arg_list_.resize(arg_list_size);
9013                delete_branch_.resize(arg_list_size);
9014
9015                for (std::size_t i = 0; i < arg_list_size; ++i)
9016                {
9017                   if (arg_list[i])
9018                   {
9019                           arg_list_[i] = arg_list[i];
9020                      delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0);
9021                   }
9022                   else
9023                   {
9024                      arg_list_     .clear();
9025                      delete_branch_.clear();
9026                      return;
9027                   }
9028                }
9029             }
9030          }
9031
9032         ~str_vararg_node()
9033          {
9034             if (final_node_ && final_deletable_)
9035             {
9036                destroy_node(final_node_);
9037             }
9038
9039             for (std::size_t i = 0; i < arg_list_.size(); ++i)
9040             {
9041                if (arg_list_[i] && delete_branch_[i])
9042                {
9043                   destroy_node(arg_list_[i]);
9044                }
9045             }
9046          }
9047
9048          inline T value() const
9049          {
9050             if (!arg_list_.empty())
9051             {
9052                VarArgFunction::process(arg_list_);
9053             }
9054
9055             final_node_->value();
9056
9057             return std::numeric_limits<T>::quiet_NaN();
9058          }
9059
9060          std::string str() const
9061          {
9062             return str_base_ptr_->str();
9063          }
9064
9065          char_cptr base() const
9066          {
9067             return str_base_ptr_->base();
9068          }
9069
9070          std::size_t size() const
9071          {
9072             return str_base_ptr_->size();
9073          }
9074
9075          range_t& range_ref()
9076          {
9077             return str_range_ptr_->range_ref();
9078          }
9079
9080          const range_t& range_ref() const
9081          {
9082             return str_range_ptr_->range_ref();
9083          }
9084
9085          inline typename expression_node<T>::node_type type() const
9086          {
9087             return expression_node<T>::e_stringvararg;
9088          }
9089
9090       private:
9091
9092          expression_ptr final_node_;
9093          bool           final_deletable_;
9094          bool           initialised_;
9095          str_base_ptr   str_base_ptr_;
9096          irange_ptr     str_range_ptr_;
9097          std::vector<expression_ptr> arg_list_;
9098          std::vector<unsigned char> delete_branch_;
9099       };
9100       #endif
9101
9102       template <typename T, std::size_t N>
9103       inline T axn(T a, T x)
9104       {
9105          // a*x^n
9106          return a * exprtk::details::numeric::fast_exp<T,N>::result(x);
9107       }
9108
9109       template <typename T, std::size_t N>
9110       inline T axnb(T a, T x, T b)
9111       {
9112          // a*x^n+b
9113          return a * exprtk::details::numeric::fast_exp<T,N>::result(x) + b;
9114       }
9115
9116       template <typename T>
9117       struct sf_base
9118       {
9119          typedef typename details::functor_t<T>::Type Type;
9120          typedef typename details::functor_t<T> functor_t;
9121          typedef typename functor_t::qfunc_t quaternary_functor_t;
9122          typedef typename functor_t::tfunc_t    trinary_functor_t;
9123          typedef typename functor_t::bfunc_t     binary_functor_t;
9124          typedef typename functor_t::ufunc_t      unary_functor_t;
9125       };
9126
9127       #define define_sfop3(NN,OP0,OP1)                   \
9128       template <typename T>                              \
9129       struct sf##NN##_op : public sf_base<T>             \
9130       {                                                  \
9131          typedef typename sf_base<T>::Type const Type;   \
9132          static inline T process(Type x, Type y, Type z) \
9133          {                                               \
9134             return (OP0);                                \
9135          }                                               \
9136          static inline std::string id()                  \
9137          {                                               \
9138             return OP1;                                  \
9139          }                                               \
9140       };                                                 \
9141
9142       define_sfop3(00,(x + y) / z       ,"(t+t)/t")
9143       define_sfop3(01,(x + y) * z       ,"(t+t)*t")
9144       define_sfop3(02,(x + y) - z       ,"(t+t)-t")
9145       define_sfop3(03,(x + y) + z       ,"(t+t)+t")
9146       define_sfop3(04,(x - y) + z       ,"(t-t)+t")
9147       define_sfop3(05,(x - y) / z       ,"(t-t)/t")
9148       define_sfop3(06,(x - y) * z       ,"(t-t)*t")
9149       define_sfop3(07,(x * y) + z       ,"(t*t)+t")
9150       define_sfop3(08,(x * y) - z       ,"(t*t)-t")
9151       define_sfop3(09,(x * y) / z       ,"(t*t)/t")
9152       define_sfop3(10,(x * y) * z       ,"(t*t)*t")
9153       define_sfop3(11,(x / y) + z       ,"(t/t)+t")
9154       define_sfop3(12,(x / y) - z       ,"(t/t)-t")
9155       define_sfop3(13,(x / y) / z       ,"(t/t)/t")
9156       define_sfop3(14,(x / y) * z       ,"(t/t)*t")
9157       define_sfop3(15,x / (y + z)       ,"t/(t+t)")
9158       define_sfop3(16,x / (y - z)       ,"t/(t-t)")
9159       define_sfop3(17,x / (y * z)       ,"t/(t*t)")
9160       define_sfop3(18,x / (y / z)       ,"t/(t/t)")
9161       define_sfop3(19,x * (y + z)       ,"t*(t+t)")
9162       define_sfop3(20,x * (y - z)       ,"t*(t-t)")
9163       define_sfop3(21,x * (y * z)       ,"t*(t*t)")
9164       define_sfop3(22,x * (y / z)       ,"t*(t/t)")
9165       define_sfop3(23,x - (y + z)       ,"t-(t+t)")
9166       define_sfop3(24,x - (y - z)       ,"t-(t-t)")
9167       define_sfop3(25,x - (y / z)       ,"t-(t/t)")
9168       define_sfop3(26,x - (y * z)       ,"t-(t*t)")
9169       define_sfop3(27,x + (y * z)       ,"t+(t*t)")
9170       define_sfop3(28,x + (y / z)       ,"t+(t/t)")
9171       define_sfop3(29,x + (y + z)       ,"t+(t+t)")
9172       define_sfop3(30,x + (y - z)       ,"t+(t-t)")
9173       define_sfop3(31,(axnb<T,2>(x,y,z)),"       ")
9174       define_sfop3(32,(axnb<T,3>(x,y,z)),"       ")
9175       define_sfop3(33,(axnb<T,4>(x,y,z)),"       ")
9176       define_sfop3(34,(axnb<T,5>(x,y,z)),"       ")
9177       define_sfop3(35,(axnb<T,6>(x,y,z)),"       ")
9178       define_sfop3(36,(axnb<T,7>(x,y,z)),"       ")
9179       define_sfop3(37,(axnb<T,8>(x,y,z)),"       ")
9180       define_sfop3(38,(axnb<T,9>(x,y,z)),"       ")
9181       define_sfop3(39,x * numeric::log(y)   + z,"")
9182       define_sfop3(40,x * numeric::log(y)   - z,"")
9183       define_sfop3(41,x * numeric::log10(y) + z,"")
9184       define_sfop3(42,x * numeric::log10(y) - z,"")
9185       define_sfop3(43,x * numeric::sin(y) + z  ,"")
9186       define_sfop3(44,x * numeric::sin(y) - z  ,"")
9187       define_sfop3(45,x * numeric::cos(y) + z  ,"")
9188       define_sfop3(46,x * numeric::cos(y) - z  ,"")
9189       define_sfop3(47,details::is_true(x) ? y : z,"")
9190
9191       #define define_sfop4(NN,OP0,OP1)                           \
9192       template <typename T>                                      \
9193       struct sf##NN##_op : public sf_base<T>                     \
9194       {                                                          \
9195          typedef typename sf_base<T>::Type const Type;           \
9196          static inline T process(Type x, Type y, Type z, Type w) \
9197          {                                                       \
9198             return (OP0);                                        \
9199          }                                                       \
9200          static inline std::string id() { return OP1; }          \
9201       };                                                         \
9202
9203       define_sfop4(48,(x + ((y + z) / w)),"t+((t+t)/t)")
9204       define_sfop4(49,(x + ((y + z) * w)),"t+((t+t)*t)")
9205       define_sfop4(50,(x + ((y - z) / w)),"t+((t-t)/t)")
9206       define_sfop4(51,(x + ((y - z) * w)),"t+((t-t)*t)")
9207       define_sfop4(52,(x + ((y * z) / w)),"t+((t*t)/t)")
9208       define_sfop4(53,(x + ((y * z) * w)),"t+((t*t)*t)")
9209       define_sfop4(54,(x + ((y / z) + w)),"t+((t/t)+t)")
9210       define_sfop4(55,(x + ((y / z) / w)),"t+((t/t)/t)")
9211       define_sfop4(56,(x + ((y / z) * w)),"t+((t/t)*t)")
9212       define_sfop4(57,(x - ((y + z) / w)),"t-((t+t)/t)")
9213       define_sfop4(58,(x - ((y + z) * w)),"t-((t+t)*t)")
9214       define_sfop4(59,(x - ((y - z) / w)),"t-((t-t)/t)")
9215       define_sfop4(60,(x - ((y - z) * w)),"t-((t-t)*t)")
9216       define_sfop4(61,(x - ((y * z) / w)),"t-((t*t)/t)")
9217       define_sfop4(62,(x - ((y * z) * w)),"t-((t*t)*t)")
9218       define_sfop4(63,(x - ((y / z) / w)),"t-((t/t)/t)")
9219       define_sfop4(64,(x - ((y / z) * w)),"t-((t/t)*t)")
9220       define_sfop4(65,(((x + y) * z) - w),"((t+t)*t)-t")
9221       define_sfop4(66,(((x - y) * z) - w),"((t-t)*t)-t")
9222       define_sfop4(67,(((x * y) * z) - w),"((t*t)*t)-t")
9223       define_sfop4(68,(((x / y) * z) - w),"((t/t)*t)-t")
9224       define_sfop4(69,(((x + y) / z) - w),"((t+t)/t)-t")
9225       define_sfop4(70,(((x - y) / z) - w),"((t-t)/t)-t")
9226       define_sfop4(71,(((x * y) / z) - w),"((t*t)/t)-t")
9227       define_sfop4(72,(((x / y) / z) - w),"((t/t)/t)-t")
9228       define_sfop4(73,((x * y) + (z * w)),"(t*t)+(t*t)")
9229       define_sfop4(74,((x * y) - (z * w)),"(t*t)-(t*t)")
9230       define_sfop4(75,((x * y) + (z / w)),"(t*t)+(t/t)")
9231       define_sfop4(76,((x * y) - (z / w)),"(t*t)-(t/t)")
9232       define_sfop4(77,((x / y) + (z / w)),"(t/t)+(t/t)")
9233       define_sfop4(78,((x / y) - (z / w)),"(t/t)-(t/t)")
9234       define_sfop4(79,((x / y) - (z * w)),"(t/t)-(t*t)")
9235       define_sfop4(80,(x / (y + (z * w))),"t/(t+(t*t))")
9236       define_sfop4(81,(x / (y - (z * w))),"t/(t-(t*t))")
9237       define_sfop4(82,(x * (y + (z * w))),"t*(t+(t*t))")
9238       define_sfop4(83,(x * (y - (z * w))),"t*(t-(t*t))")
9239
9240       define_sfop4(84,(axn<T,2>(x,y) + axn<T,2>(z,w)),"")
9241       define_sfop4(85,(axn<T,3>(x,y) + axn<T,3>(z,w)),"")
9242       define_sfop4(86,(axn<T,4>(x,y) + axn<T,4>(z,w)),"")
9243       define_sfop4(87,(axn<T,5>(x,y) + axn<T,5>(z,w)),"")
9244       define_sfop4(88,(axn<T,6>(x,y) + axn<T,6>(z,w)),"")
9245       define_sfop4(89,(axn<T,7>(x,y) + axn<T,7>(z,w)),"")
9246       define_sfop4(90,(axn<T,8>(x,y) + axn<T,8>(z,w)),"")
9247       define_sfop4(91,(axn<T,9>(x,y) + axn<T,9>(z,w)),"")
9248       define_sfop4(92,((details::is_true(x) && details::is_true(y)) ? z : w),"")
9249       define_sfop4(93,((details::is_true(x) || details::is_true(y)) ? z : w),"")
9250       define_sfop4(94,((x <  y) ? z : w),"")
9251       define_sfop4(95,((x <= y) ? z : w),"")
9252       define_sfop4(96,((x >  y) ? z : w),"")
9253       define_sfop4(97,((x >= y) ? z : w),"")
9254       define_sfop4(98,(details::is_true(numeric::equal(x,y)) ? z : w),"")
9255       define_sfop4(99,(x * numeric::sin(y) + z * numeric::cos(w)),"")
9256
9257       define_sfop4(ext00,((x + y) - (z * w)),"(t+t)-(t*t)")
9258       define_sfop4(ext01,((x + y) - (z / w)),"(t+t)-(t/t)")
9259       define_sfop4(ext02,((x + y) + (z * w)),"(t+t)+(t*t)")
9260       define_sfop4(ext03,((x + y) + (z / w)),"(t+t)+(t/t)")
9261       define_sfop4(ext04,((x - y) + (z * w)),"(t-t)+(t*t)")
9262       define_sfop4(ext05,((x - y) + (z / w)),"(t-t)+(t/t)")
9263       define_sfop4(ext06,((x - y) - (z * w)),"(t-t)-(t*t)")
9264       define_sfop4(ext07,((x - y) - (z / w)),"(t-t)-(t/t)")
9265       define_sfop4(ext08,((x + y) - (z - w)),"(t+t)-(t-t)")
9266       define_sfop4(ext09,((x + y) + (z - w)),"(t+t)+(t-t)")
9267       define_sfop4(ext10,((x + y) + (z + w)),"(t+t)+(t+t)")
9268       define_sfop4(ext11,((x + y) * (z - w)),"(t+t)*(t-t)")
9269       define_sfop4(ext12,((x + y) / (z - w)),"(t+t)/(t-t)")
9270       define_sfop4(ext13,((x - y) - (z + w)),"(t-t)-(t+t)")
9271       define_sfop4(ext14,((x - y) + (z + w)),"(t-t)+(t+t)")
9272       define_sfop4(ext15,((x - y) * (z + w)),"(t-t)*(t+t)")
9273       define_sfop4(ext16,((x - y) / (z + w)),"(t-t)/(t+t)")
9274       define_sfop4(ext17,((x * y) - (z + w)),"(t*t)-(t+t)")
9275       define_sfop4(ext18,((x / y) - (z + w)),"(t/t)-(t+t)")
9276       define_sfop4(ext19,((x * y) + (z + w)),"(t*t)+(t+t)")
9277       define_sfop4(ext20,((x / y) + (z + w)),"(t/t)+(t+t)")
9278       define_sfop4(ext21,((x * y) + (z - w)),"(t*t)+(t-t)")
9279       define_sfop4(ext22,((x / y) + (z - w)),"(t/t)+(t-t)")
9280       define_sfop4(ext23,((x * y) - (z - w)),"(t*t)-(t-t)")
9281       define_sfop4(ext24,((x / y) - (z - w)),"(t/t)-(t-t)")
9282       define_sfop4(ext25,((x + y) * (z * w)),"(t+t)*(t*t)")
9283       define_sfop4(ext26,((x + y) * (z / w)),"(t+t)*(t/t)")
9284       define_sfop4(ext27,((x + y) / (z * w)),"(t+t)/(t*t)")
9285       define_sfop4(ext28,((x + y) / (z / w)),"(t+t)/(t/t)")
9286       define_sfop4(ext29,((x - y) / (z * w)),"(t-t)/(t*t)")
9287       define_sfop4(ext30,((x - y) / (z / w)),"(t-t)/(t/t)")
9288       define_sfop4(ext31,((x - y) * (z * w)),"(t-t)*(t*t)")
9289       define_sfop4(ext32,((x - y) * (z / w)),"(t-t)*(t/t)")
9290       define_sfop4(ext33,((x * y) * (z + w)),"(t*t)*(t+t)")
9291       define_sfop4(ext34,((x / y) * (z + w)),"(t/t)*(t+t)")
9292       define_sfop4(ext35,((x * y) / (z + w)),"(t*t)/(t+t)")
9293       define_sfop4(ext36,((x / y) / (z + w)),"(t/t)/(t+t)")
9294       define_sfop4(ext37,((x * y) / (z - w)),"(t*t)/(t-t)")
9295       define_sfop4(ext38,((x / y) / (z - w)),"(t/t)/(t-t)")
9296       define_sfop4(ext39,((x * y) * (z - w)),"(t*t)*(t-t)")
9297       define_sfop4(ext40,((x * y) / (z * w)),"(t*t)/(t*t)")
9298       define_sfop4(ext41,((x / y) * (z / w)),"(t/t)*(t/t)")
9299       define_sfop4(ext42,((x / y) * (z - w)),"(t/t)*(t-t)")
9300       define_sfop4(ext43,((x * y) * (z * w)),"(t*t)*(t*t)")
9301       define_sfop4(ext44,(x + (y * (z / w))),"t+(t*(t/t))")
9302       define_sfop4(ext45,(x - (y * (z / w))),"t-(t*(t/t))")
9303       define_sfop4(ext46,(x + (y / (z * w))),"t+(t/(t*t))")
9304       define_sfop4(ext47,(x - (y / (z * w))),"t-(t/(t*t))")
9305       define_sfop4(ext48,(((x - y) - z) * w),"((t-t)-t)*t")
9306       define_sfop4(ext49,(((x - y) - z) / w),"((t-t)-t)/t")
9307       define_sfop4(ext50,(((x - y) + z) * w),"((t-t)+t)*t")
9308       define_sfop4(ext51,(((x - y) + z) / w),"((t-t)+t)/t")
9309       define_sfop4(ext52,((x + (y - z)) * w),"(t+(t-t))*t")
9310       define_sfop4(ext53,((x + (y - z)) / w),"(t+(t-t))/t")
9311       define_sfop4(ext54,((x + y) / (z + w)),"(t+t)/(t+t)")
9312       define_sfop4(ext55,((x - y) / (z - w)),"(t-t)/(t-t)")
9313       define_sfop4(ext56,((x + y) * (z + w)),"(t+t)*(t+t)")
9314       define_sfop4(ext57,((x - y) * (z - w)),"(t-t)*(t-t)")
9315       define_sfop4(ext58,((x - y) + (z - w)),"(t-t)+(t-t)")
9316       define_sfop4(ext59,((x - y) - (z - w)),"(t-t)-(t-t)")
9317       define_sfop4(ext60,((x / y) + (z * w)),"(t/t)+(t*t)")
9318       define_sfop4(ext61,(((x * y) * z) / w),"((t*t)*t)/t")
9319
9320       #undef define_sfop3
9321       #undef define_sfop4
9322
9323       template <typename T, typename SpecialFunction>
9324       class sf3_node : public trinary_node<T>
9325       {
9326       public:
9327
9328          typedef expression_node<T>* expression_ptr;
9329
9330          sf3_node(const operator_type& opr,
9331                   expression_ptr branch0,
9332                   expression_ptr branch1,
9333                   expression_ptr branch2)
9334          : trinary_node<T>(opr, branch0, branch1, branch2)
9335          {}
9336
9337          inline T value() const
9338          {
9339             const T x = trinary_node<T>::branch_[0].first->value();
9340             const T y = trinary_node<T>::branch_[1].first->value();
9341             const T z = trinary_node<T>::branch_[2].first->value();
9342
9343             return SpecialFunction::process(x, y, z);
9344          }
9345       };
9346
9347       template <typename T, typename SpecialFunction>
9348       class sf4_node : public quaternary_node<T>
9349       {
9350       public:
9351
9352          typedef expression_node<T>* expression_ptr;
9353
9354          sf4_node(const operator_type& opr,
9355                   expression_ptr branch0,
9356                   expression_ptr branch1,
9357                   expression_ptr branch2,
9358                   expression_ptr branch3)
9359          : quaternary_node<T>(opr, branch0, branch1, branch2, branch3)
9360          {}
9361
9362          inline T value() const
9363          {
9364             const T x = quaternary_node<T>::branch_[0].first->value();
9365             const T y = quaternary_node<T>::branch_[1].first->value();
9366             const T z = quaternary_node<T>::branch_[2].first->value();
9367             const T w = quaternary_node<T>::branch_[3].first->value();
9368
9369             return SpecialFunction::process(x, y, z, w);
9370          }
9371       };
9372
9373       template <typename T, typename SpecialFunction>
9374       class sf3_var_node : public expression_node<T>
9375       {
9376       public:
9377
9378          typedef expression_node<T>* expression_ptr;
9379
9380          sf3_var_node(const T& v0, const T& v1, const T& v2)
9381          : v0_(v0),
9382            v1_(v1),
9383            v2_(v2)
9384          {}
9385
9386          inline T value() const
9387          {
9388             return SpecialFunction::process(v0_, v1_, v2_);
9389          }
9390
9391          inline typename expression_node<T>::node_type type() const
9392          {
9393             return expression_node<T>::e_trinary;
9394          }
9395
9396       private:
9397
9398          sf3_var_node(sf3_var_node<T,SpecialFunction>&);
9399          sf3_var_node<T,SpecialFunction>& operator=(sf3_var_node<T,SpecialFunction>&);
9400
9401          const T& v0_;
9402          const T& v1_;
9403          const T& v2_;
9404       };
9405
9406       template <typename T, typename SpecialFunction>
9407       class sf4_var_node : public expression_node<T>
9408       {
9409       public:
9410
9411          typedef expression_node<T>* expression_ptr;
9412
9413          sf4_var_node(const T& v0, const T& v1, const T& v2, const T& v3)
9414          : v0_(v0),
9415            v1_(v1),
9416            v2_(v2),
9417            v3_(v3)
9418          {}
9419
9420          inline T value() const
9421          {
9422             return SpecialFunction::process(v0_, v1_, v2_, v3_);
9423          }
9424
9425          inline typename expression_node<T>::node_type type() const
9426          {
9427             return expression_node<T>::e_trinary;
9428          }
9429
9430       private:
9431
9432          sf4_var_node(sf4_var_node<T,SpecialFunction>&);
9433          sf4_var_node<T,SpecialFunction>& operator=(sf4_var_node<T,SpecialFunction>&);
9434
9435          const T& v0_;
9436          const T& v1_;
9437          const T& v2_;
9438          const T& v3_;
9439       };
9440
9441       template <typename T, typename VarArgFunction>
9442       class vararg_node : public expression_node<T>
9443       {
9444       public:
9445
9446          typedef expression_node<T>* expression_ptr;
9447
9448          template <typename Allocator,
9449                    template <typename, typename> class Sequence>
9450          explicit vararg_node(const Sequence<expression_ptr,Allocator>& arg_list)
9451          {
9452             arg_list_     .resize(arg_list.size());
9453             delete_branch_.resize(arg_list.size());
9454
9455             for (std::size_t i = 0; i < arg_list.size(); ++i)
9456             {
9457                if (arg_list[i])
9458                {
9459                        arg_list_[i] = arg_list[i];
9460                   delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0);
9461                }
9462                else
9463                {
9464                   arg_list_.clear();
9465                   delete_branch_.clear();
9466                   return;
9467                }
9468             }
9469          }
9470
9471         ~vararg_node()
9472          {
9473             for (std::size_t i = 0; i < arg_list_.size(); ++i)
9474             {
9475                if (arg_list_[i] && delete_branch_[i])
9476                {
9477                   destroy_node(arg_list_[i]);
9478                }
9479             }
9480          }
9481
9482          inline T value() const
9483          {
9484             return VarArgFunction::process(arg_list_);
9485          }
9486
9487          inline typename expression_node<T>::node_type type() const
9488          {
9489             return expression_node<T>::e_vararg;
9490          }
9491
9492       private:
9493
9494          std::vector<expression_ptr> arg_list_;
9495          std::vector<unsigned char> delete_branch_;
9496       };
9497
9498       template <typename T, typename VarArgFunction>
9499       class vararg_varnode : public expression_node<T>
9500       {
9501       public:
9502
9503          typedef expression_node<T>* expression_ptr;
9504
9505          template <typename Allocator,
9506                    template <typename, typename> class Sequence>
9507          explicit vararg_varnode(const Sequence<expression_ptr,Allocator>& arg_list)
9508          {
9509             arg_list_.resize(arg_list.size());
9510
9511             for (std::size_t i = 0; i < arg_list.size(); ++i)
9512             {
9513                if (arg_list[i] && is_variable_node(arg_list[i]))
9514                {
9515                   variable_node<T>* var_node_ptr = static_cast<variable_node<T>*>(arg_list[i]);
9516                   arg_list_[i] = (&var_node_ptr->ref());
9517                }
9518                else
9519                {
9520                   arg_list_.clear();
9521                   return;
9522                }
9523             }
9524          }
9525
9526          inline T value() const
9527          {
9528             if (!arg_list_.empty())
9529                return VarArgFunction::process(arg_list_);
9530             else
9531                return std::numeric_limits<T>::quiet_NaN();
9532          }
9533
9534          inline typename expression_node<T>::node_type type() const
9535          {
9536             return expression_node<T>::e_vararg;
9537          }
9538
9539       private:
9540
9541          std::vector<const T*> arg_list_;
9542       };
9543
9544       template <typename T, typename VecFunction>
9545       class vectorize_node : public expression_node<T>
9546       {
9547       public:
9548
9549          typedef expression_node<T>* expression_ptr;
9550
9551          explicit vectorize_node(const expression_ptr v)
9552          : ivec_ptr_(0),
9553            v_(v),
9554            v_deletable_(branch_deletable(v_))
9555          {
9556             if (is_ivector_node(v))
9557             {
9558                ivec_ptr_ = dynamic_cast<vector_interface<T>*>(v);
9559             }
9560             else
9561                ivec_ptr_ = 0;
9562          }
9563
9564         ~vectorize_node()
9565          {
9566             if (v_ && v_deletable_)
9567             {
9568                destroy_node(v_);
9569             }
9570          }
9571
9572          inline T value() const
9573          {
9574             if (ivec_ptr_)
9575             {
9576                v_->value();
9577                return VecFunction::process(ivec_ptr_);
9578             }
9579             else
9580                return std::numeric_limits<T>::quiet_NaN();
9581          }
9582
9583          inline typename expression_node<T>::node_type type() const
9584          {
9585             return expression_node<T>::e_vecfunc;
9586          }
9587
9588       private:
9589
9590          vector_interface<T>* ivec_ptr_;
9591          expression_ptr              v_;
9592          const bool        v_deletable_;
9593       };
9594
9595       template <typename T>
9596       class assignment_node : public binary_node<T>
9597       {
9598       public:
9599
9600          typedef expression_node<T>* expression_ptr;
9601
9602          assignment_node(const operator_type& opr,
9603                          expression_ptr branch0,
9604                          expression_ptr branch1)
9605          : binary_node<T>(opr, branch0, branch1),
9606            var_node_ptr_(0)
9607          {
9608             if (is_variable_node(binary_node<T>::branch_[0].first))
9609             {
9610                var_node_ptr_ = static_cast<variable_node<T>*>(binary_node<T>::branch_[0].first);
9611             }
9612          }
9613
9614          inline T value() const
9615          {
9616             if (var_node_ptr_)
9617             {
9618                T& result = var_node_ptr_->ref();
9619
9620                result = binary_node<T>::branch_[1].first->value();
9621
9622                return result;
9623             }
9624             else
9625                return std::numeric_limits<T>::quiet_NaN();
9626          }
9627
9628       private:
9629
9630          variable_node<T>* var_node_ptr_;
9631       };
9632
9633       template <typename T>
9634       class assignment_vec_elem_node : public binary_node<T>
9635       {
9636       public:
9637
9638          typedef expression_node<T>* expression_ptr;
9639
9640          assignment_vec_elem_node(const operator_type& opr,
9641                                   expression_ptr branch0,
9642                                   expression_ptr branch1)
9643          : binary_node<T>(opr, branch0, branch1),
9644            vec_node_ptr_(0)
9645          {
9646             if (is_vector_elem_node(binary_node<T>::branch_[0].first))
9647             {
9648                vec_node_ptr_ = static_cast<vector_elem_node<T>*>(binary_node<T>::branch_[0].first);
9649             }
9650          }
9651
9652          inline T value() const
9653          {
9654             if (vec_node_ptr_)
9655             {
9656                T& result = vec_node_ptr_->ref();
9657
9658                result = binary_node<T>::branch_[1].first->value();
9659
9660                return result;
9661             }
9662             else
9663                return std::numeric_limits<T>::quiet_NaN();
9664          }
9665
9666       private:
9667
9668          vector_elem_node<T>* vec_node_ptr_;
9669       };
9670
9671       template <typename T>
9672       class assignment_rebasevec_elem_node : public binary_node<T>
9673       {
9674       public:
9675
9676          typedef expression_node<T>* expression_ptr;
9677
9678          assignment_rebasevec_elem_node(const operator_type& opr,
9679                                         expression_ptr branch0,
9680                                         expression_ptr branch1)
9681          : binary_node<T>(opr, branch0, branch1),
9682            rbvec_node_ptr_(0)
9683          {
9684             if (is_rebasevector_elem_node(binary_node<T>::branch_[0].first))
9685             {
9686                rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(binary_node<T>::branch_[0].first);
9687             }
9688          }
9689
9690          inline T value() const
9691          {
9692             if (rbvec_node_ptr_)
9693             {
9694                T& result = rbvec_node_ptr_->ref();
9695
9696                result = binary_node<T>::branch_[1].first->value();
9697
9698                return result;
9699             }
9700             else
9701                return std::numeric_limits<T>::quiet_NaN();
9702          }
9703
9704       private:
9705
9706          rebasevector_elem_node<T>* rbvec_node_ptr_;
9707       };
9708
9709       template <typename T>
9710       class assignment_rebasevec_celem_node : public binary_node<T>
9711       {
9712       public:
9713
9714          typedef expression_node<T>* expression_ptr;
9715
9716          assignment_rebasevec_celem_node(const operator_type& opr,
9717                                          expression_ptr branch0,
9718                                          expression_ptr branch1)
9719          : binary_node<T>(opr, branch0, branch1),
9720            rbvec_node_ptr_(0)
9721          {
9722             if (is_rebasevector_celem_node(binary_node<T>::branch_[0].first))
9723             {
9724                rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(binary_node<T>::branch_[0].first);
9725             }
9726          }
9727
9728          inline T value() const
9729          {
9730             if (rbvec_node_ptr_)
9731             {
9732                T& result = rbvec_node_ptr_->ref();
9733
9734                result = binary_node<T>::branch_[1].first->value();
9735
9736                return result;
9737             }
9738             else
9739                return std::numeric_limits<T>::quiet_NaN();
9740          }
9741
9742       private:
9743
9744          rebasevector_celem_node<T>* rbvec_node_ptr_;
9745       };
9746
9747       template <typename T>
9748       class assignment_vec_node : public binary_node     <T>,
9749                                   public vector_interface<T>
9750       {
9751       public:
9752
9753          typedef expression_node<T>* expression_ptr;
9754          typedef vector_node<T>*    vector_node_ptr;
9755          typedef vec_data_store<T>            vds_t;
9756
9757          assignment_vec_node(const operator_type& opr,
9758                              expression_ptr branch0,
9759                              expression_ptr branch1)
9760          : binary_node<T>(opr, branch0, branch1),
9761            vec_node_ptr_(0)
9762          {
9763             if (is_vector_node(binary_node<T>::branch_[0].first))
9764             {
9765                vec_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
9766                vds()         = vec_node_ptr_->vds();
9767             }
9768          }
9769
9770          inline T value() const
9771          {
9772             if (vec_node_ptr_)
9773             {
9774                const T v = binary_node<T>::branch_[1].first->value();
9775
9776                T* vec = vds().data();
9777
9778                loop_unroll::details lud(size());
9779                const T* upper_bound = vec + lud.upper_bound;
9780
9781                while (vec < upper_bound)
9782                {
9783                   #define exprtk_loop(N) \
9784                   vec[N] = v;            \
9785
9786                   exprtk_loop( 0) exprtk_loop( 1)
9787                   exprtk_loop( 2) exprtk_loop( 3)
9788                   #ifndef exprtk_disable_superscalar_unroll
9789                   exprtk_loop( 4) exprtk_loop( 5)
9790                   exprtk_loop( 6) exprtk_loop( 7)
9791                   exprtk_loop( 8) exprtk_loop( 9)
9792                   exprtk_loop(10) exprtk_loop(11)
9793                   exprtk_loop(12) exprtk_loop(13)
9794                   exprtk_loop(14) exprtk_loop(15)
9795                   #endif
9796
9797                   vec += lud.batch_size;
9798                }
9799
9800                exprtk_disable_fallthrough_begin
9801                switch (lud.remainder)
9802                {
9803                   #define case_stmt(N) \
9804                   case N : *vec++ = v; \
9805
9806                   #ifndef exprtk_disable_superscalar_unroll
9807                   case_stmt(15) case_stmt(14)
9808                   case_stmt(13) case_stmt(12)
9809                   case_stmt(11) case_stmt(10)
9810                   case_stmt( 9) case_stmt( 8)
9811                   case_stmt( 7) case_stmt( 6)
9812                   case_stmt( 5) case_stmt( 4)
9813                   #endif
9814                   case_stmt( 3) case_stmt( 2)
9815                   case_stmt( 1)
9816                }
9817                exprtk_disable_fallthrough_end
9818
9819                #undef exprtk_loop
9820                #undef case_stmt
9821
9822                return vec_node_ptr_->value();
9823             }
9824             else
9825                return std::numeric_limits<T>::quiet_NaN();
9826          }
9827
9828          vector_node_ptr vec() const
9829          {
9830             return vec_node_ptr_;
9831          }
9832
9833          vector_node_ptr vec()
9834          {
9835             return vec_node_ptr_;
9836          }
9837
9838          inline typename expression_node<T>::node_type type() const
9839          {
9840             return expression_node<T>::e_vecvalass;
9841          }
9842
9843          std::size_t size() const
9844          {
9845             return vds().size();
9846          }
9847
9848          vds_t& vds()
9849          {
9850             return vds_;
9851          }
9852
9853          const vds_t& vds() const
9854          {
9855             return vds_;
9856          }
9857
9858       private:
9859
9860          vector_node<T>* vec_node_ptr_;
9861          vds_t           vds_;
9862       };
9863
9864       template <typename T>
9865       class assignment_vecvec_node : public binary_node     <T>,
9866                                      public vector_interface<T>
9867       {
9868       public:
9869
9870          typedef expression_node<T>*  expression_ptr;
9871          typedef vector_node<T>*     vector_node_ptr;
9872          typedef vec_data_store<T>             vds_t;
9873
9874          assignment_vecvec_node(const operator_type& opr,
9875                                 expression_ptr branch0,
9876                                 expression_ptr branch1)
9877          : binary_node<T>(opr, branch0, branch1),
9878            vec0_node_ptr_(0),
9879            vec1_node_ptr_(0),
9880            initialised_(false),
9881            src_is_ivec_(false)
9882          {
9883             if (is_vector_node(binary_node<T>::branch_[0].first))
9884             {
9885                vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
9886                vds()          = vec0_node_ptr_->vds();
9887             }
9888
9889             if (is_vector_node(binary_node<T>::branch_[1].first))
9890             {
9891                vec1_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first);
9892                vds_t::match_sizes(vds(),vec1_node_ptr_->vds());
9893             }
9894             else if (is_ivector_node(binary_node<T>::branch_[1].first))
9895             {
9896                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
9897
9898                if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
9899                {
9900                   vec1_node_ptr_ = vi->vec();
9901
9902                   if (!vi->side_effect())
9903                   {
9904                      vi->vds()    = vds();
9905                      src_is_ivec_ = true;
9906                   }
9907                   else
9908                      vds_t::match_sizes(vds(),vi->vds());
9909                }
9910             }
9911
9912             initialised_ = (vec0_node_ptr_ && vec1_node_ptr_);
9913          }
9914
9915          inline T value() const
9916          {
9917             if (initialised_)
9918             {
9919                binary_node<T>::branch_[1].first->value();
9920
9921                if (src_is_ivec_)
9922                   return vec0_node_ptr_->value();
9923
9924                T* vec0 = vec0_node_ptr_->vds().data();
9925                T* vec1 = vec1_node_ptr_->vds().data();
9926
9927                loop_unroll::details lud(size());
9928                const T* upper_bound = vec0 + lud.upper_bound;
9929
9930                while (vec0 < upper_bound)
9931                {
9932                   #define exprtk_loop(N) \
9933                   vec0[N] = vec1[N];     \
9934
9935                   exprtk_loop( 0) exprtk_loop( 1)
9936                   exprtk_loop( 2) exprtk_loop( 3)
9937                   #ifndef exprtk_disable_superscalar_unroll
9938                   exprtk_loop( 4) exprtk_loop( 5)
9939                   exprtk_loop( 6) exprtk_loop( 7)
9940                   exprtk_loop( 8) exprtk_loop( 9)
9941                   exprtk_loop(10) exprtk_loop(11)
9942                   exprtk_loop(12) exprtk_loop(13)
9943                   exprtk_loop(14) exprtk_loop(15)
9944                   #endif
9945
9946                   vec0 += lud.batch_size;
9947                   vec1 += lud.batch_size;
9948                }
9949
9950                exprtk_disable_fallthrough_begin
9951                switch (lud.remainder)
9952                {
9953                   #define case_stmt(N)        \
9954                   case N : *vec0++ = *vec1++; \
9955
9956                   #ifndef exprtk_disable_superscalar_unroll
9957                   case_stmt(15) case_stmt(14)
9958                   case_stmt(13) case_stmt(12)
9959                   case_stmt(11) case_stmt(10)
9960                   case_stmt( 9) case_stmt( 8)
9961                   case_stmt( 7) case_stmt( 6)
9962                   case_stmt( 5) case_stmt( 4)
9963                   #endif
9964                   case_stmt( 3) case_stmt( 2)
9965                   case_stmt( 1)
9966                }
9967                exprtk_disable_fallthrough_end
9968
9969                #undef exprtk_loop
9970                #undef case_stmt
9971
9972                return vec0_node_ptr_->value();
9973             }
9974             else
9975                return std::numeric_limits<T>::quiet_NaN();
9976          }
9977
9978          vector_node_ptr vec() const
9979          {
9980             return vec0_node_ptr_;
9981          }
9982
9983          vector_node_ptr vec()
9984          {
9985             return vec0_node_ptr_;
9986          }
9987
9988          inline typename expression_node<T>::node_type type() const
9989          {
9990             return expression_node<T>::e_vecvecass;
9991          }
9992
9993          std::size_t size() const
9994          {
9995             return vds().size();
9996          }
9997
9998          vds_t& vds()
9999          {
10000             return vds_;
10001          }
10002
10003          const vds_t& vds() const
10004          {
10005             return vds_;
10006          }
10007
10008       private:
10009
10010          vector_node<T>* vec0_node_ptr_;
10011          vector_node<T>* vec1_node_ptr_;
10012          bool            initialised_;
10013          bool            src_is_ivec_;
10014          vds_t           vds_;
10015       };
10016
10017       template <typename T, typename Operation>
10018       class assignment_op_node : public binary_node<T>
10019       {
10020       public:
10021
10022          typedef expression_node<T>* expression_ptr;
10023
10024          assignment_op_node(const operator_type& opr,
10025                             expression_ptr branch0,
10026                             expression_ptr branch1)
10027          : binary_node<T>(opr, branch0, branch1),
10028            var_node_ptr_(0)
10029          {
10030             if (is_variable_node(binary_node<T>::branch_[0].first))
10031             {
10032                var_node_ptr_ = static_cast<variable_node<T>*>(binary_node<T>::branch_[0].first);
10033             }
10034          }
10035
10036          inline T value() const
10037          {
10038             if (var_node_ptr_)
10039             {
10040                T& v = var_node_ptr_->ref();
10041                v = Operation::process(v,binary_node<T>::branch_[1].first->value());
10042
10043                return v;
10044             }
10045             else
10046                return std::numeric_limits<T>::quiet_NaN();
10047          }
10048
10049       private:
10050
10051          variable_node<T>* var_node_ptr_;
10052       };
10053
10054       template <typename T, typename Operation>
10055       class assignment_vec_elem_op_node : public binary_node<T>
10056       {
10057       public:
10058
10059          typedef expression_node<T>* expression_ptr;
10060
10061          assignment_vec_elem_op_node(const operator_type& opr,
10062                                      expression_ptr branch0,
10063                                      expression_ptr branch1)
10064          : binary_node<T>(opr, branch0, branch1),
10065            vec_node_ptr_(0)
10066          {
10067             if (is_vector_elem_node(binary_node<T>::branch_[0].first))
10068             {
10069                vec_node_ptr_ = static_cast<vector_elem_node<T>*>(binary_node<T>::branch_[0].first);
10070             }
10071          }
10072
10073          inline T value() const
10074          {
10075             if (vec_node_ptr_)
10076             {
10077                T& v = vec_node_ptr_->ref();
10078                   v = Operation::process(v,binary_node<T>::branch_[1].first->value());
10079
10080                return v;
10081             }
10082             else
10083                return std::numeric_limits<T>::quiet_NaN();
10084          }
10085
10086       private:
10087
10088          vector_elem_node<T>* vec_node_ptr_;
10089       };
10090
10091       template <typename T, typename Operation>
10092       class assignment_rebasevec_elem_op_node : public binary_node<T>
10093       {
10094       public:
10095
10096          typedef expression_node<T>* expression_ptr;
10097
10098          assignment_rebasevec_elem_op_node(const operator_type& opr,
10099                                            expression_ptr branch0,
10100                                            expression_ptr branch1)
10101          : binary_node<T>(opr, branch0, branch1),
10102            rbvec_node_ptr_(0)
10103          {
10104             if (is_rebasevector_elem_node(binary_node<T>::branch_[0].first))
10105             {
10106                rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(binary_node<T>::branch_[0].first);
10107             }
10108          }
10109
10110          inline T value() const
10111          {
10112             if (rbvec_node_ptr_)
10113             {
10114                T& v = rbvec_node_ptr_->ref();
10115                   v = Operation::process(v,binary_node<T>::branch_[1].first->value());
10116
10117                return v;
10118             }
10119             else
10120                return std::numeric_limits<T>::quiet_NaN();
10121          }
10122
10123       private:
10124
10125          rebasevector_elem_node<T>* rbvec_node_ptr_;
10126       };
10127
10128       template <typename T, typename Operation>
10129       class assignment_rebasevec_celem_op_node : public binary_node<T>
10130       {
10131       public:
10132
10133          typedef expression_node<T>* expression_ptr;
10134
10135          assignment_rebasevec_celem_op_node(const operator_type& opr,
10136                                             expression_ptr branch0,
10137                                             expression_ptr branch1)
10138          : binary_node<T>(opr, branch0, branch1),
10139            rbvec_node_ptr_(0)
10140          {
10141             if (is_rebasevector_celem_node(binary_node<T>::branch_[0].first))
10142             {
10143                rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(binary_node<T>::branch_[0].first);
10144             }
10145          }
10146
10147          inline T value() const
10148          {
10149             if (rbvec_node_ptr_)
10150             {
10151                T& v = rbvec_node_ptr_->ref();
10152                   v = Operation::process(v,binary_node<T>::branch_[1].first->value());
10153
10154                return v;
10155             }
10156             else
10157                return std::numeric_limits<T>::quiet_NaN();
10158          }
10159
10160       private:
10161
10162          rebasevector_celem_node<T>* rbvec_node_ptr_;
10163       };
10164
10165       template <typename T, typename Operation>
10166       class assignment_vec_op_node : public binary_node     <T>,
10167                                      public vector_interface<T>
10168       {
10169       public:
10170
10171          typedef expression_node<T>*  expression_ptr;
10172          typedef vector_node<T>*     vector_node_ptr;
10173          typedef vec_data_store<T>             vds_t;
10174
10175          assignment_vec_op_node(const operator_type& opr,
10176                                 expression_ptr branch0,
10177                                 expression_ptr branch1)
10178          : binary_node<T>(opr, branch0, branch1),
10179            vec_node_ptr_(0)
10180          {
10181             if (is_vector_node(binary_node<T>::branch_[0].first))
10182             {
10183                vec_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
10184                vds()         = vec_node_ptr_->vds();
10185             }
10186          }
10187
10188          inline T value() const
10189          {
10190             if (vec_node_ptr_)
10191             {
10192                const T v = binary_node<T>::branch_[1].first->value();
10193
10194                T* vec = vds().data();
10195
10196                loop_unroll::details lud(size());
10197                const T* upper_bound = vec + lud.upper_bound;
10198
10199                while (vec < upper_bound)
10200                {
10201                   #define exprtk_loop(N)       \
10202                   Operation::assign(vec[N],v); \
10203
10204                   exprtk_loop( 0) exprtk_loop( 1)
10205                   exprtk_loop( 2) exprtk_loop( 3)
10206                   #ifndef exprtk_disable_superscalar_unroll
10207                   exprtk_loop( 4) exprtk_loop( 5)
10208                   exprtk_loop( 6) exprtk_loop( 7)
10209                   exprtk_loop( 8) exprtk_loop( 9)
10210                   exprtk_loop(10) exprtk_loop(11)
10211                   exprtk_loop(12) exprtk_loop(13)
10212                   exprtk_loop(14) exprtk_loop(15)
10213                   #endif
10214
10215                   vec += lud.batch_size;
10216                }
10217
10218                exprtk_disable_fallthrough_begin
10219                switch (lud.remainder)
10220                {
10221                   #define case_stmt(N)                  \
10222                   case N : Operation::assign(*vec++,v); \
10223
10224                   #ifndef exprtk_disable_superscalar_unroll
10225                   case_stmt(15) case_stmt(14)
10226                   case_stmt(13) case_stmt(12)
10227                   case_stmt(11) case_stmt(10)
10228                   case_stmt( 9) case_stmt( 8)
10229                   case_stmt( 7) case_stmt( 6)
10230                   case_stmt( 5) case_stmt( 4)
10231                   #endif
10232                   case_stmt( 3) case_stmt( 2)
10233                   case_stmt( 1)
10234                }
10235                exprtk_disable_fallthrough_end
10236
10237
10238                #undef exprtk_loop
10239                #undef case_stmt
10240
10241                return vec_node_ptr_->value();
10242             }
10243             else
10244                return std::numeric_limits<T>::quiet_NaN();
10245          }
10246
10247          vector_node_ptr vec() const
10248          {
10249             return vec_node_ptr_;
10250          }
10251
10252          vector_node_ptr vec()
10253          {
10254             return vec_node_ptr_;
10255          }
10256
10257          inline typename expression_node<T>::node_type type() const
10258          {
10259             return expression_node<T>::e_vecopvalass;
10260          }
10261
10262          std::size_t size() const
10263          {
10264             return vds().size();
10265          }
10266
10267          vds_t& vds()
10268          {
10269             return vds_;
10270          }
10271
10272          const vds_t& vds() const
10273          {
10274             return vds_;
10275          }
10276
10277          bool side_effect() const
10278          {
10279             return true;
10280          }
10281
10282       private:
10283
10284          vector_node<T>* vec_node_ptr_;
10285          vds_t           vds_;
10286       };
10287
10288       template <typename T, typename Operation>
10289       class assignment_vecvec_op_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
10298          assignment_vecvec_op_node(const operator_type& opr,
10299                                    expression_ptr branch0,
10300                                    expression_ptr branch1)
10301          : binary_node<T>(opr, branch0, branch1),
10302            vec0_node_ptr_(0),
10303            vec1_node_ptr_(0),
10304            initialised_(false)
10305          {
10306             if (is_vector_node(binary_node<T>::branch_[0].first))
10307             {
10308                vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
10309                vds()          = vec0_node_ptr_->vds();
10310             }
10311
10312             if (is_vector_node(binary_node<T>::branch_[1].first))
10313             {
10314                vec1_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first);
10315                vec1_node_ptr_->vds() = vds();
10316             }
10317             else if (is_ivector_node(binary_node<T>::branch_[1].first))
10318             {
10319                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
10320
10321                if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
10322                {
10323                   vec1_node_ptr_ = vi->vec();
10324                   vec1_node_ptr_->vds() = vds();
10325                }
10326                else
10327                   vds_t::match_sizes(vds(),vec1_node_ptr_->vds());
10328             }
10329
10330             initialised_ = (vec0_node_ptr_ && vec1_node_ptr_);
10331          }
10332
10333          inline T value() const
10334          {
10335             if (initialised_)
10336             {
10337                binary_node<T>::branch_[0].first->value();
10338                binary_node<T>::branch_[1].first->value();
10339
10340                      T* vec0 = vec0_node_ptr_->vds().data();
10341                const T* vec1 = vec1_node_ptr_->vds().data();
10342
10343                loop_unroll::details lud(size());
10344                const T* upper_bound = vec0 + lud.upper_bound;
10345
10346                while (vec0 < upper_bound)
10347                {
10348                   #define exprtk_loop(N)                          \
10349                   vec0[N] = Operation::process(vec0[N], vec1[N]); \
10350
10351                   exprtk_loop( 0) exprtk_loop( 1)
10352                   exprtk_loop( 2) exprtk_loop( 3)
10353                   #ifndef exprtk_disable_superscalar_unroll
10354                   exprtk_loop( 4) exprtk_loop( 5)
10355                   exprtk_loop( 6) exprtk_loop( 7)
10356                   exprtk_loop( 8) exprtk_loop( 9)
10357                   exprtk_loop(10) exprtk_loop(11)
10358                   exprtk_loop(12) exprtk_loop(13)
10359                   exprtk_loop(14) exprtk_loop(15)
10360                   #endif
10361
10362                   vec0 += lud.batch_size;
10363                   vec1 += lud.batch_size;
10364                }
10365
10366                int i = 0;
10367
10368                exprtk_disable_fallthrough_begin
10369                switch (lud.remainder)
10370                {
10371                   #define case_stmt(N)                                              \
10372                   case N : { vec0[i] = Operation::process(vec0[i], vec1[i]); ++i; } \
10373
10374                   #ifndef exprtk_disable_superscalar_unroll
10375                   case_stmt(15) case_stmt(14)
10376                   case_stmt(13) case_stmt(12)
10377                   case_stmt(11) case_stmt(10)
10378                   case_stmt( 9) case_stmt( 8)
10379                   case_stmt( 7) case_stmt( 6)
10380                   case_stmt( 5) case_stmt( 4)
10381                   #endif
10382                   case_stmt( 3) case_stmt( 2)
10383                   case_stmt( 1)
10384                }
10385                exprtk_disable_fallthrough_end
10386
10387                #undef exprtk_loop
10388                #undef case_stmt
10389
10390                return vec0_node_ptr_->value();
10391             }
10392             else
10393                return std::numeric_limits<T>::quiet_NaN();
10394          }
10395
10396          vector_node_ptr vec() const
10397          {
10398             return vec0_node_ptr_;
10399          }
10400
10401          vector_node_ptr vec()
10402          {
10403             return vec0_node_ptr_;
10404          }
10405
10406          inline typename expression_node<T>::node_type type() const
10407          {
10408             return expression_node<T>::e_vecopvecass;
10409          }
10410
10411          std::size_t size() const
10412          {
10413             return vds().size();
10414          }
10415
10416          vds_t& vds()
10417          {
10418             return vds_;
10419          }
10420
10421          const vds_t& vds() const
10422          {
10423             return vds_;
10424          }
10425
10426          bool side_effect() const
10427          {
10428             return true;
10429          }
10430
10431       private:
10432
10433          vector_node<T>* vec0_node_ptr_;
10434          vector_node<T>* vec1_node_ptr_;
10435          bool            initialised_;
10436          vds_t           vds_;
10437       };
10438
10439       template <typename T, typename Operation>
10440       class vec_binop_vecvec_node : public binary_node     <T>,
10441                                     public vector_interface<T>
10442       {
10443       public:
10444
10445          typedef expression_node<T>*    expression_ptr;
10446          typedef vector_node<T>*       vector_node_ptr;
10447          typedef vector_holder<T>*   vector_holder_ptr;
10448          typedef vec_data_store<T>               vds_t;
10449
10450          vec_binop_vecvec_node(const operator_type& opr,
10451                                expression_ptr branch0,
10452                                expression_ptr branch1)
10453          : binary_node<T>(opr, branch0, branch1),
10454            vec0_node_ptr_(0),
10455            vec1_node_ptr_(0),
10456            temp_         (0),
10457            temp_vec_node_(0),
10458            initialised_(false)
10459          {
10460             bool v0_is_ivec = false;
10461             bool v1_is_ivec = false;
10462
10463             if (is_vector_node(binary_node<T>::branch_[0].first))
10464             {
10465                vec0_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[0].first);
10466             }
10467             else if (is_ivector_node(binary_node<T>::branch_[0].first))
10468             {
10469                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
10470
10471                if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
10472                {
10473                   vec0_node_ptr_ = vi->vec();
10474                   v0_is_ivec     = true;
10475                }
10476             }
10477
10478             if (is_vector_node(binary_node<T>::branch_[1].first))
10479             {
10480                vec1_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[1].first);
10481             }
10482             else if (is_ivector_node(binary_node<T>::branch_[1].first))
10483             {
10484                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
10485
10486                if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
10487                {
10488                   vec1_node_ptr_ = vi->vec();
10489                   v1_is_ivec     = true;
10490                }
10491             }
10492
10493             if (vec0_node_ptr_ && vec1_node_ptr_)
10494             {
10495                vector_holder<T>& vec0 = vec0_node_ptr_->vec_holder();
10496                vector_holder<T>& vec1 = vec1_node_ptr_->vec_holder();
10497
10498                if (v0_is_ivec && (vec0.size() <= vec1.size()))
10499                   vds_ = vds_t(vec0_node_ptr_->vds());
10500                else if (v1_is_ivec && (vec1.size() <= vec0.size()))
10501                   vds_ = vds_t(vec1_node_ptr_->vds());
10502                else
10503                   vds_ = vds_t(std::min(vec0.size(),vec1.size()));
10504
10505                temp_          = new vector_holder<T>(vds().data(),vds().size());
10506                temp_vec_node_ = new vector_node<T>  (vds(),temp_);
10507
10508                initialised_ = true;
10509             }
10510          }
10511
10512         ~vec_binop_vecvec_node()
10513          {
10514             delete temp_;
10515             delete temp_vec_node_;
10516          }
10517
10518          inline T value() const
10519          {
10520             if (initialised_)
10521             {
10522                binary_node<T>::branch_[0].first->value();
10523                binary_node<T>::branch_[1].first->value();
10524
10525                const T* vec0 = vec0_node_ptr_->vds().data();
10526                const T* vec1 = vec1_node_ptr_->vds().data();
10527                      T* vec2 = vds().data();
10528
10529                loop_unroll::details lud(size());
10530                const T* upper_bound = vec2 + lud.upper_bound;
10531
10532                while (vec2 < upper_bound)
10533                {
10534                   #define exprtk_loop(N)                          \
10535                   vec2[N] = Operation::process(vec0[N], vec1[N]); \
10536
10537                   exprtk_loop( 0) exprtk_loop( 1)
10538                   exprtk_loop( 2) exprtk_loop( 3)
10539                   #ifndef exprtk_disable_superscalar_unroll
10540                   exprtk_loop( 4) exprtk_loop( 5)
10541                   exprtk_loop( 6) exprtk_loop( 7)
10542                   exprtk_loop( 8) exprtk_loop( 9)
10543                   exprtk_loop(10) exprtk_loop(11)
10544                   exprtk_loop(12) exprtk_loop(13)
10545                   exprtk_loop(14) exprtk_loop(15)
10546                   #endif
10547
10548                   vec0 += lud.batch_size;
10549                   vec1 += lud.batch_size;
10550                   vec2 += lud.batch_size;
10551                }
10552
10553                int i = 0;
10554
10555                exprtk_disable_fallthrough_begin
10556                switch (lud.remainder)
10557                {
10558                   #define case_stmt(N)                                              \
10559                   case N : { vec2[i] = Operation::process(vec0[i], vec1[i]); ++i; } \
10560
10561                   #ifndef exprtk_disable_superscalar_unroll
10562                   case_stmt(15) case_stmt(14)
10563                   case_stmt(13) case_stmt(12)
10564                   case_stmt(11) case_stmt(10)
10565                   case_stmt( 9) case_stmt( 8)
10566                   case_stmt( 7) case_stmt( 6)
10567                   case_stmt( 5) case_stmt( 4)
10568                   #endif
10569                   case_stmt( 3) case_stmt( 2)
10570                   case_stmt( 1)
10571                }
10572                exprtk_disable_fallthrough_end
10573
10574                #undef exprtk_loop
10575                #undef case_stmt
10576
10577                return (vds().data())[0];
10578             }
10579             else
10580                return std::numeric_limits<T>::quiet_NaN();
10581          }
10582
10583          vector_node_ptr vec() const
10584          {
10585             return temp_vec_node_;
10586          }
10587
10588          vector_node_ptr vec()
10589          {
10590             return temp_vec_node_;
10591          }
10592
10593          inline typename expression_node<T>::node_type type() const
10594          {
10595             return expression_node<T>::e_vecvecarith;
10596          }
10597
10598          std::size_t size() const
10599          {
10600             return vds_.size();
10601          }
10602
10603          vds_t& vds()
10604          {
10605             return vds_;
10606          }
10607
10608          const vds_t& vds() const
10609          {
10610             return vds_;
10611          }
10612
10613       private:
10614
10615          vector_node_ptr   vec0_node_ptr_;
10616          vector_node_ptr   vec1_node_ptr_;
10617          vector_holder_ptr temp_;
10618          vector_node_ptr   temp_vec_node_;
10619          bool              initialised_;
10620          vds_t             vds_;
10621       };
10622
10623       template <typename T, typename Operation>
10624       class vec_binop_vecval_node : public binary_node     <T>,
10625                                     public vector_interface<T>
10626       {
10627       public:
10628
10629          typedef expression_node<T>*    expression_ptr;
10630          typedef vector_node<T>*       vector_node_ptr;
10631          typedef vector_holder<T>*   vector_holder_ptr;
10632          typedef vec_data_store<T>               vds_t;
10633
10634          vec_binop_vecval_node(const operator_type& opr,
10635                                expression_ptr branch0,
10636                                expression_ptr branch1)
10637          : binary_node<T>(opr, branch0, branch1),
10638            vec0_node_ptr_(0),
10639            temp_         (0),
10640            temp_vec_node_(0)
10641          {
10642             bool v0_is_ivec = false;
10643
10644             if (is_vector_node(binary_node<T>::branch_[0].first))
10645             {
10646                vec0_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[0].first);
10647             }
10648             else if (is_ivector_node(binary_node<T>::branch_[0].first))
10649             {
10650                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
10651
10652                if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
10653                {
10654                   vec0_node_ptr_ = vi->vec();
10655                   v0_is_ivec     = true;
10656                }
10657             }
10658
10659             if (vec0_node_ptr_)
10660             {
10661                if (v0_is_ivec)
10662                   vds() = vec0_node_ptr_->vds();
10663                else
10664                   vds() = vds_t(vec0_node_ptr_->size());
10665
10666                temp_          = new vector_holder<T>(vds());
10667                temp_vec_node_ = new vector_node<T>  (vds(),temp_);
10668             }
10669          }
10670
10671         ~vec_binop_vecval_node()
10672          {
10673             delete temp_;
10674             delete temp_vec_node_;
10675          }
10676
10677          inline T value() const
10678          {
10679             if (vec0_node_ptr_)
10680             {
10681                            binary_node<T>::branch_[0].first->value();
10682                const T v = binary_node<T>::branch_[1].first->value();
10683
10684                const T* vec0 = vec0_node_ptr_->vds().data();
10685                      T* vec1 = vds().data();
10686
10687                loop_unroll::details lud(size());
10688                const T* upper_bound = vec0 + lud.upper_bound;
10689
10690                while (vec0 < upper_bound)
10691                {
10692                   #define exprtk_loop(N)                    \
10693                   vec1[N] = Operation::process(vec0[N], v); \
10694
10695                   exprtk_loop( 0) exprtk_loop( 1)
10696                   exprtk_loop( 2) exprtk_loop( 3)
10697                   #ifndef exprtk_disable_superscalar_unroll
10698                   exprtk_loop( 4) exprtk_loop( 5)
10699                   exprtk_loop( 6) exprtk_loop( 7)
10700                   exprtk_loop( 8) exprtk_loop( 9)
10701                   exprtk_loop(10) exprtk_loop(11)
10702                   exprtk_loop(12) exprtk_loop(13)
10703                   exprtk_loop(14) exprtk_loop(15)
10704                   #endif
10705
10706                   vec0 += lud.batch_size;
10707                   vec1 += lud.batch_size;
10708                }
10709
10710                int i = 0;
10711
10712                exprtk_disable_fallthrough_begin
10713                switch (lud.remainder)
10714                {
10715                   #define case_stmt(N)                                        \
10716                   case N : { vec1[i] = Operation::process(vec0[i], v); ++i; } \
10717
10718                   #ifndef exprtk_disable_superscalar_unroll
10719                   case_stmt(15) case_stmt(14)
10720                   case_stmt(13) case_stmt(12)
10721                   case_stmt(11) case_stmt(10)
10722                   case_stmt( 9) case_stmt( 8)
10723                   case_stmt( 7) case_stmt( 6)
10724                   case_stmt( 5) case_stmt( 4)
10725                   #endif
10726                   case_stmt( 3) case_stmt( 2)
10727                   case_stmt( 1)
10728                }
10729                exprtk_disable_fallthrough_end
10730
10731                #undef exprtk_loop
10732                #undef case_stmt
10733
10734                return (vds().data())[0];
10735             }
10736             else
10737                return std::numeric_limits<T>::quiet_NaN();
10738          }
10739
10740          vector_node_ptr vec() const
10741          {
10742             return temp_vec_node_;
10743          }
10744
10745          vector_node_ptr vec()
10746          {
10747             return temp_vec_node_;
10748          }
10749
10750          inline typename expression_node<T>::node_type type() const
10751          {
10752             return expression_node<T>::e_vecvalarith;
10753          }
10754
10755          std::size_t size() const
10756          {
10757             return vds().size();
10758          }
10759
10760          vds_t& vds()
10761          {
10762             return vds_;
10763          }
10764
10765          const vds_t& vds() const
10766          {
10767             return vds_;
10768          }
10769
10770       private:
10771
10772          vector_node_ptr   vec0_node_ptr_;
10773          vector_holder_ptr temp_;
10774          vector_node_ptr   temp_vec_node_;
10775          vds_t             vds_;
10776       };
10777
10778       template <typename T, typename Operation>
10779       class vec_binop_valvec_node : public binary_node     <T>,
10780                                     public vector_interface<T>
10781       {
10782       public:
10783
10784          typedef expression_node<T>*    expression_ptr;
10785          typedef vector_node<T>*       vector_node_ptr;
10786          typedef vector_holder<T>*   vector_holder_ptr;
10787          typedef vec_data_store<T>               vds_t;
10788
10789          vec_binop_valvec_node(const operator_type& opr,
10790                                expression_ptr branch0,
10791                                expression_ptr branch1)
10792          : binary_node<T>(opr, branch0, branch1),
10793            vec1_node_ptr_(0),
10794            temp_         (0),
10795            temp_vec_node_(0)
10796          {
10797             bool v1_is_ivec = false;
10798
10799             if (is_vector_node(binary_node<T>::branch_[1].first))
10800             {
10801                vec1_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[1].first);
10802             }
10803             else if (is_ivector_node(binary_node<T>::branch_[1].first))
10804             {
10805                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
10806
10807                if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
10808                {
10809                   vec1_node_ptr_ = vi->vec();
10810                   v1_is_ivec     = true;
10811                }
10812             }
10813
10814             if (vec1_node_ptr_)
10815             {
10816                if (v1_is_ivec)
10817                   vds() = vec1_node_ptr_->vds();
10818                else
10819                   vds() = vds_t(vec1_node_ptr_->size());
10820
10821                temp_          = new vector_holder<T>(vds());
10822                temp_vec_node_ = new vector_node<T>  (vds(),temp_);
10823             }
10824          }
10825
10826         ~vec_binop_valvec_node()
10827          {
10828             delete temp_;
10829             delete temp_vec_node_;
10830          }
10831
10832          inline T value() const
10833          {
10834             if (vec1_node_ptr_)
10835             {
10836                const T v = binary_node<T>::branch_[0].first->value();
10837                            binary_node<T>::branch_[1].first->value();
10838
10839                      T* vec0 = vds().data();
10840                const T* vec1 = vec1_node_ptr_->vds().data();
10841
10842                loop_unroll::details lud(size());
10843                const T* upper_bound = vec0 + lud.upper_bound;
10844
10845                while (vec0 < upper_bound)
10846                {
10847                   #define exprtk_loop(N)                    \
10848                   vec0[N] = Operation::process(v, vec1[N]); \
10849
10850                   exprtk_loop( 0) exprtk_loop( 1)
10851                   exprtk_loop( 2) exprtk_loop( 3)
10852                   #ifndef exprtk_disable_superscalar_unroll
10853                   exprtk_loop( 4) exprtk_loop( 5)
10854                   exprtk_loop( 6) exprtk_loop( 7)
10855                   exprtk_loop( 8) exprtk_loop( 9)
10856                   exprtk_loop(10) exprtk_loop(11)
10857                   exprtk_loop(12) exprtk_loop(13)
10858                   exprtk_loop(14) exprtk_loop(15)
10859                   #endif
10860
10861                   vec0 += lud.batch_size;
10862                   vec1 += lud.batch_size;
10863                }
10864
10865                int i = 0;
10866
10867                exprtk_disable_fallthrough_begin
10868                switch (lud.remainder)
10869                {
10870                   #define case_stmt(N)                                        \
10871                   case N : { vec0[i] = Operation::process(v, vec1[i]); ++i; } \
10872
10873                   #ifndef exprtk_disable_superscalar_unroll
10874                   case_stmt(15) case_stmt(14)
10875                   case_stmt(13) case_stmt(12)
10876                   case_stmt(11) case_stmt(10)
10877                   case_stmt( 9) case_stmt( 8)
10878                   case_stmt( 7) case_stmt( 6)
10879                   case_stmt( 5) case_stmt( 4)
10880                   #endif
10881                   case_stmt( 3) case_stmt( 2)
10882                   case_stmt( 1)
10883                }
10884                exprtk_disable_fallthrough_end
10885
10886                #undef exprtk_loop
10887                #undef case_stmt
10888
10889                return (vds().data())[0];
10890             }
10891             else
10892                return std::numeric_limits<T>::quiet_NaN();
10893          }
10894
10895          vector_node_ptr vec() const
10896          {
10897             return temp_vec_node_;
10898          }
10899
10900          vector_node_ptr vec()
10901          {
10902             return temp_vec_node_;
10903          }
10904
10905          inline typename expression_node<T>::node_type type() const
10906          {
10907             return expression_node<T>::e_vecvalarith;
10908          }
10909
10910          std::size_t size() const
10911          {
10912             return vds().size();
10913          }
10914
10915          vds_t& vds()
10916          {
10917             return vds_;
10918          }
10919
10920          const vds_t& vds() const
10921          {
10922             return vds_;
10923          }
10924
10925       private:
10926
10927          vector_node_ptr   vec1_node_ptr_;
10928          vector_holder_ptr temp_;
10929          vector_node_ptr   temp_vec_node_;
10930          vds_t             vds_;
10931       };
10932
10933       template <typename T, typename Operation>
10934       class unary_vector_node : public unary_node      <T>,
10935                                 public vector_interface<T>
10936       {
10937       public:
10938
10939          typedef expression_node<T>*    expression_ptr;
10940          typedef vector_node<T>*       vector_node_ptr;
10941          typedef vector_holder<T>*   vector_holder_ptr;
10942          typedef vec_data_store<T>               vds_t;
10943
10944          unary_vector_node(const operator_type& opr, expression_ptr branch0)
10945          : unary_node<T>(opr, branch0),
10946            vec0_node_ptr_(0),
10947            temp_         (0),
10948            temp_vec_node_(0)
10949          {
10950             bool vec0_is_ivec = false;
10951
10952             if (is_vector_node(unary_node<T>::branch_))
10953             {
10954                vec0_node_ptr_ = static_cast<vector_node_ptr>(unary_node<T>::branch_);
10955             }
10956             else if (is_ivector_node(unary_node<T>::branch_))
10957             {
10958                vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
10959
10960                if (0 != (vi = dynamic_cast<vector_interface<T>*>(unary_node<T>::branch_)))
10961                {
10962                   vec0_node_ptr_ = vi->vec();
10963                   vec0_is_ivec   = true;
10964                }
10965             }
10966
10967             if (vec0_node_ptr_)
10968             {
10969                if (vec0_is_ivec)
10970                   vds_ = vec0_node_ptr_->vds();
10971                else
10972                   vds_ = vds_t(vec0_node_ptr_->size());
10973
10974                temp_          = new vector_holder<T>(vds());
10975                temp_vec_node_ = new vector_node<T>  (vds(),temp_);
10976             }
10977          }
10978
10979         ~unary_vector_node()
10980          {
10981             delete temp_;
10982             delete temp_vec_node_;
10983          }
10984
10985          inline T value() const
10986          {
10987             unary_node<T>::branch_->value();
10988
10989             if (vec0_node_ptr_)
10990             {
10991                const T* vec0 = vec0_node_ptr_->vds().data();
10992                      T* vec1 = vds().data();
10993
10994                loop_unroll::details lud(size());
10995                const T* upper_bound = vec0 + lud.upper_bound;
10996
10997                while (vec0 < upper_bound)
10998                {
10999                   #define exprtk_loop(N)                 \
11000                   vec1[N] = Operation::process(vec0[N]); \
11001
11002                   exprtk_loop( 0) exprtk_loop( 1)
11003                   exprtk_loop( 2) exprtk_loop( 3)
11004                   #ifndef exprtk_disable_superscalar_unroll
11005                   exprtk_loop( 4) exprtk_loop( 5)
11006                   exprtk_loop( 6) exprtk_loop( 7)
11007                   exprtk_loop( 8) exprtk_loop( 9)
11008                   exprtk_loop(10) exprtk_loop(11)
11009                   exprtk_loop(12) exprtk_loop(13)
11010                   exprtk_loop(14) exprtk_loop(15)
11011                   #endif
11012
11013                   vec0 += lud.batch_size;
11014                   vec1 += lud.batch_size;
11015                }
11016
11017                int i = 0;
11018
11019                exprtk_disable_fallthrough_begin
11020                switch (lud.remainder)
11021                {
11022                   #define case_stmt(N)                                     \
11023                   case N : { vec1[i] = Operation::process(vec0[i]); ++i; } \
11024
11025                   #ifndef exprtk_disable_superscalar_unroll
11026                   case_stmt(15) case_stmt(14)
11027                   case_stmt(13) case_stmt(12)
11028                   case_stmt(11) case_stmt(10)
11029                   case_stmt( 9) case_stmt( 8)
11030                   case_stmt( 7) case_stmt( 6)
11031                   case_stmt( 5) case_stmt( 4)
11032                   #endif
11033                   case_stmt( 3) case_stmt( 2)
11034                   case_stmt( 1)
11035                }
11036                exprtk_disable_fallthrough_end
11037
11038                #undef exprtk_loop
11039                #undef case_stmt
11040
11041                return (vds().data())[0];
11042             }
11043             else
11044                return std::numeric_limits<T>::quiet_NaN();
11045          }
11046
11047          vector_node_ptr vec() const
11048          {
11049             return temp_vec_node_;
11050          }
11051
11052          vector_node_ptr vec()
11053          {
11054             return temp_vec_node_;
11055          }
11056
11057          inline typename expression_node<T>::node_type type() const
11058          {
11059             return expression_node<T>::e_vecunaryop;
11060          }
11061
11062          std::size_t size() const
11063          {
11064             return vds().size();
11065          }
11066
11067          vds_t& vds()
11068          {
11069             return vds_;
11070          }
11071
11072          const vds_t& vds() const
11073          {
11074             return vds_;
11075          }
11076
11077       private:
11078
11079          vector_node_ptr   vec0_node_ptr_;
11080          vector_holder_ptr temp_;
11081          vector_node_ptr   temp_vec_node_;
11082          vds_t             vds_;
11083       };
11084
11085       template <typename T>
11086       class scand_node : public binary_node<T>
11087       {
11088       public:
11089
11090          typedef expression_node<T>* expression_ptr;
11091
11092          scand_node(const operator_type& opr,
11093                     expression_ptr branch0,
11094                     expression_ptr branch1)
11095          : binary_node<T>(opr, branch0, branch1)
11096          {}
11097
11098          inline T value() const
11099          {
11100             return (
11101                      std::not_equal_to<T>()
11102                         (T(0),binary_node<T>::branch_[0].first->value()) &&
11103                      std::not_equal_to<T>()
11104                         (T(0),binary_node<T>::branch_[1].first->value())
11105                    ) ? T(1) : T(0);
11106          }
11107       };
11108
11109       template <typename T>
11110       class scor_node : public binary_node<T>
11111       {
11112       public:
11113
11114          typedef expression_node<T>* expression_ptr;
11115
11116          scor_node(const operator_type& opr,
11117                    expression_ptr branch0,
11118                    expression_ptr branch1)
11119          : binary_node<T>(opr, branch0, branch1)
11120          {}
11121
11122          inline T value() const
11123          {
11124             return (
11125                      std::not_equal_to<T>()
11126                         (T(0),binary_node<T>::branch_[0].first->value()) ||
11127                      std::not_equal_to<T>()
11128                         (T(0),binary_node<T>::branch_[1].first->value())
11129                    ) ? T(1) : T(0);
11130          }
11131       };
11132
11133       template <typename T, typename IFunction, std::size_t N>
11134       class function_N_node : public expression_node<T>
11135       {
11136       public:
11137
11138          // Function of N paramters.
11139          typedef expression_node<T>* expression_ptr;
11140          typedef std::pair<expression_ptr,bool> branch_t;
11141          typedef IFunction ifunction;
11142
11143          explicit function_N_node(ifunction* func)
11144          : function_((N == func->param_count) ? func : reinterpret_cast<ifunction*>(0)),
11145            parameter_count_(func->param_count)
11146          {}
11147
11148         ~function_N_node()
11149          {
11150             cleanup_branches::execute<T,N>(branch_);
11151          }
11152
11153          template <std::size_t NumBranches>
11154          bool init_branches(expression_ptr (&b)[NumBranches])
11155          {
11156             // Needed for incompetent and broken msvc compiler versions
11157             #ifdef _MSC_VER
11158              #pragma warning(push)
11159              #pragma warning(disable: 4127)
11160             #endif
11161             if (N != NumBranches)
11162                return false;
11163             else
11164             {
11165                for (std::size_t i = 0; i < NumBranches; ++i)
11166                {
11167                   if (b[i])
11168                      branch_[i] = std::make_pair(b[i],branch_deletable(b[i]));
11169                   else
11170                      return false;
11171                }
11172                return true;
11173             }
11174             #ifdef _MSC_VER
11175              #pragma warning(pop)
11176             #endif
11177          }
11178
11179          inline bool operator <(const function_N_node<T,IFunction,N>& fn) const
11180          {
11181             return this < (&fn);
11182          }
11183
11184          inline T value() const
11185          {
11186             // Needed for incompetent and broken msvc compiler versions
11187             #ifdef _MSC_VER
11188              #pragma warning(push)
11189              #pragma warning(disable: 4127)
11190             #endif
11191             if ((0 == function_) || (0 == N))
11192                return std::numeric_limits<T>::quiet_NaN();
11193             else
11194             {
11195                T v[N];
11196                evaluate_branches<T,N>::execute(v,branch_);
11197                return invoke<T,N>::execute(*function_,v);
11198             }
11199             #ifdef _MSC_VER
11200              #pragma warning(pop)
11201             #endif
11202          }
11203
11204          template <typename T_, std::size_t BranchCount>
11205          struct evaluate_branches
11206          {
11207             static inline void execute(T_ (&v)[BranchCount], const branch_t (&b)[BranchCount])
11208             {
11209                for (std::size_t i = 0; i < BranchCount; ++i)
11210                {
11211                   v[i] = b[i].first->value();
11212                }
11213             }
11214          };
11215
11216          template <typename T_>
11217          struct evaluate_branches <T_,5>
11218          {
11219             static inline void execute(T_ (&v)[5], const branch_t (&b)[5])
11220             {
11221                v[0] = b[0].first->value();
11222                v[1] = b[1].first->value();
11223                v[2] = b[2].first->value();
11224                v[3] = b[3].first->value();
11225                v[4] = b[4].first->value();
11226             }
11227          };
11228
11229          template <typename T_>
11230          struct evaluate_branches <T_,4>
11231          {
11232             static inline void execute(T_ (&v)[4], const branch_t (&b)[4])
11233             {
11234                v[0] = b[0].first->value();
11235                v[1] = b[1].first->value();
11236                v[2] = b[2].first->value();
11237                v[3] = b[3].first->value();
11238             }
11239          };
11240
11241          template <typename T_>
11242          struct evaluate_branches <T_,3>
11243          {
11244             static inline void execute(T_ (&v)[3], const branch_t (&b)[3])
11245             {
11246                v[0] = b[0].first->value();
11247                v[1] = b[1].first->value();
11248                v[2] = b[2].first->value();
11249             }
11250          };
11251
11252          template <typename T_>
11253          struct evaluate_branches <T_,2>
11254          {
11255             static inline void execute(T_ (&v)[2], const branch_t (&b)[2])
11256             {
11257                v[0] = b[0].first->value();
11258                v[1] = b[1].first->value();
11259             }
11260          };
11261
11262          template <typename T_>
11263          struct evaluate_branches <T_,1>
11264          {
11265             static inline void execute(T_ (&v)[1], const branch_t (&b)[1])
11266             {
11267                v[0] = b[0].first->value();
11268             }
11269          };
11270
11271          template <typename T_, std::size_t ParamCount>
11272          struct invoke { static inline T execute(ifunction&, branch_t (&)[ParamCount]) { return std::numeric_limits<T_>::quiet_NaN(); } };
11273
11274          template <typename T_>
11275          struct invoke<T_,20>
11276          {
11277             static inline T_ execute(ifunction& f, T_ (&v)[20])
11278             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16],v[17],v[18],v[19]); }
11279          };
11280
11281          template <typename T_>
11282          struct invoke<T_,19>
11283          {
11284             static inline T_ execute(ifunction& f, T_ (&v)[19])
11285             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16],v[17],v[18]); }
11286          };
11287
11288          template <typename T_>
11289          struct invoke<T_,18>
11290          {
11291             static inline T_ execute(ifunction& f, T_ (&v)[18])
11292             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16],v[17]); }
11293          };
11294
11295          template <typename T_>
11296          struct invoke<T_,17>
11297          {
11298             static inline T_ execute(ifunction& f, T_ (&v)[17])
11299             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16]); }
11300          };
11301
11302          template <typename T_>
11303          struct invoke<T_,16>
11304          {
11305             static inline T_ execute(ifunction& f, T_ (&v)[16])
11306             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15]); }
11307          };
11308
11309          template <typename T_>
11310          struct invoke<T_,15>
11311          {
11312             static inline T_ execute(ifunction& f, T_ (&v)[15])
11313             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14]); }
11314          };
11315
11316          template <typename T_>
11317          struct invoke<T_,14>
11318          {
11319             static inline T_ execute(ifunction& f, T_ (&v)[14])
11320             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13]); }
11321          };
11322
11323          template <typename T_>
11324          struct invoke<T_,13>
11325          {
11326             static inline T_ execute(ifunction& f, T_ (&v)[13])
11327             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12]); }
11328          };
11329
11330          template <typename T_>
11331          struct invoke<T_,12>
11332          {
11333             static inline T_ execute(ifunction& f, T_ (&v)[12])
11334             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11]); }
11335          };
11336
11337          template <typename T_>
11338          struct invoke<T_,11>
11339          {
11340             static inline T_ execute(ifunction& f, T_ (&v)[11])
11341             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10]); }
11342          };
11343
11344          template <typename T_>
11345          struct invoke<T_,10>
11346          {
11347             static inline T_ execute(ifunction& f, T_ (&v)[10])
11348             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9]); }
11349          };
11350
11351          template <typename T_>
11352          struct invoke<T_,9>
11353          {
11354             static inline T_ execute(ifunction& f, T_ (&v)[9])
11355             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8]); }
11356          };
11357
11358          template <typename T_>
11359          struct invoke<T_,8>
11360          {
11361             static inline T_ execute(ifunction& f, T_ (&v)[8])
11362             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]); }
11363          };
11364
11365          template <typename T_>
11366          struct invoke<T_,7>
11367          {
11368             static inline T_ execute(ifunction& f, T_ (&v)[7])
11369             { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6]); }
11370          };
11371
11372          template <typename T_>
11373          struct invoke<T_,6>
11374          {
11375             static inline T_ execute(ifunction& f, T_ (&v)[6])
11376             { return f(v[0],v[1],v[2],v[3],v[4],v[5]); }
11377          };
11378
11379          template <typename T_>
11380          struct invoke<T_,5>
11381          {
11382             static inline T_ execute(ifunction& f, T_ (&v)[5])
11383             { return f(v[0],v[1],v[2],v[3],v[4]); }
11384          };
11385
11386          template <typename T_>
11387          struct invoke<T_,4>
11388          {
11389             static inline T_ execute(ifunction& f, T_ (&v)[4])
11390             { return f(v[0],v[1],v[2],v[3]); }
11391          };
11392
11393          template <typename T_>
11394          struct invoke<T_,3>
11395          {
11396             static inline T_ execute(ifunction& f, T_ (&v)[3])
11397             { return f(v[0],v[1],v[2]); }
11398          };
11399
11400          template <typename T_>
11401          struct invoke<T_,2>
11402          {
11403             static inline T_ execute(ifunction& f, T_ (&v)[2])
11404             { return f(v[0],v[1]); }
11405          };
11406
11407          template <typename T_>
11408          struct invoke<T_,1>
11409          {
11410             static inline T_ execute(ifunction& f, T_ (&v)[1])
11411             { return f(v[0]); }
11412          };
11413
11414          inline typename expression_node<T>::node_type type() const
11415          {
11416             return expression_node<T>::e_function;
11417          }
11418
11419       private:
11420
11421          ifunction*  function_;
11422          std::size_t parameter_count_;
11423          branch_t    branch_[N];
11424       };
11425
11426       template <typename T, typename IFunction>
11427       class function_N_node<T,IFunction,0> : public expression_node<T>
11428       {
11429       public:
11430
11431          typedef expression_node<T>* expression_ptr;
11432          typedef IFunction ifunction;
11433
11434          explicit function_N_node(ifunction* func)
11435          : function_((0 == func->param_count) ? func : reinterpret_cast<ifunction*>(0))
11436          {}
11437
11438          inline bool operator <(const function_N_node<T,IFunction,0>& fn) const
11439          {
11440             return this < (&fn);
11441          }
11442
11443          inline T value() const
11444          {
11445             if (function_)
11446                return (*function_)();
11447             else
11448                return std::numeric_limits<T>::quiet_NaN();
11449          }
11450
11451          inline typename expression_node<T>::node_type type() const
11452          {
11453             return expression_node<T>::e_function;
11454          }
11455
11456       private:
11457
11458          ifunction* function_;
11459       };
11460
11461       template <typename T, typename VarArgFunction>
11462       class vararg_function_node : public expression_node<T>
11463       {
11464       public:
11465
11466          typedef expression_node<T>* expression_ptr;
11467
11468          vararg_function_node(VarArgFunction*  func,
11469                               const std::vector<expression_ptr>& arg_list)
11470          : function_(func),
11471            arg_list_(arg_list)
11472          {
11473             value_list_.resize(arg_list.size(),std::numeric_limits<T>::quiet_NaN());
11474          }
11475
11476         ~vararg_function_node()
11477          {
11478             for (std::size_t i = 0; i < arg_list_.size(); ++i)
11479             {
11480                if (arg_list_[i] && !details::is_variable_node(arg_list_[i]))
11481                {
11482                   destroy_node(arg_list_[i]);
11483                }
11484             }
11485          }
11486
11487          inline bool operator <(const vararg_function_node<T,VarArgFunction>& fn) const
11488          {
11489             return this < (&fn);
11490          }
11491
11492          inline T value() const
11493          {
11494             if (function_)
11495             {
11496                populate_value_list();
11497                return (*function_)(value_list_);
11498             }
11499             else
11500                return std::numeric_limits<T>::quiet_NaN();
11501          }
11502
11503          inline typename expression_node<T>::node_type type() const
11504          {
11505             return expression_node<T>::e_vafunction;
11506          }
11507
11508       private:
11509
11510          inline void populate_value_list() const
11511          {
11512             for (std::size_t i = 0; i < arg_list_.size(); ++i)
11513             {
11514                value_list_[i] = arg_list_[i]->value();
11515             }
11516          }
11517
11518          VarArgFunction* function_;
11519          std::vector<expression_ptr> arg_list_;
11520          mutable std::vector<T> value_list_;
11521       };
11522
11523       template <typename T, typename GenericFunction>
11524       class generic_function_node : public expression_node<T>
11525       {
11526       public:
11527
11528          typedef type_store<T>                         type_store_t;
11529          typedef expression_node<T>*                 expression_ptr;
11530          typedef variable_node<T>                   variable_node_t;
11531          typedef vector_node<T>                       vector_node_t;
11532          typedef variable_node_t*               variable_node_ptr_t;
11533          typedef vector_node_t*                   vector_node_ptr_t;
11534          typedef range_interface<T>               range_interface_t;
11535          typedef range_data_type<T>               range_data_type_t;
11536          typedef range_pack<T>                              range_t;
11537          typedef std::pair<expression_ptr,bool>            branch_t;
11538          typedef std::pair<void*,std::size_t>                void_t;
11539          typedef std::vector<T>                            tmp_vs_t;
11540          typedef std::vector<type_store_t>         typestore_list_t;
11541          typedef std::vector<range_data_type_t>        range_list_t;
11542
11543          generic_function_node(const std::vector<expression_ptr>& arg_list,
11544                                GenericFunction* func = (GenericFunction*)(0))
11545          : function_(func),
11546            arg_list_(arg_list)
11547          {}
11548
11549          virtual ~generic_function_node()
11550          {
11551             cleanup_branches::execute(branch_);
11552          }
11553
11554          virtual bool init_branches()
11555          {
11556             expr_as_vec1_store_.resize(arg_list_.size(),T(0)               );
11557             typestore_list_    .resize(arg_list_.size(),type_store_t()     );
11558             range_list_        .resize(arg_list_.size(),range_data_type_t());
11559             branch_            .resize(arg_list_.size(),branch_t((expression_ptr)0,false));
11560
11561             for (std::size_t i = 0; i < arg_list_.size(); ++i)
11562             {
11563                type_store_t& ts = typestore_list_[i];
11564
11565                if (0 == arg_list_[i])
11566                   return false;
11567                else if (is_ivector_node(arg_list_[i]))
11568                {
11569                   vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
11570
11571                   if (0 == (vi = dynamic_cast<vector_interface<T>*>(arg_list_[i])))
11572                      return false;
11573
11574                   ts.size = vi->size();
11575                   ts.data = vi->vds().data();
11576                   ts.type = type_store_t::e_vector;
11577                   vi->vec()->vec_holder().set_ref(&ts.vec_data);
11578                }
11579                #ifndef exprtk_disable_string_capabilities
11580                else if (is_generally_string_node(arg_list_[i]))
11581                {
11582                   string_base_node<T>* sbn = reinterpret_cast<string_base_node<T>*>(0);
11583
11584                   if (0 == (sbn = dynamic_cast<string_base_node<T>*>(arg_list_[i])))
11585                      return false;
11586
11587                   ts.size = sbn->size();
11588                   ts.data = reinterpret_cast<void*>(const_cast<char_ptr>(sbn->base()));
11589                   ts.type = type_store_t::e_string;
11590
11591                   range_list_[i].data      = ts.data;
11592                   range_list_[i].size      = ts.size;
11593                   range_list_[i].type_size = sizeof(char);
11594                   range_list_[i].str_node  = sbn;
11595
11596                   range_interface_t* ri = reinterpret_cast<range_interface_t*>(0);
11597
11598                   if (0 == (ri = dynamic_cast<range_interface_t*>(arg_list_[i])))
11599                      return false;
11600
11601                   range_t& rp = ri->range_ref();
11602
11603                   if (
11604                        rp.const_range() &&
11605                        is_const_string_range_node(arg_list_[i])
11606                      )
11607                   {
11608                      ts.size = rp.const_size();
11609                      ts.data = static_cast<char_ptr>(ts.data) + rp.n0_c.second;
11610                      range_list_[i].range = reinterpret_cast<range_t*>(0);
11611                   }
11612                   else
11613                      range_list_[i].range = &(ri->range_ref());
11614                }
11615                #endif
11616                else if (is_variable_node(arg_list_[i]))
11617                {
11618                   variable_node_ptr_t var = variable_node_ptr_t(0);
11619
11620                   if (0 == (var = dynamic_cast<variable_node_ptr_t>(arg_list_[i])))
11621                      return false;
11622
11623                   ts.size = 1;
11624                   ts.data = &var->ref();
11625                   ts.type = type_store_t::e_scalar;
11626                }
11627                else
11628                {
11629                   ts.size = 1;
11630                   ts.data = reinterpret_cast<void*>(&expr_as_vec1_store_[i]);
11631                   ts.type = type_store_t::e_scalar;
11632                }
11633
11634                branch_[i] = std::make_pair(arg_list_[i],branch_deletable(arg_list_[i]));
11635             }
11636
11637             return true;
11638          }
11639
11640          inline bool operator <(const generic_function_node<T,GenericFunction>& fn) const
11641          {
11642             return this < (&fn);
11643          }
11644
11645          inline T value() const
11646          {
11647             if (function_)
11648             {
11649                if (populate_value_list())
11650                {
11651                   typedef typename GenericFunction::parameter_list_t parameter_list_t;
11652
11653                   return (*function_)(parameter_list_t(typestore_list_));
11654                }
11655             }
11656
11657             return std::numeric_limits<T>::quiet_NaN();
11658          }
11659
11660          inline typename expression_node<T>::node_type type() const
11661          {
11662             return expression_node<T>::e_genfunction;
11663          }
11664
11665       protected:
11666
11667          inline virtual bool populate_value_list() const
11668          {
11669             for (std::size_t i = 0; i < branch_.size(); ++i)
11670             {
11671                expr_as_vec1_store_[i] = branch_[i].first->value();
11672             }
11673
11674             for (std::size_t i = 0; i < branch_.size(); ++i)
11675             {
11676                range_data_type_t& rdt = range_list_[i];
11677
11678                if (rdt.range)
11679                {
11680                   range_t&    rp = (*rdt.range);
11681                   std::size_t r0 = 0;
11682                   std::size_t r1 = 0;
11683
11684                   if (rp(r0,r1,rdt.size))
11685                   {
11686                      type_store_t& ts = typestore_list_[i];
11687
11688                      ts.size = rp.cache_size();
11689                      #ifndef exprtk_disable_string_capabilities
11690                      if (ts.type == type_store_t::e_string)
11691                         ts.data = const_cast<char_ptr>(rdt.str_node->base()) + rp.cache.first;
11692                      else
11693                      #endif
11694                         ts.data = static_cast<char_ptr>(rdt.data) + (rp.cache.first * rdt.type_size);
11695                   }
11696                   else
11697                      return false;
11698                }
11699             }
11700
11701             return true;
11702          }
11703
11704          GenericFunction* function_;
11705          mutable typestore_list_t typestore_list_;
11706
11707       private:
11708
11709          std::vector<expression_ptr> arg_list_;
11710          std::vector<branch_t>         branch_;
11711          mutable tmp_vs_t  expr_as_vec1_store_;
11712          mutable range_list_t      range_list_;
11713       };
11714
11715       #ifndef exprtk_disable_string_capabilities
11716       template <typename T, typename StringFunction>
11717       class string_function_node : public generic_function_node<T,StringFunction>,
11718                                    public string_base_node<T>,
11719                                    public range_interface <T>
11720       {
11721       public:
11722
11723          typedef generic_function_node<T,StringFunction> gen_function_t;
11724          typedef range_pack<T> range_t;
11725
11726          string_function_node(StringFunction* func,
11727                               const std::vector<typename gen_function_t::expression_ptr>& arg_list)
11728          : gen_function_t(arg_list,func)
11729          {
11730             range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
11731             range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
11732             range_.cache.first  = range_.n0_c.second;
11733             range_.cache.second = range_.n1_c.second;
11734          }
11735
11736          inline bool operator <(const string_function_node<T,StringFunction>& fn) const
11737          {
11738             return this < (&fn);
11739          }
11740
11741          inline T value() const
11742          {
11743             if (gen_function_t::function_)
11744             {
11745                if (gen_function_t::populate_value_list())
11746                {
11747                   typedef typename StringFunction::parameter_list_t parameter_list_t;
11748
11749                   const T result = (*gen_function_t::function_)
11750                                       (
11751                                         ret_string_,
11752                                         parameter_list_t(gen_function_t::typestore_list_)
11753                                       );
11754
11755                   range_.n1_c.second  = ret_string_.size() - 1;
11756                   range_.cache.second = range_.n1_c.second;
11757
11758                   return result;
11759                }
11760             }
11761
11762             return std::numeric_limits<T>::quiet_NaN();
11763          }
11764
11765          inline typename expression_node<T>::node_type type() const
11766          {
11767             return expression_node<T>::e_strfunction;
11768          }
11769
11770          std::string str() const
11771          {
11772             return ret_string_;
11773          }
11774
11775          char_cptr base() const
11776          {
11777            return &ret_string_[0];
11778          }
11779
11780          std::size_t size() const
11781          {
11782             return ret_string_.size();
11783          }
11784
11785          range_t& range_ref()
11786          {
11787             return range_;
11788          }
11789
11790          const range_t& range_ref() const
11791          {
11792             return range_;
11793          }
11794
11795       protected:
11796
11797          mutable range_t     range_;
11798          mutable std::string ret_string_;
11799       };
11800       #endif
11801
11802       template <typename T, typename GenericFunction>
11803       class multimode_genfunction_node : public generic_function_node<T,GenericFunction>
11804       {
11805       public:
11806
11807          typedef generic_function_node<T,GenericFunction> gen_function_t;
11808          typedef range_pack<T> range_t;
11809
11810          multimode_genfunction_node(GenericFunction* func,
11811                                     const std::size_t& param_seq_index,
11812                                     const std::vector<typename gen_function_t::expression_ptr>& arg_list)
11813          : gen_function_t(arg_list,func),
11814            param_seq_index_(param_seq_index)
11815          {}
11816
11817          inline T value() const
11818          {
11819             if (gen_function_t::function_)
11820             {
11821                if (gen_function_t::populate_value_list())
11822                {
11823                   typedef typename GenericFunction::parameter_list_t parameter_list_t;
11824
11825                   return (*gen_function_t::function_)
11826                             (
11827                               param_seq_index_,
11828                               parameter_list_t(gen_function_t::typestore_list_)
11829                             );
11830                }
11831             }
11832
11833             return std::numeric_limits<T>::quiet_NaN();
11834          }
11835
11836          inline typename expression_node<T>::node_type type() const
11837          {
11838             return expression_node<T>::e_genfunction;
11839          }
11840
11841       private:
11842
11843          std::size_t param_seq_index_;
11844       };
11845
11846       #ifndef exprtk_disable_string_capabilities
11847       template <typename T, typename StringFunction>
11848       class multimode_strfunction_node : public string_function_node<T,StringFunction>
11849       {
11850       public:
11851
11852          typedef string_function_node<T,StringFunction> str_function_t;
11853          typedef range_pack<T> range_t;
11854
11855          multimode_strfunction_node(StringFunction* func,
11856                                     const std::size_t& param_seq_index,
11857                                     const std::vector<typename str_function_t::expression_ptr>& arg_list)
11858          : str_function_t(func,arg_list),
11859            param_seq_index_(param_seq_index)
11860          {}
11861
11862          inline T value() const
11863          {
11864             if (str_function_t::function_)
11865             {
11866                if (str_function_t::populate_value_list())
11867                {
11868                   typedef typename StringFunction::parameter_list_t parameter_list_t;
11869
11870                   const T result = (*str_function_t::function_)
11871                                       (
11872                                         param_seq_index_,
11873                                         str_function_t::ret_string_,
11874                                         parameter_list_t(str_function_t::typestore_list_)
11875                                       );
11876
11877                   str_function_t::range_.n1_c.second  = str_function_t::ret_string_.size() - 1;
11878                   str_function_t::range_.cache.second = str_function_t::range_.n1_c.second;
11879
11880                   return result;
11881                }
11882             }
11883
11884             return std::numeric_limits<T>::quiet_NaN();
11885          }
11886
11887          inline typename expression_node<T>::node_type type() const
11888          {
11889             return expression_node<T>::e_strfunction;
11890          }
11891
11892       private:
11893
11894          const std::size_t param_seq_index_;
11895       };
11896       #endif
11897
11898       class return_exception
11899       {};
11900
11901       template <typename T>
11902       class null_igenfunc
11903       {
11904       public:
11905
11906          virtual ~null_igenfunc()
11907          {}
11908
11909          typedef type_store<T> generic_type;
11910          typedef typename generic_type::parameter_list parameter_list_t;
11911
11912          inline virtual T operator() (parameter_list_t)
11913          {
11914             return std::numeric_limits<T>::quiet_NaN();
11915          }
11916       };
11917
11918       #ifndef exprtk_disable_return_statement
11919       template <typename T>
11920       class return_node : public generic_function_node<T,null_igenfunc<T> >
11921       {
11922       public:
11923
11924          typedef null_igenfunc<T> igeneric_function_t;
11925          typedef igeneric_function_t* igeneric_function_ptr;
11926          typedef generic_function_node<T,igeneric_function_t> gen_function_t;
11927          typedef results_context<T> results_context_t;
11928
11929          return_node(const std::vector<typename gen_function_t::expression_ptr>& arg_list,
11930                      results_context_t& rc)
11931          : gen_function_t  (arg_list),
11932            results_context_(&rc)
11933          {}
11934
11935          inline T value() const
11936          {
11937             if (
11938                  (0 != results_context_) &&
11939                  gen_function_t::populate_value_list()
11940                )
11941             {
11942                typedef typename type_store<T>::parameter_list parameter_list_t;
11943
11944                results_context_->
11945                   assign(parameter_list_t(gen_function_t::typestore_list_));
11946
11947                throw return_exception();
11948             }
11949
11950             return std::numeric_limits<T>::quiet_NaN();
11951          }
11952
11953          inline typename expression_node<T>::node_type type() const
11954          {
11955             return expression_node<T>::e_return;
11956          }
11957
11958       private:
11959
11960          results_context_t* results_context_;
11961       };
11962
11963       template <typename T>
11964       class return_envelope_node : public expression_node<T>
11965       {
11966       public:
11967
11968          typedef expression_node<T>* expression_ptr;
11969          typedef results_context<T>  results_context_t;
11970
11971          return_envelope_node(expression_ptr body, results_context_t& rc)
11972          : results_context_(&rc  ),
11973            return_invoked_ (false),
11974            body_           (body ),
11975            body_deletable_ (branch_deletable(body_))
11976          {}
11977
11978         ~return_envelope_node()
11979          {
11980             if (body_ && body_deletable_)
11981             {
11982                destroy_node(body_);
11983             }
11984          }
11985
11986          inline T value() const
11987          {
11988             try
11989             {
11990                return_invoked_ = false;
11991                results_context_->clear();
11992
11993                return body_->value();
11994             }
11995             catch(const return_exception&)
11996             {
11997                return_invoked_ = true;
11998                return std::numeric_limits<T>::quiet_NaN();
11999             }
12000          }
12001
12002          inline typename expression_node<T>::node_type type() const
12003          {
12004             return expression_node<T>::e_retenv;
12005          }
12006
12007          inline bool* retinvk_ptr()
12008          {
12009             return &return_invoked_;
12010          }
12011
12012       private:
12013
12014          results_context_t* results_context_;
12015          mutable bool       return_invoked_;
12016          expression_ptr     body_;
12017          const bool         body_deletable_;
12018       };
12019       #endif
12020
12021       #define exprtk_define_unary_op(OpName)                    \
12022       template <typename T>                                     \
12023       struct OpName##_op                                        \
12024       {                                                         \
12025          typedef typename functor_t<T>::Type Type;              \
12026          typedef typename expression_node<T>::node_type node_t; \
12027                                                                 \
12028          static inline T process(Type v)                        \
12029          {                                                      \
12030             return numeric:: OpName (v);                        \
12031          }                                                      \
12032                                                                 \
12033          static inline node_t type()                            \
12034          {                                                      \
12035             return expression_node<T>::e_##OpName;              \
12036          }                                                      \
12037                                                                 \
12038          static inline details::operator_type operation()       \
12039          {                                                      \
12040             return details::e_##OpName;                         \
12041          }                                                      \
12042       };                                                        \
12043
12044       exprtk_define_unary_op(abs  )
12045       exprtk_define_unary_op(acos )
12046       exprtk_define_unary_op(acosh)
12047       exprtk_define_unary_op(asin )
12048       exprtk_define_unary_op(asinh)
12049       exprtk_define_unary_op(atan )
12050       exprtk_define_unary_op(atanh)
12051       exprtk_define_unary_op(ceil )
12052       exprtk_define_unary_op(cos  )
12053       exprtk_define_unary_op(cosh )
12054       exprtk_define_unary_op(cot  )
12055       exprtk_define_unary_op(csc  )
12056       exprtk_define_unary_op(d2g  )
12057       exprtk_define_unary_op(d2r  )
12058       exprtk_define_unary_op(erf  )
12059       exprtk_define_unary_op(erfc )
12060       exprtk_define_unary_op(exp  )
12061       exprtk_define_unary_op(expm1)
12062       exprtk_define_unary_op(floor)
12063       exprtk_define_unary_op(frac )
12064       exprtk_define_unary_op(g2d  )
12065       exprtk_define_unary_op(log  )
12066       exprtk_define_unary_op(log10)
12067       exprtk_define_unary_op(log2 )
12068       exprtk_define_unary_op(log1p)
12069       exprtk_define_unary_op(ncdf )
12070       exprtk_define_unary_op(neg  )
12071       exprtk_define_unary_op(notl )
12072       exprtk_define_unary_op(pos  )
12073       exprtk_define_unary_op(r2d  )
12074       exprtk_define_unary_op(round)
12075       exprtk_define_unary_op(sec  )
12076       exprtk_define_unary_op(sgn  )
12077       exprtk_define_unary_op(sin  )
12078       exprtk_define_unary_op(sinc )
12079       exprtk_define_unary_op(sinh )
12080       exprtk_define_unary_op(sqrt )
12081       exprtk_define_unary_op(tan  )
12082       exprtk_define_unary_op(tanh )
12083       exprtk_define_unary_op(trunc)
12084       #undef exprtk_define_unary_op
12085
12086       template <typename T>
12087       struct opr_base
12088       {
12089          typedef typename details::functor_t<T>::Type    Type;
12090          typedef typename details::functor_t<T>::RefType RefType;
12091          typedef typename details::functor_t<T>          functor_t;
12092          typedef typename functor_t::qfunc_t  quaternary_functor_t;
12093          typedef typename functor_t::tfunc_t     trinary_functor_t;
12094          typedef typename functor_t::bfunc_t      binary_functor_t;
12095          typedef typename functor_t::ufunc_t       unary_functor_t;
12096       };
12097
12098       template <typename T>
12099       struct add_op : public opr_base<T>
12100       {
12101          typedef typename opr_base<T>::Type    Type;
12102          typedef typename opr_base<T>::RefType RefType;
12103
12104          static inline T process(Type t1, Type t2) { return t1 + t2; }
12105          static inline T process(Type t1, Type t2, Type t3) { return t1 + t2 + t3; }
12106          static inline void assign(RefType t1, Type t2) { t1 += t2; }
12107          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_add; }
12108          static inline details::operator_type operation() { return details::e_add; }
12109       };
12110
12111       template <typename T>
12112       struct mul_op : public opr_base<T>
12113       {
12114          typedef typename opr_base<T>::Type    Type;
12115          typedef typename opr_base<T>::RefType RefType;
12116
12117          static inline T process(Type t1, Type t2) { return t1 * t2; }
12118          static inline T process(Type t1, Type t2, Type t3) { return t1 * t2 * t3; }
12119          static inline void assign(RefType t1, Type t2) { t1 *= t2; }
12120          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mul; }
12121          static inline details::operator_type operation() { return details::e_mul; }
12122       };
12123
12124       template <typename T>
12125       struct sub_op : public opr_base<T>
12126       {
12127          typedef typename opr_base<T>::Type    Type;
12128          typedef typename opr_base<T>::RefType RefType;
12129
12130          static inline T process(Type t1, Type t2) { return t1 - t2; }
12131          static inline T process(Type t1, Type t2, Type t3) { return t1 - t2 - t3; }
12132          static inline void assign(RefType t1, Type t2) { t1 -= t2; }
12133          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_sub; }
12134          static inline details::operator_type operation() { return details::e_sub; }
12135       };
12136
12137       template <typename T>
12138       struct div_op : public opr_base<T>
12139       {
12140          typedef typename opr_base<T>::Type    Type;
12141          typedef typename opr_base<T>::RefType RefType;
12142
12143          static inline T process(Type t1, Type t2) { return t1 / t2; }
12144          static inline T process(Type t1, Type t2, Type t3) { return t1 / t2 / t3; }
12145          static inline void assign(RefType t1, Type t2) { t1 /= t2; }
12146          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_div; }
12147          static inline details::operator_type operation() { return details::e_div; }
12148       };
12149
12150       template <typename T>
12151       struct mod_op : public opr_base<T>
12152       {
12153          typedef typename opr_base<T>::Type    Type;
12154          typedef typename opr_base<T>::RefType RefType;
12155
12156          static inline T process(Type t1, Type t2) { return numeric::modulus<T>(t1,t2); }
12157          static inline void assign(RefType t1, Type t2) { t1 = numeric::modulus<T>(t1,t2); }
12158          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mod; }
12159          static inline details::operator_type operation() { return details::e_mod; }
12160       };
12161
12162       template <typename T>
12163       struct pow_op : public opr_base<T>
12164       {
12165          typedef typename opr_base<T>::Type    Type;
12166          typedef typename opr_base<T>::RefType RefType;
12167
12168          static inline T process(Type t1, Type t2) { return numeric::pow<T>(t1,t2); }
12169          static inline void assign(RefType t1, Type t2) { t1 = numeric::pow<T>(t1,t2); }
12170          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_pow; }
12171          static inline details::operator_type operation() { return details::e_pow; }
12172       };
12173
12174       template <typename T>
12175       struct lt_op : public opr_base<T>
12176       {
12177          typedef typename opr_base<T>::Type Type;
12178
12179          static inline T process(Type t1, Type t2) { return ((t1 < t2) ? T(1) : T(0)); }
12180          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 < t2) ? T(1) : T(0)); }
12181          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lt; }
12182          static inline details::operator_type operation() { return details::e_lt; }
12183       };
12184
12185       template <typename T>
12186       struct lte_op : public opr_base<T>
12187       {
12188          typedef typename opr_base<T>::Type Type;
12189
12190          static inline T process(Type t1, Type t2) { return ((t1 <= t2) ? T(1) : T(0)); }
12191          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 <= t2) ? T(1) : T(0)); }
12192          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lte; }
12193          static inline details::operator_type operation() { return details::e_lte; }
12194       };
12195
12196       template <typename T>
12197       struct gt_op : public opr_base<T>
12198       {
12199          typedef typename opr_base<T>::Type Type;
12200
12201          static inline T process(Type t1, Type t2) { return ((t1 > t2) ? T(1) : T(0)); }
12202          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 > t2) ? T(1) : T(0)); }
12203          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gt; }
12204          static inline details::operator_type operation() { return details::e_gt; }
12205       };
12206
12207       template <typename T>
12208       struct gte_op : public opr_base<T>
12209       {
12210          typedef typename opr_base<T>::Type Type;
12211
12212          static inline T process(Type t1, Type t2) { return ((t1 >= t2) ? T(1) : T(0)); }
12213          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 >= t2) ? T(1) : T(0)); }
12214          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gte; }
12215          static inline details::operator_type operation() { return details::e_gte; }
12216       };
12217
12218       template <typename T>
12219       struct eq_op : public opr_base<T>
12220       {
12221          typedef typename opr_base<T>::Type Type;
12222          static inline T process(Type t1, Type t2) { return (std::equal_to<T>()(t1,t2) ? T(1) : T(0)); }
12223          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); }
12224          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_eq; }
12225          static inline details::operator_type operation() { return details::e_eq; }
12226       };
12227
12228       template <typename T>
12229       struct equal_op : public opr_base<T>
12230       {
12231          typedef typename opr_base<T>::Type Type;
12232
12233          static inline T process(Type t1, Type t2) { return numeric::equal(t1,t2); }
12234          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); }
12235          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_eq; }
12236          static inline details::operator_type operation() { return details::e_equal; }
12237       };
12238
12239       template <typename T>
12240       struct ne_op : public opr_base<T>
12241       {
12242          typedef typename opr_base<T>::Type Type;
12243
12244          static inline T process(Type t1, Type t2) { return (std::not_equal_to<T>()(t1,t2) ? T(1) : T(0)); }
12245          static inline T process(const std::string& t1, const std::string& t2) { return ((t1 != t2) ? T(1) : T(0)); }
12246          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ne; }
12247          static inline details::operator_type operation() { return details::e_ne; }
12248       };
12249
12250       template <typename T>
12251       struct and_op : public opr_base<T>
12252       {
12253          typedef typename opr_base<T>::Type Type;
12254
12255          static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(1) : T(0); }
12256          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_and; }
12257          static inline details::operator_type operation() { return details::e_and; }
12258       };
12259
12260       template <typename T>
12261       struct nand_op : public opr_base<T>
12262       {
12263          typedef typename opr_base<T>::Type Type;
12264
12265          static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(0) : T(1); }
12266          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nand; }
12267          static inline details::operator_type operation() { return details::e_nand; }
12268       };
12269
12270       template <typename T>
12271       struct or_op : public opr_base<T>
12272       {
12273          typedef typename opr_base<T>::Type Type;
12274
12275          static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(1) : T(0); }
12276          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_or; }
12277          static inline details::operator_type operation() { return details::e_or; }
12278       };
12279
12280       template <typename T>
12281       struct nor_op : public opr_base<T>
12282       {
12283          typedef typename opr_base<T>::Type Type;
12284
12285          static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(0) : T(1); }
12286          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
12287          static inline details::operator_type operation() { return details::e_nor; }
12288       };
12289
12290       template <typename T>
12291       struct xor_op : public opr_base<T>
12292       {
12293          typedef typename opr_base<T>::Type Type;
12294
12295          static inline T process(Type t1, Type t2) { return numeric::xor_opr<T>(t1,t2); }
12296          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
12297          static inline details::operator_type operation() { return details::e_xor; }
12298       };
12299
12300       template <typename T>
12301       struct xnor_op : public opr_base<T>
12302       {
12303          typedef typename opr_base<T>::Type Type;
12304
12305          static inline T process(Type t1, Type t2) { return numeric::xnor_opr<T>(t1,t2); }
12306          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
12307          static inline details::operator_type operation() { return details::e_xnor; }
12308       };
12309
12310       template <typename T>
12311       struct in_op : public opr_base<T>
12312       {
12313          typedef typename opr_base<T>::Type Type;
12314
12315          static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
12316          static inline T process(const std::string& t1, const std::string& t2) { return ((std::string::npos != t2.find(t1)) ? T(1) : T(0)); }
12317          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_in; }
12318          static inline details::operator_type operation() { return details::e_in; }
12319       };
12320
12321       template <typename T>
12322       struct like_op : public opr_base<T>
12323       {
12324          typedef typename opr_base<T>::Type Type;
12325
12326          static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
12327          static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_match(t2,t1) ? T(1) : T(0)); }
12328          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_like; }
12329          static inline details::operator_type operation() { return details::e_like; }
12330       };
12331
12332       template <typename T>
12333       struct ilike_op : public opr_base<T>
12334       {
12335          typedef typename opr_base<T>::Type Type;
12336
12337          static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
12338          static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_imatch(t2,t1) ? T(1) : T(0)); }
12339          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ilike; }
12340          static inline details::operator_type operation() { return details::e_ilike; }
12341       };
12342
12343       template <typename T>
12344       struct inrange_op : public opr_base<T>
12345       {
12346          typedef typename opr_base<T>::Type Type;
12347
12348          static inline T process(const T& t0, const T& t1, const T& t2) { return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); }
12349          static inline T process(const std::string& t0, const std::string& t1, const std::string& t2)
12350          {
12351             return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0);
12352          }
12353          static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_inranges; }
12354          static inline details::operator_type operation() { return details::e_inrange; }
12355       };
12356
12357       template <typename T>
12358       inline T value(details::expression_node<T>* n)
12359       {
12360          return n->value();
12361       }
12362
12363       template <typename T>
12364       inline T value(T* t)
12365       {
12366          return (*t);
12367       }
12368
12369       template <typename T>
12370       struct vararg_add_op : public opr_base<T>
12371       {
12372          typedef typename opr_base<T>::Type Type;
12373
12374          template <typename Type,
12375                    typename Allocator,
12376                    template <typename, typename> class Sequence>
12377          static inline T process(const Sequence<Type,Allocator>& arg_list)
12378          {
12379             switch (arg_list.size())
12380             {
12381                case 0  : return T(0);
12382                case 1  : return process_1(arg_list);
12383                case 2  : return process_2(arg_list);
12384                case 3  : return process_3(arg_list);
12385                case 4  : return process_4(arg_list);
12386                case 5  : return process_5(arg_list);
12387                default :
12388                          {
12389                             T result = T(0);
12390
12391                             for (std::size_t i = 0; i < arg_list.size(); ++i)
12392                             {
12393                               result += value(arg_list[i]);
12394                             }
12395
12396                             return result;
12397                          }
12398             }
12399          }
12400
12401          template <typename Sequence>
12402          static inline T process_1(const Sequence& arg_list)
12403          {
12404             return value(arg_list[0]);
12405          }
12406
12407          template <typename Sequence>
12408          static inline T process_2(const Sequence& arg_list)
12409          {
12410             return value(arg_list[0]) + value(arg_list[1]);
12411          }
12412
12413          template <typename Sequence>
12414          static inline T process_3(const Sequence& arg_list)
12415          {
12416             return value(arg_list[0]) + value(arg_list[1]) +
12417                    value(arg_list[2]) ;
12418          }
12419
12420          template <typename Sequence>
12421          static inline T process_4(const Sequence& arg_list)
12422          {
12423             return value(arg_list[0]) + value(arg_list[1]) +
12424                    value(arg_list[2]) + value(arg_list[3]) ;
12425          }
12426
12427          template <typename Sequence>
12428          static inline T process_5(const Sequence& arg_list)
12429          {
12430             return value(arg_list[0]) + value(arg_list[1]) +
12431                    value(arg_list[2]) + value(arg_list[3]) +
12432                    value(arg_list[4]) ;
12433          }
12434       };
12435
12436       template <typename T>
12437       struct vararg_mul_op : public opr_base<T>
12438       {
12439          typedef typename opr_base<T>::Type Type;
12440
12441          template <typename Type,
12442                    typename Allocator,
12443                    template <typename, typename> class Sequence>
12444          static inline T process(const Sequence<Type,Allocator>& arg_list)
12445          {
12446             switch (arg_list.size())
12447             {
12448                case 0  : return T(0);
12449                case 1  : return process_1(arg_list);
12450                case 2  : return process_2(arg_list);
12451                case 3  : return process_3(arg_list);
12452                case 4  : return process_4(arg_list);
12453                case 5  : return process_5(arg_list);
12454                default :
12455                          {
12456                             T result = T(value(arg_list[0]));
12457
12458                             for (std::size_t i = 1; i < arg_list.size(); ++i)
12459                             {
12460                                result *= value(arg_list[i]);
12461                             }
12462
12463                             return result;
12464                          }
12465             }
12466          }
12467
12468          template <typename Sequence>
12469          static inline T process_1(const Sequence& arg_list)
12470          {
12471             return value(arg_list[0]);
12472          }
12473
12474          template <typename Sequence>
12475          static inline T process_2(const Sequence& arg_list)
12476          {
12477             return value(arg_list[0]) * value(arg_list[1]);
12478          }
12479
12480          template <typename Sequence>
12481          static inline T process_3(const Sequence& arg_list)
12482          {
12483             return value(arg_list[0]) * value(arg_list[1]) *
12484                    value(arg_list[2]) ;
12485          }
12486
12487          template <typename Sequence>
12488          static inline T process_4(const Sequence& arg_list)
12489          {
12490             return value(arg_list[0]) * value(arg_list[1]) *
12491                    value(arg_list[2]) * value(arg_list[3]) ;
12492          }
12493
12494          template <typename Sequence>
12495          static inline T process_5(const Sequence& arg_list)
12496          {
12497             return value(arg_list[0]) * value(arg_list[1]) *
12498                    value(arg_list[2]) * value(arg_list[3]) *
12499                    value(arg_list[4]) ;
12500          }
12501       };
12502
12503       template <typename T>
12504       struct vararg_avg_op : public opr_base<T>
12505       {
12506          typedef typename opr_base<T>::Type Type;
12507
12508          template <typename Type,
12509                    typename Allocator,
12510                    template <typename, typename> class Sequence>
12511          static inline T process(const Sequence<Type,Allocator>& arg_list)
12512          {
12513             switch (arg_list.size())
12514             {
12515                case 0  : return T(0);
12516                case 1  : return process_1(arg_list);
12517                case 2  : return process_2(arg_list);
12518                case 3  : return process_3(arg_list);
12519                case 4  : return process_4(arg_list);
12520                case 5  : return process_5(arg_list);
12521                default : return vararg_add_op<T>::process(arg_list) / arg_list.size();
12522             }
12523          }
12524
12525          template <typename Sequence>
12526          static inline T process_1(const Sequence& arg_list)
12527          {
12528             return value(arg_list[0]);
12529          }
12530
12531          template <typename Sequence>
12532          static inline T process_2(const Sequence& arg_list)
12533          {
12534             return (value(arg_list[0]) + value(arg_list[1])) / T(2);
12535          }
12536
12537          template <typename Sequence>
12538          static inline T process_3(const Sequence& arg_list)
12539          {
12540             return (value(arg_list[0]) + value(arg_list[1]) + value(arg_list[2])) / T(3);
12541          }
12542
12543          template <typename Sequence>
12544          static inline T process_4(const Sequence& arg_list)
12545          {
12546             return (value(arg_list[0]) + value(arg_list[1]) +
12547                     value(arg_list[2]) + value(arg_list[3])) / T(4);
12548          }
12549
12550          template <typename Sequence>
12551          static inline T process_5(const Sequence& arg_list)
12552          {
12553             return (value(arg_list[0]) + value(arg_list[1]) +
12554                     value(arg_list[2]) + value(arg_list[3]) +
12555                     value(arg_list[4])) / T(5);
12556          }
12557       };
12558
12559       template <typename T>
12560       struct vararg_min_op : public opr_base<T>
12561       {
12562          typedef typename opr_base<T>::Type Type;
12563
12564          template <typename Type,
12565                    typename Allocator,
12566                    template <typename, typename> class Sequence>
12567          static inline T process(const Sequence<Type,Allocator>& arg_list)
12568          {
12569             switch (arg_list.size())
12570             {
12571                case 0  : return T(0);
12572                case 1  : return process_1(arg_list);
12573                case 2  : return process_2(arg_list);
12574                case 3  : return process_3(arg_list);
12575                case 4  : return process_4(arg_list);
12576                case 5  : return process_5(arg_list);
12577                default :
12578                          {
12579                             T result = T(value(arg_list[0]));
12580
12581                             for (std::size_t i = 1; i < arg_list.size(); ++i)
12582                             {
12583                                const T v = value(arg_list[i]);
12584
12585                                if (v < result)
12586                                   result = v;
12587                             }
12588
12589                             return result;
12590                          }
12591             }
12592          }
12593
12594          template <typename Sequence>
12595          static inline T process_1(const Sequence& arg_list)
12596          {
12597             return value(arg_list[0]);
12598          }
12599
12600          template <typename Sequence>
12601          static inline T process_2(const Sequence& arg_list)
12602          {
12603             return std::min<T>(value(arg_list[0]),value(arg_list[1]));
12604          }
12605
12606          template <typename Sequence>
12607          static inline T process_3(const Sequence& arg_list)
12608          {
12609             return std::min<T>(std::min<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2]));
12610          }
12611
12612          template <typename Sequence>
12613          static inline T process_4(const Sequence& arg_list)
12614          {
12615             return std::min<T>(
12616                         std::min<T>(value(arg_list[0]), value(arg_list[1])),
12617                         std::min<T>(value(arg_list[2]), value(arg_list[3])));
12618          }
12619
12620          template <typename Sequence>
12621          static inline T process_5(const Sequence& arg_list)
12622          {
12623             return std::min<T>(
12624                    std::min<T>(std::min<T>(value(arg_list[0]), value(arg_list[1])),
12625                                std::min<T>(value(arg_list[2]), value(arg_list[3]))),
12626                                value(arg_list[4]));
12627          }
12628       };
12629
12630       template <typename T>
12631       struct vararg_max_op : public opr_base<T>
12632       {
12633          typedef typename opr_base<T>::Type Type;
12634
12635          template <typename Type,
12636                    typename Allocator,
12637                    template <typename, typename> class Sequence>
12638          static inline T process(const Sequence<Type,Allocator>& arg_list)
12639          {
12640             switch (arg_list.size())
12641             {
12642                case 0  : return T(0);
12643                case 1  : return process_1(arg_list);
12644                case 2  : return process_2(arg_list);
12645                case 3  : return process_3(arg_list);
12646                case 4  : return process_4(arg_list);
12647                case 5  : return process_5(arg_list);
12648                default :
12649                          {
12650                             T result = T(value(arg_list[0]));
12651
12652                             for (std::size_t i = 1; i < arg_list.size(); ++i)
12653                             {
12654                                const T v = value(arg_list[i]);
12655
12656                                if (v > result)
12657                                   result = v;
12658                             }
12659
12660                             return result;
12661                          }
12662             }
12663          }
12664
12665          template <typename Sequence>
12666          static inline T process_1(const Sequence& arg_list)
12667          {
12668             return value(arg_list[0]);
12669          }
12670
12671          template <typename Sequence>
12672          static inline T process_2(const Sequence& arg_list)
12673          {
12674             return std::max<T>(value(arg_list[0]),value(arg_list[1]));
12675          }
12676
12677          template <typename Sequence>
12678          static inline T process_3(const Sequence& arg_list)
12679          {
12680             return std::max<T>(std::max<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2]));
12681          }
12682
12683          template <typename Sequence>
12684          static inline T process_4(const Sequence& arg_list)
12685          {
12686             return std::max<T>(
12687                         std::max<T>(value(arg_list[0]), value(arg_list[1])),
12688                         std::max<T>(value(arg_list[2]), value(arg_list[3])));
12689          }
12690
12691          template <typename Sequence>
12692          static inline T process_5(const Sequence& arg_list)
12693          {
12694             return std::max<T>(
12695                    std::max<T>(std::max<T>(value(arg_list[0]), value(arg_list[1])),
12696                                std::max<T>(value(arg_list[2]), value(arg_list[3]))),
12697                                value(arg_list[4]));
12698          }
12699       };
12700
12701       template <typename T>
12702       struct vararg_mand_op : public opr_base<T>
12703       {
12704          typedef typename opr_base<T>::Type Type;
12705
12706          template <typename Type,
12707                    typename Allocator,
12708                    template <typename, typename> class Sequence>
12709          static inline T process(const Sequence<Type,Allocator>& arg_list)
12710          {
12711             switch (arg_list.size())
12712             {
12713                case 1  : return process_1(arg_list);
12714                case 2  : return process_2(arg_list);
12715                case 3  : return process_3(arg_list);
12716                case 4  : return process_4(arg_list);
12717                case 5  : return process_5(arg_list);
12718                default :
12719                          {
12720                             for (std::size_t i = 0; i < arg_list.size(); ++i)
12721                             {
12722                                if (std::equal_to<T>()(T(0), value(arg_list[i])))
12723                                   return T(0);
12724                             }
12725
12726                             return T(1);
12727                          }
12728             }
12729          }
12730
12731          template <typename Sequence>
12732          static inline T process_1(const Sequence& arg_list)
12733          {
12734             return std::not_equal_to<T>()
12735                       (T(0), value(arg_list[0])) ? T(1) : T(0);
12736          }
12737
12738          template <typename Sequence>
12739          static inline T process_2(const Sequence& arg_list)
12740          {
12741             return (
12742                      std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
12743                      std::not_equal_to<T>()(T(0), value(arg_list[1]))
12744                    ) ? T(1) : T(0);
12745          }
12746
12747          template <typename Sequence>
12748          static inline T process_3(const Sequence& arg_list)
12749          {
12750             return (
12751                      std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
12752                      std::not_equal_to<T>()(T(0), value(arg_list[1])) &&
12753                      std::not_equal_to<T>()(T(0), value(arg_list[2]))
12754                    ) ? T(1) : T(0);
12755          }
12756
12757          template <typename Sequence>
12758          static inline T process_4(const Sequence& arg_list)
12759          {
12760             return (
12761                      std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
12762                      std::not_equal_to<T>()(T(0), value(arg_list[1])) &&
12763                      std::not_equal_to<T>()(T(0), value(arg_list[2])) &&
12764                      std::not_equal_to<T>()(T(0), value(arg_list[3]))
12765                    ) ? T(1) : T(0);
12766          }
12767
12768          template <typename Sequence>
12769          static inline T process_5(const Sequence& arg_list)
12770          {
12771             return (
12772                      std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
12773                      std::not_equal_to<T>()(T(0), value(arg_list[1])) &&
12774                      std::not_equal_to<T>()(T(0), value(arg_list[2])) &&
12775                      std::not_equal_to<T>()(T(0), value(arg_list[3])) &&
12776                      std::not_equal_to<T>()(T(0), value(arg_list[4]))
12777                    ) ? T(1) : T(0);
12778          }
12779       };
12780
12781       template <typename T>
12782       struct vararg_mor_op : public opr_base<T>
12783       {
12784          typedef typename opr_base<T>::Type Type;
12785
12786          template <typename Type,
12787                    typename Allocator,
12788                    template <typename, typename> class Sequence>
12789          static inline T process(const Sequence<Type,Allocator>& arg_list)
12790          {
12791             switch (arg_list.size())
12792             {
12793                case 1  : return process_1(arg_list);
12794                case 2  : return process_2(arg_list);
12795                case 3  : return process_3(arg_list);
12796                case 4  : return process_4(arg_list);
12797                case 5  : return process_5(arg_list);
12798                default :
12799                          {
12800                             for (std::size_t i = 0; i < arg_list.size(); ++i)
12801                             {
12802                                if (std::not_equal_to<T>()(T(0), value(arg_list[i])))
12803                                   return T(1);
12804                             }
12805
12806                             return T(0);
12807                          }
12808             }
12809          }
12810
12811          template <typename Sequence>
12812          static inline T process_1(const Sequence& arg_list)
12813          {
12814             return std::not_equal_to<T>()
12815                       (T(0), value(arg_list[0])) ? T(1) : T(0);
12816          }
12817
12818          template <typename Sequence>
12819          static inline T process_2(const Sequence& arg_list)
12820          {
12821             return (
12822                      std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
12823                      std::not_equal_to<T>()(T(0), value(arg_list[1]))
12824                    ) ? T(1) : T(0);
12825          }
12826
12827          template <typename Sequence>
12828          static inline T process_3(const Sequence& arg_list)
12829          {
12830             return (
12831                      std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
12832                      std::not_equal_to<T>()(T(0), value(arg_list[1])) ||
12833                      std::not_equal_to<T>()(T(0), value(arg_list[2]))
12834                    ) ? T(1) : T(0);
12835          }
12836
12837          template <typename Sequence>
12838          static inline T process_4(const Sequence& arg_list)
12839          {
12840             return (
12841                      std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
12842                      std::not_equal_to<T>()(T(0), value(arg_list[1])) ||
12843                      std::not_equal_to<T>()(T(0), value(arg_list[2])) ||
12844                      std::not_equal_to<T>()(T(0), value(arg_list[3]))
12845                    ) ? T(1) : T(0);
12846          }
12847
12848          template <typename Sequence>
12849          static inline T process_5(const Sequence& arg_list)
12850          {
12851             return (
12852                      std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
12853                      std::not_equal_to<T>()(T(0), value(arg_list[1])) ||
12854                      std::not_equal_to<T>()(T(0), value(arg_list[2])) ||
12855                      std::not_equal_to<T>()(T(0), value(arg_list[3])) ||
12856                      std::not_equal_to<T>()(T(0), value(arg_list[4]))
12857                    ) ? T(1) : T(0);
12858          }
12859       };
12860
12861       template <typename T>
12862       struct vararg_multi_op : public opr_base<T>
12863       {
12864          typedef typename opr_base<T>::Type Type;
12865
12866          template <typename Type,
12867                    typename Allocator,
12868                    template <typename, typename> class Sequence>
12869          static inline T process(const Sequence<Type,Allocator>& arg_list)
12870          {
12871             switch (arg_list.size())
12872             {
12873                case 0  : return std::numeric_limits<T>::quiet_NaN();
12874                case 1  : return process_1(arg_list);
12875                case 2  : return process_2(arg_list);
12876                case 3  : return process_3(arg_list);
12877                case 4  : return process_4(arg_list);
12878                case 5  : return process_5(arg_list);
12879                case 6  : return process_6(arg_list);
12880                case 7  : return process_7(arg_list);
12881                case 8  : return process_8(arg_list);
12882                default :
12883                          {
12884                             for (std::size_t i = 0; i < (arg_list.size() - 1); ++i)
12885                             {
12886                                value(arg_list[i]);
12887                             }
12888
12889                             return value(arg_list.back());
12890                          }
12891             }
12892          }
12893
12894          template <typename Sequence>
12895          static inline T process_1(const Sequence& arg_list)
12896          {
12897             return value(arg_list[0]);
12898          }
12899
12900          template <typename Sequence>
12901          static inline T process_2(const Sequence& arg_list)
12902          {
12903                    value(arg_list[0]);
12904             return value(arg_list[1]);
12905          }
12906
12907          template <typename Sequence>
12908          static inline T process_3(const Sequence& arg_list)
12909          {
12910                    value(arg_list[0]);
12911                    value(arg_list[1]);
12912             return value(arg_list[2]);
12913          }
12914
12915          template <typename Sequence>
12916          static inline T process_4(const Sequence& arg_list)
12917          {
12918                    value(arg_list[0]);
12919                    value(arg_list[1]);
12920                    value(arg_list[2]);
12921             return value(arg_list[3]);
12922          }
12923
12924          template <typename Sequence>
12925          static inline T process_5(const Sequence& arg_list)
12926          {
12927                    value(arg_list[0]);
12928                    value(arg_list[1]);
12929                    value(arg_list[2]);
12930                    value(arg_list[3]);
12931             return value(arg_list[4]);
12932          }
12933
12934          template <typename Sequence>
12935          static inline T process_6(const Sequence& arg_list)
12936          {
12937                    value(arg_list[0]);
12938                    value(arg_list[1]);
12939                    value(arg_list[2]);
12940                    value(arg_list[3]);
12941                    value(arg_list[4]);
12942             return value(arg_list[5]);
12943          }
12944
12945          template <typename Sequence>
12946          static inline T process_7(const Sequence& arg_list)
12947          {
12948                    value(arg_list[0]);
12949                    value(arg_list[1]);
12950                    value(arg_list[2]);
12951                    value(arg_list[3]);
12952                    value(arg_list[4]);
12953                    value(arg_list[5]);
12954             return value(arg_list[6]);
12955          }
12956
12957          template <typename Sequence>
12958          static inline T process_8(const Sequence& arg_list)
12959          {
12960                    value(arg_list[0]);
12961                    value(arg_list[1]);
12962                    value(arg_list[2]);
12963                    value(arg_list[3]);
12964                    value(arg_list[4]);
12965                    value(arg_list[5]);
12966                    value(arg_list[6]);
12967             return value(arg_list[7]);
12968          }
12969       };
12970
12971       template <typename T>
12972       struct vec_add_op
12973       {
12974          typedef vector_interface<T>* ivector_ptr;
12975
12976          static inline T process(const ivector_ptr v)
12977          {
12978             const T* vec = v->vec()->vds().data();
12979             const std::size_t vec_size = v->vec()->vds().size();
12980
12981             loop_unroll::details lud(vec_size);
12982
12983             if (vec_size <= static_cast<std::size_t>(lud.batch_size))
12984             {
12985                T result = T(0);
12986                int i    = 0;
12987
12988                exprtk_disable_fallthrough_begin
12989                switch (vec_size)
12990                {
12991                   #define case_stmt(N)         \
12992                   case N : result += vec[i++]; \
12993
12994                   #ifndef exprtk_disable_superscalar_unroll
12995                   case_stmt(16) case_stmt(15)
12996                   case_stmt(14) case_stmt(13)
12997                   case_stmt(12) case_stmt(11)
12998                   case_stmt(10) case_stmt( 9)
12999                   case_stmt( 8) case_stmt( 7)
13000                   case_stmt( 6) case_stmt( 5)
13001                   #endif
13002                   case_stmt( 4) case_stmt( 3)
13003                   case_stmt( 2) case_stmt( 1)
13004                }
13005                exprtk_disable_fallthrough_end
13006
13007                #undef case_stmt
13008
13009                return result;
13010             }
13011
13012             T r[] = {
13013                       T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0),
13014                       T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0)
13015                     };
13016
13017             const T* upper_bound = vec + lud.upper_bound;
13018
13019             while (vec < upper_bound)
13020             {
13021                #define exprtk_loop(N) \
13022                r[N] += vec[N];        \
13023
13024                exprtk_loop( 0) exprtk_loop( 1)
13025                exprtk_loop( 2) exprtk_loop( 3)
13026                #ifndef exprtk_disable_superscalar_unroll
13027                exprtk_loop( 4) exprtk_loop( 5)
13028                exprtk_loop( 6) exprtk_loop( 7)
13029                exprtk_loop( 8) exprtk_loop( 9)
13030                exprtk_loop(10) exprtk_loop(11)
13031                exprtk_loop(12) exprtk_loop(13)
13032                exprtk_loop(14) exprtk_loop(15)
13033                #endif
13034
13035                vec += lud.batch_size;
13036             }
13037
13038             int i = 0;
13039
13040             exprtk_disable_fallthrough_begin
13041             switch (lud.remainder)
13042             {
13043                #define case_stmt(N)       \
13044                case N : r[0] += vec[i++]; \
13045
13046                #ifndef exprtk_disable_superscalar_unroll
13047                case_stmt(15) case_stmt(14)
13048                case_stmt(13) case_stmt(12)
13049                case_stmt(11) case_stmt(10)
13050                case_stmt( 9) case_stmt( 8)
13051                case_stmt( 7) case_stmt( 6)
13052                case_stmt( 5) case_stmt( 4)
13053                #endif
13054                case_stmt( 3) case_stmt( 2)
13055                case_stmt( 1)
13056             }
13057             exprtk_disable_fallthrough_end
13058
13059             #undef exprtk_loop
13060             #undef case_stmt
13061
13062             return (r[ 0] + r[ 1] + r[ 2] + r[ 3])
13063                    #ifndef exprtk_disable_superscalar_unroll
13064                  + (r[ 4] + r[ 5] + r[ 6] + r[ 7])
13065                  + (r[ 8] + r[ 9] + r[10] + r[11])
13066                  + (r[12] + r[13] + r[14] + r[15])
13067                    #endif
13068                    ;
13069          }
13070       };
13071
13072       template <typename T>
13073       struct vec_mul_op
13074       {
13075          typedef vector_interface<T>* ivector_ptr;
13076
13077          static inline T process(const ivector_ptr v)
13078          {
13079             const T* vec = v->vec()->vds().data();
13080             const std::size_t vec_size = v->vec()->vds().size();
13081
13082             loop_unroll::details lud(vec_size);
13083
13084             if (vec_size <= static_cast<std::size_t>(lud.batch_size))
13085             {
13086                T result = T(1);
13087                int i    = 0;
13088
13089                exprtk_disable_fallthrough_begin
13090                switch (vec_size)
13091                {
13092                   #define case_stmt(N)         \
13093                   case N : result *= vec[i++]; \
13094
13095                   #ifndef exprtk_disable_superscalar_unroll
13096                   case_stmt(16) case_stmt(15)
13097                   case_stmt(14) case_stmt(13)
13098                   case_stmt(12) case_stmt(11)
13099                   case_stmt(10) case_stmt( 9)
13100                   case_stmt( 8) case_stmt( 7)
13101                   case_stmt( 6) case_stmt( 5)
13102                   #endif
13103                   case_stmt( 4) case_stmt( 3)
13104                   case_stmt( 2) case_stmt( 1)
13105                }
13106                exprtk_disable_fallthrough_end
13107
13108                #undef case_stmt
13109
13110                return result;
13111             }
13112
13113             T r[] = {
13114                       T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1),
13115                       T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1)
13116                     };
13117
13118             const T* upper_bound = vec + lud.upper_bound;
13119
13120             while (vec < upper_bound)
13121             {
13122                #define exprtk_loop(N) \
13123                r[N] *= vec[N];        \
13124
13125                exprtk_loop( 0) exprtk_loop( 1)
13126                exprtk_loop( 2) exprtk_loop( 3)
13127                #ifndef exprtk_disable_superscalar_unroll
13128                exprtk_loop( 4) exprtk_loop( 5)
13129                exprtk_loop( 6) exprtk_loop( 7)
13130                exprtk_loop( 8) exprtk_loop( 9)
13131                exprtk_loop(10) exprtk_loop(11)
13132                exprtk_loop(12) exprtk_loop(13)
13133                exprtk_loop(14) exprtk_loop(15)
13134                #endif
13135
13136                vec += lud.batch_size;
13137             }
13138
13139             int i = 0;
13140
13141             exprtk_disable_fallthrough_begin
13142             switch (lud.remainder)
13143             {
13144                #define case_stmt(N)       \
13145                case N : r[0] *= vec[i++]; \
13146
13147                #ifndef exprtk_disable_superscalar_unroll
13148                case_stmt(15) case_stmt(14)
13149                case_stmt(13) case_stmt(12)
13150                case_stmt(11) case_stmt(10)
13151                case_stmt( 9) case_stmt( 8)
13152                case_stmt( 7) case_stmt( 6)
13153                case_stmt( 5) case_stmt( 4)
13154                #endif
13155                case_stmt( 3) case_stmt( 2)
13156                case_stmt( 1)
13157             }
13158             exprtk_disable_fallthrough_end
13159
13160             #undef exprtk_loop
13161             #undef case_stmt
13162
13163             return (r[ 0] * r[ 1] * r[ 2] * r[ 3])
13164                    #ifndef exprtk_disable_superscalar_unroll
13165                  + (r[ 4] * r[ 5] * r[ 6] * r[ 7])
13166                  + (r[ 8] * r[ 9] * r[10] * r[11])
13167                  + (r[12] * r[13] * r[14] * r[15])
13168                    #endif
13169                    ;
13170          }
13171       };
13172
13173       template <typename T>
13174       struct vec_avg_op
13175       {
13176          typedef vector_interface<T>* ivector_ptr;
13177
13178          static inline T process(const ivector_ptr v)
13179          {
13180             const std::size_t vec_size = v->vec()->vds().size();
13181
13182             return vec_add_op<T>::process(v) / vec_size;
13183          }
13184       };
13185
13186       template <typename T>
13187       struct vec_min_op
13188       {
13189          typedef vector_interface<T>* ivector_ptr;
13190
13191          static inline T process(const ivector_ptr v)
13192          {
13193             const T* vec = v->vec()->vds().data();
13194             const std::size_t vec_size = v->vec()->vds().size();
13195
13196             T result = vec[0];
13197
13198             for (std::size_t i = 1; i < vec_size; ++i)
13199             {
13200                T v_i = vec[i];
13201
13202                if (v_i < result)
13203                   result = v_i;
13204             }
13205
13206             return result;
13207          }
13208       };
13209
13210       template <typename T>
13211       struct vec_max_op
13212       {
13213          typedef vector_interface<T>* ivector_ptr;
13214
13215          static inline T process(const ivector_ptr v)
13216          {
13217             const T* vec = v->vec()->vds().data();
13218             const std::size_t vec_size = v->vec()->vds().size();
13219
13220             T result = vec[0];
13221
13222             for (std::size_t i = 1; i < vec_size; ++i)
13223             {
13224                T v_i = vec[i];
13225
13226                if (v_i > result)
13227                   result = v_i;
13228             }
13229
13230             return result;
13231          }
13232       };
13233
13234       template <typename T>
13235       class vov_base_node : public expression_node<T>
13236       {
13237       public:
13238
13239          virtual ~vov_base_node()
13240          {}
13241
13242          inline virtual operator_type operation() const
13243          {
13244             return details::e_default;
13245          }
13246
13247          virtual const T& v0() const = 0;
13248
13249          virtual const T& v1() const = 0;
13250       };
13251
13252       template <typename T>
13253       class cov_base_node : public expression_node<T>
13254       {
13255       public:
13256
13257        virtual ~cov_base_node()
13258           {}
13259
13260          inline virtual operator_type operation() const
13261          {
13262             return details::e_default;
13263          }
13264
13265          virtual const T c() const = 0;
13266
13267          virtual const T& v() const = 0;
13268       };
13269
13270       template <typename T>
13271       class voc_base_node : public expression_node<T>
13272       {
13273       public:
13274
13275          virtual ~voc_base_node()
13276          {}
13277
13278          inline virtual operator_type operation() const
13279          {
13280             return details::e_default;
13281          }
13282
13283          virtual const T c() const = 0;
13284
13285          virtual const T& v() const = 0;
13286       };
13287
13288       template <typename T>
13289       class vob_base_node : public expression_node<T>
13290       {
13291       public:
13292
13293          virtual ~vob_base_node()
13294          {}
13295
13296          virtual const T& v() const = 0;
13297       };
13298
13299       template <typename T>
13300       class bov_base_node : public expression_node<T>
13301       {
13302       public:
13303
13304          virtual ~bov_base_node()
13305          {}
13306
13307          virtual const T& v() const = 0;
13308       };
13309
13310       template <typename T>
13311       class cob_base_node : public expression_node<T>
13312       {
13313       public:
13314
13315        virtual ~cob_base_node()
13316        {}
13317
13318          inline virtual operator_type operation() const
13319          {
13320             return details::e_default;
13321          }
13322
13323          virtual const T c() const = 0;
13324
13325          virtual void set_c(const T) = 0;
13326
13327          virtual expression_node<T>* move_branch(const std::size_t& index) = 0;
13328       };
13329
13330       template <typename T>
13331       class boc_base_node : public expression_node<T>
13332       {
13333       public:
13334
13335          virtual ~boc_base_node()
13336          {}
13337
13338          inline virtual operator_type operation() const
13339          {
13340             return details::e_default;
13341          }
13342
13343          virtual const T c() const = 0;
13344
13345          virtual void set_c(const T) = 0;
13346
13347          virtual expression_node<T>* move_branch(const std::size_t& index) = 0;
13348       };
13349
13350       template <typename T>
13351       class uv_base_node : public expression_node<T>
13352       {
13353       public:
13354
13355          virtual ~uv_base_node()
13356          {}
13357
13358          inline virtual operator_type operation() const
13359          {
13360             return details::e_default;
13361          }
13362
13363          virtual const T& v() const = 0;
13364       };
13365
13366       template <typename T>
13367       class sos_base_node : public expression_node<T>
13368       {
13369       public:
13370
13371          virtual ~sos_base_node()
13372          {}
13373
13374          inline virtual operator_type operation() const
13375          {
13376             return details::e_default;
13377          }
13378       };
13379
13380       template <typename T>
13381       class sosos_base_node : public expression_node<T>
13382       {
13383       public:
13384
13385          virtual ~sosos_base_node()
13386          {}
13387
13388          inline virtual operator_type operation() const
13389          {
13390             return details::e_default;
13391          }
13392       };
13393
13394       template <typename T>
13395       class T0oT1oT2_base_node : public expression_node<T>
13396       {
13397       public:
13398
13399          virtual ~T0oT1oT2_base_node()
13400          {}
13401
13402          virtual std::string type_id() const = 0;
13403       };
13404
13405       template <typename T>
13406       class T0oT1oT2oT3_base_node : public expression_node<T>
13407       {
13408       public:
13409
13410          virtual ~T0oT1oT2oT3_base_node()
13411          {}
13412
13413          virtual std::string type_id() const = 0;
13414       };
13415
13416       template <typename T, typename Operation>
13417       class unary_variable_node : public uv_base_node<T>
13418       {
13419       public:
13420
13421          typedef expression_node<T>* expression_ptr;
13422          typedef Operation operation_t;
13423
13424          explicit unary_variable_node(const T& var)
13425          : v_(var)
13426          {}
13427
13428          inline T value() const
13429          {
13430             return Operation::process(v_);
13431          }
13432
13433          inline typename expression_node<T>::node_type type() const
13434          {
13435             return Operation::type();
13436          }
13437
13438          inline operator_type operation() const
13439          {
13440             return Operation::operation();
13441          }
13442
13443          inline const T& v() const
13444          {
13445             return v_;
13446          }
13447
13448       private:
13449
13450          unary_variable_node(unary_variable_node<T,Operation>&);
13451          unary_variable_node<T,Operation>& operator=(unary_variable_node<T,Operation>&);
13452
13453          const T& v_;
13454       };
13455
13456       template <typename T>
13457       class uvouv_node : public expression_node<T>
13458       {
13459       public:
13460
13461          // UOpr1(v0) Op UOpr2(v1)
13462
13463          typedef expression_node<T>* expression_ptr;
13464          typedef typename details::functor_t<T> functor_t;
13465          typedef typename functor_t::bfunc_t      bfunc_t;
13466          typedef typename functor_t::ufunc_t      ufunc_t;
13467
13468          explicit uvouv_node(const T& var0,const T& var1,
13469                              ufunc_t uf0, ufunc_t uf1, bfunc_t bf)
13470          : v0_(var0),
13471            v1_(var1),
13472            u0_(uf0 ),
13473            u1_(uf1 ),
13474            f_ (bf  )
13475          {}
13476
13477          inline T value() const
13478          {
13479             return f_(u0_(v0_),u1_(v1_));
13480          }
13481
13482          inline typename expression_node<T>::node_type type() const
13483          {
13484             return expression_node<T>::e_uvouv;
13485          }
13486
13487          inline operator_type operation() const
13488          {
13489             return details::e_default;
13490          }
13491
13492          inline const T& v0()
13493          {
13494             return v0_;
13495          }
13496
13497          inline const T& v1()
13498          {
13499             return v1_;
13500          }
13501
13502          inline ufunc_t u0()
13503          {
13504             return u0_;
13505          }
13506
13507          inline ufunc_t u1()
13508          {
13509             return u1_;
13510          }
13511
13512          inline ufunc_t f()
13513          {
13514             return f_;
13515          }
13516
13517       private:
13518
13519          uvouv_node(uvouv_node<T>&);
13520          uvouv_node<T>& operator=(uvouv_node<T>&);
13521
13522          const T& v0_;
13523          const T& v1_;
13524          const ufunc_t u0_;
13525          const ufunc_t u1_;
13526          const bfunc_t f_;
13527       };
13528
13529       template <typename T, typename Operation>
13530       class unary_branch_node : public expression_node<T>
13531       {
13532       public:
13533
13534          typedef expression_node<T>* expression_ptr;
13535          typedef Operation operation_t;
13536
13537          explicit unary_branch_node(expression_ptr brnch)
13538          : branch_(brnch),
13539            branch_deletable_(branch_deletable(branch_))
13540          {}
13541
13542         ~unary_branch_node()
13543          {
13544             if (branch_ && branch_deletable_)
13545             {
13546                destroy_node(branch_);
13547             }
13548          }
13549
13550          inline T value() const
13551          {
13552             return Operation::process(branch_->value());
13553          }
13554
13555          inline typename expression_node<T>::node_type type() const
13556          {
13557             return Operation::type();
13558          }
13559
13560          inline operator_type operation() const
13561          {
13562             return Operation::operation();
13563          }
13564
13565          inline expression_node<T>* branch(const std::size_t&) const
13566          {
13567             return branch_;
13568          }
13569
13570          inline void release()
13571          {
13572             branch_deletable_ = false;
13573          }
13574
13575       private:
13576
13577          unary_branch_node(unary_branch_node<T,Operation>&);
13578          unary_branch_node<T,Operation>& operator=(unary_branch_node<T,Operation>&);
13579
13580          expression_ptr branch_;
13581          bool           branch_deletable_;
13582       };
13583
13584       template <typename T> struct is_const                { enum {result = 0}; };
13585       template <typename T> struct is_const <const T>      { enum {result = 1}; };
13586       template <typename T> struct is_const_ref            { enum {result = 0}; };
13587       template <typename T> struct is_const_ref <const T&> { enum {result = 1}; };
13588       template <typename T> struct is_ref                  { enum {result = 0}; };
13589       template <typename T> struct is_ref<T&>              { enum {result = 1}; };
13590       template <typename T> struct is_ref<const T&>        { enum {result = 0}; };
13591
13592       template <std::size_t State>
13593       struct param_to_str { static std::string result() { static const std::string r("v"); return r; } };
13594
13595       template <>
13596       struct param_to_str<0> { static std::string result() { static const std::string r("c"); return r; } };
13597
13598       #define exprtk_crtype(Type)                          \
13599       param_to_str<is_const_ref< Type >::result>::result() \
13600
13601       template <typename T>
13602       struct T0oT1oT2process
13603       {
13604          typedef typename details::functor_t<T> functor_t;
13605          typedef typename functor_t::bfunc_t      bfunc_t;
13606
13607          struct mode0
13608          {
13609             static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1)
13610             {
13611                // (T0 o0 T1) o1 T2
13612                return bf1(bf0(t0,t1),t2);
13613             }
13614
13615             template <typename T0, typename T1, typename T2>
13616             static inline std::string id()
13617             {
13618                static const std::string result = "(" + exprtk_crtype(T0) + "o"   +
13619                                                        exprtk_crtype(T1) + ")o(" +
13620                                                        exprtk_crtype(T2) + ")"   ;
13621                return result;
13622             }
13623          };
13624
13625          struct mode1
13626          {
13627             static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1)
13628             {
13629                // T0 o0 (T1 o1 T2)
13630                return bf0(t0,bf1(t1,t2));
13631             }
13632
13633             template <typename T0, typename T1, typename T2>
13634             static inline std::string id()
13635             {
13636                static const std::string result = "(" + exprtk_crtype(T0) + ")o(" +
13637                                                        exprtk_crtype(T1) + "o"   +
13638                                                        exprtk_crtype(T2) + ")"   ;
13639                return result;
13640             }
13641          };
13642       };
13643
13644       template <typename T>
13645       struct T0oT1oT20T3process
13646       {
13647          typedef typename details::functor_t<T> functor_t;
13648          typedef typename functor_t::bfunc_t      bfunc_t;
13649
13650          struct mode0
13651          {
13652             static inline T process(const T& t0, const T& t1,
13653                                     const T& t2, const T& t3,
13654                                     const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
13655             {
13656                // (T0 o0 T1) o1 (T2 o2 T3)
13657                return bf1(bf0(t0,t1),bf2(t2,t3));
13658             }
13659
13660             template <typename T0, typename T1, typename T2, typename T3>
13661             static inline std::string id()
13662             {
13663                static const std::string result = "(" + exprtk_crtype(T0) + "o"  +
13664                                                        exprtk_crtype(T1) + ")o" +
13665                                                  "(" + exprtk_crtype(T2) + "o"  +
13666                                                        exprtk_crtype(T3) + ")"  ;
13667                return result;
13668             }
13669          };
13670
13671          struct mode1
13672          {
13673             static inline T process(const T& t0, const T& t1,
13674                                     const T& t2, const T& t3,
13675                                     const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
13676             {
13677                // (T0 o0 (T1 o1 (T2 o2 T3))
13678                return bf0(t0,bf1(t1,bf2(t2,t3)));
13679             }
13680             template <typename T0, typename T1, typename T2, typename T3>
13681             static inline std::string id()
13682             {
13683                static const std::string result = "(" + exprtk_crtype(T0) +  ")o((" +
13684                                                        exprtk_crtype(T1) +  ")o("  +
13685                                                        exprtk_crtype(T2) +  "o"    +
13686                                                        exprtk_crtype(T3) +  "))"   ;
13687                return result;
13688             }
13689          };
13690
13691          struct mode2
13692          {
13693             static inline T process(const T& t0, const T& t1,
13694                                     const T& t2, const T& t3,
13695                                     const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
13696             {
13697                // (T0 o0 ((T1 o1 T2) o2 T3)
13698                return bf0(t0,bf2(bf1(t1,t2),t3));
13699             }
13700
13701             template <typename T0, typename T1, typename T2, typename T3>
13702             static inline std::string id()
13703             {
13704                static const std::string result = "(" + exprtk_crtype(T0) + ")o((" +
13705                                                        exprtk_crtype(T1) + "o"    +
13706                                                        exprtk_crtype(T2) + ")o("  +
13707                                                        exprtk_crtype(T3) + "))"   ;
13708                return result;
13709             }
13710          };
13711
13712          struct mode3
13713          {
13714             static inline T process(const T& t0, const T& t1,
13715                                     const T& t2, const T& t3,
13716                                     const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
13717             {
13718                // (((T0 o0 T1) o1 T2) o2 T3)
13719                return bf2(bf1(bf0(t0,t1),t2),t3);
13720             }
13721
13722             template <typename T0, typename T1, typename T2, typename T3>
13723             static inline std::string id()
13724             {
13725                static const std::string result = "((" + exprtk_crtype(T0) + "o"    +
13726                                                         exprtk_crtype(T1) + ")o("  +
13727                                                         exprtk_crtype(T2) + "))o(" +
13728                                                         exprtk_crtype(T3) + ")";
13729                return result;
13730             }
13731          };
13732
13733          struct mode4
13734          {
13735             static inline T process(const T& t0, const T& t1,
13736                                     const T& t2, const T& t3,
13737                                     const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
13738             {
13739                // ((T0 o0 (T1 o1 T2)) o2 T3
13740                return bf2(bf0(t0,bf1(t1,t2)),t3);
13741             }
13742
13743             template <typename T0, typename T1, typename T2, typename T3>
13744             static inline std::string id()
13745             {
13746                static const std::string result = "((" + exprtk_crtype(T0) + ")o("  +
13747                                                         exprtk_crtype(T1) + "o"    +
13748                                                         exprtk_crtype(T2) + "))o(" +
13749                                                         exprtk_crtype(T3) + ")"    ;
13750                return result;
13751             }
13752          };
13753       };
13754
13755       #undef exprtk_crtype
13756
13757       template <typename T, typename T0, typename T1>
13758       struct nodetype_T0oT1 { static const typename expression_node<T>::node_type result; };
13759       template <typename T, typename T0, typename T1>
13760       const typename expression_node<T>::node_type nodetype_T0oT1<T,T0,T1>::result = expression_node<T>::e_none;
13761
13762       #define synthesis_node_type_define(T0_,T1_,v_)                                                            \
13763       template <typename T, typename T0, typename T1>                                                           \
13764       struct nodetype_T0oT1<T,T0_,T1_> { static const typename expression_node<T>::node_type result; };         \
13765       template <typename T, typename T0, typename T1>                                                           \
13766       const typename expression_node<T>::node_type nodetype_T0oT1<T,T0_,T1_>::result = expression_node<T>:: v_; \
13767
13768       synthesis_node_type_define(const T0&, const T1&,  e_vov)
13769       synthesis_node_type_define(const T0&, const T1 ,  e_voc)
13770       synthesis_node_type_define(const T0 , const T1&,  e_cov)
13771       synthesis_node_type_define(      T0&,       T1&, e_none)
13772       synthesis_node_type_define(const T0 , const T1 , e_none)
13773       synthesis_node_type_define(      T0&, const T1 , e_none)
13774       synthesis_node_type_define(const T0 ,       T1&, e_none)
13775       synthesis_node_type_define(const T0&,       T1&, e_none)
13776       synthesis_node_type_define(      T0&, const T1&, e_none)
13777       #undef synthesis_node_type_define
13778
13779       template <typename T, typename T0, typename T1, typename T2>
13780       struct nodetype_T0oT1oT2 { static const typename expression_node<T>::node_type result; };
13781       template <typename T, typename T0, typename T1, typename T2>
13782       const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0,T1,T2>::result = expression_node<T>::e_none;
13783
13784       #define synthesis_node_type_define(T0_,T1_,T2_,v_)                                                               \
13785       template <typename T, typename T0, typename T1, typename T2>                                                     \
13786       struct nodetype_T0oT1oT2<T,T0_,T1_,T2_> { static const typename expression_node<T>::node_type result; };         \
13787       template <typename T, typename T0, typename T1, typename T2>                                                     \
13788       const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0_,T1_,T2_>::result = expression_node<T>:: v_; \
13789
13790       synthesis_node_type_define(const T0&, const T1&, const T2&, e_vovov)
13791       synthesis_node_type_define(const T0&, const T1&, const T2 , e_vovoc)
13792       synthesis_node_type_define(const T0&, const T1 , const T2&, e_vocov)
13793       synthesis_node_type_define(const T0 , const T1&, const T2&, e_covov)
13794       synthesis_node_type_define(const T0 , const T1&, const T2 , e_covoc)
13795       synthesis_node_type_define(const T0 , const T1 , const T2 , e_none )
13796       synthesis_node_type_define(const T0 , const T1 , const T2&, e_none )
13797       synthesis_node_type_define(const T0&, const T1 , const T2 , e_none )
13798       synthesis_node_type_define(      T0&,       T1&,       T2&, e_none )
13799       #undef synthesis_node_type_define
13800
13801       template <typename T, typename T0, typename T1, typename T2, typename T3>
13802       struct nodetype_T0oT1oT2oT3 { static const typename expression_node<T>::node_type result; };
13803       template <typename T, typename T0, typename T1, typename T2, typename T3>
13804       const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result = expression_node<T>::e_none;
13805
13806       #define synthesis_node_type_define(T0_,T1_,T2_,T3_,v_)                                                                  \
13807       template <typename T, typename T0, typename T1, typename T2, typename T3>                                               \
13808       struct nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_> { static const typename expression_node<T>::node_type result; };         \
13809       template <typename T, typename T0, typename T1, typename T2, typename T3>                                               \
13810       const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_>::result = expression_node<T>:: v_; \
13811
13812       synthesis_node_type_define(const T0&, const T1&, const T2&, const T3&, e_vovovov)
13813       synthesis_node_type_define(const T0&, const T1&, const T2&, const T3 , e_vovovoc)
13814       synthesis_node_type_define(const T0&, const T1&, const T2 , const T3&, e_vovocov)
13815       synthesis_node_type_define(const T0&, const T1 , const T2&, const T3&, e_vocovov)
13816       synthesis_node_type_define(const T0 , const T1&, const T2&, const T3&, e_covovov)
13817       synthesis_node_type_define(const T0 , const T1&, const T2 , const T3&, e_covocov)
13818       synthesis_node_type_define(const T0&, const T1 , const T2&, const T3 , e_vocovoc)
13819       synthesis_node_type_define(const T0 , const T1&, const T2&, const T3 , e_covovoc)
13820       synthesis_node_type_define(const T0&, const T1 , const T2 , const T3&, e_vococov)
13821       synthesis_node_type_define(const T0 , const T1 , const T2 , const T3 , e_none   )
13822       synthesis_node_type_define(const T0 , const T1 , const T2 , const T3&, e_none   )
13823       synthesis_node_type_define(const T0 , const T1 , const T2&, const T3 , e_none   )
13824       synthesis_node_type_define(const T0 , const T1&, const T2 , const T3 , e_none   )
13825       synthesis_node_type_define(const T0&, const T1 , const T2 , const T3 , e_none   )
13826       synthesis_node_type_define(const T0 , const T1 , const T2&, const T3&, e_none   )
13827       synthesis_node_type_define(const T0&, const T1&, const T2 , const T3 , e_none   )
13828       #undef synthesis_node_type_define
13829
13830       template <typename T, typename T0, typename T1>
13831       class T0oT1 : public expression_node<T>
13832       {
13833       public:
13834
13835          typedef typename details::functor_t<T> functor_t;
13836          typedef typename functor_t::bfunc_t      bfunc_t;
13837          typedef T value_type;
13838          typedef T0oT1<T,T0,T1> node_type;
13839
13840          T0oT1(T0 p0, T1 p1, const bfunc_t p2)
13841          : t0_(p0),
13842            t1_(p1),
13843            f_ (p2)
13844          {}
13845
13846          inline typename expression_node<T>::node_type type() const
13847          {
13848             static const typename expression_node<T>::node_type result = nodetype_T0oT1<T,T0,T1>::result;
13849             return result;
13850          }
13851
13852          inline operator_type operation() const
13853          {
13854             return e_default;
13855          }
13856
13857          inline T value() const
13858          {
13859             return f_(t0_,t1_);
13860          }
13861
13862          inline T0 t0() const
13863          {
13864             return t0_;
13865          }
13866
13867          inline T1 t1() const
13868          {
13869             return t1_;
13870          }
13871
13872          inline bfunc_t f() const
13873          {
13874             return f_;
13875          }
13876
13877          template <typename Allocator>
13878          static inline expression_node<T>* allocate(Allocator& allocator,
13879                                                     T0 p0, T1 p1,
13880                                                     bfunc_t p2)
13881          {
13882             return allocator
13883                      .template allocate_type<node_type, T0, T1, bfunc_t&>
13884                         (p0, p1, p2);
13885          }
13886
13887       private:
13888
13889          T0oT1(T0oT1<T,T0,T1>&) {}
13890          T0oT1<T,T0,T1>& operator=(T0oT1<T,T0,T1>&) { return (*this); }
13891
13892          T0 t0_;
13893          T1 t1_;
13894          const bfunc_t f_;
13895       };
13896
13897       template <typename T, typename T0, typename T1, typename T2, typename ProcessMode>
13898       class T0oT1oT2 : public T0oT1oT2_base_node<T>
13899       {
13900       public:
13901
13902          typedef typename details::functor_t<T> functor_t;
13903          typedef typename functor_t::bfunc_t      bfunc_t;
13904          typedef T value_type;
13905          typedef T0oT1oT2<T,T0,T1,T2,ProcessMode> node_type;
13906          typedef ProcessMode process_mode_t;
13907
13908          T0oT1oT2(T0 p0, T1 p1, T2 p2, const bfunc_t p3, const bfunc_t p4)
13909          : t0_(p0),
13910            t1_(p1),
13911            t2_(p2),
13912            f0_(p3),
13913            f1_(p4)
13914          {}
13915
13916          inline typename expression_node<T>::node_type type() const
13917          {
13918             static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
13919             return result;
13920          }
13921
13922          inline operator_type operation() const
13923          {
13924             return e_default;
13925          }
13926
13927          inline T value() const
13928          {
13929             return ProcessMode::process(t0_, t1_, t2_, f0_, f1_);
13930          }
13931
13932          inline T0 t0() const
13933          {
13934             return t0_;
13935          }
13936
13937          inline T1 t1() const
13938          {
13939             return t1_;
13940          }
13941
13942          inline T2 t2() const
13943          {
13944             return t2_;
13945          }
13946
13947          bfunc_t f0() const
13948          {
13949             return f0_;
13950          }
13951
13952          bfunc_t f1() const
13953          {
13954             return f1_;
13955          }
13956
13957          std::string type_id() const
13958          {
13959             return id();
13960          }
13961
13962          static inline std::string id()
13963          {
13964             return process_mode_t::template id<T0,T1,T2>();
13965          }
13966
13967          template <typename Allocator>
13968          static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, bfunc_t p3, bfunc_t p4)
13969          {
13970             return allocator
13971                       .template allocate_type<node_type, T0, T1, T2, bfunc_t, bfunc_t>
13972                          (p0, p1, p2, p3, p4);
13973          }
13974
13975       private:
13976
13977          T0oT1oT2(node_type&) {}
13978          node_type& operator=(node_type&) { return (*this); }
13979
13980          T0 t0_;
13981          T1 t1_;
13982          T2 t2_;
13983          const bfunc_t f0_;
13984          const bfunc_t f1_;
13985       };
13986
13987       template <typename T, typename T0_, typename T1_, typename T2_, typename T3_, typename ProcessMode>
13988       class T0oT1oT2oT3 : public T0oT1oT2oT3_base_node<T>
13989       {
13990       public:
13991
13992          typedef typename details::functor_t<T> functor_t;
13993          typedef typename functor_t::bfunc_t      bfunc_t;
13994          typedef T value_type;
13995          typedef T0_ T0;
13996          typedef T1_ T1;
13997          typedef T2_ T2;
13998          typedef T3_ T3;
13999          typedef T0oT1oT2oT3<T,T0,T1,T2,T3,ProcessMode> node_type;
14000          typedef ProcessMode process_mode_t;
14001
14002          T0oT1oT2oT3(T0 p0, T1 p1, T2 p2, T3 p3, bfunc_t p4, bfunc_t p5, bfunc_t p6)
14003          : t0_(p0),
14004            t1_(p1),
14005            t2_(p2),
14006            t3_(p3),
14007            f0_(p4),
14008            f1_(p5),
14009            f2_(p6)
14010          {}
14011
14012          inline T value() const
14013          {
14014             return ProcessMode::process(t0_, t1_, t2_, t3_, f0_, f1_, f2_);
14015          }
14016
14017          inline T0 t0() const
14018          {
14019             return t0_;
14020          }
14021
14022          inline T1 t1() const
14023          {
14024             return t1_;
14025          }
14026
14027          inline T2 t2() const
14028          {
14029             return t2_;
14030          }
14031
14032          inline T3 t3() const
14033          {
14034             return t3_;
14035          }
14036
14037          inline bfunc_t f0() const
14038          {
14039             return f0_;
14040          }
14041
14042          inline bfunc_t f1() const
14043          {
14044             return f1_;
14045          }
14046
14047          inline bfunc_t f2() const
14048          {
14049             return f2_;
14050          }
14051
14052          inline std::string type_id() const
14053          {
14054             return id();
14055          }
14056
14057          static inline std::string id()
14058          {
14059             return process_mode_t::template id<T0, T1, T2, T3>();
14060          }
14061
14062          template <typename Allocator>
14063          static inline expression_node<T>* allocate(Allocator& allocator,
14064                                                     T0 p0, T1 p1, T2 p2, T3 p3,
14065                                                     bfunc_t p4, bfunc_t p5, bfunc_t p6)
14066          {
14067             return allocator
14068                       .template allocate_type<node_type, T0, T1, T2, T3, bfunc_t, bfunc_t>
14069                          (p0, p1, p2, p3, p4, p5, p6);
14070          }
14071
14072       private:
14073
14074          T0oT1oT2oT3(node_type&) {}
14075          node_type& operator=(node_type&) { return (*this); }
14076
14077          T0 t0_;
14078          T1 t1_;
14079          T2 t2_;
14080          T3 t3_;
14081          const bfunc_t f0_;
14082          const bfunc_t f1_;
14083          const bfunc_t f2_;
14084       };
14085
14086       template <typename T, typename T0, typename T1, typename T2>
14087       class T0oT1oT2_sf3 : public T0oT1oT2_base_node<T>
14088       {
14089       public:
14090
14091          typedef typename details::functor_t<T> functor_t;
14092          typedef typename functor_t::tfunc_t      tfunc_t;
14093          typedef T value_type;
14094          typedef T0oT1oT2_sf3<T,T0,T1,T2> node_type;
14095
14096          T0oT1oT2_sf3(T0 p0, T1 p1, T2 p2, const tfunc_t p3)
14097          : t0_(p0),
14098            t1_(p1),
14099            t2_(p2),
14100            f_ (p3)
14101          {}
14102
14103          inline typename expression_node<T>::node_type type() const
14104          {
14105             static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
14106             return result;
14107          }
14108
14109          inline operator_type operation() const
14110          {
14111             return e_default;
14112          }
14113
14114          inline T value() const
14115          {
14116             return f_(t0_, t1_, t2_);
14117          }
14118
14119          inline T0 t0() const
14120          {
14121             return t0_;
14122          }
14123
14124          inline T1 t1() const
14125          {
14126             return t1_;
14127          }
14128
14129          inline T2 t2() const
14130          {
14131             return t2_;
14132          }
14133
14134          tfunc_t f() const
14135          {
14136             return f_;
14137          }
14138
14139          std::string type_id() const
14140          {
14141             return id();
14142          }
14143
14144          static inline std::string id()
14145          {
14146             return "sf3";
14147          }
14148
14149          template <typename Allocator>
14150          static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, tfunc_t p3)
14151          {
14152             return allocator
14153                      .template allocate_type<node_type, T0, T1, T2, tfunc_t>
14154                         (p0, p1, p2, p3);
14155          }
14156
14157       private:
14158
14159          T0oT1oT2_sf3(node_type&) {}
14160          node_type& operator=(node_type&) { return (*this); }
14161
14162          T0 t0_;
14163          T1 t1_;
14164          T2 t2_;
14165          const tfunc_t f_;
14166       };
14167
14168       template <typename T, typename T0, typename T1, typename T2>
14169       class sf3ext_type_node : public T0oT1oT2_base_node<T>
14170       {
14171       public:
14172
14173          virtual ~sf3ext_type_node()
14174          {}
14175
14176          virtual T0 t0() const = 0;
14177
14178          virtual T1 t1() const = 0;
14179
14180          virtual T2 t2() const = 0;
14181       };
14182
14183       template <typename T, typename T0, typename T1, typename T2, typename SF3Operation>
14184       class T0oT1oT2_sf3ext : public sf3ext_type_node<T,T0,T1,T2>
14185       {
14186       public:
14187
14188          typedef typename details::functor_t<T> functor_t;
14189          typedef typename functor_t::tfunc_t      tfunc_t;
14190          typedef T value_type;
14191          typedef T0oT1oT2_sf3ext<T,T0,T1,T2,SF3Operation> node_type;
14192
14193          T0oT1oT2_sf3ext(T0 p0, T1 p1, T2 p2)
14194          : t0_(p0),
14195            t1_(p1),
14196            t2_(p2)
14197          {}
14198
14199          inline typename expression_node<T>::node_type type() const
14200          {
14201             static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
14202             return result;
14203          }
14204
14205          inline operator_type operation() const
14206          {
14207             return e_default;
14208          }
14209
14210          inline T value() const
14211          {
14212             return SF3Operation::process(t0_, t1_, t2_);
14213          }
14214
14215          T0 t0() const
14216          {
14217             return t0_;
14218          }
14219
14220          T1 t1() const
14221          {
14222             return t1_;
14223          }
14224
14225          T2 t2() const
14226          {
14227             return t2_;
14228          }
14229
14230          std::string type_id() const
14231          {
14232             return id();
14233          }
14234
14235          static inline std::string id()
14236          {
14237             return SF3Operation::id();
14238          }
14239
14240          template <typename Allocator>
14241          static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2)
14242          {
14243             return allocator
14244                      .template allocate_type<node_type, T0, T1, T2>
14245                         (p0, p1, p2);
14246          }
14247
14248       private:
14249
14250          T0oT1oT2_sf3ext(node_type&) {}
14251          node_type& operator=(node_type&) { return (*this); }
14252
14253          T0 t0_;
14254          T1 t1_;
14255          T2 t2_;
14256       };
14257
14258       template <typename T>
14259       inline bool is_sf3ext_node(const expression_node<T>* n)
14260       {
14261          switch (n->type())
14262          {
14263             case expression_node<T>::e_vovov : return true;
14264             case expression_node<T>::e_vovoc : return true;
14265             case expression_node<T>::e_vocov : return true;
14266             case expression_node<T>::e_covov : return true;
14267             case expression_node<T>::e_covoc : return true;
14268             default                          : return false;
14269          }
14270       }
14271
14272       template <typename T, typename T0, typename T1, typename T2, typename T3>
14273       class T0oT1oT2oT3_sf4 : public T0oT1oT2_base_node<T>
14274       {
14275       public:
14276
14277          typedef typename details::functor_t<T> functor_t;
14278          typedef typename functor_t::qfunc_t      qfunc_t;
14279          typedef T value_type;
14280          typedef T0oT1oT2oT3_sf4<T,T0,T1,T2,T3> node_type;
14281
14282          T0oT1oT2oT3_sf4(T0 p0, T1 p1, T2 p2, T3 p3, const qfunc_t p4)
14283          : t0_(p0),
14284            t1_(p1),
14285            t2_(p2),
14286            t3_(p3),
14287            f_ (p4)
14288          {}
14289
14290          inline typename expression_node<T>::node_type type() const
14291          {
14292             static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result;
14293             return result;
14294          }
14295
14296          inline operator_type operation() const
14297          {
14298             return e_default;
14299          }
14300
14301          inline T value() const
14302          {
14303             return f_(t0_, t1_, t2_, t3_);
14304          }
14305
14306          inline T0 t0() const
14307          {
14308             return t0_;
14309          }
14310
14311          inline T1 t1() const
14312          {
14313             return t1_;
14314          }
14315
14316          inline T2 t2() const
14317          {
14318             return t2_;
14319          }
14320
14321          inline T3 t3() const
14322          {
14323             return t3_;
14324          }
14325
14326          qfunc_t f() const
14327          {
14328             return f_;
14329          }
14330
14331          std::string type_id() const
14332          {
14333             return id();
14334          }
14335
14336          static inline std::string id()
14337          {
14338             return "sf4";
14339          }
14340
14341          template <typename Allocator>
14342          static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3, qfunc_t p4)
14343          {
14344             return allocator
14345                      .template allocate_type<node_type, T0, T1, T2, T3, qfunc_t>
14346                         (p0, p1, p2, p3, p4);
14347          }
14348
14349       private:
14350
14351          T0oT1oT2oT3_sf4(node_type&) {}
14352          node_type& operator=(node_type&) { return (*this); }
14353
14354          T0 t0_;
14355          T1 t1_;
14356          T2 t2_;
14357          T3 t3_;
14358          const qfunc_t f_;
14359       };
14360
14361       template <typename T, typename T0, typename T1, typename T2, typename T3, typename SF4Operation>
14362       class T0oT1oT2oT3_sf4ext : public T0oT1oT2oT3_base_node<T>
14363       {
14364       public:
14365
14366          typedef typename details::functor_t<T> functor_t;
14367          typedef typename functor_t::tfunc_t      tfunc_t;
14368          typedef T value_type;
14369          typedef T0oT1oT2oT3_sf4ext<T,T0,T1,T2,T3,SF4Operation> node_type;
14370
14371          T0oT1oT2oT3_sf4ext(T0 p0, T1 p1, T2 p2, T3 p3)
14372          : t0_(p0),
14373            t1_(p1),
14374            t2_(p2),
14375            t3_(p3)
14376          {}
14377
14378          inline typename expression_node<T>::node_type type() const
14379          {
14380             static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result;
14381             return result;
14382          }
14383
14384          inline operator_type operation() const
14385          {
14386             return e_default;
14387          }
14388
14389          inline T value() const
14390          {
14391             return SF4Operation::process(t0_, t1_, t2_, t3_);
14392          }
14393
14394          inline T0 t0() const
14395          {
14396             return t0_;
14397          }
14398
14399          inline T1 t1() const
14400          {
14401             return t1_;
14402          }
14403
14404          inline T2 t2() const
14405          {
14406             return t2_;
14407          }
14408
14409          inline T3 t3() const
14410          {
14411             return t3_;
14412          }
14413
14414          std::string type_id() const
14415          {
14416             return id();
14417          }
14418
14419          static inline std::string id()
14420          {
14421             return SF4Operation::id();
14422          }
14423
14424          template <typename Allocator>
14425          static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3)
14426          {
14427             return allocator
14428                      .template allocate_type<node_type, T0, T1, T2, T3>
14429                         (p0, p1, p2, p3);
14430          }
14431
14432       private:
14433
14434          T0oT1oT2oT3_sf4ext(node_type&) {}
14435          node_type& operator=(node_type&) { return (*this); }
14436
14437          T0 t0_;
14438          T1 t1_;
14439          T2 t2_;
14440          T3 t3_;
14441       };
14442
14443       template <typename T>
14444       inline bool is_sf4ext_node(const expression_node<T>* n)
14445       {
14446          switch (n->type())
14447          {
14448             case expression_node<T>::e_vovovov : return true;
14449             case expression_node<T>::e_vovovoc : return true;
14450             case expression_node<T>::e_vovocov : return true;
14451             case expression_node<T>::e_vocovov : return true;
14452             case expression_node<T>::e_covovov : return true;
14453             case expression_node<T>::e_covocov : return true;
14454             case expression_node<T>::e_vocovoc : return true;
14455             case expression_node<T>::e_covovoc : return true;
14456             case expression_node<T>::e_vococov : return true;
14457             default                            : return false;
14458          }
14459       }
14460
14461       template <typename T, typename T0, typename T1>
14462       struct T0oT1_define
14463       {
14464          typedef details::T0oT1<T, T0, T1> type0;
14465       };
14466
14467       template <typename T, typename T0, typename T1, typename T2>
14468       struct T0oT1oT2_define
14469       {
14470          typedef details::T0oT1oT2<T, T0, T1, T2, typename T0oT1oT2process<T>::mode0> type0;
14471          typedef details::T0oT1oT2<T, T0, T1, T2, typename T0oT1oT2process<T>::mode1> type1;
14472          typedef details::T0oT1oT2_sf3<T, T0, T1, T2> sf3_type;
14473          typedef details::sf3ext_type_node<T, T0, T1, T2> sf3_type_node;
14474       };
14475
14476       template <typename T, typename T0, typename T1, typename T2, typename T3>
14477       struct T0oT1oT2oT3_define
14478       {
14479          typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode0> type0;
14480          typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode1> type1;
14481          typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode2> type2;
14482          typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode3> type3;
14483          typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode4> type4;
14484          typedef details::T0oT1oT2oT3_sf4<T, T0, T1, T2, T3> sf4_type;
14485       };
14486
14487       template <typename T, typename Operation>
14488       class vov_node : public vov_base_node<T>
14489       {
14490       public:
14491
14492          typedef expression_node<T>* expression_ptr;
14493          typedef Operation operation_t;
14494
14495          // variable op variable node
14496          explicit vov_node(const T& var0, const T& var1)
14497          : v0_(var0),
14498            v1_(var1)
14499          {}
14500
14501          inline T value() const
14502          {
14503             return Operation::process(v0_,v1_);
14504          }
14505
14506          inline typename expression_node<T>::node_type type() const
14507          {
14508             return Operation::type();
14509          }
14510
14511          inline operator_type operation() const
14512          {
14513             return Operation::operation();
14514          }
14515
14516          inline const T& v0() const
14517          {
14518             return v0_;
14519          }
14520
14521          inline const T& v1() const
14522          {
14523             return v1_;
14524          }
14525
14526       protected:
14527
14528          const T& v0_;
14529          const T& v1_;
14530
14531       private:
14532
14533          vov_node(vov_node<T,Operation>&);
14534          vov_node<T,Operation>& operator=(vov_node<T,Operation>&);
14535       };
14536
14537       template <typename T, typename Operation>
14538       class cov_node : public cov_base_node<T>
14539       {
14540       public:
14541
14542          typedef expression_node<T>* expression_ptr;
14543          typedef Operation operation_t;
14544
14545          // constant op variable node
14546          explicit cov_node(const T& const_var, const T& var)
14547          : c_(const_var),
14548            v_(var)
14549          {}
14550
14551          inline T value() const
14552          {
14553             return Operation::process(c_,v_);
14554          }
14555
14556          inline typename expression_node<T>::node_type type() const
14557          {
14558             return Operation::type();
14559          }
14560
14561          inline operator_type operation() const
14562          {
14563             return Operation::operation();
14564          }
14565
14566          inline const T c() const
14567          {
14568             return c_;
14569          }
14570
14571          inline const T& v() const
14572          {
14573             return v_;
14574          }
14575
14576       protected:
14577
14578          const T  c_;
14579          const T& v_;
14580
14581       private:
14582
14583          cov_node(const cov_node<T,Operation>&);
14584          cov_node<T,Operation>& operator=(const cov_node<T,Operation>&);
14585       };
14586
14587       template <typename T, typename Operation>
14588       class voc_node : public voc_base_node<T>
14589       {
14590       public:
14591
14592          typedef expression_node<T>* expression_ptr;
14593          typedef Operation operation_t;
14594
14595          // variable op constant node
14596          explicit voc_node(const T& var, const T& const_var)
14597          : v_(var),
14598            c_(const_var)
14599          {}
14600
14601          inline T value() const
14602          {
14603             return Operation::process(v_,c_);
14604          }
14605
14606          inline operator_type operation() const
14607          {
14608             return Operation::operation();
14609          }
14610
14611          inline const T c() const
14612          {
14613             return c_;
14614          }
14615
14616          inline const T& v() const
14617          {
14618             return v_;
14619          }
14620
14621       protected:
14622
14623          const T& v_;
14624          const T  c_;
14625
14626       private:
14627
14628          voc_node(const voc_node<T,Operation>&);
14629          voc_node<T,Operation>& operator=(const voc_node<T,Operation>&);
14630       };
14631
14632       template <typename T, typename Operation>
14633       class vob_node : public vob_base_node<T>
14634       {
14635       public:
14636
14637          typedef expression_node<T>* expression_ptr;
14638          typedef std::pair<expression_ptr,bool> branch_t;
14639          typedef Operation operation_t;
14640
14641          // variable op constant node
14642          explicit vob_node(const T& var, const expression_ptr brnch)
14643          : v_(var)
14644          {
14645             init_branches<1>(branch_,brnch);
14646          }
14647
14648         ~vob_node()
14649          {
14650             cleanup_branches::execute<T,1>(branch_);
14651          }
14652
14653          inline T value() const
14654          {
14655             return Operation::process(v_,branch_[0].first->value());
14656          }
14657
14658          inline operator_type operation() const
14659          {
14660             return Operation::operation();
14661          }
14662
14663          inline const T& v() const
14664          {
14665             return v_;
14666          }
14667
14668          inline expression_node<T>* branch(const std::size_t&) const
14669          {
14670             return branch_[0].first;
14671          }
14672
14673       private:
14674
14675          vob_node(const vob_node<T,Operation>&);
14676          vob_node<T,Operation>& operator=(const vob_node<T,Operation>&);
14677
14678          const T& v_;
14679          branch_t branch_[1];
14680       };
14681
14682       template <typename T, typename Operation>
14683       class bov_node : public bov_base_node<T>
14684       {
14685       public:
14686
14687          typedef expression_node<T>* expression_ptr;
14688          typedef std::pair<expression_ptr,bool> branch_t;
14689          typedef Operation operation_t;
14690
14691          // variable op constant node
14692          explicit bov_node(const expression_ptr brnch, const T& var)
14693          : v_(var)
14694          {
14695             init_branches<1>(branch_,brnch);
14696          }
14697
14698         ~bov_node()
14699          {
14700             cleanup_branches::execute<T,1>(branch_);
14701          }
14702
14703          inline T value() const
14704          {
14705             return Operation::process(branch_[0].first->value(),v_);
14706          }
14707
14708          inline operator_type operation() const
14709          {
14710             return Operation::operation();
14711          }
14712
14713          inline const T& v() const
14714          {
14715             return v_;
14716          }
14717
14718          inline expression_node<T>* branch(const std::size_t&) const
14719          {
14720             return branch_[0].first;
14721          }
14722
14723       private:
14724
14725          bov_node(const bov_node<T,Operation>&);
14726          bov_node<T,Operation>& operator=(const bov_node<T,Operation>&);
14727
14728          const T& v_;
14729          branch_t branch_[1];
14730       };
14731
14732       template <typename T, typename Operation>
14733       class cob_node : public cob_base_node<T>
14734       {
14735       public:
14736
14737          typedef expression_node<T>* expression_ptr;
14738          typedef std::pair<expression_ptr,bool> branch_t;
14739          typedef Operation operation_t;
14740
14741          // variable op constant node
14742          explicit cob_node(const T const_var, const expression_ptr brnch)
14743          : c_(const_var)
14744          {
14745             init_branches<1>(branch_,brnch);
14746          }
14747
14748         ~cob_node()
14749          {
14750             cleanup_branches::execute<T,1>(branch_);
14751          }
14752
14753          inline T value() const
14754          {
14755             return Operation::process(c_,branch_[0].first->value());
14756          }
14757
14758          inline operator_type operation() const
14759          {
14760             return Operation::operation();
14761          }
14762
14763          inline const T c() const
14764          {
14765             return c_;
14766          }
14767
14768          inline void set_c(const T new_c)
14769          {
14770             (*const_cast<T*>(&c_)) = new_c;
14771          }
14772
14773          inline expression_node<T>* branch(const std::size_t&) const
14774          {
14775             return branch_[0].first;
14776          }
14777
14778          inline expression_node<T>* move_branch(const std::size_t&)
14779          {
14780             branch_[0].second = false;
14781             return branch_[0].first;
14782          }
14783
14784       private:
14785
14786          cob_node(const cob_node<T,Operation>&);
14787          cob_node<T,Operation>& operator=(const cob_node<T,Operation>&);
14788
14789          const T  c_;
14790          branch_t branch_[1];
14791       };
14792
14793       template <typename T, typename Operation>
14794       class boc_node : public boc_base_node<T>
14795       {
14796       public:
14797
14798          typedef expression_node<T>* expression_ptr;
14799          typedef std::pair<expression_ptr,bool> branch_t;
14800          typedef Operation operation_t;
14801
14802          // variable op constant node
14803          explicit boc_node(const expression_ptr brnch, const T const_var)
14804          : c_(const_var)
14805          {
14806             init_branches<1>(branch_,brnch);
14807          }
14808
14809         ~boc_node()
14810          {
14811             cleanup_branches::execute<T,1>(branch_);
14812          }
14813
14814          inline T value() const
14815          {
14816             return Operation::process(branch_[0].first->value(),c_);
14817          }
14818
14819          inline operator_type operation() const
14820          {
14821             return Operation::operation();
14822          }
14823
14824          inline const T c() const
14825          {
14826             return c_;
14827          }
14828
14829          inline void set_c(const T new_c)
14830          {
14831             (*const_cast<T*>(&c_)) = new_c;
14832          }
14833
14834          inline expression_node<T>* branch(const std::size_t&) const
14835          {
14836             return branch_[0].first;
14837          }
14838
14839          inline expression_node<T>* move_branch(const std::size_t&)
14840          {
14841             branch_[0].second = false;
14842             return branch_[0].first;
14843          }
14844
14845       private:
14846
14847          boc_node(const boc_node<T,Operation>&);
14848          boc_node<T,Operation>& operator=(const boc_node<T,Operation>&);
14849
14850          const T  c_;
14851          branch_t branch_[1];
14852       };
14853
14854       #ifndef exprtk_disable_string_capabilities
14855       template <typename T, typename SType0, typename SType1, typename Operation>
14856       class sos_node : public sos_base_node<T>
14857       {
14858       public:
14859
14860          typedef expression_node<T>* expression_ptr;
14861          typedef Operation operation_t;
14862
14863          // string op string node
14864          explicit sos_node(SType0 p0, SType1 p1)
14865          : s0_(p0),
14866            s1_(p1)
14867          {}
14868
14869          inline T value() const
14870          {
14871             return Operation::process(s0_,s1_);
14872          }
14873
14874          inline typename expression_node<T>::node_type type() const
14875          {
14876             return Operation::type();
14877          }
14878
14879          inline operator_type operation() const
14880          {
14881             return Operation::operation();
14882          }
14883
14884          inline std::string& s0()
14885          {
14886             return s0_;
14887          }
14888
14889          inline std::string& s1()
14890          {
14891             return s1_;
14892          }
14893
14894       protected:
14895
14896          SType0 s0_;
14897          SType1 s1_;
14898
14899       private:
14900
14901          sos_node(sos_node<T,SType0,SType1,Operation>&);
14902          sos_node<T,SType0,SType1,Operation>& operator=(sos_node<T,SType0,SType1,Operation>&);
14903       };
14904
14905       template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
14906       class str_xrox_node : public sos_base_node<T>
14907       {
14908       public:
14909
14910          typedef expression_node<T>* expression_ptr;
14911          typedef Operation operation_t;
14912
14913          // string-range op string node
14914          explicit str_xrox_node(SType0 p0, SType1 p1, RangePack rp0)
14915          : s0_ (p0 ),
14916            s1_ (p1 ),
14917            rp0_(rp0)
14918          {}
14919
14920         ~str_xrox_node()
14921          {
14922             rp0_.free();
14923          }
14924
14925          inline T value() const
14926          {
14927             std::size_t r0 = 0;
14928             std::size_t r1 = 0;
14929
14930             if (rp0_(r0, r1, s0_.size()))
14931                return Operation::process(s0_.substr(r0, (r1 - r0) + 1), s1_);
14932             else
14933                return T(0);
14934          }
14935
14936          inline typename expression_node<T>::node_type type() const
14937          {
14938             return Operation::type();
14939          }
14940
14941          inline operator_type operation() const
14942          {
14943             return Operation::operation();
14944          }
14945
14946          inline std::string& s0()
14947          {
14948             return s0_;
14949          }
14950
14951          inline std::string& s1()
14952          {
14953             return s1_;
14954          }
14955
14956       protected:
14957
14958          SType0    s0_;
14959          SType1    s1_;
14960          RangePack rp0_;
14961
14962       private:
14963
14964          str_xrox_node(str_xrox_node<T,SType0,SType1,RangePack,Operation>&);
14965          str_xrox_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xrox_node<T,SType0,SType1,RangePack,Operation>&);
14966       };
14967
14968       template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
14969       class str_xoxr_node : public sos_base_node<T>
14970       {
14971       public:
14972
14973          typedef expression_node<T>* expression_ptr;
14974          typedef Operation operation_t;
14975
14976          // string op string range node
14977          explicit str_xoxr_node(SType0 p0, SType1 p1, RangePack rp1)
14978          : s0_ (p0 ),
14979            s1_ (p1 ),
14980            rp1_(rp1)
14981          {}
14982
14983         ~str_xoxr_node()
14984          {
14985             rp1_.free();
14986          }
14987
14988          inline T value() const
14989          {
14990             std::size_t r0 = 0;
14991             std::size_t r1 = 0;
14992
14993             if (rp1_(r0, r1, s1_.size()))
14994                return Operation::process(s0_, s1_.substr(r0, (r1 - r0) + 1));
14995             else
14996                return T(0);
14997          }
14998
14999          inline typename expression_node<T>::node_type type() const
15000          {
15001             return Operation::type();
15002          }
15003
15004          inline operator_type operation() const
15005          {
15006             return Operation::operation();
15007          }
15008
15009          inline std::string& s0()
15010          {
15011             return s0_;
15012          }
15013
15014          inline std::string& s1()
15015          {
15016             return s1_;
15017          }
15018
15019       protected:
15020
15021          SType0    s0_;
15022          SType1    s1_;
15023          RangePack rp1_;
15024
15025       private:
15026
15027          str_xoxr_node(str_xoxr_node<T,SType0,SType1,RangePack,Operation>&);
15028          str_xoxr_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xoxr_node<T,SType0,SType1,RangePack,Operation>&);
15029       };
15030
15031       template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
15032       class str_xroxr_node : public sos_base_node<T>
15033       {
15034       public:
15035
15036          typedef expression_node<T>* expression_ptr;
15037          typedef Operation operation_t;
15038
15039          // string-range op string-range node
15040          explicit str_xroxr_node(SType0 p0, SType1 p1, RangePack rp0, RangePack rp1)
15041          : s0_ (p0 ),
15042            s1_ (p1 ),
15043            rp0_(rp0),
15044            rp1_(rp1)
15045          {}
15046
15047         ~str_xroxr_node()
15048          {
15049             rp0_.free();
15050             rp1_.free();
15051          }
15052
15053          inline T value() const
15054          {
15055             std::size_t r0_0 = 0;
15056             std::size_t r0_1 = 0;
15057             std::size_t r1_0 = 0;
15058             std::size_t r1_1 = 0;
15059
15060             if (
15061                  rp0_(r0_0, r1_0, s0_.size()) &&
15062                  rp1_(r0_1, r1_1, s1_.size())
15063                )
15064             {
15065                return Operation::process(
15066                                           s0_.substr(r0_0, (r1_0 - r0_0) + 1),
15067                                           s1_.substr(r0_1, (r1_1 - r0_1) + 1)
15068                                         );
15069             }
15070             else
15071                return T(0);
15072          }
15073
15074          inline typename expression_node<T>::node_type type() const
15075          {
15076             return Operation::type();
15077          }
15078
15079          inline operator_type operation() const
15080          {
15081             return Operation::operation();
15082          }
15083
15084          inline std::string& s0()
15085          {
15086             return s0_;
15087          }
15088
15089          inline std::string& s1()
15090          {
15091             return s1_;
15092          }
15093
15094       protected:
15095
15096          SType0    s0_;
15097          SType1    s1_;
15098          RangePack rp0_;
15099          RangePack rp1_;
15100
15101       private:
15102
15103          str_xroxr_node(str_xroxr_node<T,SType0,SType1,RangePack,Operation>&);
15104          str_xroxr_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xroxr_node<T,SType0,SType1,RangePack,Operation>&);
15105       };
15106
15107       template <typename T, typename Operation>
15108       class str_sogens_node : public binary_node<T>
15109       {
15110       public:
15111
15112          typedef expression_node <T>* expression_ptr;
15113          typedef string_base_node<T>*   str_base_ptr;
15114          typedef range_pack      <T>         range_t;
15115          typedef range_t*                  range_ptr;
15116          typedef range_interface<T>         irange_t;
15117          typedef irange_t*                irange_ptr;
15118
15119          str_sogens_node(const operator_type& opr,
15120                          expression_ptr branch0,
15121                          expression_ptr branch1)
15122          : binary_node<T>(opr, branch0, branch1),
15123            str0_base_ptr_ (0),
15124            str1_base_ptr_ (0),
15125            str0_range_ptr_(0),
15126            str1_range_ptr_(0)
15127          {
15128             if (is_generally_string_node(binary_node<T>::branch_[0].first))
15129             {
15130                str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
15131
15132                if (0 == str0_base_ptr_)
15133                   return;
15134
15135                irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
15136
15137                if (0 == range)
15138                   return;
15139
15140                str0_range_ptr_ = &(range->range_ref());
15141             }
15142
15143             if (is_generally_string_node(binary_node<T>::branch_[1].first))
15144             {
15145                str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
15146
15147                if (0 == str1_base_ptr_)
15148                   return;
15149
15150                irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
15151
15152                if (0 == range)
15153                   return;
15154
15155                str1_range_ptr_ = &(range->range_ref());
15156             }
15157          }
15158
15159          inline T value() const
15160          {
15161             if (
15162                  str0_base_ptr_  &&
15163                  str1_base_ptr_  &&
15164                  str0_range_ptr_ &&
15165                  str1_range_ptr_
15166                )
15167             {
15168                binary_node<T>::branch_[0].first->value();
15169                binary_node<T>::branch_[1].first->value();
15170
15171                std::size_t str0_r0 = 0;
15172                std::size_t str0_r1 = 0;
15173
15174                std::size_t str1_r0 = 0;
15175                std::size_t str1_r1 = 0;
15176
15177                range_t& range0 = (*str0_range_ptr_);
15178                range_t& range1 = (*str1_range_ptr_);
15179
15180                if (
15181                     range0(str0_r0, str0_r1, str0_base_ptr_->size()) &&
15182                     range1(str1_r0, str1_r1, str1_base_ptr_->size())
15183                   )
15184                {
15185                   return Operation::process(
15186                                              str0_base_ptr_->str().substr(str0_r0,(str0_r1 - str0_r0) + 1),
15187                                              str1_base_ptr_->str().substr(str1_r0,(str1_r1 - str1_r0) + 1)
15188                                            );
15189                }
15190             }
15191
15192             return std::numeric_limits<T>::quiet_NaN();
15193          }
15194
15195          inline typename expression_node<T>::node_type type() const
15196          {
15197             return Operation::type();
15198          }
15199
15200          inline operator_type operation() const
15201          {
15202             return Operation::operation();
15203          }
15204
15205       private:
15206
15207          str_sogens_node(str_sogens_node<T,Operation>&);
15208          str_sogens_node<T,Operation>& operator=(str_sogens_node<T,Operation>&);
15209
15210          str_base_ptr str0_base_ptr_;
15211          str_base_ptr str1_base_ptr_;
15212          range_ptr    str0_range_ptr_;
15213          range_ptr    str1_range_ptr_;
15214       };
15215
15216       template <typename T, typename SType0, typename SType1, typename SType2, typename Operation>
15217       class sosos_node : public sosos_base_node<T>
15218       {
15219       public:
15220
15221          typedef expression_node<T>* expression_ptr;
15222          typedef Operation operation_t;
15223
15224          // variable op variable node
15225          explicit sosos_node(SType0 p0, SType1 p1, SType2 p2)
15226          : s0_(p0),
15227            s1_(p1),
15228            s2_(p2)
15229          {}
15230
15231          inline T value() const
15232          {
15233             return Operation::process(s0_,s1_,s2_);
15234          }
15235
15236          inline typename expression_node<T>::node_type type() const
15237          {
15238             return Operation::type();
15239          }
15240
15241          inline operator_type operation() const
15242          {
15243             return Operation::operation();
15244          }
15245
15246          inline std::string& s0()
15247          {
15248             return s0_;
15249          }
15250
15251          inline std::string& s1()
15252          {
15253             return s1_;
15254          }
15255
15256          inline std::string& s2()
15257          {
15258             return s2_;
15259          }
15260
15261       protected:
15262
15263          SType0 s0_;
15264          SType1 s1_;
15265          SType2 s2_;
15266
15267       private:
15268
15269          sosos_node(sosos_node<T,SType0,SType1,SType2,Operation>&);
15270          sosos_node<T,SType0,SType1,SType2,Operation>& operator=(sosos_node<T,SType0,SType1,SType2,Operation>&);
15271       };
15272       #endif
15273
15274       template <typename T, typename PowOp>
15275       class ipow_node : public expression_node<T>
15276       {
15277       public:
15278
15279          typedef expression_node<T>* expression_ptr;
15280          typedef PowOp operation_t;
15281
15282          explicit ipow_node(const T& v)
15283          : v_(v)
15284          {}
15285
15286          inline T value() const
15287          {
15288             return PowOp::result(v_);
15289          }
15290
15291          inline typename expression_node<T>::node_type type() const
15292          {
15293             return expression_node<T>::e_ipow;
15294          }
15295
15296       private:
15297
15298          ipow_node(const ipow_node<T,PowOp>&);
15299          ipow_node<T,PowOp>& operator=(const ipow_node<T,PowOp>&);
15300
15301          const T& v_;
15302       };
15303
15304       template <typename T, typename PowOp>
15305       class bipow_node : public expression_node<T>
15306       {
15307       public:
15308
15309          typedef expression_node<T>* expression_ptr;
15310          typedef std::pair<expression_ptr, bool> branch_t;
15311          typedef PowOp operation_t;
15312
15313          explicit bipow_node(expression_ptr brnch)
15314          {
15315             init_branches<1>(branch_, brnch);
15316          }
15317
15318         ~bipow_node()
15319          {
15320             cleanup_branches::execute<T,1>(branch_);
15321          }
15322
15323          inline T value() const
15324          {
15325             return PowOp::result(branch_[0].first->value());
15326          }
15327
15328          inline typename expression_node<T>::node_type type() const
15329          {
15330             return expression_node<T>::e_ipow;
15331          }
15332
15333       private:
15334
15335          bipow_node(const bipow_node<T,PowOp>&);
15336          bipow_node<T,PowOp>& operator=(const bipow_node<T,PowOp>&);
15337
15338          branch_t branch_[1];
15339       };
15340
15341       template <typename T, typename PowOp>
15342       class ipowinv_node : public expression_node<T>
15343       {
15344       public:
15345
15346          typedef expression_node<T>* expression_ptr;
15347          typedef PowOp operation_t;
15348
15349          explicit ipowinv_node(const T& v)
15350          : v_(v)
15351          {}
15352
15353          inline T value() const
15354          {
15355             return (T(1) / PowOp::result(v_));
15356          }
15357
15358          inline typename expression_node<T>::node_type type() const
15359          {
15360             return expression_node<T>::e_ipowinv;
15361          }
15362
15363       private:
15364
15365          ipowinv_node(const ipowinv_node<T,PowOp>&);
15366          ipowinv_node<T,PowOp>& operator=(const ipowinv_node<T,PowOp>&);
15367
15368          const T& v_;
15369       };
15370
15371       template <typename T, typename PowOp>
15372       class bipowninv_node : public expression_node<T>
15373       {
15374       public:
15375
15376          typedef expression_node<T>* expression_ptr;
15377          typedef std::pair<expression_ptr, bool> branch_t;
15378          typedef PowOp operation_t;
15379
15380          explicit bipowninv_node(expression_ptr brnch)
15381          {
15382             init_branches<1>(branch_, brnch);
15383          }
15384
15385         ~bipowninv_node()
15386          {
15387             cleanup_branches::execute<T,1>(branch_);
15388          }
15389
15390          inline T value() const
15391          {
15392             return (T(1) / PowOp::result(branch_[0].first->value()));
15393          }
15394
15395          inline typename expression_node<T>::node_type type() const
15396          {
15397             return expression_node<T>::e_ipowinv;
15398          }
15399
15400       private:
15401
15402          bipowninv_node(const bipowninv_node<T,PowOp>&);
15403          bipowninv_node<T,PowOp>& operator=(const bipowninv_node<T,PowOp>&);
15404
15405          branch_t branch_[1];
15406       };
15407
15408       template <typename T>
15409       inline bool is_vov_node(const expression_node<T>* node)
15410       {
15411          return (0 != dynamic_cast<const vov_base_node<T>*>(node));
15412       }
15413
15414       template <typename T>
15415       inline bool is_cov_node(const expression_node<T>* node)
15416       {
15417          return (0 != dynamic_cast<const cov_base_node<T>*>(node));
15418       }
15419
15420       template <typename T>
15421       inline bool is_voc_node(const expression_node<T>* node)
15422       {
15423          return (0 != dynamic_cast<const voc_base_node<T>*>(node));
15424       }
15425
15426       template <typename T>
15427       inline bool is_cob_node(const expression_node<T>* node)
15428       {
15429          return (0 != dynamic_cast<const cob_base_node<T>*>(node));
15430       }
15431
15432       template <typename T>
15433       inline bool is_boc_node(const expression_node<T>* node)
15434       {
15435          return (0 != dynamic_cast<const boc_base_node<T>*>(node));
15436       }
15437
15438       template <typename T>
15439       inline bool is_t0ot1ot2_node(const expression_node<T>* node)
15440       {
15441          return (0 != dynamic_cast<const T0oT1oT2_base_node<T>*>(node));
15442       }
15443
15444       template <typename T>
15445       inline bool is_t0ot1ot2ot3_node(const expression_node<T>* node)
15446       {
15447          return (0 != dynamic_cast<const T0oT1oT2oT3_base_node<T>*>(node));
15448       }
15449
15450       template <typename T>
15451       inline bool is_uv_node(const expression_node<T>* node)
15452       {
15453          return (0 != dynamic_cast<const uv_base_node<T>*>(node));
15454       }
15455
15456       template <typename T>
15457       inline bool is_string_node(const expression_node<T>* node)
15458       {
15459          return node && (expression_node<T>::e_stringvar == node->type());
15460       }
15461
15462       template <typename T>
15463       inline bool is_string_range_node(const expression_node<T>* node)
15464       {
15465          return node && (expression_node<T>::e_stringvarrng == node->type());
15466       }
15467
15468       template <typename T>
15469       inline bool is_const_string_node(const expression_node<T>* node)
15470       {
15471          return node && (expression_node<T>::e_stringconst == node->type());
15472       }
15473
15474       template <typename T>
15475       inline bool is_const_string_range_node(const expression_node<T>* node)
15476       {
15477          return node && (expression_node<T>::e_cstringvarrng == node->type());
15478       }
15479
15480       template <typename T>
15481       inline bool is_string_assignment_node(const expression_node<T>* node)
15482       {
15483          return node && (expression_node<T>::e_strass == node->type());
15484       }
15485
15486       template <typename T>
15487       inline bool is_string_concat_node(const expression_node<T>* node)
15488       {
15489          return node && (expression_node<T>::e_strconcat == node->type());
15490       }
15491
15492       template <typename T>
15493       inline bool is_string_function_node(const expression_node<T>* node)
15494       {
15495          return node && (expression_node<T>::e_strfunction == node->type());
15496       }
15497
15498       template <typename T>
15499       inline bool is_string_condition_node(const expression_node<T>* node)
15500       {
15501          return node && (expression_node<T>::e_strcondition == node->type());
15502       }
15503
15504       template <typename T>
15505       inline bool is_string_ccondition_node(const expression_node<T>* node)
15506       {
15507          return node && (expression_node<T>::e_strccondition == node->type());
15508       }
15509
15510       template <typename T>
15511       inline bool is_string_vararg_node(const expression_node<T>* node)
15512       {
15513          return node && (expression_node<T>::e_stringvararg == node->type());
15514       }
15515
15516       template <typename T>
15517       inline bool is_genricstring_range_node(const expression_node<T>* node)
15518       {
15519          return node && (expression_node<T>::e_strgenrange == node->type());
15520       }
15521
15522       template <typename T>
15523       inline bool is_generally_string_node(const expression_node<T>* node)
15524       {
15525          if (node)
15526          {
15527             switch (node->type())
15528             {
15529                case expression_node<T>::e_stringvar     :
15530                case expression_node<T>::e_stringconst   :
15531                case expression_node<T>::e_stringvarrng  :
15532                case expression_node<T>::e_cstringvarrng :
15533                case expression_node<T>::e_strgenrange   :
15534                case expression_node<T>::e_strass        :
15535                case expression_node<T>::e_strconcat     :
15536                case expression_node<T>::e_strfunction   :
15537                case expression_node<T>::e_strcondition  :
15538                case expression_node<T>::e_strccondition :
15539                case expression_node<T>::e_stringvararg  : return true;
15540                default                                  : return false;
15541             }
15542          }
15543
15544          return false;
15545       }
15546
15547       class node_allocator
15548       {
15549       public:
15550
15551          template <typename ResultNode, typename OpType, typename ExprNode>
15552          inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[1])
15553          {
15554             return allocate<ResultNode>(operation, branch[0]);
15555          }
15556
15557          template <typename ResultNode, typename OpType, typename ExprNode>
15558          inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[2])
15559          {
15560             return allocate<ResultNode>(operation, branch[0], branch[1]);
15561          }
15562
15563          template <typename ResultNode, typename OpType, typename ExprNode>
15564          inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[3])
15565          {
15566             return allocate<ResultNode>(operation, branch[0], branch[1], branch[2]);
15567          }
15568
15569          template <typename ResultNode, typename OpType, typename ExprNode>
15570          inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[4])
15571          {
15572             return allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3]);
15573          }
15574
15575          template <typename ResultNode, typename OpType, typename ExprNode>
15576          inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[5])
15577          {
15578             return allocate<ResultNode>(operation, branch[0],branch[1], branch[2], branch[3], branch[4]);
15579          }
15580
15581          template <typename ResultNode, typename OpType, typename ExprNode>
15582          inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[6])
15583          {
15584             return allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3], branch[4], branch[5]);
15585          }
15586
15587          template <typename node_type>
15588          inline expression_node<typename node_type::value_type>* allocate() const
15589          {
15590             return (new node_type());
15591          }
15592
15593          template <typename node_type,
15594                    typename Type,
15595                    typename Allocator,
15596                    template <typename, typename> class Sequence>
15597          inline expression_node<typename node_type::value_type>* allocate(const Sequence<Type,Allocator>& seq) const
15598          {
15599             return (new node_type(seq));
15600          }
15601
15602          template <typename node_type, typename T1>
15603          inline expression_node<typename node_type::value_type>* allocate(T1& t1) const
15604          {
15605             return (new node_type(t1));
15606          }
15607
15608          template <typename node_type, typename T1>
15609          inline expression_node<typename node_type::value_type>* allocate_c(const T1& t1) const
15610          {
15611             return (new node_type(t1));
15612          }
15613
15614          template <typename node_type,
15615                    typename T1, typename T2>
15616          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2) const
15617          {
15618             return (new node_type(t1, t2));
15619          }
15620
15621          template <typename node_type,
15622                    typename T1, typename T2>
15623          inline expression_node<typename node_type::value_type>* allocate_cr(const T1& t1, T2& t2) const
15624          {
15625             return (new node_type(t1, t2));
15626          }
15627
15628          template <typename node_type,
15629                    typename T1, typename T2>
15630          inline expression_node<typename node_type::value_type>* allocate_rc(T1& t1, const T2& t2) const
15631          {
15632             return (new node_type(t1, t2));
15633          }
15634
15635          template <typename node_type,
15636                    typename T1, typename T2>
15637          inline expression_node<typename node_type::value_type>* allocate_rr(T1& t1, T2& t2) const
15638          {
15639             return (new node_type(t1, t2));
15640          }
15641
15642          template <typename node_type,
15643                    typename T1, typename T2>
15644          inline expression_node<typename node_type::value_type>* allocate_tt(T1 t1, T2 t2) const
15645          {
15646             return (new node_type(t1, t2));
15647          }
15648
15649          template <typename node_type,
15650                    typename T1, typename T2, typename T3>
15651          inline expression_node<typename node_type::value_type>* allocate_ttt(T1 t1, T2 t2, T3 t3) const
15652          {
15653             return (new node_type(t1, t2, t3));
15654          }
15655
15656          template <typename node_type,
15657                    typename T1, typename T2, typename T3, typename T4>
15658          inline expression_node<typename node_type::value_type>* allocate_tttt(T1 t1, T2 t2, T3 t3, T4 t4) const
15659          {
15660             return (new node_type(t1, t2, t3, t4));
15661          }
15662
15663          template <typename node_type,
15664                    typename T1, typename T2, typename T3>
15665          inline expression_node<typename node_type::value_type>* allocate_rrr(T1& t1, T2& t2, T3& t3) const
15666          {
15667             return (new node_type(t1, t2, t3));
15668          }
15669
15670          template <typename node_type,
15671                    typename T1, typename T2, typename T3, typename T4>
15672          inline expression_node<typename node_type::value_type>* allocate_rrrr(T1& t1, T2& t2, T3& t3, T4& t4) const
15673          {
15674             return (new node_type(t1, t2, t3, t4));
15675          }
15676
15677          template <typename node_type,
15678                    typename T1, typename T2, typename T3, typename T4, typename T5>
15679          inline expression_node<typename node_type::value_type>* allocate_rrrrr(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5) const
15680          {
15681             return (new node_type(t1, t2, t3, t4, t5));
15682          }
15683
15684          template <typename node_type,
15685                    typename T1, typename T2, typename T3>
15686          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
15687                                                                           const T3& t3) const
15688          {
15689             return (new node_type(t1, t2, t3));
15690          }
15691
15692          template <typename node_type,
15693                    typename T1, typename T2,
15694                    typename T3, typename T4>
15695          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
15696                                                                           const T3& t3, const T4& t4) const
15697          {
15698             return (new node_type(t1, t2, t3, t4));
15699          }
15700
15701          template <typename node_type,
15702                    typename T1, typename T2,
15703                    typename T3, typename T4, typename T5>
15704          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
15705                                                                           const T3& t3, const T4& t4,
15706                                                                           const T5& t5) const
15707          {
15708             return (new node_type(t1, t2, t3, t4, t5));
15709          }
15710
15711          template <typename node_type,
15712                    typename T1, typename T2,
15713                    typename T3, typename T4, typename T5, typename T6>
15714          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
15715                                                                           const T3& t3, const T4& t4,
15716                                                                           const T5& t5, const T6& t6) const
15717          {
15718             return (new node_type(t1, t2, t3, t4, t5, t6));
15719          }
15720
15721          template <typename node_type,
15722                    typename T1, typename T2,
15723                    typename T3, typename T4,
15724                    typename T5, typename T6, typename T7>
15725          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
15726                                                                           const T3& t3, const T4& t4,
15727                                                                           const T5& t5, const T6& t6,
15728                                                                           const T7& t7) const
15729          {
15730             return (new node_type(t1, t2, t3, t4, t5, t6, t7));
15731          }
15732
15733          template <typename node_type,
15734                    typename T1, typename T2,
15735                    typename T3, typename T4,
15736                    typename T5, typename T6,
15737                    typename T7, typename T8>
15738          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
15739                                                                           const T3& t3, const T4& t4,
15740                                                                           const T5& t5, const T6& t6,
15741                                                                           const T7& t7, const T8& t8) const
15742          {
15743             return (new node_type(t1, t2, t3, t4, t5, t6, t7, t8));
15744          }
15745
15746          template <typename node_type,
15747                    typename T1, typename T2,
15748                    typename T3, typename T4,
15749                    typename T5, typename T6,
15750                    typename T7, typename T8, typename T9>
15751          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
15752                                                                           const T3& t3, const T4& t4,
15753                                                                           const T5& t5, const T6& t6,
15754                                                                           const T7& t7, const T8& t8,
15755                                                                           const T9& t9) const
15756          {
15757             return (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9));
15758          }
15759
15760          template <typename node_type,
15761                    typename T1, typename T2,
15762                    typename T3, typename T4,
15763                    typename T5, typename T6,
15764                    typename T7, typename T8,
15765                    typename T9, typename T10>
15766          inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const  T2&  t2,
15767                                                                           const T3& t3, const  T4&  t4,
15768                                                                           const T5& t5, const  T6&  t6,
15769                                                                           const T7& t7, const  T8&  t8,
15770                                                                           const T9& t9, const T10& t10) const
15771          {
15772             return (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10));
15773          }
15774
15775          template <typename node_type,
15776                    typename T1, typename T2, typename T3>
15777          inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, T3 t3) const
15778          {
15779             return (new node_type(t1, t2, t3));
15780          }
15781
15782          template <typename node_type,
15783                    typename T1, typename T2,
15784                    typename T3, typename T4>
15785          inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
15786                                                                                T3 t3, T4 t4) const
15787          {
15788             return (new node_type(t1, t2, t3, t4));
15789          }
15790
15791          template <typename node_type,
15792                    typename T1, typename T2,
15793                    typename T3, typename T4,
15794                    typename T5>
15795          inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
15796                                                                                T3 t3, T4 t4,
15797                                                                                T5 t5) const
15798          {
15799             return (new node_type(t1, t2, t3, t4, t5));
15800          }
15801
15802          template <typename node_type,
15803                    typename T1, typename T2,
15804                    typename T3, typename T4,
15805                    typename T5, typename T6>
15806          inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
15807                                                                                T3 t3, T4 t4,
15808                                                                                T5 t5, T6 t6) const
15809          {
15810             return (new node_type(t1, t2, t3, t4, t5, t6));
15811          }
15812
15813          template <typename node_type,
15814                    typename T1, typename T2,
15815                    typename T3, typename T4,
15816                    typename T5, typename T6, typename T7>
15817          inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
15818                                                                                T3 t3, T4 t4,
15819                                                                                T5 t5, T6 t6,
15820                                                                                T7 t7) const
15821          {
15822             return (new node_type(t1, t2, t3, t4, t5, t6, t7));
15823          }
15824
15825          template <typename T>
15826          void inline free(expression_node<T>*& e) const
15827          {
15828             delete e;
15829             e = 0;
15830          }
15831       };
15832
15833       inline void load_operations_map(std::multimap<std::string,details::base_operation_t,details::ilesscompare>& m)
15834       {
15835          #define register_op(Symbol,Type,Args)                                               \
15836          m.insert(std::make_pair(std::string(Symbol),details::base_operation_t(Type,Args))); \
15837
15838          register_op(      "abs", e_abs     , 1)
15839          register_op(     "acos", e_acos    , 1)
15840          register_op(    "acosh", e_acosh   , 1)
15841          register_op(     "asin", e_asin    , 1)
15842          register_op(    "asinh", e_asinh   , 1)
15843          register_op(     "atan", e_atan    , 1)
15844          register_op(    "atanh", e_atanh   , 1)
15845          register_op(     "ceil", e_ceil    , 1)
15846          register_op(      "cos", e_cos     , 1)
15847          register_op(     "cosh", e_cosh    , 1)
15848          register_op(      "exp", e_exp     , 1)
15849          register_op(    "expm1", e_expm1   , 1)
15850          register_op(    "floor", e_floor   , 1)
15851          register_op(      "log", e_log     , 1)
15852          register_op(    "log10", e_log10   , 1)
15853          register_op(     "log2", e_log2    , 1)
15854          register_op(    "log1p", e_log1p   , 1)
15855          register_op(    "round", e_round   , 1)
15856          register_op(      "sin", e_sin     , 1)
15857          register_op(     "sinc", e_sinc    , 1)
15858          register_op(     "sinh", e_sinh    , 1)
15859          register_op(      "sec", e_sec     , 1)
15860          register_op(      "csc", e_csc     , 1)
15861          register_op(     "sqrt", e_sqrt    , 1)
15862          register_op(      "tan", e_tan     , 1)
15863          register_op(     "tanh", e_tanh    , 1)
15864          register_op(      "cot", e_cot     , 1)
15865          register_op(  "rad2deg", e_r2d     , 1)
15866          register_op(  "deg2rad", e_d2r     , 1)
15867          register_op( "deg2grad", e_d2g     , 1)
15868          register_op( "grad2deg", e_g2d     , 1)
15869          register_op(      "sgn", e_sgn     , 1)
15870          register_op(      "not", e_notl    , 1)
15871          register_op(      "erf", e_erf     , 1)
15872          register_op(     "erfc", e_erfc    , 1)
15873          register_op(     "ncdf", e_ncdf    , 1)
15874          register_op(     "frac", e_frac    , 1)
15875          register_op(    "trunc", e_trunc   , 1)
15876          register_op(    "atan2", e_atan2   , 2)
15877          register_op(      "mod", e_mod     , 2)
15878          register_op(     "logn", e_logn    , 2)
15879          register_op(      "pow", e_pow     , 2)
15880          register_op(     "root", e_root    , 2)
15881          register_op(   "roundn", e_roundn  , 2)
15882          register_op(    "equal", e_equal   , 2)
15883          register_op("not_equal", e_nequal  , 2)
15884          register_op(    "hypot", e_hypot   , 2)
15885          register_op(      "shr", e_shr     , 2)
15886          register_op(      "shl", e_shl     , 2)
15887          register_op(    "clamp", e_clamp   , 3)
15888          register_op(   "iclamp", e_iclamp  , 3)
15889          register_op(  "inrange", e_inrange , 3)
15890          #undef register_op
15891       }
15892
15893    } // namespace details
15894
15895    class function_traits
15896    {
15897    public:
15898
15899       function_traits()
15900       : allow_zero_parameters_(false),
15901         has_side_effects_(true),
15902         min_num_args_(0),
15903         max_num_args_(std::numeric_limits<std::size_t>::max())
15904       {}
15905
15906       inline bool& allow_zero_parameters()
15907       {
15908          return allow_zero_parameters_;
15909       }
15910
15911       inline bool& has_side_effects()
15912       {
15913          return has_side_effects_;
15914       }
15915
15916       std::size_t& min_num_args()
15917       {
15918          return min_num_args_;
15919       }
15920
15921       std::size_t& max_num_args()
15922       {
15923          return max_num_args_;
15924       }
15925
15926    private:
15927
15928       bool allow_zero_parameters_;
15929       bool has_side_effects_;
15930       std::size_t min_num_args_;
15931       std::size_t max_num_args_;
15932    };
15933
15934    template <typename FunctionType>
15935    void enable_zero_parameters(FunctionType& func)
15936    {
15937       func.allow_zero_parameters() = true;
15938
15939       if (0 != func.min_num_args())
15940       {
15941          func.min_num_args() = 0;
15942       }
15943    }
15944
15945    template <typename FunctionType>
15946    void disable_zero_parameters(FunctionType& func)
15947    {
15948       func.allow_zero_parameters() = false;
15949    }
15950
15951    template <typename FunctionType>
15952    void enable_has_side_effects(FunctionType& func)
15953    {
15954       func.has_side_effects() = true;
15955    }
15956
15957    template <typename FunctionType>
15958    void disable_has_side_effects(FunctionType& func)
15959    {
15960       func.has_side_effects() = false;
15961    }
15962
15963    template <typename FunctionType>
15964    void set_min_num_args(FunctionType& func, const std::size_t& num_args)
15965    {
15966       func.min_num_args() = num_args;
15967
15968       if ((0 != func.min_num_args()) && func.allow_zero_parameters())
15969          func.allow_zero_parameters() = false;
15970    }
15971
15972    template <typename FunctionType>
15973    void set_max_num_args(FunctionType& func, const std::size_t& num_args)
15974    {
15975       func.max_num_args() = num_args;
15976    }
15977
15978    template <typename T>
15979    class ifunction : public function_traits
15980    {
15981    public:
15982
15983       explicit ifunction(const std::size_t& pc)
15984       : param_count(pc)
15985       {}
15986
15987       virtual ~ifunction()
15988       {}
15989
15990       #define empty_method_body                      \
15991       {                                              \
15992          return std::numeric_limits<T>::quiet_NaN(); \
15993       }                                              \
15994
15995       inline virtual T operator() ()
15996       empty_method_body
15997
15998        inline virtual T operator() (const T&)
15999       empty_method_body
16000
16001        inline virtual T operator() (const T&,const T&)
16002       empty_method_body
16003
16004        inline virtual T operator() (const T&, const T&, const T&)
16005       empty_method_body
16006
16007       inline virtual T operator() (const T&, const T&, const T&, const T&)
16008       empty_method_body
16009
16010       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&)
16011       empty_method_body
16012
16013       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&)
16014       empty_method_body
16015
16016       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16017       empty_method_body
16018
16019       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16020       empty_method_body
16021
16022       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16023       empty_method_body
16024
16025       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16026       empty_method_body
16027
16028       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16029                                   const T&)
16030       empty_method_body
16031
16032       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16033                                    const T&, const T&)
16034       empty_method_body
16035
16036       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16037                                    const T&, const T&, const T&)
16038       empty_method_body
16039
16040       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16041                                    const T&, const T&, const T&, const T&)
16042       empty_method_body
16043
16044       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16045                                    const T&, const T&, const T&, const T&, const T&)
16046       empty_method_body
16047
16048       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16049                                    const T&, const T&, const T&, const T&, const T&, const T&)
16050       empty_method_body
16051
16052       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16053                                    const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16054       empty_method_body
16055
16056       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16057                                    const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16058       empty_method_body
16059
16060       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16061                                    const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16062       empty_method_body
16063
16064       inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16065                                    const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16066       empty_method_body
16067
16068       #undef empty_method_body
16069
16070       std::size_t param_count;
16071    };
16072
16073    template <typename T>
16074    class ivararg_function : public function_traits
16075    {
16076    public:
16077
16078       virtual ~ivararg_function()
16079       {}
16080
16081       inline virtual T operator() (const std::vector<T>&)
16082       {
16083          exprtk_debug(("ivararg_function::operator() - Operator has not been overridden.\n"));
16084          return std::numeric_limits<T>::quiet_NaN();
16085       }
16086    };
16087
16088    template <typename T>
16089    class igeneric_function : public function_traits
16090    {
16091    public:
16092
16093       enum return_type
16094       {
16095          e_rtrn_scalar   = 0,
16096          e_rtrn_string   = 1,
16097          e_rtrn_overload = 2
16098       };
16099
16100       typedef T type;
16101       typedef type_store<T> generic_type;
16102       typedef typename generic_type::parameter_list parameter_list_t;
16103
16104       igeneric_function(const std::string& param_seq = "", const return_type rtr_type = e_rtrn_scalar)
16105       : parameter_sequence(param_seq),
16106         rtrn_type(rtr_type)
16107       {}
16108
16109       virtual ~igeneric_function()
16110       {}
16111
16112       #define igeneric_function_empty_body(N)        \
16113       {                                              \
16114          exprtk_debug(("igeneric_function::operator() - Operator has not been overridden. ["#N"]\n")); \
16115          return std::numeric_limits<T>::quiet_NaN(); \
16116       }                                              \
16117
16118       // f(i_0,i_1,....,i_N) --> Scalar
16119       inline virtual T operator() (parameter_list_t)
16120       igeneric_function_empty_body(1)
16121
16122       // f(i_0,i_1,....,i_N) --> String
16123       inline virtual T operator() (std::string&, parameter_list_t)
16124       igeneric_function_empty_body(2)
16125
16126       // f(psi,i_0,i_1,....,i_N) --> Scalar
16127       inline virtual T operator() (const std::size_t&, parameter_list_t)
16128       igeneric_function_empty_body(3)
16129
16130       // f(psi,i_0,i_1,....,i_N) --> String
16131       inline virtual T operator() (const std::size_t&, std::string&, parameter_list_t)
16132       igeneric_function_empty_body(4)
16133
16134       std::string parameter_sequence;
16135       return_type rtrn_type;
16136    };
16137
16138    template <typename T> class parser;
16139    template <typename T> class expression_helper;
16140
16141    template <typename T>
16142    class symbol_table
16143    {
16144    public:
16145
16146       typedef T (*ff00_functor)();
16147       typedef T (*ff01_functor)(T);
16148       typedef T (*ff02_functor)(T, T);
16149       typedef T (*ff03_functor)(T, T, T);
16150       typedef T (*ff04_functor)(T, T, T, T);
16151       typedef T (*ff05_functor)(T, T, T, T, T);
16152       typedef T (*ff06_functor)(T, T, T, T, T, T);
16153       typedef T (*ff07_functor)(T, T, T, T, T, T, T);
16154       typedef T (*ff08_functor)(T, T, T, T, T, T, T, T);
16155       typedef T (*ff09_functor)(T, T, T, T, T, T, T, T, T);
16156       typedef T (*ff10_functor)(T, T, T, T, T, T, T, T, T, T);
16157       typedef T (*ff11_functor)(T, T, T, T, T, T, T, T, T, T, T);
16158       typedef T (*ff12_functor)(T, T, T, T, T, T, T, T, T, T, T, T);
16159       typedef T (*ff13_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T);
16160       typedef T (*ff14_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T);
16161       typedef T (*ff15_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T);
16162
16163    protected:
16164
16165        struct freefunc00 : public exprtk::ifunction<T>
16166        {
16167           using exprtk::ifunction<T>::operator();
16168
16169           explicit freefunc00(ff00_functor ff) : exprtk::ifunction<T>(0), f(ff) {}
16170           inline T operator() ()
16171           { return f(); }
16172           ff00_functor f;
16173        };
16174
16175       struct freefunc01 : public exprtk::ifunction<T>
16176       {
16177          using exprtk::ifunction<T>::operator();
16178
16179          explicit freefunc01(ff01_functor ff) : exprtk::ifunction<T>(1), f(ff) {}
16180          inline T operator() (const T& v0)
16181          { return f(v0); }
16182          ff01_functor f;
16183       };
16184
16185       struct freefunc02 : public exprtk::ifunction<T>
16186       {
16187          using exprtk::ifunction<T>::operator();
16188
16189          explicit freefunc02(ff02_functor ff) : exprtk::ifunction<T>(2), f(ff) {}
16190          inline T operator() (const T& v0, const T& v1)
16191          { return f(v0, v1); }
16192          ff02_functor f;
16193       };
16194
16195       struct freefunc03 : public exprtk::ifunction<T>
16196       {
16197          using exprtk::ifunction<T>::operator();
16198
16199          explicit freefunc03(ff03_functor ff) : exprtk::ifunction<T>(3), f(ff) {}
16200          inline T operator() (const T& v0, const T& v1, const T& v2)
16201          { return f(v0, v1, v2); }
16202          ff03_functor f;
16203       };
16204
16205       struct freefunc04 : public exprtk::ifunction<T>
16206       {
16207          using exprtk::ifunction<T>::operator();
16208
16209          explicit freefunc04(ff04_functor ff) : exprtk::ifunction<T>(4), f(ff) {}
16210          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3)
16211          { return f(v0, v1, v2, v3); }
16212          ff04_functor f;
16213       };
16214
16215       struct freefunc05 : public exprtk::ifunction<T>
16216       {
16217          using exprtk::ifunction<T>::operator();
16218
16219          explicit freefunc05(ff05_functor ff) : exprtk::ifunction<T>(5), f(ff) {}
16220          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4)
16221          { return f(v0, v1, v2, v3, v4); }
16222          ff05_functor f;
16223       };
16224
16225       struct freefunc06 : public exprtk::ifunction<T>
16226       {
16227          using exprtk::ifunction<T>::operator();
16228
16229          explicit freefunc06(ff06_functor ff) : exprtk::ifunction<T>(6), f(ff) {}
16230          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5)
16231          { return f(v0, v1, v2, v3, v4, v5); }
16232          ff06_functor f;
16233       };
16234
16235       struct freefunc07 : public exprtk::ifunction<T>
16236       {
16237          using exprtk::ifunction<T>::operator();
16238
16239          explicit freefunc07(ff07_functor ff) : exprtk::ifunction<T>(7), f(ff) {}
16240          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
16241                               const T& v5, const T& v6)
16242          { return f(v0, v1, v2, v3, v4, v5, v6); }
16243          ff07_functor f;
16244       };
16245
16246       struct freefunc08 : public exprtk::ifunction<T>
16247       {
16248          using exprtk::ifunction<T>::operator();
16249
16250          explicit freefunc08(ff08_functor ff) : exprtk::ifunction<T>(8), f(ff) {}
16251          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
16252                               const T& v5, const T& v6, const T& v7)
16253          { return f(v0, v1, v2, v3, v4, v5, v6, v7); }
16254          ff08_functor f;
16255       };
16256
16257       struct freefunc09 : public exprtk::ifunction<T>
16258       {
16259          using exprtk::ifunction<T>::operator();
16260
16261          explicit freefunc09(ff09_functor ff) : exprtk::ifunction<T>(9), f(ff) {}
16262          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
16263                               const T& v5, const T& v6, const T& v7, const T& v8)
16264          { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8); }
16265          ff09_functor f;
16266       };
16267
16268       struct freefunc10 : public exprtk::ifunction<T>
16269       {
16270          using exprtk::ifunction<T>::operator();
16271
16272          explicit freefunc10(ff10_functor ff) : exprtk::ifunction<T>(10), f(ff) {}
16273          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
16274                               const T& v5, const T& v6, const T& v7, const T& v8, const T& v9)
16275          { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9); }
16276          ff10_functor f;
16277       };
16278
16279       struct freefunc11 : public exprtk::ifunction<T>
16280       {
16281          using exprtk::ifunction<T>::operator();
16282
16283          explicit freefunc11(ff11_functor ff) : exprtk::ifunction<T>(11), f(ff) {}
16284          inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
16285                               const T& v5, const T& v6, const T& v7, const T& v8, const T& v9, const T& v10)
16286          { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10); }
16287          ff11_functor f;
16288       };
16289
16290       struct freefunc12 : public exprtk::ifunction<T>
16291       {
16292          using exprtk::ifunction<T>::operator();
16293
16294          explicit freefunc12(ff12_functor ff) : exprtk::ifunction<T>(12), f(ff) {}
16295          inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
16296                               const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
16297                               const T& v10, const T& v11)
16298          { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11); }
16299          ff12_functor f;
16300       };
16301
16302       struct freefunc13 : public exprtk::ifunction<T>
16303       {
16304          using exprtk::ifunction<T>::operator();
16305
16306          explicit freefunc13(ff13_functor ff) : exprtk::ifunction<T>(13), f(ff) {}
16307          inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
16308                               const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
16309                               const T& v10, const T& v11, const T& v12)
16310          { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12); }
16311          ff13_functor f;
16312       };
16313
16314       struct freefunc14 : public exprtk::ifunction<T>
16315       {
16316          using exprtk::ifunction<T>::operator();
16317
16318          explicit freefunc14(ff14_functor ff) : exprtk::ifunction<T>(14), f(ff) {}
16319          inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
16320                               const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
16321                               const T& v10, const T& v11, const T& v12, const T& v13)
16322          { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13); }
16323          ff14_functor f;
16324       };
16325
16326       struct freefunc15 : public exprtk::ifunction<T>
16327       {
16328          using exprtk::ifunction<T>::operator();
16329
16330          explicit freefunc15(ff15_functor ff) : exprtk::ifunction<T>(15), f(ff) {}
16331          inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
16332                               const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
16333                               const T& v10, const T& v11, const T& v12, const T& v13, const T& v14)
16334          { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13, v14); }
16335          ff15_functor f;
16336       };
16337
16338       template <typename Type, typename RawType>
16339       struct type_store
16340       {
16341          typedef details::expression_node<T>*        expression_ptr;
16342          typedef typename details::variable_node<T>  variable_node_t;
16343          typedef ifunction<T>                        ifunction_t;
16344          typedef ivararg_function<T>                 ivararg_function_t;
16345          typedef igeneric_function<T>                igeneric_function_t;
16346          typedef details::vector_holder<T>           vector_t;
16347          #ifndef exprtk_disable_string_capabilities
16348          typedef typename details::stringvar_node<T> stringvar_node_t;
16349          #endif
16350
16351          typedef Type type_t;
16352          typedef type_t* type_ptr;
16353          typedef std::pair<bool,type_ptr> type_pair_t;
16354          typedef std::map<std::string,type_pair_t,details::ilesscompare> type_map_t;
16355          typedef typename type_map_t::iterator tm_itr_t;
16356          typedef typename type_map_t::const_iterator tm_const_itr_t;
16357
16358          enum { lut_size = 256 };
16359
16360          type_map_t  map;
16361          std::size_t size;
16362
16363          type_store()
16364          : size(0)
16365          {}
16366
16367          inline bool symbol_exists(const std::string& symbol_name) const
16368          {
16369             if (symbol_name.empty())
16370                return false;
16371             else if (map.end() != map.find(symbol_name))
16372                return true;
16373             else
16374                return false;
16375          }
16376
16377          template <typename PtrType>
16378          inline std::string entity_name(const PtrType& ptr) const
16379          {
16380             if (map.empty())
16381                return std::string();
16382
16383             tm_const_itr_t itr = map.begin();
16384
16385             while (map.end() != itr)
16386             {
16387                if (itr->second.second == ptr)
16388                {
16389                   return itr->first;
16390                }
16391                else
16392                   ++itr;
16393             }
16394
16395             return std::string();
16396          }
16397
16398          inline bool is_constant(const std::string& symbol_name) const
16399          {
16400             if (symbol_name.empty())
16401                return false;
16402             else
16403             {
16404                const tm_const_itr_t itr = map.find(symbol_name);
16405
16406                if (map.end() == itr)
16407                   return false;
16408                else
16409                   return (*itr).second.first;
16410             }
16411          }
16412
16413          template <typename Tie, typename RType>
16414          inline bool add_impl(const std::string& symbol_name, RType t, const bool is_const)
16415          {
16416             if (symbol_name.size() > 1)
16417             {
16418                for (std::size_t i = 0; i < details::reserved_symbols_size; ++i)
16419                {
16420                   if (details::imatch(symbol_name, details::reserved_symbols[i]))
16421                   {
16422                      return false;
16423                   }
16424                }
16425             }
16426
16427             const tm_itr_t itr = map.find(symbol_name);
16428
16429             if (map.end() == itr)
16430             {
16431                map[symbol_name] = Tie::make(t,is_const);
16432                ++size;
16433             }
16434
16435             return true;
16436          }
16437
16438          struct tie_array
16439          {
16440             static inline std::pair<bool,vector_t*> make(std::pair<T*,std::size_t> v, const bool is_const = false)
16441             {
16442                return std::make_pair(is_const, new vector_t(v.first, v.second));
16443             }
16444          };
16445
16446          struct tie_stdvec
16447          {
16448             template <typename Allocator>
16449             static inline std::pair<bool,vector_t*> make(std::vector<T,Allocator>& v, const bool is_const = false)
16450             {
16451                return std::make_pair(is_const, new vector_t(v));
16452             }
16453          };
16454
16455          struct tie_vecview
16456          {
16457             static inline std::pair<bool,vector_t*> make(exprtk::vector_view<T>& v, const bool is_const = false)
16458             {
16459                return std::make_pair(is_const, new vector_t(v));
16460             }
16461          };
16462
16463          struct tie_stddeq
16464          {
16465             template <typename Allocator>
16466             static inline std::pair<bool,vector_t*> make(std::deque<T,Allocator>& v, const bool is_const = false)
16467             {
16468                return std::make_pair(is_const, new vector_t(v));
16469             }
16470          };
16471
16472          template <std::size_t v_size>
16473          inline bool add(const std::string& symbol_name, T (&v)[v_size], const bool is_const = false)
16474          {
16475             return add_impl<tie_array,std::pair<T*,std::size_t> >
16476                       (symbol_name, std::make_pair(v,v_size), is_const);
16477          }
16478
16479          inline bool add(const std::string& symbol_name, T* v, const std::size_t v_size, const bool is_const = false)
16480          {
16481             return add_impl<tie_array,std::pair<T*,std::size_t> >
16482                      (symbol_name, std::make_pair(v,v_size), is_const);
16483          }
16484
16485          template <typename Allocator>
16486          inline bool add(const std::string& symbol_name, std::vector<T,Allocator>& v, const bool is_const = false)
16487          {
16488             return add_impl<tie_stdvec,std::vector<T,Allocator>&>
16489                       (symbol_name, v, is_const);
16490          }
16491
16492          inline bool add(const std::string& symbol_name, exprtk::vector_view<T>& v, const bool is_const = false)
16493          {
16494             return add_impl<tie_vecview,exprtk::vector_view<T>&>
16495                       (symbol_name, v, is_const);
16496          }
16497
16498          template <typename Allocator>
16499          inline bool add(const std::string& symbol_name, std::deque<T,Allocator>& v, const bool is_const = false)
16500          {
16501             return add_impl<tie_stddeq,std::deque<T,Allocator>&>
16502                       (symbol_name, v, is_const);
16503          }
16504
16505          inline bool add(const std::string& symbol_name, RawType& t, const bool is_const = false)
16506          {
16507             struct tie
16508             {
16509                static inline std::pair<bool,variable_node_t*> make(T& t,const bool is_const = false)
16510                {
16511                   return std::make_pair(is_const, new variable_node_t(t));
16512                }
16513
16514                #ifndef exprtk_disable_string_capabilities
16515                static inline std::pair<bool,stringvar_node_t*> make(std::string& t,const bool is_const = false)
16516                {
16517                   return std::make_pair(is_const, new stringvar_node_t(t));
16518                }
16519                #endif
16520
16521                static inline std::pair<bool,function_t*> make(function_t& t, const bool is_constant = false)
16522                {
16523                   return std::make_pair(is_constant,&t);
16524                }
16525
16526                static inline std::pair<bool,vararg_function_t*> make(vararg_function_t& t, const bool is_const = false)
16527                {
16528                   return std::make_pair(is_const,&t);
16529                }
16530
16531                static inline std::pair<bool,generic_function_t*> make(generic_function_t& t, const bool is_constant = false)
16532                {
16533                   return std::make_pair(is_constant,&t);
16534                }
16535             };
16536
16537             const tm_itr_t itr = map.find(symbol_name);
16538
16539             if (map.end() == itr)
16540             {
16541                map[symbol_name] = tie::make(t,is_const);
16542                ++size;
16543             }
16544
16545             return true;
16546          }
16547
16548          inline type_ptr get(const std::string& symbol_name) const
16549          {
16550             const tm_const_itr_t itr = map.find(symbol_name);
16551
16552             if (map.end() == itr)
16553                return reinterpret_cast<type_ptr>(0);
16554             else
16555                return itr->second.second;
16556          }
16557
16558          template <typename TType, typename TRawType, typename PtrType>
16559          struct ptr_match
16560          {
16561             static inline bool test(const PtrType, const void*)
16562             {
16563                return false;
16564             }
16565          };
16566
16567          template <typename TType, typename TRawType>
16568          struct ptr_match<TType,TRawType,variable_node_t*>
16569          {
16570             static inline bool test(const variable_node_t* p, const void* ptr)
16571             {
16572                exprtk_debug(("ptr_match::test() - %p <--> %p\n",(void*)(&(p->ref())),ptr));
16573                return (&(p->ref()) == ptr);
16574             }
16575          };
16576
16577          inline type_ptr get_from_varptr(const void* ptr) const
16578          {
16579             tm_const_itr_t itr = map.begin();
16580
16581             while (map.end() != itr)
16582             {
16583                type_ptr ret_ptr = itr->second.second;
16584
16585                if (ptr_match<Type,RawType,type_ptr>::test(ret_ptr,ptr))
16586                {
16587                   return ret_ptr;
16588                }
16589
16590                ++itr;
16591             }
16592
16593             return type_ptr(0);
16594          }
16595
16596          inline bool remove(const std::string& symbol_name, const bool delete_node = true)
16597          {
16598             const tm_itr_t itr = map.find(symbol_name);
16599
16600             if (map.end() != itr)
16601             {
16602                struct deleter
16603                {
16604                   static inline void process(std::pair<bool,variable_node_t*>& n)  { delete n.second; }
16605                   static inline void process(std::pair<bool,vector_t*>& n)         { delete n.second; }
16606                   #ifndef exprtk_disable_string_capabilities
16607                   static inline void process(std::pair<bool,stringvar_node_t*>& n) { delete n.second; }
16608                   #endif
16609                   static inline void process(std::pair<bool,function_t*>&)         {                  }
16610                };
16611
16612                if (delete_node)
16613                {
16614                   deleter::process((*itr).second);
16615                }
16616
16617                map.erase(itr);
16618                --size;
16619
16620                return true;
16621             }
16622             else
16623                return false;
16624          }
16625
16626          inline RawType& type_ref(const std::string& symbol_name)
16627          {
16628             struct init_type
16629             {
16630                static inline double set(double)           { return (0.0);           }
16631                static inline double set(long double)      { return (0.0);           }
16632                static inline float  set(float)            { return (0.0f);          }
16633                static inline std::string set(std::string) { return std::string(""); }
16634             };
16635
16636             static RawType null_type = init_type::set(RawType());
16637
16638             const tm_const_itr_t itr = map.find(symbol_name);
16639
16640             if (map.end() == itr)
16641                return null_type;
16642             else
16643                return itr->second.second->ref();
16644          }
16645
16646          inline void clear(const bool delete_node = true)
16647          {
16648             struct deleter
16649             {
16650                static inline void process(std::pair<bool,variable_node_t*>& n)  { delete n.second; }
16651                static inline void process(std::pair<bool,vector_t*>& n)         { delete n.second; }
16652                static inline void process(std::pair<bool,function_t*>&)         {                  }
16653                #ifndef exprtk_disable_string_capabilities
16654                static inline void process(std::pair<bool,stringvar_node_t*>& n) { delete n.second; }
16655                #endif
16656             };
16657
16658             if (!map.empty())
16659             {
16660                if (delete_node)
16661                {
16662                   tm_itr_t itr = map.begin();
16663                   tm_itr_t end = map.end  ();
16664
16665                   while (end != itr)
16666                   {
16667                      deleter::process((*itr).second);
16668                      ++itr;
16669                   }
16670                }
16671
16672                map.clear();
16673             }
16674
16675             size = 0;
16676          }
16677
16678          template <typename Allocator,
16679                    template <typename, typename> class Sequence>
16680          inline std::size_t get_list(Sequence<std::pair<std::string,RawType>,Allocator>& list) const
16681          {
16682             std::size_t count = 0;
16683
16684             if (!map.empty())
16685             {
16686                tm_const_itr_t itr = map.begin();
16687                tm_const_itr_t end = map.end  ();
16688
16689                while (end != itr)
16690                {
16691                   list.push_back(std::make_pair((*itr).first,itr->second.second->ref()));
16692                   ++itr;
16693                   ++count;
16694                }
16695             }
16696
16697             return count;
16698          }
16699
16700          template <typename Allocator,
16701                    template <typename, typename> class Sequence>
16702          inline std::size_t get_list(Sequence<std::string,Allocator>& vlist) const
16703          {
16704             std::size_t count = 0;
16705
16706             if (!map.empty())
16707             {
16708                tm_const_itr_t itr = map.begin();
16709                tm_const_itr_t end = map.end  ();
16710
16711                while (end != itr)
16712                {
16713                   vlist.push_back((*itr).first);
16714                   ++itr;
16715                   ++count;
16716                }
16717             }
16718
16719             return count;
16720          }
16721       };
16722
16723       typedef details::expression_node<T>* expression_ptr;
16724       typedef typename details::variable_node<T> variable_t;
16725       typedef typename details::vector_holder<T> vector_holder_t;
16726       typedef variable_t* variable_ptr;
16727       #ifndef exprtk_disable_string_capabilities
16728       typedef typename details::stringvar_node<T> stringvar_t;
16729       typedef stringvar_t* stringvar_ptr;
16730       #endif
16731       typedef ifunction        <T> function_t;
16732       typedef ivararg_function <T> vararg_function_t;
16733       typedef igeneric_function<T> generic_function_t;
16734       typedef function_t* function_ptr;
16735       typedef vararg_function_t*  vararg_function_ptr;
16736       typedef generic_function_t* generic_function_ptr;
16737
16738       static const std::size_t lut_size = 256;
16739
16740       // Symbol Table Holder
16741       struct control_block
16742       {
16743          struct st_data
16744          {
16745             type_store<typename details::variable_node<T>,T> variable_store;
16746             #ifndef exprtk_disable_string_capabilities
16747             type_store<typename details::stringvar_node<T>,std::string> stringvar_store;
16748             #endif
16749             type_store<ifunction<T>,ifunction<T> >                 function_store;
16750             type_store<ivararg_function <T>,ivararg_function <T> > vararg_function_store;
16751             type_store<igeneric_function<T>,igeneric_function<T> > generic_function_store;
16752             type_store<igeneric_function<T>,igeneric_function<T> > string_function_store;
16753             type_store<igeneric_function<T>,igeneric_function<T> > overload_function_store;
16754             type_store<vector_holder_t,vector_holder_t>            vector_store;
16755
16756             st_data()
16757             {
16758                for (std::size_t i = 0; i < details::reserved_words_size; ++i)
16759                {
16760                   reserved_symbol_table_.insert(details::reserved_words[i]);
16761                }
16762
16763                for (std::size_t i = 0; i < details::reserved_symbols_size; ++i)
16764                {
16765                   reserved_symbol_table_.insert(details::reserved_symbols[i]);
16766                }
16767             }
16768
16769            ~st_data()
16770             {
16771                for (std::size_t i = 0; i < free_function_list_.size(); ++i)
16772                {
16773                   delete free_function_list_[i];
16774                }
16775             }
16776
16777             inline bool is_reserved_symbol(const std::string& symbol) const
16778             {
16779                return (reserved_symbol_table_.end() != reserved_symbol_table_.find(symbol));
16780             }
16781
16782             static inline st_data* create()
16783             {
16784                return (new st_data);
16785             }
16786
16787             static inline void destroy(st_data*& sd)
16788             {
16789                delete sd;
16790                sd = reinterpret_cast<st_data*>(0);
16791             }
16792
16793             std::list<T>               local_symbol_list_;
16794             std::list<std::string>     local_stringvar_list_;
16795             std::set<std::string>      reserved_symbol_table_;
16796             std::vector<ifunction<T>*> free_function_list_;
16797          };
16798
16799          control_block()
16800          : ref_count(1),
16801            data_(st_data::create())
16802          {}
16803
16804          explicit control_block(st_data* data)
16805          : ref_count(1),
16806            data_(data)
16807          {}
16808
16809         ~control_block()
16810          {
16811             if (data_ && (0 == ref_count))
16812             {
16813                st_data::destroy(data_);
16814             }
16815          }
16816
16817          static inline control_block* create()
16818          {
16819             return (new control_block);
16820          }
16821
16822          template <typename SymTab>
16823          static inline void destroy(control_block*& cntrl_blck, SymTab* sym_tab)
16824          {
16825             if (cntrl_blck)
16826             {
16827                if (
16828                     (0 !=   cntrl_blck->ref_count) &&
16829                     (0 == --cntrl_blck->ref_count)
16830                   )
16831                {
16832                   if (sym_tab)
16833                      sym_tab->clear();
16834
16835                   delete cntrl_blck;
16836                }
16837
16838                cntrl_blck = 0;
16839             }
16840          }
16841
16842          std::size_t ref_count;
16843          st_data* data_;
16844       };
16845
16846    public:
16847
16848       symbol_table()
16849       : control_block_(control_block::create())
16850       {
16851          clear();
16852       }
16853
16854      ~symbol_table()
16855       {
16856          control_block::destroy(control_block_,this);
16857       }
16858
16859       symbol_table(const symbol_table<T>& st)
16860       {
16861          control_block_ = st.control_block_;
16862          control_block_->ref_count++;
16863       }
16864
16865       inline symbol_table<T>& operator=(const symbol_table<T>& st)
16866       {
16867          if (this != &st)
16868          {
16869             control_block::destroy(control_block_,reinterpret_cast<symbol_table<T>*>(0));
16870
16871             control_block_ = st.control_block_;
16872             control_block_->ref_count++;
16873          }
16874
16875          return (*this);
16876       }
16877
16878       inline bool operator==(const symbol_table<T>& st) const
16879       {
16880          return (this == &st) || (control_block_ == st.control_block_);
16881       }
16882
16883       inline void clear_variables(const bool delete_node = true)
16884       {
16885          local_data().variable_store.clear(delete_node);
16886       }
16887
16888       inline void clear_functions()
16889       {
16890          local_data().function_store.clear();
16891       }
16892
16893       inline void clear_strings()
16894       {
16895          #ifndef exprtk_disable_string_capabilities
16896          local_data().stringvar_store.clear();
16897          #endif
16898       }
16899
16900       inline void clear_vectors()
16901       {
16902          local_data().vector_store.clear();
16903       }
16904
16905       inline void clear_local_constants()
16906       {
16907          local_data().local_symbol_list_.clear();
16908       }
16909
16910       inline void clear()
16911       {
16912          if (!valid()) return;
16913          clear_variables      ();
16914          clear_functions      ();
16915          clear_strings        ();
16916          clear_vectors        ();
16917          clear_local_constants();
16918       }
16919
16920       inline std::size_t variable_count() const
16921       {
16922          if (valid())
16923             return local_data().variable_store.size;
16924          else
16925             return 0;
16926       }
16927
16928       #ifndef exprtk_disable_string_capabilities
16929       inline std::size_t stringvar_count() const
16930       {
16931          if (valid())
16932             return local_data().stringvar_store.size;
16933          else
16934             return 0;
16935       }
16936       #endif
16937
16938       inline std::size_t function_count() const
16939       {
16940          if (valid())
16941             return local_data().function_store.size;
16942          else
16943             return 0;
16944       }
16945
16946       inline std::size_t vector_count() const
16947       {
16948          if (valid())
16949             return local_data().vector_store.size;
16950          else
16951             return 0;
16952       }
16953
16954       inline variable_ptr get_variable(const std::string& variable_name) const
16955       {
16956          if (!valid())
16957             return reinterpret_cast<variable_ptr>(0);
16958          else if (!valid_symbol(variable_name))
16959             return reinterpret_cast<variable_ptr>(0);
16960          else
16961             return local_data().variable_store.get(variable_name);
16962       }
16963
16964       inline variable_ptr get_variable(const T& var_ref) const
16965       {
16966          if (!valid())
16967             return reinterpret_cast<variable_ptr>(0);
16968          else
16969             return local_data().variable_store.get_from_varptr(
16970                                                   reinterpret_cast<const void*>(&var_ref));
16971       }
16972
16973       #ifndef exprtk_disable_string_capabilities
16974       inline stringvar_ptr get_stringvar(const std::string& string_name) const
16975       {
16976          if (!valid())
16977             return reinterpret_cast<stringvar_ptr>(0);
16978          else if (!valid_symbol(string_name))
16979             return reinterpret_cast<stringvar_ptr>(0);
16980          else
16981             return local_data().stringvar_store.get(string_name);
16982       }
16983       #endif
16984
16985       inline function_ptr get_function(const std::string& function_name) const
16986       {
16987          if (!valid())
16988             return reinterpret_cast<function_ptr>(0);
16989          else if (!valid_symbol(function_name))
16990             return reinterpret_cast<function_ptr>(0);
16991          else
16992             return local_data().function_store.get(function_name);
16993       }
16994
16995       inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const
16996       {
16997          if (!valid())
16998             return reinterpret_cast<vararg_function_ptr>(0);
16999          else if (!valid_symbol(vararg_function_name))
17000             return reinterpret_cast<vararg_function_ptr>(0);
17001          else
17002             return local_data().vararg_function_store.get(vararg_function_name);
17003       }
17004
17005       inline generic_function_ptr get_generic_function(const std::string& function_name) const
17006       {
17007          if (!valid())
17008             return reinterpret_cast<generic_function_ptr>(0);
17009          else if (!valid_symbol(function_name))
17010             return reinterpret_cast<generic_function_ptr>(0);
17011          else
17012             return local_data().generic_function_store.get(function_name);
17013       }
17014
17015       inline generic_function_ptr get_string_function(const std::string& function_name) const
17016       {
17017          if (!valid())
17018             return reinterpret_cast<generic_function_ptr>(0);
17019          else if (!valid_symbol(function_name))
17020             return reinterpret_cast<generic_function_ptr>(0);
17021          else
17022             return local_data().string_function_store.get(function_name);
17023       }
17024
17025       inline generic_function_ptr get_overload_function(const std::string& function_name) const
17026       {
17027          if (!valid())
17028             return reinterpret_cast<generic_function_ptr>(0);
17029          else if (!valid_symbol(function_name))
17030             return reinterpret_cast<generic_function_ptr>(0);
17031          else
17032             return local_data().overload_function_store.get(function_name);
17033       }
17034
17035       typedef vector_holder_t* vector_holder_ptr;
17036
17037       inline vector_holder_ptr get_vector(const std::string& vector_name) const
17038       {
17039          if (!valid())
17040             return reinterpret_cast<vector_holder_ptr>(0);
17041          else if (!valid_symbol(vector_name))
17042             return reinterpret_cast<vector_holder_ptr>(0);
17043          else
17044             return local_data().vector_store.get(vector_name);
17045       }
17046
17047       inline T& variable_ref(const std::string& symbol_name)
17048       {
17049          static T null_var = T(0);
17050          if (!valid())
17051             return null_var;
17052          else if (!valid_symbol(symbol_name))
17053             return null_var;
17054          else
17055             return local_data().variable_store.type_ref(symbol_name);
17056       }
17057
17058       #ifndef exprtk_disable_string_capabilities
17059       inline std::string& stringvar_ref(const std::string& symbol_name)
17060       {
17061          static std::string null_stringvar;
17062          if (!valid())
17063             return null_stringvar;
17064          else if (!valid_symbol(symbol_name))
17065             return null_stringvar;
17066          else
17067             return local_data().stringvar_store.type_ref(symbol_name);
17068       }
17069       #endif
17070
17071       inline bool is_constant_node(const std::string& symbol_name) const
17072       {
17073          if (!valid())
17074             return false;
17075          else if (!valid_symbol(symbol_name))
17076             return false;
17077          else
17078             return local_data().variable_store.is_constant(symbol_name);
17079       }
17080
17081       #ifndef exprtk_disable_string_capabilities
17082       inline bool is_constant_string(const std::string& symbol_name) const
17083       {
17084          if (!valid())
17085             return false;
17086          else if (!valid_symbol(symbol_name))
17087             return false;
17088          else if (!local_data().stringvar_store.symbol_exists(symbol_name))
17089             return false;
17090          else
17091             return local_data().stringvar_store.is_constant(symbol_name);
17092       }
17093       #endif
17094
17095       inline bool create_variable(const std::string& variable_name, const T& value = T(0))
17096       {
17097          if (!valid())
17098             return false;
17099          else if (!valid_symbol(variable_name))
17100             return false;
17101          else if (symbol_exists(variable_name))
17102             return false;
17103
17104          local_data().local_symbol_list_.push_back(value);
17105          T& t = local_data().local_symbol_list_.back();
17106
17107          return add_variable(variable_name,t);
17108       }
17109
17110       #ifndef exprtk_disable_string_capabilities
17111       inline bool create_stringvar(const std::string& stringvar_name, const std::string& value = std::string(""))
17112       {
17113          if (!valid())
17114             return false;
17115          else if (!valid_symbol(stringvar_name))
17116             return false;
17117          else if (symbol_exists(stringvar_name))
17118             return false;
17119
17120          local_data().local_stringvar_list_.push_back(value);
17121          std::string& s = local_data().local_stringvar_list_.back();
17122
17123          return add_stringvar(stringvar_name,s);
17124       }
17125       #endif
17126
17127       inline bool add_variable(const std::string& variable_name, T& t, const bool is_constant = false)
17128       {
17129          if (!valid())
17130             return false;
17131          else if (!valid_symbol(variable_name))
17132             return false;
17133          else if (symbol_exists(variable_name))
17134             return false;
17135          else
17136             return local_data().variable_store.add(variable_name, t, is_constant);
17137       }
17138
17139       inline bool add_constant(const std::string& constant_name, const T& value)
17140       {
17141          if (!valid())
17142             return false;
17143          else if (!valid_symbol(constant_name))
17144             return false;
17145          else if (symbol_exists(constant_name))
17146             return false;
17147
17148          local_data().local_symbol_list_.push_back(value);
17149          T& t = local_data().local_symbol_list_.back();
17150
17151          return add_variable(constant_name, t, true);
17152       }
17153
17154       #ifndef exprtk_disable_string_capabilities
17155       inline bool add_stringvar(const std::string& stringvar_name, std::string& s, const bool is_constant = false)
17156       {
17157          if (!valid())
17158             return false;
17159          else if (!valid_symbol(stringvar_name))
17160             return false;
17161          else if (symbol_exists(stringvar_name))
17162             return false;
17163          else
17164             return local_data().stringvar_store.add(stringvar_name, s, is_constant);
17165       }
17166       #endif
17167
17168       inline bool add_function(const std::string& function_name, function_t& function)
17169       {
17170          if (!valid())
17171             return false;
17172          else if (!valid_symbol(function_name))
17173             return false;
17174          else if (symbol_exists(function_name))
17175             return false;
17176          else
17177             return local_data().function_store.add(function_name,function);
17178       }
17179
17180       inline bool add_function(const std::string& vararg_function_name, vararg_function_t& vararg_function)
17181       {
17182          if (!valid())
17183             return false;
17184          else if (!valid_symbol(vararg_function_name))
17185             return false;
17186          else if (symbol_exists(vararg_function_name))
17187             return false;
17188          else
17189             return local_data().vararg_function_store.add(vararg_function_name,vararg_function);
17190       }
17191
17192       inline bool add_function(const std::string& function_name, generic_function_t& function)
17193       {
17194          if (!valid())
17195             return false;
17196          else if (!valid_symbol(function_name))
17197             return false;
17198          else if (symbol_exists(function_name))
17199             return false;
17200          else if (
17201                    (
17202                      (generic_function_t::e_rtrn_scalar == function.rtrn_type) ||
17203                      (generic_function_t::e_rtrn_string == function.rtrn_type)
17204                    ) &&
17205                    std::string::npos != function.parameter_sequence.find_first_not_of("STVZ*?|")
17206                  )
17207             return false;
17208          else if (
17209                    (generic_function_t::e_rtrn_overload  == function.rtrn_type) &&
17210                    std::string::npos != function.parameter_sequence.find_first_not_of("STVZ*?|:")
17211                  )
17212             return false;
17213
17214          switch (function.rtrn_type)
17215          {
17216             case generic_function_t::e_rtrn_scalar :
17217                return local_data().generic_function_store.add(function_name,function);
17218
17219             case generic_function_t::e_rtrn_string :
17220                return local_data().string_function_store.add(function_name,function);
17221
17222             case generic_function_t::e_rtrn_overload :
17223                return local_data().overload_function_store.add(function_name,function);
17224          }
17225
17226          return false;
17227       }
17228
17229       #define exprtk_define_freefunction(NN)                                                \
17230       inline bool add_function(const std::string& function_name, ff##NN##_functor function) \
17231       {                                                                                     \
17232          if (!valid())                                                                      \
17233          { return false; }                                                                  \
17234          if (!valid_symbol(function_name))                                                  \
17235          { return false; }                                                                  \
17236          if (symbol_exists(function_name))                                                  \
17237          { return false; }                                                                  \
17238                                                                                             \
17239          exprtk::ifunction<T>* ifunc = new freefunc##NN(function);                          \
17240                                                                                             \
17241          local_data().free_function_list_.push_back(ifunc);                                 \
17242                                                                                             \
17243          return add_function(function_name,(*local_data().free_function_list_.back()));     \
17244       }                                                                                     \
17245
17246       exprtk_define_freefunction(00) exprtk_define_freefunction(01)
17247       exprtk_define_freefunction(02) exprtk_define_freefunction(03)
17248       exprtk_define_freefunction(04) exprtk_define_freefunction(05)
17249       exprtk_define_freefunction(06) exprtk_define_freefunction(07)
17250       exprtk_define_freefunction(08) exprtk_define_freefunction(09)
17251       exprtk_define_freefunction(10) exprtk_define_freefunction(11)
17252       exprtk_define_freefunction(12) exprtk_define_freefunction(13)
17253       exprtk_define_freefunction(14) exprtk_define_freefunction(15)
17254
17255       #undef exprtk_define_freefunction
17256
17257       inline bool add_reserved_function(const std::string& function_name, function_t& function)
17258       {
17259          if (!valid())
17260             return false;
17261          else if (!valid_symbol(function_name,false))
17262             return false;
17263          else if (symbol_exists(function_name,false))
17264             return false;
17265          else
17266             return local_data().function_store.add(function_name,function);
17267       }
17268
17269       inline bool add_reserved_function(const std::string& vararg_function_name, vararg_function_t& vararg_function)
17270       {
17271          if (!valid())
17272             return false;
17273          else if (!valid_symbol(vararg_function_name,false))
17274             return false;
17275          else if (symbol_exists(vararg_function_name,false))
17276             return false;
17277          else
17278             return local_data().vararg_function_store.add(vararg_function_name,vararg_function);
17279       }
17280
17281       inline bool add_reserved_function(const std::string& function_name, generic_function_t& function)
17282       {
17283          if (!valid())
17284             return false;
17285          else if (!valid_symbol(function_name,false))
17286             return false;
17287          else if (symbol_exists(function_name,false))
17288             return false;
17289          else if (
17290                    (
17291                      (generic_function_t::e_rtrn_scalar == function.rtrn_type) ||
17292                      (generic_function_t::e_rtrn_string == function.rtrn_type)
17293                    ) &&
17294                    std::string::npos != function.parameter_sequence.find_first_not_of("STV*?|")
17295                  )
17296             return false;
17297          else if (
17298                    generic_function_t::e_rtrn_overload &&
17299                    std::string::npos != function.parameter_sequence.find_first_not_of("STV*?|:")
17300                  )
17301             return false;
17302
17303          switch (function.rtrn_type)
17304          {
17305             case generic_function_t::e_rtrn_scalar :
17306                return local_data().generic_function_store.add(function_name,function);
17307
17308             case generic_function_t::e_rtrn_string :
17309                return local_data().string_function_store.add(function_name,function);
17310
17311             case generic_function_t::e_rtrn_overload :
17312                return local_data().overload_function_store.add(function_name,function);
17313          }
17314
17315          return false;
17316       }
17317
17318       template <std::size_t N>
17319       inline bool add_vector(const std::string& vector_name, T (&v)[N])
17320       {
17321          if (!valid())
17322             return false;
17323          else if (!valid_symbol(vector_name))
17324             return false;
17325          else if (symbol_exists(vector_name))
17326             return false;
17327          else
17328             return local_data().vector_store.add(vector_name,v);
17329       }
17330
17331       inline bool add_vector(const std::string& vector_name, T* v, const std::size_t& v_size)
17332       {
17333          if (!valid())
17334             return false;
17335          else if (!valid_symbol(vector_name))
17336             return false;
17337          else if (symbol_exists(vector_name))
17338             return false;
17339          else if (0 == v_size)
17340             return false;
17341          else
17342             return local_data().vector_store.add(vector_name, v, v_size);
17343       }
17344
17345       template <typename Allocator>
17346       inline bool add_vector(const std::string& vector_name, std::vector<T,Allocator>& v)
17347       {
17348          if (!valid())
17349             return false;
17350          else if (!valid_symbol(vector_name))
17351             return false;
17352          else if (symbol_exists(vector_name))
17353             return false;
17354          else if (0 == v.size())
17355             return false;
17356          else
17357             return local_data().vector_store.add(vector_name,v);
17358       }
17359
17360       inline bool add_vector(const std::string& vector_name, exprtk::vector_view<T>& v)
17361       {
17362          if (!valid())
17363             return false;
17364          else if (!valid_symbol(vector_name))
17365             return false;
17366          else if (symbol_exists(vector_name))
17367             return false;
17368          else if (0 == v.size())
17369             return false;
17370          else
17371             return local_data().vector_store.add(vector_name,v);
17372       }
17373
17374       inline bool remove_variable(const std::string& variable_name, const bool delete_node = true)
17375       {
17376          if (!valid())
17377             return false;
17378          else
17379             return local_data().variable_store.remove(variable_name, delete_node);
17380       }
17381
17382       #ifndef exprtk_disable_string_capabilities
17383       inline bool remove_stringvar(const std::string& string_name)
17384       {
17385          if (!valid())
17386             return false;
17387          else
17388             return local_data().stringvar_store.remove(string_name);
17389       }
17390       #endif
17391
17392       inline bool remove_function(const std::string& function_name)
17393       {
17394          if (!valid())
17395             return false;
17396          else
17397             return local_data().function_store.remove(function_name);
17398       }
17399
17400       inline bool remove_vararg_function(const std::string& vararg_function_name)
17401       {
17402          if (!valid())
17403             return false;
17404          else
17405             return local_data().vararg_function_store.remove(vararg_function_name);
17406       }
17407
17408       inline bool remove_vector(const std::string& vector_name)
17409       {
17410          if (!valid())
17411             return false;
17412          else
17413             return local_data().vector_store.remove(vector_name);
17414       }
17415
17416       inline bool add_constants()
17417       {
17418          return add_pi      () &&
17419                 add_epsilon () &&
17420                 add_infinity() ;
17421       }
17422
17423       inline bool add_pi()
17424       {
17425          const typename details::numeric::details::number_type<T>::type num_type;
17426          static const T local_pi = details::numeric::details::const_pi_impl<T>(num_type);
17427          return add_constant("pi",local_pi);
17428       }
17429
17430       inline bool add_epsilon()
17431       {
17432          static const T local_epsilon = details::numeric::details::epsilon_type<T>::value();
17433          return add_constant("epsilon",local_epsilon);
17434       }
17435
17436       inline bool add_infinity()
17437       {
17438          static const T local_infinity = std::numeric_limits<T>::infinity();
17439          return add_constant("inf",local_infinity);
17440       }
17441
17442       template <typename Package>
17443       inline bool add_package(Package& package)
17444       {
17445          return package.register_package(*this);
17446       }
17447
17448       template <typename Allocator,
17449                 template <typename, typename> class Sequence>
17450       inline std::size_t get_variable_list(Sequence<std::pair<std::string,T>,Allocator>& vlist) const
17451       {
17452          if (!valid())
17453             return 0;
17454          else
17455             return local_data().variable_store.get_list(vlist);
17456       }
17457
17458       template <typename Allocator,
17459                 template <typename, typename> class Sequence>
17460       inline std::size_t get_variable_list(Sequence<std::string,Allocator>& vlist) const
17461       {
17462          if (!valid())
17463             return 0;
17464          else
17465             return local_data().variable_store.get_list(vlist);
17466       }
17467
17468       #ifndef exprtk_disable_string_capabilities
17469       template <typename Allocator,
17470                 template <typename, typename> class Sequence>
17471       inline std::size_t get_stringvar_list(Sequence<std::pair<std::string,std::string>,Allocator>& svlist) const
17472       {
17473          if (!valid())
17474             return 0;
17475          else
17476             return local_data().stringvar_store.get_list(svlist);
17477       }
17478
17479       template <typename Allocator,
17480                 template <typename, typename> class Sequence>
17481       inline std::size_t get_stringvar_list(Sequence<std::string,Allocator>& svlist) const
17482       {
17483          if (!valid())
17484             return 0;
17485          else
17486             return local_data().stringvar_store.get_list(svlist);
17487       }
17488       #endif
17489
17490       template <typename Allocator,
17491                 template <typename, typename> class Sequence>
17492       inline std::size_t get_vector_list(Sequence<std::string,Allocator>& vlist) const
17493       {
17494          if (!valid())
17495             return 0;
17496          else
17497             return local_data().vector_store.get_list(vlist);
17498       }
17499
17500       inline bool symbol_exists(const std::string& symbol_name, const bool check_reserved_symb = true) const
17501       {
17502          /*
17503             Function will return true if symbol_name exists as either a
17504             reserved symbol, variable, stringvar, vector or function name
17505             in any of the type stores.
17506          */
17507          if (!valid())
17508             return false;
17509          else if (local_data().variable_store.symbol_exists(symbol_name))
17510             return true;
17511          #ifndef exprtk_disable_string_capabilities
17512          else if (local_data().stringvar_store.symbol_exists(symbol_name))
17513             return true;
17514          #endif
17515          else if (local_data().vector_store.symbol_exists(symbol_name))
17516             return true;
17517          else if (local_data().function_store.symbol_exists(symbol_name))
17518             return true;
17519          else if (check_reserved_symb && local_data().is_reserved_symbol(symbol_name))
17520             return true;
17521          else
17522             return false;
17523       }
17524
17525       inline bool is_variable(const std::string& variable_name) const
17526       {
17527          if (!valid())
17528             return false;
17529          else
17530             return local_data().variable_store.symbol_exists(variable_name);
17531       }
17532
17533       #ifndef exprtk_disable_string_capabilities
17534       inline bool is_stringvar(const std::string& stringvar_name) const
17535       {
17536          if (!valid())
17537             return false;
17538          else
17539             return local_data().stringvar_store.symbol_exists(stringvar_name);
17540       }
17541
17542       inline bool is_conststr_stringvar(const std::string& symbol_name) const
17543       {
17544          if (!valid())
17545             return false;
17546          else if (!valid_symbol(symbol_name))
17547             return false;
17548          else if (!local_data().stringvar_store.symbol_exists(symbol_name))
17549             return false;
17550
17551          return (
17552                   local_data().stringvar_store.symbol_exists(symbol_name) ||
17553                   local_data().stringvar_store.is_constant  (symbol_name)
17554                 );
17555       }
17556       #endif
17557
17558       inline bool is_function(const std::string& function_name) const
17559       {
17560          if (!valid())
17561             return false;
17562          else
17563             return local_data().function_store.symbol_exists(function_name);
17564       }
17565
17566       inline bool is_vararg_function(const std::string& vararg_function_name) const
17567       {
17568          if (!valid())
17569             return false;
17570          else
17571             return local_data().vararg_function_store.symbol_exists(vararg_function_name);
17572       }
17573
17574       inline bool is_vector(const std::string& vector_name) const
17575       {
17576          if (!valid())
17577             return false;
17578          else
17579             return local_data().vector_store.symbol_exists(vector_name);
17580       }
17581
17582       inline std::string get_variable_name(const expression_ptr& ptr) const
17583       {
17584          return local_data().variable_store.entity_name(ptr);
17585       }
17586
17587       inline std::string get_vector_name(const vector_holder_ptr& ptr) const
17588       {
17589          return local_data().vector_store.entity_name(ptr);
17590       }
17591
17592       #ifndef exprtk_disable_string_capabilities
17593       inline std::string get_stringvar_name(const expression_ptr& ptr) const
17594       {
17595          return local_data().stringvar_store.entity_name(ptr);
17596       }
17597
17598       inline std::string get_conststr_stringvar_name(const expression_ptr& ptr) const
17599       {
17600          return local_data().stringvar_store.entity_name(ptr);
17601       }
17602       #endif
17603
17604       inline bool valid() const
17605       {
17606          // Symbol table sanity check.
17607          return control_block_ && control_block_->data_;
17608       }
17609
17610       inline void load_from(const symbol_table<T>& st)
17611       {
17612          {
17613             std::vector<std::string> name_list;
17614
17615             st.local_data().function_store.get_list(name_list);
17616
17617             if (!name_list.empty())
17618             {
17619                for (std::size_t i = 0; i < name_list.size(); ++i)
17620                {
17621                   exprtk::ifunction<T>& ifunc = *st.get_function(name_list[i]);
17622                   add_function(name_list[i],ifunc);
17623                }
17624             }
17625          }
17626
17627          {
17628             std::vector<std::string> name_list;
17629
17630             st.local_data().vararg_function_store.get_list(name_list);
17631
17632             if (!name_list.empty())
17633             {
17634                for (std::size_t i = 0; i < name_list.size(); ++i)
17635                {
17636                   exprtk::ivararg_function<T>& ivafunc = *st.get_vararg_function(name_list[i]);
17637                   add_function(name_list[i],ivafunc);
17638                }
17639             }
17640          }
17641
17642          {
17643             std::vector<std::string> name_list;
17644
17645             st.local_data().generic_function_store.get_list(name_list);
17646
17647             if (!name_list.empty())
17648             {
17649                for (std::size_t i = 0; i < name_list.size(); ++i)
17650                {
17651                   exprtk::igeneric_function<T>& ifunc = *st.get_generic_function(name_list[i]);
17652                   add_function(name_list[i],ifunc);
17653                }
17654             }
17655          }
17656
17657          {
17658             std::vector<std::string> name_list;
17659
17660             st.local_data().string_function_store.get_list(name_list);
17661
17662             if (!name_list.empty())
17663             {
17664                for (std::size_t i = 0; i < name_list.size(); ++i)
17665                {
17666                   exprtk::igeneric_function<T>& ifunc = *st.get_string_function(name_list[i]);
17667                   add_function(name_list[i],ifunc);
17668                }
17669             }
17670          }
17671
17672          {
17673             std::vector<std::string> name_list;
17674
17675             st.local_data().overload_function_store.get_list(name_list);
17676
17677             if (!name_list.empty())
17678             {
17679                for (std::size_t i = 0; i < name_list.size(); ++i)
17680                {
17681                   exprtk::igeneric_function<T>& ifunc = *st.get_overload_function(name_list[i]);
17682                   add_function(name_list[i],ifunc);
17683                }
17684             }
17685          }
17686       }
17687
17688    private:
17689
17690       inline bool valid_symbol(const std::string& symbol, const bool check_reserved_symb = true) const
17691       {
17692          if (symbol.empty())
17693             return false;
17694          else if (!details::is_letter(symbol[0]))
17695             return false;
17696          else if (symbol.size() > 1)
17697          {
17698             for (std::size_t i = 1; i < symbol.size(); ++i)
17699             {
17700                if (
17701                     !details::is_letter_or_digit(symbol[i]) &&
17702                     ('_' != symbol[i])
17703                   )
17704                {
17705                   if (('.' == symbol[i]) && (i < (symbol.size() - 1)))
17706                      continue;
17707                   else
17708                      return false;
17709                }
17710             }
17711          }
17712
17713          return (check_reserved_symb) ? (!local_data().is_reserved_symbol(symbol)) : true;
17714       }
17715
17716       inline bool valid_function(const std::string& symbol) const
17717       {
17718          if (symbol.empty())
17719             return false;
17720          else if (!details::is_letter(symbol[0]))
17721             return false;
17722          else if (symbol.size() > 1)
17723          {
17724             for (std::size_t i = 1; i < symbol.size(); ++i)
17725             {
17726                if (
17727                     !details::is_letter_or_digit(symbol[i]) &&
17728                     ('_' != symbol[i])
17729                   )
17730                {
17731                   if (('.' == symbol[i]) && (i < (symbol.size() - 1)))
17732                      continue;
17733                   else
17734                      return false;
17735                }
17736             }
17737          }
17738
17739          return true;
17740       }
17741
17742       typedef typename control_block::st_data local_data_t;
17743
17744       inline local_data_t& local_data()
17745       {
17746          return *(control_block_->data_);
17747       }
17748
17749       inline const local_data_t& local_data() const
17750       {
17751          return *(control_block_->data_);
17752       }
17753
17754       control_block* control_block_;
17755
17756       friend class parser<T>;
17757    };
17758
17759    template <typename T>
17760    class function_compositor;
17761
17762    template <typename T>
17763    class expression
17764    {
17765    private:
17766
17767       typedef details::expression_node<T>*  expression_ptr;
17768       typedef details::vector_holder<T>* vector_holder_ptr;
17769       typedef std::vector<symbol_table<T> >  symtab_list_t;
17770
17771       struct control_block
17772       {
17773          enum data_type
17774          {
17775             e_unknown  ,
17776             e_expr     ,
17777             e_vecholder,
17778             e_data     ,
17779             e_vecdata  ,
17780             e_string
17781          };
17782
17783          struct data_pack
17784          {
17785             data_pack()
17786             : pointer(0),
17787               type(e_unknown),
17788               size(0)
17789             {}
17790
17791             data_pack(void* ptr, const data_type dt, const std::size_t sz = 0)
17792             : pointer(ptr),
17793               type(dt),
17794               size(sz)
17795             {}
17796
17797             void*       pointer;
17798             data_type   type;
17799             std::size_t size;
17800          };
17801
17802          typedef std::vector<data_pack> local_data_list_t;
17803          typedef results_context<T>     results_context_t;
17804
17805          control_block()
17806          : ref_count(0),
17807            expr     (0),
17808            results  (0),
17809            retinv_null(false),
17810            return_invoked(&retinv_null)
17811          {}
17812
17813          explicit control_block(expression_ptr e)
17814          : ref_count(1),
17815            expr     (e),
17816            results  (0),
17817            retinv_null(false),
17818            return_invoked(&retinv_null)
17819          {}
17820
17821         ~control_block()
17822          {
17823             if (expr && details::branch_deletable(expr))
17824             {
17825                destroy_node(expr);
17826             }
17827
17828             if (!local_data_list.empty())
17829             {
17830                for (std::size_t i = 0; i < local_data_list.size(); ++i)
17831                {
17832                   switch (local_data_list[i].type)
17833                   {
17834                      case e_expr      : delete reinterpret_cast<expression_ptr>(local_data_list[i].pointer);
17835                                         break;
17836
17837                      case e_vecholder : delete reinterpret_cast<vector_holder_ptr>(local_data_list[i].pointer);
17838                                         break;
17839
17840                      case e_data      : delete (T*)(local_data_list[i].pointer);
17841                                         break;
17842
17843                      case e_vecdata   : delete [] (T*)(local_data_list[i].pointer);
17844                                         break;
17845
17846                      case e_string    : delete (std::string*)(local_data_list[i].pointer);
17847                                         break;
17848
17849                      default          : break;
17850                   }
17851                }
17852             }
17853
17854             if (results)
17855             {
17856                delete results;
17857             }
17858          }
17859
17860          static inline control_block* create(expression_ptr e)
17861          {
17862             return new control_block(e);
17863          }
17864
17865          static inline void destroy(control_block*& cntrl_blck)
17866          {
17867             if (cntrl_blck)
17868             {
17869                if (
17870                     (0 !=   cntrl_blck->ref_count) &&
17871                     (0 == --cntrl_blck->ref_count)
17872                   )
17873                {
17874                   delete cntrl_blck;
17875                }
17876
17877                cntrl_blck = 0;
17878             }
17879          }
17880
17881          std::size_t ref_count;
17882          expression_ptr expr;
17883          local_data_list_t local_data_list;
17884          results_context_t* results;
17885          bool  retinv_null;
17886          bool* return_invoked;
17887
17888          friend class function_compositor<T>;
17889       };
17890
17891    public:
17892
17893       expression()
17894       : control_block_(0)
17895       {
17896          set_expression(new details::null_node<T>());
17897       }
17898
17899       expression(const expression<T>& e)
17900       : control_block_    (e.control_block_    ),
17901         symbol_table_list_(e.symbol_table_list_)
17902       {
17903          control_block_->ref_count++;
17904       }
17905
17906       explicit expression(const symbol_table<T>& symbol_table)
17907       : control_block_(0)
17908       {
17909          set_expression(new details::null_node<T>());
17910          symbol_table_list_.push_back(symbol_table);
17911       }
17912
17913       inline expression<T>& operator=(const expression<T>& e)
17914       {
17915          if (this != &e)
17916          {
17917             if (control_block_)
17918             {
17919                if (
17920                     (0 !=   control_block_->ref_count) &&
17921                     (0 == --control_block_->ref_count)
17922                   )
17923                {
17924                   delete control_block_;
17925                }
17926
17927                control_block_ = 0;
17928             }
17929
17930             control_block_ = e.control_block_;
17931             control_block_->ref_count++;
17932             symbol_table_list_ = e.symbol_table_list_;
17933          }
17934
17935          return *this;
17936       }
17937
17938       inline bool operator==(const expression<T>& e) const
17939       {
17940          return (this == &e);
17941       }
17942
17943       inline bool operator!() const
17944       {
17945          return (
17946                   (0 == control_block_      ) ||
17947                   (0 == control_block_->expr)
17948                 );
17949       }
17950
17951       inline expression<T>& release()
17952       {
17953          control_block::destroy(control_block_);
17954
17955          return (*this);
17956       }
17957
17958      ~expression()
17959       {
17960          control_block::destroy(control_block_);
17961       }
17962
17963       inline T value() const
17964       {
17965          return control_block_->expr->value();
17966       }
17967
17968       inline T operator() () const
17969       {
17970          return value();
17971       }
17972
17973       inline operator T() const
17974       {
17975          return value();
17976       }
17977
17978       inline operator bool() const
17979       {
17980          return details::is_true(value());
17981       }
17982
17983       inline void register_symbol_table(symbol_table<T>& st)
17984       {
17985          symbol_table_list_.push_back(st);
17986       }
17987
17988       inline const symbol_table<T>& get_symbol_table(const std::size_t& index = 0) const
17989       {
17990          return symbol_table_list_[index];
17991       }
17992
17993       inline symbol_table<T>& get_symbol_table(const std::size_t& index = 0)
17994       {
17995          return symbol_table_list_[index];
17996       }
17997
17998       typedef results_context<T> results_context_t;
17999
18000       inline const results_context_t& results() const
18001       {
18002          if (control_block_->results)
18003             return (*control_block_->results);
18004          else
18005          {
18006             static const results_context_t null_results;
18007             return null_results;
18008          }
18009       }
18010
18011       inline bool return_invoked() const
18012       {
18013          return (*control_block_->return_invoked);
18014       }
18015
18016    private:
18017
18018       inline symtab_list_t get_symbol_table_list() const
18019       {
18020          return symbol_table_list_;
18021       }
18022
18023       inline void set_expression(const expression_ptr expr)
18024       {
18025          if (expr)
18026          {
18027             if (control_block_)
18028             {
18029                if (0 == --control_block_->ref_count)
18030                {
18031                   delete control_block_;
18032                }
18033             }
18034
18035             control_block_ = control_block::create(expr);
18036          }
18037       }
18038
18039       inline void register_local_var(expression_ptr expr)
18040       {
18041          if (expr)
18042          {
18043             if (control_block_)
18044             {
18045                control_block_->
18046                   local_data_list.push_back(
18047                      typename expression<T>::control_block::
18048                         data_pack(reinterpret_cast<void*>(expr),
18049                                   control_block::e_expr));
18050             }
18051          }
18052       }
18053
18054       inline void register_local_var(vector_holder_ptr vec_holder)
18055       {
18056          if (vec_holder)
18057          {
18058             if (control_block_)
18059             {
18060                control_block_->
18061                   local_data_list.push_back(
18062                      typename expression<T>::control_block::
18063                         data_pack(reinterpret_cast<void*>(vec_holder),
18064                                   control_block::e_vecholder));
18065             }
18066          }
18067       }
18068
18069       inline void register_local_data(void* data, const std::size_t& size = 0, const std::size_t data_mode = 0)
18070       {
18071          if (data)
18072          {
18073             if (control_block_)
18074             {
18075                typename control_block::data_type dt = control_block::e_data;
18076
18077                switch (data_mode)
18078                {
18079                   case 0 : dt = control_block::e_data;    break;
18080                   case 1 : dt = control_block::e_vecdata; break;
18081                   case 2 : dt = control_block::e_string;  break;
18082                }
18083
18084                control_block_->
18085                   local_data_list.push_back(
18086                      typename expression<T>::control_block::
18087                         data_pack(reinterpret_cast<void*>(data), dt, size));
18088             }
18089          }
18090       }
18091
18092       inline const typename control_block::local_data_list_t& local_data_list()
18093       {
18094          if (control_block_)
18095          {
18096             return control_block_->local_data_list;
18097          }
18098          else
18099          {
18100             static typename control_block::local_data_list_t null_local_data_list;
18101             return null_local_data_list;
18102          }
18103       }
18104
18105       inline void register_return_results(results_context_t* rc)
18106       {
18107          if (control_block_ && rc)
18108          {
18109             control_block_->results = rc;
18110          }
18111       }
18112
18113       inline void set_retinvk(bool* retinvk_ptr)
18114       {
18115          if (control_block_)
18116          {
18117             control_block_->return_invoked = retinvk_ptr;
18118          }
18119       }
18120
18121       control_block* control_block_;
18122       symtab_list_t  symbol_table_list_;
18123
18124       friend class parser<T>;
18125       friend class expression_helper<T>;
18126       friend class function_compositor<T>;
18127    };
18128
18129    template <typename T>
18130    class expression_helper
18131    {
18132    public:
18133
18134       static inline bool is_constant(const expression<T>& expr)
18135       {
18136          return details::is_constant_node(expr.control_block_->expr);
18137       }
18138
18139       static inline bool is_variable(const expression<T>& expr)
18140       {
18141          return details::is_variable_node(expr.control_block_->expr);
18142       }
18143
18144       static inline bool is_unary(const expression<T>& expr)
18145       {
18146          return details::is_unary_node(expr.control_block_->expr);
18147       }
18148
18149       static inline bool is_binary(const expression<T>& expr)
18150       {
18151          return details::is_binary_node(expr.control_block_->expr);
18152       }
18153
18154       static inline bool is_function(const expression<T>& expr)
18155       {
18156          return details::is_function(expr.control_block_->expr);
18157       }
18158
18159       static inline bool is_null(const expression<T>& expr)
18160       {
18161          return details::is_null_node(expr.control_block_->expr);
18162       }
18163    };
18164
18165    template <typename T>
18166    inline bool is_valid(const expression<T>& expr)
18167    {
18168       return !expression_helper<T>::is_null(expr);
18169    }
18170
18171    namespace parser_error
18172    {
18173       enum error_mode
18174       {
18175          e_unknown = 0,
18176          e_syntax  = 1,
18177          e_token   = 2,
18178          e_numeric = 4,
18179          e_symtab  = 5,
18180          e_lexer   = 6,
18181          e_helper  = 7
18182       };
18183
18184       struct type
18185       {
18186          type()
18187          : mode(parser_error::e_unknown),
18188            line_no  (0),
18189            column_no(0)
18190          {}
18191
18192          lexer::token token;
18193          error_mode mode;
18194          std::string diagnostic;
18195          std::string src_location;
18196          std::string error_line;
18197          std::size_t line_no;
18198          std::size_t column_no;
18199       };
18200
18201       inline type make_error(const error_mode mode,
18202                              const std::string& diagnostic   = "",
18203                              const std::string& src_location = "")
18204       {
18205          type t;
18206          t.mode         = mode;
18207          t.token.type   = lexer::token::e_error;
18208          t.diagnostic   = diagnostic;
18209          t.src_location = src_location;
18210          exprtk_debug(("%s\n",diagnostic .c_str()));
18211          return t;
18212       }
18213
18214       inline type make_error(const error_mode mode,
18215                              const lexer::token& tk,
18216                              const std::string& diagnostic   = "",
18217                              const std::string& src_location = "")
18218       {
18219          type t;
18220          t.mode       = mode;
18221          t.token      = tk;
18222          t.diagnostic = diagnostic;
18223          t.src_location = src_location;
18224          exprtk_debug(("%s\n",diagnostic .c_str()));
18225          return t;
18226       }
18227
18228       inline std::string to_str(error_mode mode)
18229       {
18230          switch (mode)
18231          {
18232             case e_unknown : return std::string("Unknown Error");
18233             case e_syntax  : return std::string("Syntax Error" );
18234             case e_token   : return std::string("Token Error"  );
18235             case e_numeric : return std::string("Numeric Error");
18236             case e_symtab  : return std::string("Symbol Error" );
18237             case e_lexer   : return std::string("Lexer Error"  );
18238             case e_helper  : return std::string("Helper Error" );
18239             default        : return std::string("Unknown Error");
18240          }
18241       }
18242
18243       inline bool update_error(type& error, const std::string& expression)
18244       {
18245          if (
18246               expression.empty()                         ||
18247               (error.token.position > expression.size()) ||
18248               (std::numeric_limits<std::size_t>::max() == error.token.position)
18249             )
18250          {
18251             return false;
18252          }
18253
18254          std::size_t error_line_start = 0;
18255
18256          for (std::size_t i = error.token.position; i > 0; --i)
18257          {
18258             const details::char_t c = expression[i];
18259
18260             if (('\n' == c) || ('\r' == c))
18261             {
18262                error_line_start = i + 1;
18263                break;
18264             }
18265          }
18266
18267          std::size_t next_nl_position = std::min(expression.size(),
18268                                                  expression.find_first_of('\n',error.token.position + 1));
18269
18270          error.column_no  = error.token.position - error_line_start;
18271          error.error_line = expression.substr(error_line_start,
18272                                               next_nl_position - error_line_start);
18273
18274          error.line_no = 0;
18275
18276          for (std::size_t i = 0; i < next_nl_position; ++i)
18277          {
18278             if ('\n' == expression[i])
18279                ++error.line_no;
18280          }
18281
18282          return true;
18283       }
18284
18285       inline void dump_error(const type& error)
18286       {
18287          printf("Position: %02d   Type: [%s]   Msg: %s\n",
18288                 static_cast<int>(error.token.position),
18289                 exprtk::parser_error::to_str(error.mode).c_str(),
18290                 error.diagnostic.c_str());
18291       }
18292    }
18293
18294    namespace details
18295    {
18296       template <typename Parser>
18297       inline void disable_type_checking(Parser& p)
18298       {
18299          p.state_.type_check_enabled = false;
18300       }
18301    }
18302
18303    template <typename T>
18304    class parser : public lexer::parser_helper
18305    {
18306    private:
18307
18308       enum precedence_level
18309       {
18310          e_level00,
18311          e_level01,
18312          e_level02,
18313          e_level03,
18314          e_level04,
18315          e_level05,
18316          e_level06,
18317          e_level07,
18318          e_level08,
18319          e_level09,
18320          e_level10,
18321          e_level11,
18322          e_level12,
18323          e_level13,
18324          e_level14
18325       };
18326
18327       typedef const T&                                               cref_t;
18328       typedef const T                                               const_t;
18329       typedef ifunction                <T>                                F;
18330       typedef ivararg_function         <T>                              VAF;
18331       typedef igeneric_function        <T>                               GF;
18332       typedef ifunction                <T>                      ifunction_t;
18333       typedef ivararg_function         <T>               ivararg_function_t;
18334       typedef igeneric_function        <T>              igeneric_function_t;
18335       typedef details::expression_node <T>                expression_node_t;
18336       typedef details::literal_node    <T>                   literal_node_t;
18337       typedef details::unary_node      <T>                     unary_node_t;
18338       typedef details::binary_node     <T>                    binary_node_t;
18339       typedef details::trinary_node    <T>                   trinary_node_t;
18340       typedef details::quaternary_node <T>                quaternary_node_t;
18341       typedef details::conditional_node<T>               conditional_node_t;
18342       typedef details::cons_conditional_node<T>     cons_conditional_node_t;
18343       typedef details::while_loop_node <T>                while_loop_node_t;
18344       typedef details::repeat_until_loop_node<T>   repeat_until_loop_node_t;
18345       typedef details::for_loop_node   <T>                  for_loop_node_t;
18346       #ifndef exprtk_disable_break_continue
18347       typedef details::while_loop_bc_node <T>          while_loop_bc_node_t;
18348       typedef details::repeat_until_loop_bc_node<T> repeat_until_loop_bc_node_t;
18349       typedef details::for_loop_bc_node<T>               for_loop_bc_node_t;
18350       #endif
18351       typedef details::switch_node     <T>                    switch_node_t;
18352       typedef details::variable_node   <T>                  variable_node_t;
18353       typedef details::vector_elem_node<T>               vector_elem_node_t;
18354       typedef details::rebasevector_elem_node<T>   rebasevector_elem_node_t;
18355       typedef details::rebasevector_celem_node<T> rebasevector_celem_node_t;
18356       typedef details::vector_node     <T>                    vector_node_t;
18357       typedef details::range_pack      <T>                          range_t;
18358       #ifndef exprtk_disable_string_capabilities
18359       typedef details::stringvar_node     <T>              stringvar_node_t;
18360       typedef details::string_literal_node<T>         string_literal_node_t;
18361       typedef details::string_range_node  <T>           string_range_node_t;
18362       typedef details::const_string_range_node<T> const_string_range_node_t;
18363       typedef details::generic_string_range_node<T> generic_string_range_node_t;
18364       typedef details::string_concat_node <T>          string_concat_node_t;
18365       typedef details::assignment_string_node<T>   assignment_string_node_t;
18366       typedef details::assignment_string_range_node<T> assignment_string_range_node_t;
18367       typedef details::conditional_string_node<T>  conditional_string_node_t;
18368       typedef details::cons_conditional_str_node<T> cons_conditional_str_node_t;
18369       #endif
18370       typedef details::assignment_node<T>                 assignment_node_t;
18371       typedef details::assignment_vec_elem_node       <T> assignment_vec_elem_node_t;
18372       typedef details::assignment_rebasevec_elem_node <T> assignment_rebasevec_elem_node_t;
18373       typedef details::assignment_rebasevec_celem_node<T> assignment_rebasevec_celem_node_t;
18374       typedef details::assignment_vec_node     <T>    assignment_vec_node_t;
18375       typedef details::assignment_vecvec_node  <T> assignment_vecvec_node_t;
18376       typedef details::scand_node<T>                           scand_node_t;
18377       typedef details::scor_node<T>                             scor_node_t;
18378       typedef lexer::token                                          token_t;
18379       typedef expression_node_t*                        expression_node_ptr;
18380       typedef expression<T>                                    expression_t;
18381       typedef symbol_table<T>                                symbol_table_t;
18382       typedef typename expression<T>::symtab_list_t     symbol_table_list_t;
18383       typedef details::vector_holder<T>*                  vector_holder_ptr;
18384
18385       typedef typename details::functor_t<T>            functor_t;
18386       typedef typename functor_t::qfunc_t    quaternary_functor_t;
18387       typedef typename functor_t::tfunc_t       trinary_functor_t;
18388       typedef typename functor_t::bfunc_t        binary_functor_t;
18389       typedef typename functor_t::ufunc_t         unary_functor_t;
18390
18391       typedef details::operator_type operator_t;
18392
18393       typedef std::map<operator_t,  unary_functor_t>   unary_op_map_t;
18394       typedef std::map<operator_t, binary_functor_t>  binary_op_map_t;
18395       typedef std::map<operator_t,trinary_functor_t> trinary_op_map_t;
18396
18397       typedef std::map<std::string,std::pair<trinary_functor_t   ,operator_t> > sf3_map_t;
18398       typedef std::map<std::string,std::pair<quaternary_functor_t,operator_t> > sf4_map_t;
18399
18400       typedef std::map<binary_functor_t,operator_t> inv_binary_op_map_t;
18401       typedef std::multimap<std::string,details::base_operation_t,details::ilesscompare> base_ops_map_t;
18402       typedef std::set<std::string,details::ilesscompare> disabled_func_set_t;
18403
18404       typedef details::T0oT1_define<T,  cref_t,  cref_t> vov_t;
18405       typedef details::T0oT1_define<T, const_t,  cref_t> cov_t;
18406       typedef details::T0oT1_define<T,  cref_t, const_t> voc_t;
18407
18408       typedef details::T0oT1oT2_define<T,  cref_t,  cref_t,  cref_t> vovov_t;
18409       typedef details::T0oT1oT2_define<T,  cref_t,  cref_t, const_t> vovoc_t;
18410       typedef details::T0oT1oT2_define<T,  cref_t, const_t,  cref_t> vocov_t;
18411       typedef details::T0oT1oT2_define<T, const_t,  cref_t,  cref_t> covov_t;
18412       typedef details::T0oT1oT2_define<T, const_t,  cref_t, const_t> covoc_t;
18413       typedef details::T0oT1oT2_define<T, const_t, const_t,  cref_t> cocov_t;
18414       typedef details::T0oT1oT2_define<T,  cref_t, const_t, const_t> vococ_t;
18415
18416       typedef details::T0oT1oT2oT3_define<T,  cref_t,  cref_t,  cref_t,  cref_t> vovovov_t;
18417       typedef details::T0oT1oT2oT3_define<T,  cref_t,  cref_t,  cref_t, const_t> vovovoc_t;
18418       typedef details::T0oT1oT2oT3_define<T,  cref_t,  cref_t, const_t,  cref_t> vovocov_t;
18419       typedef details::T0oT1oT2oT3_define<T,  cref_t, const_t,  cref_t,  cref_t> vocovov_t;
18420       typedef details::T0oT1oT2oT3_define<T, const_t,  cref_t,  cref_t,  cref_t> covovov_t;
18421
18422       typedef details::T0oT1oT2oT3_define<T, const_t,  cref_t, const_t,  cref_t> covocov_t;
18423       typedef details::T0oT1oT2oT3_define<T,  cref_t, const_t,  cref_t, const_t> vocovoc_t;
18424       typedef details::T0oT1oT2oT3_define<T, const_t,  cref_t,  cref_t, const_t> covovoc_t;
18425       typedef details::T0oT1oT2oT3_define<T,  cref_t, const_t, const_t,  cref_t> vococov_t;
18426
18427       typedef results_context<T> results_context_t;
18428
18429       typedef parser_helper prsrhlpr_t;
18430
18431       struct scope_element
18432       {
18433          enum element_type
18434          {
18435             e_none    ,
18436             e_variable,
18437             e_vector  ,
18438             e_vecelem ,
18439             e_string
18440          };
18441
18442          typedef details::vector_holder<T> vector_holder_t;
18443          typedef variable_node_t*        variable_node_ptr;
18444          typedef vector_holder_t*        vector_holder_ptr;
18445          typedef expression_node_t*    expression_node_ptr;
18446          #ifndef exprtk_disable_string_capabilities
18447          typedef stringvar_node_t*      stringvar_node_ptr;
18448          #endif
18449
18450          scope_element()
18451          : name("???"),
18452            size (std::numeric_limits<std::size_t>::max()),
18453            index(std::numeric_limits<std::size_t>::max()),
18454            depth(std::numeric_limits<std::size_t>::max()),
18455            ref_count(0),
18456            ip_index (0),
18457            type (e_none),
18458            active(false),
18459            data    (0),
18460            var_node(0),
18461            vec_node(0)
18462            #ifndef exprtk_disable_string_capabilities
18463            ,str_node(0)
18464            #endif
18465          {}
18466
18467          bool operator < (const scope_element& se) const
18468          {
18469             if (ip_index < se.ip_index)
18470                return true;
18471             else if (ip_index > se.ip_index)
18472                return false;
18473             else if (depth < se.depth)
18474                return true;
18475             else if (depth > se.depth)
18476                return false;
18477             else if (index < se.index)
18478                return true;
18479             else if (index > se.index)
18480                return false;
18481             else
18482                return (name < se.name);
18483          }
18484
18485          void clear()
18486          {
18487             name   = "???";
18488             size   = std::numeric_limits<std::size_t>::max();
18489             index  = std::numeric_limits<std::size_t>::max();
18490             depth  = std::numeric_limits<std::size_t>::max();
18491             type   = e_none;
18492             active = false;
18493             ref_count = 0;
18494             ip_index  = 0;
18495             data      = 0;
18496             var_node  = 0;
18497             vec_node  = 0;
18498             #ifndef exprtk_disable_string_capabilities
18499             str_node  = 0;
18500             #endif
18501          }
18502
18503          std::string  name;
18504          std::size_t  size;
18505          std::size_t  index;
18506          std::size_t  depth;
18507          std::size_t  ref_count;
18508          std::size_t  ip_index;
18509          element_type type;
18510          bool         active;
18511          void*        data;
18512          expression_node_ptr var_node;
18513          vector_holder_ptr   vec_node;
18514          #ifndef exprtk_disable_string_capabilities
18515          stringvar_node_ptr str_node;
18516          #endif
18517       };
18518
18519       class scope_element_manager
18520       {
18521       public:
18522
18523          typedef expression_node_t* expression_node_ptr;
18524          typedef variable_node_t*     variable_node_ptr;
18525          typedef parser<T>                     parser_t;
18526
18527          explicit scope_element_manager(parser<T>& p)
18528          : parser_(p),
18529            input_param_cnt_(0)
18530          {}
18531
18532          inline std::size_t size() const
18533          {
18534             return element_.size();
18535          }
18536
18537          inline bool empty() const
18538          {
18539             return element_.empty();
18540          }
18541
18542          inline scope_element& get_element(const std::size_t& index)
18543          {
18544             if (index < element_.size())
18545                return element_[index];
18546             else
18547                return null_element_;
18548          }
18549
18550          inline scope_element& get_element(const std::string& var_name,
18551                                            const std::size_t index = std::numeric_limits<std::size_t>::max())
18552          {
18553             const std::size_t current_depth = parser_.state_.scope_depth;
18554
18555             for (std::size_t i = 0; i < element_.size(); ++i)
18556             {
18557                scope_element& se = element_[i];
18558
18559                if (se.depth > current_depth)
18560                   continue;
18561                else if (
18562                          details::imatch(se.name, var_name) &&
18563                          (se.index == index)
18564                        )
18565                   return se;
18566             }
18567
18568             return null_element_;
18569          }
18570
18571          inline scope_element& get_active_element(const std::string& var_name,
18572                                                   const std::size_t index = std::numeric_limits<std::size_t>::max())
18573          {
18574             const std::size_t current_depth = parser_.state_.scope_depth;
18575
18576             for (std::size_t i = 0; i < element_.size(); ++i)
18577             {
18578                scope_element& se = element_[i];
18579
18580                if (se.depth > current_depth)
18581                   continue;
18582                else if (
18583                          details::imatch(se.name, var_name) &&
18584                          (se.index == index)                &&
18585                          (se.active)
18586                        )
18587                   return se;
18588             }
18589
18590             return null_element_;
18591          }
18592
18593          inline bool add_element(const scope_element& se)
18594          {
18595             for (std::size_t i = 0; i < element_.size(); ++i)
18596             {
18597                scope_element& cse = element_[i];
18598
18599                if (
18600                     details::imatch(cse.name, se.name) &&
18601                     (cse.depth <= se.depth)            &&
18602                     (cse.index == se.index)            &&
18603                     (cse.size  == se.size )            &&
18604                     (cse.type  == se.type )            &&
18605                     (cse.active)
18606                   )
18607                   return false;
18608             }
18609
18610             element_.push_back(se);
18611             std::sort(element_.begin(),element_.end());
18612
18613             return true;
18614          }
18615
18616          inline void deactivate(const std::size_t& scope_depth)
18617          {
18618             exprtk_debug(("deactivate() - Scope depth: %d\n",
18619                           static_cast<int>(parser_.state_.scope_depth)));
18620
18621             for (std::size_t i = 0; i < element_.size(); ++i)
18622             {
18623                scope_element& se = element_[i];
18624
18625                if (se.active && (se.depth >= scope_depth))
18626                {
18627                   exprtk_debug(("deactivate() - element[%02d] '%s'\n",
18628                                 static_cast<int>(i),
18629                                 se.name.c_str()));
18630
18631                   se.active = false;
18632                }
18633             }
18634          }
18635
18636          inline void free_element(scope_element& se)
18637          {
18638             #ifdef exprtk_enable_debugging
18639             exprtk_debug(("free_element() - se[%s]\n", se.name.c_str()));
18640             #endif
18641
18642             switch (se.type)
18643             {
18644                case scope_element::e_variable   : if (se.data    ) delete (T*) se.data;
18645                                                   if (se.var_node) delete se.var_node;
18646                                                   break;
18647
18648                case scope_element::e_vector     : if (se.data    ) delete[] (T*) se.data;
18649                                                   if (se.vec_node) delete se.vec_node;
18650                                                   break;
18651
18652                case scope_element::e_vecelem    : if (se.var_node) delete se.var_node;
18653                                                   break;
18654
18655                #ifndef exprtk_disable_string_capabilities
18656                case scope_element::e_string     : if (se.data    ) delete (std::string*) se.data;
18657                                                   if (se.str_node) delete se.str_node;
18658                                                   break;
18659                #endif
18660
18661                default                          : return;
18662             }
18663
18664             se.clear();
18665          }
18666
18667          inline void cleanup()
18668          {
18669             for (std::size_t i = 0; i < element_.size(); ++i)
18670             {
18671                free_element(element_[i]);
18672             }
18673
18674             element_.clear();
18675
18676             input_param_cnt_ = 0;
18677          }
18678
18679          inline std::size_t next_ip_index()
18680          {
18681             return ++input_param_cnt_;
18682          }
18683
18684          inline expression_node_ptr get_variable(const T& v)
18685          {
18686             for (std::size_t i = 0; i < element_.size(); ++i)
18687             {
18688                scope_element& se = element_[i];
18689
18690                if (
18691                     se.active   &&
18692                     se.var_node &&
18693                     details::is_variable_node(se.var_node)
18694                   )
18695                {
18696                   variable_node_ptr vn = reinterpret_cast<variable_node_ptr>(se.var_node);
18697
18698                   if (&(vn->ref()) == (&v))
18699                   {
18700                      return se.var_node;
18701                   }
18702                }
18703             }
18704
18705             return expression_node_ptr(0);
18706          }
18707
18708       private:
18709
18710          scope_element_manager& operator=(const scope_element_manager&);
18711
18712          parser_t& parser_;
18713          std::vector<scope_element> element_;
18714          scope_element null_element_;
18715          std::size_t input_param_cnt_;
18716       };
18717
18718       class scope_handler
18719       {
18720       public:
18721
18722          typedef parser<T> parser_t;
18723
18724          explicit scope_handler(parser<T>& p)
18725          : parser_(p)
18726          {
18727             parser_.state_.scope_depth++;
18728             #ifdef exprtk_enable_debugging
18729             const std::string depth(2 * parser_.state_.scope_depth,'-');
18730             exprtk_debug(("%s> Scope Depth: %02d\n",
18731                           depth.c_str(),
18732                           static_cast<int>(parser_.state_.scope_depth)));
18733             #endif
18734          }
18735
18736         ~scope_handler()
18737          {
18738             parser_.sem_.deactivate(parser_.state_.scope_depth);
18739             parser_.state_.scope_depth--;
18740             #ifdef exprtk_enable_debugging
18741             const std::string depth(2 * parser_.state_.scope_depth,'-');
18742             exprtk_debug(("<%s Scope Depth: %02d\n",
18743                           depth.c_str(),
18744                           static_cast<int>(parser_.state_.scope_depth)));
18745             #endif
18746          }
18747
18748       private:
18749
18750          scope_handler& operator=(const scope_handler&);
18751
18752          parser_t& parser_;
18753       };
18754
18755       struct symtab_store
18756       {
18757          symbol_table_list_t symtab_list_;
18758
18759          typedef typename symbol_table_t::local_data_t   local_data_t;
18760          typedef typename symbol_table_t::variable_ptr   variable_ptr;
18761          typedef typename symbol_table_t::function_ptr   function_ptr;
18762          #ifndef exprtk_disable_string_capabilities
18763          typedef typename symbol_table_t::stringvar_ptr stringvar_ptr;
18764          #endif
18765          typedef typename symbol_table_t::vector_holder_ptr       vector_holder_ptr;
18766          typedef typename symbol_table_t::vararg_function_ptr   vararg_function_ptr;
18767          typedef typename symbol_table_t::generic_function_ptr generic_function_ptr;
18768
18769          inline bool empty() const
18770          {
18771             return symtab_list_.empty();
18772          }
18773
18774          inline void clear()
18775          {
18776             symtab_list_.clear();
18777          }
18778
18779          inline bool valid() const
18780          {
18781             if (!empty())
18782             {
18783                for (std::size_t i = 0; i < symtab_list_.size(); ++i)
18784                {
18785                   if (symtab_list_[i].valid())
18786                      return true;
18787                }
18788             }
18789
18790             return false;
18791          }
18792
18793          inline bool valid_symbol(const std::string& symbol) const
18794          {
18795             if (!symtab_list_.empty())
18796                return symtab_list_[0].valid_symbol(symbol);
18797             else
18798                return false;
18799          }
18800
18801          inline bool valid_function_name(const std::string& symbol) const
18802          {
18803             if (!symtab_list_.empty())
18804                return symtab_list_[0].valid_function(symbol);
18805             else
18806                return false;
18807          }
18808
18809          inline variable_ptr get_variable(const std::string& variable_name) const
18810          {
18811             if (!valid_symbol(variable_name))
18812                return reinterpret_cast<variable_ptr>(0);
18813
18814             variable_ptr result = reinterpret_cast<variable_ptr>(0);
18815
18816             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
18817             {
18818                if (!symtab_list_[i].valid())
18819                   continue;
18820                else
18821                   result = local_data(i)
18822                               .variable_store.get(variable_name);
18823
18824                if (result) break;
18825             }
18826
18827             return result;
18828          }
18829
18830          inline variable_ptr get_variable(const T& var_ref) const
18831          {
18832             variable_ptr result = reinterpret_cast<variable_ptr>(0);
18833
18834             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
18835             {
18836                if (!symtab_list_[i].valid())
18837                   continue;
18838                else
18839                   result = local_data(i).variable_store
18840                               .get_from_varptr(reinterpret_cast<const void*>(&var_ref));
18841
18842                if (result) break;
18843             }
18844
18845             return result;
18846          }
18847
18848          #ifndef exprtk_disable_string_capabilities
18849          inline stringvar_ptr get_stringvar(const std::string& string_name) const
18850          {
18851             if (!valid_symbol(string_name))
18852                return reinterpret_cast<stringvar_ptr>(0);
18853
18854             stringvar_ptr result = reinterpret_cast<stringvar_ptr>(0);
18855
18856             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
18857             {
18858                if (!symtab_list_[i].valid())
18859                   continue;
18860                else
18861                   result = local_data(i)
18862                               .stringvar_store.get(string_name);
18863
18864                if (result) break;
18865             }
18866
18867             return result;
18868          }
18869          #endif
18870
18871          inline function_ptr get_function(const std::string& function_name) const
18872          {
18873             if (!valid_function_name(function_name))
18874                return reinterpret_cast<function_ptr>(0);
18875
18876             function_ptr result = reinterpret_cast<function_ptr>(0);
18877
18878             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
18879             {
18880                if (!symtab_list_[i].valid())
18881                   continue;
18882                else
18883                   result = local_data(i)
18884                               .function_store.get(function_name);
18885
18886                if (result) break;
18887             }
18888
18889             return result;
18890          }
18891
18892          inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const
18893          {
18894             if (!valid_function_name(vararg_function_name))
18895                return reinterpret_cast<vararg_function_ptr>(0);
18896
18897             vararg_function_ptr result = reinterpret_cast<vararg_function_ptr>(0);
18898
18899             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
18900             {
18901                if (!symtab_list_[i].valid())
18902                   continue;
18903                else
18904                   result = local_data(i)
18905                               .vararg_function_store.get(vararg_function_name);
18906
18907                if (result) break;
18908             }
18909
18910             return result;
18911          }
18912
18913          inline generic_function_ptr get_generic_function(const std::string& function_name) const
18914          {
18915             if (!valid_function_name(function_name))
18916                return reinterpret_cast<generic_function_ptr>(0);
18917
18918             generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0);
18919
18920             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
18921             {
18922                if (!symtab_list_[i].valid())
18923                   continue;
18924                else
18925                   result = local_data(i)
18926                               .generic_function_store.get(function_name);
18927
18928                if (result) break;
18929             }
18930
18931             return result;
18932          }
18933
18934          inline generic_function_ptr get_string_function(const std::string& function_name) const
18935          {
18936             if (!valid_function_name(function_name))
18937                return reinterpret_cast<generic_function_ptr>(0);
18938
18939             generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0);
18940
18941             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
18942             {
18943                if (!symtab_list_[i].valid())
18944                   continue;
18945                else
18946                   result =
18947                      local_data(i).string_function_store.get(function_name);
18948
18949                if (result) break;
18950             }
18951
18952             return result;
18953          }
18954
18955          inline generic_function_ptr get_overload_function(const std::string& function_name) const
18956          {
18957             if (!valid_function_name(function_name))
18958                return reinterpret_cast<generic_function_ptr>(0);
18959
18960             generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0);
18961
18962             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
18963             {
18964                if (!symtab_list_[i].valid())
18965                   continue;
18966                else
18967                   result =
18968                      local_data(i).overload_function_store.get(function_name);
18969
18970                if (result) break;
18971             }
18972
18973             return result;
18974          }
18975
18976          inline vector_holder_ptr get_vector(const std::string& vector_name) const
18977          {
18978             if (!valid_symbol(vector_name))
18979                return reinterpret_cast<vector_holder_ptr>(0);
18980
18981             vector_holder_ptr result = reinterpret_cast<vector_holder_ptr>(0);
18982
18983             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
18984             {
18985                if (!symtab_list_[i].valid())
18986                   continue;
18987                else
18988                   result =
18989                      local_data(i).vector_store.get(vector_name);
18990
18991                if (result) break;
18992             }
18993
18994             return result;
18995          }
18996
18997          inline bool is_constant_node(const std::string& symbol_name) const
18998          {
18999             if (!valid_symbol(symbol_name))
19000                return false;
19001
19002             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19003             {
19004                if (!symtab_list_[i].valid())
19005                   continue;
19006                else if (local_data(i).variable_store.is_constant(symbol_name))
19007                   return true;
19008             }
19009
19010             return false;
19011          }
19012
19013          #ifndef exprtk_disable_string_capabilities
19014          inline bool is_constant_string(const std::string& symbol_name) const
19015          {
19016             if (!valid_symbol(symbol_name))
19017                return false;
19018
19019             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19020             {
19021                if (!symtab_list_[i].valid())
19022                   continue;
19023                else if (!local_data(i).stringvar_store.symbol_exists(symbol_name))
19024                   continue;
19025                else if ( local_data(i).stringvar_store.is_constant(symbol_name))
19026                   return true;
19027             }
19028
19029             return false;
19030          }
19031          #endif
19032
19033          inline bool symbol_exists(const std::string& symbol) const
19034          {
19035             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19036             {
19037                if (!symtab_list_[i].valid())
19038                   continue;
19039                else if (symtab_list_[i].symbol_exists(symbol))
19040                   return true;
19041             }
19042
19043             return false;
19044          }
19045
19046          inline bool is_variable(const std::string& variable_name) const
19047          {
19048             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19049             {
19050                if (!symtab_list_[i].valid())
19051                   continue;
19052                else if (
19053                          symtab_list_[i].local_data().variable_store
19054                            .symbol_exists(variable_name)
19055                        )
19056                   return true;
19057             }
19058
19059             return false;
19060          }
19061
19062          #ifndef exprtk_disable_string_capabilities
19063          inline bool is_stringvar(const std::string& stringvar_name) const
19064          {
19065             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19066             {
19067                if (!symtab_list_[i].valid())
19068                   continue;
19069                else if (
19070                          symtab_list_[i].local_data().stringvar_store
19071                            .symbol_exists(stringvar_name)
19072                        )
19073                   return true;
19074             }
19075
19076             return false;
19077          }
19078
19079          inline bool is_conststr_stringvar(const std::string& symbol_name) const
19080          {
19081             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19082             {
19083                if (!symtab_list_[i].valid())
19084                   continue;
19085                else if (
19086                          symtab_list_[i].local_data().stringvar_store
19087                            .symbol_exists(symbol_name)
19088                        )
19089                {
19090                   return (
19091                            local_data(i).stringvar_store.symbol_exists(symbol_name) ||
19092                            local_data(i).stringvar_store.is_constant  (symbol_name)
19093                          );
19094
19095                }
19096             }
19097
19098             return false;
19099          }
19100          #endif
19101
19102          inline bool is_function(const std::string& function_name) const
19103          {
19104             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19105             {
19106                if (!symtab_list_[i].valid())
19107                   continue;
19108                else if (
19109                          local_data(i).vararg_function_store
19110                            .symbol_exists(function_name)
19111                        )
19112                   return true;
19113             }
19114
19115             return false;
19116          }
19117
19118          inline bool is_vararg_function(const std::string& vararg_function_name) const
19119          {
19120             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19121             {
19122                if (!symtab_list_[i].valid())
19123                   continue;
19124                else if (
19125                          local_data(i).vararg_function_store
19126                            .symbol_exists(vararg_function_name)
19127                        )
19128                   return true;
19129             }
19130
19131             return false;
19132          }
19133
19134          inline bool is_vector(const std::string& vector_name) const
19135          {
19136             for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19137             {
19138                if (!symtab_list_[i].valid())
19139                   continue;
19140                else if (
19141                          local_data(i).vector_store
19142                            .symbol_exists(vector_name)
19143                        )
19144                   return true;
19145             }
19146
19147             return false;
19148          }
19149
19150          inline std::string get_variable_name(const expression_node_ptr& ptr) const
19151          {
19152             return local_data().variable_store.entity_name(ptr);
19153          }
19154
19155          inline std::string get_vector_name(const vector_holder_ptr& ptr) const
19156          {
19157             return local_data().vector_store.entity_name(ptr);
19158          }
19159
19160          #ifndef exprtk_disable_string_capabilities
19161          inline std::string get_stringvar_name(const expression_node_ptr& ptr) const
19162          {
19163             return local_data().stringvar_store.entity_name(ptr);
19164          }
19165
19166          inline std::string get_conststr_stringvar_name(const expression_node_ptr& ptr) const
19167          {
19168             return local_data().stringvar_store.entity_name(ptr);
19169          }
19170          #endif
19171
19172          inline local_data_t& local_data(const std::size_t& index = 0)
19173          {
19174             return symtab_list_[index].local_data();
19175          }
19176
19177          inline const local_data_t& local_data(const std::size_t& index = 0) const
19178          {
19179             return symtab_list_[index].local_data();
19180          }
19181
19182          inline symbol_table_t& get_symbol_table(const std::size_t& index = 0)
19183          {
19184             return symtab_list_[index];
19185          }
19186       };
19187
19188       struct parser_state
19189       {
19190          parser_state()
19191          : type_check_enabled(true)
19192          {
19193             reset();
19194          }
19195
19196          void reset()
19197          {
19198             parsing_return_stmt = false;
19199             parsing_break_stmt  = false;
19200             return_stmt_present = false;
19201             side_effect_present = false;
19202             scope_depth         = 0;
19203          }
19204
19205          #ifndef exprtk_enable_debugging
19206          void activate_side_effect(const std::string&)
19207          #else
19208          void activate_side_effect(const std::string& source)
19209          #endif
19210          {
19211             if (!side_effect_present)
19212             {
19213                side_effect_present = true;
19214
19215                exprtk_debug(("activate_side_effect() - caller: %s\n",source.c_str()));
19216             }
19217          }
19218
19219          bool parsing_return_stmt;
19220          bool parsing_break_stmt;
19221          bool return_stmt_present;
19222          bool side_effect_present;
19223          bool type_check_enabled;
19224          std::size_t scope_depth;
19225       };
19226
19227    public:
19228
19229       struct unknown_symbol_resolver
19230       {
19231
19232          enum usr_symbol_type
19233          {
19234             e_usr_unknown_type  = 0,
19235             e_usr_variable_type = 1,
19236             e_usr_constant_type = 2
19237          };
19238
19239          enum usr_mode
19240          {
19241             e_usrmode_default  = 0,
19242             e_usrmode_extended = 1
19243          };
19244
19245          usr_mode mode;
19246
19247          unknown_symbol_resolver(const usr_mode m = e_usrmode_default)
19248          : mode(m)
19249          {}
19250
19251          virtual ~unknown_symbol_resolver()
19252          {}
19253
19254          virtual bool process(const std::string& /*unknown_symbol*/,
19255                               usr_symbol_type&   st,
19256                               T&                 default_value,
19257                               std::string&       error_message)
19258          {
19259             if (e_usrmode_default != mode)
19260                return false;
19261
19262             st = e_usr_variable_type;
19263             default_value = T(0);
19264             error_message.clear();
19265
19266             return true;
19267          }
19268
19269          virtual bool process(const std::string& /* unknown_symbol */,
19270                               symbol_table_t&    /* symbol_table   */,
19271                               std::string&       /* error_message  */)
19272          {
19273             return false;
19274          }
19275       };
19276
19277       enum collect_type
19278       {
19279          e_ct_none        = 0,
19280          e_ct_variables   = 1,
19281          e_ct_functions   = 2,
19282          e_ct_assignments = 4
19283       };
19284
19285       enum symbol_type
19286       {
19287          e_st_unknown        = 0,
19288          e_st_variable       = 1,
19289          e_st_vector         = 2,
19290          e_st_vecelem        = 3,
19291          e_st_string         = 4,
19292          e_st_function       = 5,
19293          e_st_local_variable = 6,
19294          e_st_local_vector   = 7,
19295          e_st_local_string   = 8
19296       };
19297
19298       class dependent_entity_collector
19299       {
19300       public:
19301
19302          typedef std::pair<std::string,symbol_type> symbol_t;
19303          typedef std::vector<symbol_t> symbol_list_t;
19304
19305          dependent_entity_collector(const std::size_t options = e_ct_none)
19306          : options_(options),
19307            collect_variables_  ((options_ & e_ct_variables  ) == e_ct_variables  ),
19308            collect_functions_  ((options_ & e_ct_functions  ) == e_ct_functions  ),
19309            collect_assignments_((options_ & e_ct_assignments) == e_ct_assignments),
19310            return_present_   (false),
19311            final_stmt_return_(false)
19312          {}
19313
19314          template <typename Allocator,
19315                    template <typename, typename> class Sequence>
19316          inline std::size_t symbols(Sequence<symbol_t,Allocator>& symbols_list)
19317          {
19318             if (!collect_variables_ && !collect_functions_)
19319                return 0;
19320             else if (symbol_name_list_.empty())
19321                return 0;
19322
19323             for (std::size_t i = 0; i < symbol_name_list_.size(); ++i)
19324             {
19325                details::case_normalise(symbol_name_list_[i].first);
19326             }
19327
19328             std::sort(symbol_name_list_.begin(),symbol_name_list_.end());
19329
19330             std::unique_copy(symbol_name_list_.begin(),
19331                              symbol_name_list_.end  (),
19332                              std::back_inserter(symbols_list));
19333
19334             return symbols_list.size();
19335          }
19336
19337          template <typename Allocator,
19338                    template <typename, typename> class Sequence>
19339          inline std::size_t assignment_symbols(Sequence<symbol_t,Allocator>& assignment_list)
19340          {
19341             if (!collect_assignments_)
19342                return 0;
19343             else if (assignment_name_list_.empty())
19344                return 0;
19345
19346             for (std::size_t i = 0; i < assignment_name_list_.size(); ++i)
19347             {
19348                details::case_normalise(assignment_name_list_[i].first);
19349             }
19350
19351             std::sort(assignment_name_list_.begin(),assignment_name_list_.end());
19352
19353             std::unique_copy(assignment_name_list_.begin(),
19354                              assignment_name_list_.end  (),
19355                              std::back_inserter(assignment_list));
19356
19357             return assignment_list.size();
19358          }
19359
19360          void clear()
19361          {
19362             symbol_name_list_    .clear();
19363             assignment_name_list_.clear();
19364             retparam_list_       .clear();
19365             return_present_    = false;
19366             final_stmt_return_ = false;
19367          }
19368
19369          bool& collect_variables()
19370          {
19371             return collect_variables_;
19372          }
19373
19374          bool& collect_functions()
19375          {
19376             return collect_functions_;
19377          }
19378
19379          bool& collect_assignments()
19380          {
19381             return collect_assignments_;
19382          }
19383
19384          bool return_present() const
19385          {
19386             return return_present_;
19387          }
19388
19389          bool final_stmt_return() const
19390          {
19391             return final_stmt_return_;
19392          }
19393
19394          typedef std::vector<std::string> retparam_list_t;
19395
19396          retparam_list_t return_param_type_list() const
19397          {
19398             return retparam_list_;
19399          }
19400
19401       private:
19402
19403          inline void add_symbol(const std::string& symbol, const symbol_type st)
19404          {
19405             switch (st)
19406             {
19407                case e_st_variable       :
19408                case e_st_vector         :
19409                case e_st_string         :
19410                case e_st_local_variable :
19411                case e_st_local_vector   :
19412                case e_st_local_string   : if (collect_variables_)
19413                                              symbol_name_list_
19414                                                 .push_back(std::make_pair(symbol, st));
19415                                           break;
19416
19417                case e_st_function       : if (collect_functions_)
19418                                              symbol_name_list_
19419                                                 .push_back(std::make_pair(symbol, st));
19420                                           break;
19421
19422                default                  : return;
19423             }
19424          }
19425
19426          inline void add_assignment(const std::string& symbol, const symbol_type st)
19427          {
19428             switch (st)
19429             {
19430                case e_st_variable       :
19431                case e_st_vector         :
19432                case e_st_string         : if (collect_assignments_)
19433                                              assignment_name_list_
19434                                                 .push_back(std::make_pair(symbol, st));
19435                                           break;
19436
19437                default                  : return;
19438             }
19439          }
19440
19441          std::size_t options_;
19442          bool collect_variables_;
19443          bool collect_functions_;
19444          bool collect_assignments_;
19445          bool return_present_;
19446          bool final_stmt_return_;
19447          symbol_list_t symbol_name_list_;
19448          symbol_list_t assignment_name_list_;
19449          retparam_list_t retparam_list_;
19450
19451          friend class parser<T>;
19452       };
19453
19454       class settings_store
19455       {
19456       private:
19457
19458          typedef std::set<std::string,details::ilesscompare> disabled_entity_set_t;
19459          typedef disabled_entity_set_t::iterator des_itr_t;
19460
19461       public:
19462
19463          enum settings_compilation_options
19464          {
19465             e_unknown              =    0,
19466             e_replacer             =    1,
19467             e_joiner               =    2,
19468             e_numeric_check        =    4,
19469             e_bracket_check        =    8,
19470             e_sequence_check       =   16,
19471             e_commutative_check    =   32,
19472             e_strength_reduction   =   64,
19473             e_disable_vardef       =  128,
19474             e_collect_vars         =  256,
19475             e_collect_funcs        =  512,
19476             e_collect_assings      = 1024,
19477             e_disable_usr_on_rsrvd = 2048,
19478             e_disable_zero_return  = 4096
19479          };
19480
19481          enum settings_base_funcs
19482          {
19483             e_bf_unknown = 0,
19484             e_bf_abs       , e_bf_acos     , e_bf_acosh    , e_bf_asin   ,
19485             e_bf_asinh     , e_bf_atan     , e_bf_atan2    , e_bf_atanh  ,
19486             e_bf_avg       , e_bf_ceil     , e_bf_clamp    , e_bf_cos    ,
19487             e_bf_cosh      , e_bf_cot      , e_bf_csc      , e_bf_equal  ,
19488             e_bf_erf       , e_bf_erfc     , e_bf_exp      , e_bf_expm1  ,
19489             e_bf_floor     , e_bf_frac     , e_bf_hypot    , e_bf_iclamp ,
19490             e_bf_like      , e_bf_log      , e_bf_log10    , e_bf_log1p  ,
19491             e_bf_log2      , e_bf_logn     , e_bf_mand     , e_bf_max    ,
19492             e_bf_min       , e_bf_mod      , e_bf_mor      , e_bf_mul    ,
19493             e_bf_ncdf      , e_bf_pow      , e_bf_root     , e_bf_round  ,
19494             e_bf_roundn    , e_bf_sec      , e_bf_sgn      , e_bf_sin    ,
19495             e_bf_sinc      , e_bf_sinh     , e_bf_sqrt     , e_bf_sum    ,
19496             e_bf_swap      , e_bf_tan      , e_bf_tanh     , e_bf_trunc  ,
19497             e_bf_not_equal , e_bf_inrange  , e_bf_deg2grad , e_bf_deg2rad,
19498             e_bf_rad2deg   , e_bf_grad2deg
19499          };
19500
19501          enum settings_control_structs
19502          {
19503             e_ctrl_unknown = 0,
19504             e_ctrl_ifelse,
19505             e_ctrl_switch,
19506             e_ctrl_for_loop,
19507             e_ctrl_while_loop,
19508             e_ctrl_repeat_loop,
19509             e_ctrl_return
19510          };
19511
19512          enum settings_logic_opr
19513          {
19514             e_logic_unknown = 0,
19515             e_logic_and, e_logic_nand,  e_logic_nor,
19516             e_logic_not, e_logic_or,    e_logic_xnor,
19517             e_logic_xor, e_logic_scand, e_logic_scor
19518          };
19519
19520          enum settings_arithmetic_opr
19521          {
19522             e_arith_unknown = 0,
19523             e_arith_add, e_arith_sub, e_arith_mul,
19524             e_arith_div, e_arith_mod, e_arith_pow
19525          };
19526
19527          enum settings_assignment_opr
19528          {
19529             e_assign_unknown = 0,
19530             e_assign_assign, e_assign_addass, e_assign_subass,
19531             e_assign_mulass, e_assign_divass, e_assign_modass
19532          };
19533
19534          enum settings_inequality_opr
19535          {
19536             e_ineq_unknown = 0,
19537             e_ineq_lt,    e_ineq_lte, e_ineq_eq,
19538             e_ineq_equal, e_ineq_ne,  e_ineq_nequal,
19539             e_ineq_gte,   e_ineq_gt
19540          };
19541
19542          static const std::size_t compile_all_opts = e_replacer          +
19543                                                      e_joiner            +
19544                                                      e_numeric_check     +
19545                                                      e_bracket_check     +
19546                                                      e_sequence_check    +
19547                                                      e_commutative_check +
19548                                                      e_strength_reduction;
19549
19550          settings_store(const std::size_t compile_options = compile_all_opts)
19551          {
19552            load_compile_options(compile_options);
19553          }
19554
19555          settings_store& enable_all_base_functions()
19556          {
19557             disabled_func_set_.clear();
19558             return (*this);
19559          }
19560
19561          settings_store& enable_all_control_structures()
19562          {
19563             disabled_ctrl_set_.clear();
19564             return (*this);
19565          }
19566
19567          settings_store& enable_all_logic_ops()
19568          {
19569             disabled_logic_set_.clear();
19570             return (*this);
19571          }
19572
19573          settings_store& enable_all_arithmetic_ops()
19574          {
19575             disabled_arithmetic_set_.clear();
19576             return (*this);
19577          }
19578
19579          settings_store& enable_all_assignment_ops()
19580          {
19581             disabled_assignment_set_.clear();
19582             return (*this);
19583          }
19584
19585          settings_store& enable_all_inequality_ops()
19586          {
19587             disabled_inequality_set_.clear();
19588             return (*this);
19589          }
19590
19591          settings_store& enable_local_vardef()
19592          {
19593             disable_vardef_ = false;
19594             return (*this);
19595          }
19596
19597          settings_store& disable_all_base_functions()
19598          {
19599             std::copy(details::base_function_list,
19600                       details::base_function_list + details::base_function_list_size,
19601                       std::insert_iterator<disabled_entity_set_t>
19602                         (disabled_func_set_, disabled_func_set_.begin()));
19603             return (*this);
19604          }
19605
19606          settings_store& disable_all_control_structures()
19607          {
19608             std::copy(details::cntrl_struct_list,
19609                       details::cntrl_struct_list + details::cntrl_struct_list_size,
19610                       std::insert_iterator<disabled_entity_set_t>
19611                         (disabled_ctrl_set_, disabled_ctrl_set_.begin()));
19612             return (*this);
19613          }
19614
19615          settings_store& disable_all_logic_ops()
19616          {
19617             std::copy(details::logic_ops_list,
19618                       details::logic_ops_list + details::logic_ops_list_size,
19619                       std::insert_iterator<disabled_entity_set_t>
19620                         (disabled_logic_set_, disabled_logic_set_.begin()));
19621             return (*this);
19622          }
19623
19624          settings_store& disable_all_arithmetic_ops()
19625          {
19626             std::copy(details::arithmetic_ops_list,
19627                       details::arithmetic_ops_list + details::arithmetic_ops_list_size,
19628                       std::insert_iterator<disabled_entity_set_t>
19629                         (disabled_arithmetic_set_, disabled_arithmetic_set_.begin()));
19630             return (*this);
19631          }
19632
19633          settings_store& disable_all_assignment_ops()
19634          {
19635             std::copy(details::assignment_ops_list,
19636                       details::assignment_ops_list + details::assignment_ops_list_size,
19637                       std::insert_iterator<disabled_entity_set_t>
19638                         (disabled_assignment_set_, disabled_assignment_set_.begin()));
19639             return (*this);
19640          }
19641
19642          settings_store& disable_all_inequality_ops()
19643          {
19644             std::copy(details::inequality_ops_list,
19645                       details::inequality_ops_list + details::inequality_ops_list_size,
19646                       std::insert_iterator<disabled_entity_set_t>
19647                         (disabled_inequality_set_, disabled_inequality_set_.begin()));
19648             return (*this);
19649          }
19650
19651          settings_store& disable_local_vardef()
19652          {
19653             disable_vardef_ = true;
19654             return (*this);
19655          }
19656
19657          bool replacer_enabled           () const { return enable_replacer_;           }
19658          bool commutative_check_enabled  () const { return enable_commutative_check_;  }
19659          bool joiner_enabled             () const { return enable_joiner_;             }
19660          bool numeric_check_enabled      () const { return enable_numeric_check_;      }
19661          bool bracket_check_enabled      () const { return enable_bracket_check_;      }
19662          bool sequence_check_enabled     () const { return enable_sequence_check_;     }
19663          bool strength_reduction_enabled () const { return enable_strength_reduction_; }
19664          bool collect_variables_enabled  () const { return enable_collect_vars_;       }
19665          bool collect_functions_enabled  () const { return enable_collect_funcs_;      }
19666          bool collect_assignments_enabled() const { return enable_collect_assings_;    }
19667          bool vardef_disabled            () const { return disable_vardef_;            }
19668          bool rsrvd_sym_usr_disabled     () const { return disable_rsrvd_sym_usr_;     }
19669          bool zero_return_disabled       () const { return disable_zero_return_;       }
19670
19671          bool function_enabled(const std::string& function_name) const
19672          {
19673             if (disabled_func_set_.empty())
19674                return true;
19675             else
19676                return (disabled_func_set_.end() == disabled_func_set_.find(function_name));
19677          }
19678
19679          bool control_struct_enabled(const std::string& control_struct) const
19680          {
19681             if (disabled_ctrl_set_.empty())
19682                return true;
19683             else
19684                return (disabled_ctrl_set_.end() == disabled_ctrl_set_.find(control_struct));
19685          }
19686
19687          bool logic_enabled(const std::string& logic_operation) const
19688          {
19689             if (disabled_logic_set_.empty())
19690                return true;
19691             else
19692                return (disabled_logic_set_.end() == disabled_logic_set_.find(logic_operation));
19693          }
19694
19695          bool arithmetic_enabled(const details::operator_type& arithmetic_operation) const
19696          {
19697             if (disabled_logic_set_.empty())
19698                return true;
19699             else
19700                return disabled_arithmetic_set_.end() == disabled_arithmetic_set_
19701                                                             .find(arith_opr_to_string(arithmetic_operation));
19702          }
19703
19704          bool assignment_enabled(const details::operator_type& assignment) const
19705          {
19706             if (disabled_assignment_set_.empty())
19707                return true;
19708             else
19709                return disabled_assignment_set_.end() == disabled_assignment_set_
19710                                                            .find(assign_opr_to_string(assignment));
19711          }
19712
19713          bool inequality_enabled(const details::operator_type& inequality) const
19714          {
19715             if (disabled_inequality_set_.empty())
19716                return true;
19717             else
19718                return disabled_inequality_set_.end() == disabled_inequality_set_
19719                                                            .find(inequality_opr_to_string(inequality));
19720          }
19721
19722          bool function_disabled(const std::string& function_name) const
19723          {
19724             if (disabled_func_set_.empty())
19725                return false;
19726             else
19727                return (disabled_func_set_.end() != disabled_func_set_.find(function_name));
19728          }
19729
19730          bool control_struct_disabled(const std::string& control_struct) const
19731          {
19732             if (disabled_ctrl_set_.empty())
19733                return false;
19734             else
19735                return (disabled_ctrl_set_.end() != disabled_ctrl_set_.find(control_struct));
19736          }
19737
19738          bool logic_disabled(const std::string& logic_operation) const
19739          {
19740             if (disabled_logic_set_.empty())
19741                return false;
19742             else
19743                return (disabled_logic_set_.end() != disabled_logic_set_.find(logic_operation));
19744          }
19745
19746          bool assignment_disabled(const details::operator_type assignment_operation) const
19747          {
19748             if (disabled_assignment_set_.empty())
19749                return false;
19750             else
19751                return disabled_assignment_set_.end() != disabled_assignment_set_
19752                                                            .find(assign_opr_to_string(assignment_operation));
19753          }
19754
19755          bool logic_disabled(const details::operator_type logic_operation) const
19756          {
19757             if (disabled_logic_set_.empty())
19758                return false;
19759             else
19760                return disabled_logic_set_.end() != disabled_logic_set_
19761                                                            .find(logic_opr_to_string(logic_operation));
19762          }
19763
19764          bool arithmetic_disabled(const details::operator_type arithmetic_operation) const
19765          {
19766             if (disabled_arithmetic_set_.empty())
19767                return false;
19768             else
19769                return disabled_arithmetic_set_.end() != disabled_arithmetic_set_
19770                                                            .find(arith_opr_to_string(arithmetic_operation));
19771          }
19772
19773          bool inequality_disabled(const details::operator_type& inequality) const
19774          {
19775             if (disabled_inequality_set_.empty())
19776                return false;
19777             else
19778                return disabled_inequality_set_.end() != disabled_inequality_set_
19779                                                            .find(inequality_opr_to_string(inequality));
19780          }
19781
19782          settings_store& disable_base_function(settings_base_funcs bf)
19783          {
19784             if (
19785                  (e_bf_unknown != bf) &&
19786                  (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1))
19787                )
19788             {
19789                disabled_func_set_.insert(details::base_function_list[bf - 1]);
19790             }
19791
19792             return (*this);
19793          }
19794
19795          settings_store& disable_control_structure(settings_control_structs ctrl_struct)
19796          {
19797             if (
19798                  (e_ctrl_unknown != ctrl_struct) &&
19799                  (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1))
19800                )
19801             {
19802                disabled_ctrl_set_.insert(details::cntrl_struct_list[ctrl_struct - 1]);
19803             }
19804
19805             return (*this);
19806          }
19807
19808          settings_store& disable_logic_operation(settings_logic_opr logic)
19809          {
19810             if (
19811                  (e_logic_unknown != logic) &&
19812                  (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1))
19813                )
19814             {
19815                disabled_logic_set_.insert(details::logic_ops_list[logic - 1]);
19816             }
19817
19818             return (*this);
19819          }
19820
19821          settings_store& disable_arithmetic_operation(settings_arithmetic_opr arithmetic)
19822          {
19823             if (
19824                  (e_arith_unknown != arithmetic) &&
19825                  (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1))
19826                )
19827             {
19828                disabled_arithmetic_set_.insert(details::arithmetic_ops_list[arithmetic - 1]);
19829             }
19830
19831             return (*this);
19832          }
19833
19834          settings_store& disable_assignment_operation(settings_assignment_opr assignment)
19835          {
19836             if (
19837                  (e_assign_unknown != assignment) &&
19838                  (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1))
19839                )
19840             {
19841                disabled_assignment_set_.insert(details::assignment_ops_list[assignment - 1]);
19842             }
19843
19844             return (*this);
19845          }
19846
19847          settings_store& disable_inequality_operation(settings_inequality_opr inequality)
19848          {
19849             if (
19850                  (e_ineq_unknown != inequality) &&
19851                  (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1))
19852                )
19853             {
19854                disabled_inequality_set_.insert(details::inequality_ops_list[inequality - 1]);
19855             }
19856
19857             return (*this);
19858          }
19859
19860          settings_store& enable_base_function(settings_base_funcs bf)
19861          {
19862             if (
19863                  (e_bf_unknown != bf) &&
19864                  (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1))
19865                )
19866             {
19867                const des_itr_t itr = disabled_func_set_.find(details::base_function_list[bf - 1]);
19868
19869                if (disabled_func_set_.end() != itr)
19870                {
19871                   disabled_func_set_.erase(itr);
19872                }
19873             }
19874
19875             return (*this);
19876          }
19877
19878          settings_store& enable_control_structure(settings_control_structs ctrl_struct)
19879          {
19880             if (
19881                  (e_ctrl_unknown != ctrl_struct) &&
19882                  (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1))
19883                )
19884             {
19885                const des_itr_t itr = disabled_ctrl_set_.find(details::cntrl_struct_list[ctrl_struct - 1]);
19886
19887                if (disabled_ctrl_set_.end() != itr)
19888                {
19889                   disabled_ctrl_set_.erase(itr);
19890                }
19891             }
19892
19893             return (*this);
19894          }
19895
19896          settings_store& enable_logic_operation(settings_logic_opr logic)
19897          {
19898             if (
19899                  (e_logic_unknown != logic) &&
19900                  (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1))
19901                )
19902             {
19903                const des_itr_t itr = disabled_logic_set_.find(details::logic_ops_list[logic - 1]);
19904
19905                if (disabled_logic_set_.end() != itr)
19906                {
19907                   disabled_logic_set_.erase(itr);
19908                }
19909             }
19910
19911             return (*this);
19912          }
19913
19914          settings_store& enable_arithmetic_operation(settings_arithmetic_opr arithmetic)
19915          {
19916             if (
19917                  (e_arith_unknown != arithmetic) &&
19918                  (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1))
19919                )
19920             {
19921                const des_itr_t itr = disabled_arithmetic_set_.find(details::arithmetic_ops_list[arithmetic - 1]);
19922
19923                if (disabled_arithmetic_set_.end() != itr)
19924                {
19925                   disabled_arithmetic_set_.erase(itr);
19926                }
19927             }
19928
19929             return (*this);
19930          }
19931
19932          settings_store& enable_assignment_operation(settings_assignment_opr assignment)
19933          {
19934             if (
19935                  (e_assign_unknown != assignment) &&
19936                  (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1))
19937                )
19938             {
19939                const des_itr_t itr = disabled_assignment_set_.find(details::assignment_ops_list[assignment - 1]);
19940
19941                if (disabled_assignment_set_.end() != itr)
19942                {
19943                   disabled_assignment_set_.erase(itr);
19944                }
19945             }
19946
19947             return (*this);
19948          }
19949
19950          settings_store& enable_inequality_operation(settings_inequality_opr inequality)
19951          {
19952             if (
19953                  (e_ineq_unknown != inequality) &&
19954                  (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1))
19955                )
19956             {
19957                const des_itr_t itr = disabled_inequality_set_.find(details::inequality_ops_list[inequality - 1]);
19958
19959                if (disabled_inequality_set_.end() != itr)
19960                {
19961                   disabled_inequality_set_.erase(itr);
19962                }
19963             }
19964
19965             return (*this);
19966          }
19967
19968       private:
19969
19970          void load_compile_options(const std::size_t compile_options)
19971          {
19972             enable_replacer_           = (compile_options & e_replacer            ) == e_replacer;
19973             enable_joiner_             = (compile_options & e_joiner              ) == e_joiner;
19974             enable_numeric_check_      = (compile_options & e_numeric_check       ) == e_numeric_check;
19975             enable_bracket_check_      = (compile_options & e_bracket_check       ) == e_bracket_check;
19976             enable_sequence_check_     = (compile_options & e_sequence_check      ) == e_sequence_check;
19977             enable_commutative_check_  = (compile_options & e_commutative_check   ) == e_commutative_check;
19978             enable_strength_reduction_ = (compile_options & e_strength_reduction  ) == e_strength_reduction;
19979             enable_collect_vars_       = (compile_options & e_collect_vars        ) == e_collect_vars;
19980             enable_collect_funcs_      = (compile_options & e_collect_funcs       ) == e_collect_funcs;
19981             enable_collect_assings_    = (compile_options & e_collect_assings     ) == e_collect_assings;
19982             disable_vardef_            = (compile_options & e_disable_vardef      ) == e_disable_vardef;
19983             disable_rsrvd_sym_usr_     = (compile_options & e_disable_usr_on_rsrvd) == e_disable_usr_on_rsrvd;
19984             disable_zero_return_       = (compile_options & e_disable_zero_return ) == e_disable_zero_return;
19985          }
19986
19987          std::string assign_opr_to_string(details::operator_type opr) const
19988          {
19989             switch (opr)
19990             {
19991                case details::e_assign : return ":=";
19992                case details::e_addass : return "+=";
19993                case details::e_subass : return "-=";
19994                case details::e_mulass : return "*=";
19995                case details::e_divass : return "/=";
19996                case details::e_modass : return "%=";
19997                default                : return   "";
19998             }
19999          }
20000
20001          std::string arith_opr_to_string(details::operator_type opr) const
20002          {
20003             switch (opr)
20004             {
20005                case details::e_add : return "+";
20006                case details::e_sub : return "-";
20007                case details::e_mul : return "*";
20008                case details::e_div : return "/";
20009                case details::e_mod : return "%";
20010                default             : return  "";
20011             }
20012          }
20013
20014          std::string inequality_opr_to_string(details::operator_type opr) const
20015          {
20016             switch (opr)
20017             {
20018                case details::e_lt    : return  "<";
20019                case details::e_lte   : return "<=";
20020                case details::e_eq    : return "==";
20021                case details::e_equal : return  "=";
20022                case details::e_ne    : return "!=";
20023                case details::e_nequal: return "<>";
20024                case details::e_gte   : return ">=";
20025                case details::e_gt    : return  ">";
20026                default               : return   "";
20027             }
20028          }
20029
20030          std::string logic_opr_to_string(details::operator_type opr) const
20031          {
20032             switch (opr)
20033             {
20034                case details::e_and  : return "and" ;
20035                case details::e_or   : return "or"  ;
20036                case details::e_xor  : return "xor" ;
20037                case details::e_nand : return "nand";
20038                case details::e_nor  : return "nor" ;
20039                case details::e_xnor : return "xnor";
20040                case details::e_notl : return "not" ;
20041                default              : return ""    ;
20042             }
20043          }
20044
20045          bool enable_replacer_;
20046          bool enable_joiner_;
20047          bool enable_numeric_check_;
20048          bool enable_bracket_check_;
20049          bool enable_sequence_check_;
20050          bool enable_commutative_check_;
20051          bool enable_strength_reduction_;
20052          bool enable_collect_vars_;
20053          bool enable_collect_funcs_;
20054          bool enable_collect_assings_;
20055          bool disable_vardef_;
20056          bool disable_rsrvd_sym_usr_;
20057          bool disable_zero_return_;
20058
20059          disabled_entity_set_t disabled_func_set_ ;
20060          disabled_entity_set_t disabled_ctrl_set_ ;
20061          disabled_entity_set_t disabled_logic_set_;
20062          disabled_entity_set_t disabled_arithmetic_set_;
20063          disabled_entity_set_t disabled_assignment_set_;
20064          disabled_entity_set_t disabled_inequality_set_;
20065
20066          friend class parser<T>;
20067       };
20068
20069       typedef settings_store settings_t;
20070
20071       parser(const settings_t& settings = settings_t())
20072       : settings_(settings),
20073         resolve_unknown_symbol_(false),
20074         results_context_(0),
20075         unknown_symbol_resolver_(reinterpret_cast<unknown_symbol_resolver*>(0)),
20076         #ifdef _MSC_VER
20077         #pragma warning(push)
20078         #pragma warning (disable:4355)
20079         #endif
20080         sem_(*this),
20081         #ifdef _MSC_VER
20082         #pragma warning(pop)
20083         #endif
20084         operator_joiner_2_(2),
20085         operator_joiner_3_(3)
20086       {
20087          init_precompilation();
20088
20089          load_operations_map           (base_ops_map_     );
20090          load_unary_operations_map     (unary_op_map_     );
20091          load_binary_operations_map    (binary_op_map_    );
20092          load_inv_binary_operations_map(inv_binary_op_map_);
20093          load_sf3_map                  (sf3_map_          );
20094          load_sf4_map                  (sf4_map_          );
20095
20096          expression_generator_.init_synthesize_map();
20097          expression_generator_.set_parser(*this);
20098          expression_generator_.set_uom(unary_op_map_);
20099          expression_generator_.set_bom(binary_op_map_);
20100          expression_generator_.set_ibom(inv_binary_op_map_);
20101          expression_generator_.set_sf3m(sf3_map_);
20102          expression_generator_.set_sf4m(sf4_map_);
20103          expression_generator_.set_strength_reduction_state(settings_.strength_reduction_enabled());
20104       }
20105
20106      ~parser()
20107       {}
20108
20109       inline void init_precompilation()
20110       {
20111          if (settings_.collect_variables_enabled())
20112             dec_.collect_variables() = true;
20113
20114          if (settings_.collect_functions_enabled())
20115             dec_.collect_functions() = true;
20116
20117          if (settings_.collect_assignments_enabled())
20118             dec_.collect_assignments() = true;
20119
20120          if (settings_.replacer_enabled())
20121          {
20122             symbol_replacer_.clear();
20123             symbol_replacer_.add_replace("true" , "1", lexer::token::e_number);
20124             symbol_replacer_.add_replace("false", "0", lexer::token::e_number);
20125             helper_assembly_.token_modifier_list.clear();
20126             helper_assembly_.register_modifier(&symbol_replacer_);
20127          }
20128
20129          if (settings_.commutative_check_enabled())
20130          {
20131             for (std::size_t i = 0; i < details::reserved_words_size; ++i)
20132             {
20133                commutative_inserter_.ignore_symbol(details::reserved_words[i]);
20134             }
20135
20136             helper_assembly_.token_inserter_list.clear();
20137             helper_assembly_.register_inserter(&commutative_inserter_);
20138          }
20139
20140          if (settings_.joiner_enabled())
20141          {
20142             helper_assembly_.token_joiner_list.clear();
20143             helper_assembly_.register_joiner(&operator_joiner_2_);
20144             helper_assembly_.register_joiner(&operator_joiner_3_);
20145          }
20146
20147          if (
20148               settings_.numeric_check_enabled () ||
20149               settings_.bracket_check_enabled () ||
20150               settings_.sequence_check_enabled()
20151             )
20152          {
20153             helper_assembly_.token_scanner_list.clear();
20154
20155             if (settings_.numeric_check_enabled())
20156             {
20157                helper_assembly_.register_scanner(&numeric_checker_);
20158             }
20159
20160             if (settings_.bracket_check_enabled())
20161             {
20162                helper_assembly_.register_scanner(&bracket_checker_);
20163             }
20164
20165             if (settings_.sequence_check_enabled())
20166             {
20167                helper_assembly_.register_scanner(&sequence_validator_      );
20168                helper_assembly_.register_scanner(&sequence_validator_3tkns_);
20169             }
20170          }
20171       }
20172
20173       inline bool compile(const std::string& expression_string, expression<T>& expr)
20174       {
20175          state_          .reset();
20176          error_list_     .clear();
20177          brkcnt_list_    .clear();
20178          synthesis_error_.clear();
20179          sem_            .cleanup();
20180
20181          return_cleanup();
20182
20183          expression_generator_.set_allocator(node_allocator_);
20184
20185          if (expression_string.empty())
20186          {
20187             set_error(
20188                make_error(parser_error::e_syntax,
20189                           "ERR000 - Empty expression!",
20190                           exprtk_error_location));
20191
20192             return false;
20193          }
20194
20195          if (!init(expression_string))
20196          {
20197             process_lexer_errors();
20198             return false;
20199          }
20200
20201          if (lexer().empty())
20202          {
20203             set_error(
20204                make_error(parser_error::e_syntax,
20205                           "ERR001 - Empty expression!",
20206                           exprtk_error_location));
20207
20208             return false;
20209          }
20210
20211          if (!run_assemblies())
20212          {
20213             return false;
20214          }
20215
20216          symtab_store_.symtab_list_ = expr.get_symbol_table_list();
20217          dec_.clear();
20218
20219          lexer().begin();
20220
20221          next_token();
20222
20223          expression_node_ptr e = parse_corpus();
20224
20225          if ((0 != e) && (token_t::e_eof == current_token().type))
20226          {
20227             bool* retinvk_ptr = 0;
20228
20229             if (state_.return_stmt_present)
20230             {
20231                dec_.return_present_ = true;
20232
20233                e = expression_generator_
20234                      .return_envelope(e, results_context_, retinvk_ptr);
20235             }
20236
20237             expr.set_expression(e);
20238             expr.set_retinvk(retinvk_ptr);
20239
20240             register_local_vars(expr);
20241             register_return_results(expr);
20242
20243             return !(!expr);
20244          }
20245          else
20246          {
20247             if (error_list_.empty())
20248             {
20249                set_error(
20250                   make_error(parser_error::e_syntax,
20251                              current_token(),
20252                              "ERR002 - Invalid expression encountered",
20253                              exprtk_error_location));
20254             }
20255
20256             if ((0 != e) && branch_deletable(e))
20257             {
20258                destroy_node(e);
20259             }
20260
20261             dec_.clear    ();
20262             sem_.cleanup  ();
20263             return_cleanup();
20264
20265             return false;
20266          }
20267       }
20268
20269       inline expression_t compile(const std::string& expression_string, symbol_table_t& symtab)
20270       {
20271          expression_t expr;
20272
20273          expr.register_symbol_table(symtab);
20274
20275          compile(expression_string,expr);
20276
20277          return expr;
20278       }
20279
20280       void process_lexer_errors()
20281       {
20282          for (std::size_t i = 0; i < lexer().size(); ++i)
20283          {
20284             if (lexer()[i].is_error())
20285             {
20286                std::string diagnostic = "ERR003 - ";
20287
20288                switch (lexer()[i].type)
20289                {
20290                   case lexer::token::e_error      : diagnostic += "General token error";
20291                                                     break;
20292
20293                   case lexer::token::e_err_symbol : diagnostic += "Symbol error";
20294                                                     break;
20295
20296                   case lexer::token::e_err_number : diagnostic += "Invalid numeric token";
20297                                                     break;
20298
20299                   case lexer::token::e_err_string : diagnostic += "Invalid string token";
20300                                                     break;
20301
20302                   case lexer::token::e_err_sfunc  : diagnostic += "Invalid special function token";
20303                                                     break;
20304
20305                   default                         : diagnostic += "Unknown compiler error";
20306                }
20307
20308                set_error(
20309                   make_error(parser_error::e_lexer,
20310                              lexer()[i],
20311                              diagnostic + ": " + lexer()[i].value,
20312                              exprtk_error_location));
20313             }
20314          }
20315       }
20316
20317       inline bool run_assemblies()
20318       {
20319          if (settings_.commutative_check_enabled())
20320          {
20321             helper_assembly_.run_inserters(lexer());
20322          }
20323
20324          if (settings_.joiner_enabled())
20325          {
20326             helper_assembly_.run_joiners(lexer());
20327          }
20328
20329          if (settings_.replacer_enabled())
20330          {
20331             helper_assembly_.run_modifiers(lexer());
20332          }
20333
20334          if (
20335               settings_.numeric_check_enabled () ||
20336               settings_.bracket_check_enabled () ||
20337               settings_.sequence_check_enabled()
20338             )
20339          {
20340             if (!helper_assembly_.run_scanners(lexer()))
20341             {
20342                if (helper_assembly_.error_token_scanner)
20343                {
20344                   lexer::helper::bracket_checker*            bracket_checker_ptr     = 0;
20345                   lexer::helper::numeric_checker*            numeric_checker_ptr     = 0;
20346                   lexer::helper::sequence_validator*         sequence_validator_ptr  = 0;
20347                   lexer::helper::sequence_validator_3tokens* sequence_validator3_ptr = 0;
20348
20349                   if (0 != (bracket_checker_ptr = dynamic_cast<lexer::helper::bracket_checker*>(helper_assembly_.error_token_scanner)))
20350                   {
20351                      set_error(
20352                         make_error(parser_error::e_token,
20353                                    bracket_checker_ptr->error_token(),
20354                                    "ERR004 - Mismatched brackets: '" + bracket_checker_ptr->error_token().value + "'",
20355                                    exprtk_error_location));
20356                   }
20357                   else if (0 != (numeric_checker_ptr = dynamic_cast<lexer::helper::numeric_checker*>(helper_assembly_.error_token_scanner)))
20358                   {
20359                      for (std::size_t i = 0; i < numeric_checker_ptr->error_count(); ++i)
20360                      {
20361                         lexer::token error_token = lexer()[numeric_checker_ptr->error_index(i)];
20362
20363                         set_error(
20364                            make_error(parser_error::e_token,
20365                                       error_token,
20366                                       "ERR005 - Invalid numeric token: '" + error_token.value + "'",
20367                                       exprtk_error_location));
20368                      }
20369
20370                      if (numeric_checker_ptr->error_count())
20371                      {
20372                         numeric_checker_ptr->clear_errors();
20373                      }
20374                   }
20375                   else if (0 != (sequence_validator_ptr = dynamic_cast<lexer::helper::sequence_validator*>(helper_assembly_.error_token_scanner)))
20376                   {
20377                      for (std::size_t i = 0; i < sequence_validator_ptr->error_count(); ++i)
20378                      {
20379                         std::pair<lexer::token,lexer::token> error_token = sequence_validator_ptr->error(i);
20380
20381                         set_error(
20382                            make_error(parser_error::e_token,
20383                                       error_token.first,
20384                                       "ERR006 - Invalid token sequence: '" +
20385                                       error_token.first.value  + "' and '" +
20386                                       error_token.second.value + "'",
20387                                       exprtk_error_location));
20388                      }
20389
20390                      if (sequence_validator_ptr->error_count())
20391                      {
20392                         sequence_validator_ptr->clear_errors();
20393                      }
20394                   }
20395                   else if (0 != (sequence_validator3_ptr = dynamic_cast<lexer::helper::sequence_validator_3tokens*>(helper_assembly_.error_token_scanner)))
20396                   {
20397                      for (std::size_t i = 0; i < sequence_validator3_ptr->error_count(); ++i)
20398                      {
20399                         std::pair<lexer::token,lexer::token> error_token = sequence_validator3_ptr->error(i);
20400
20401                         set_error(
20402                            make_error(parser_error::e_token,
20403                                       error_token.first,
20404                                       "ERR007 - Invalid token sequence: '" +
20405                                       error_token.first.value  + "' and '" +
20406                                       error_token.second.value + "'",
20407                                       exprtk_error_location));
20408                      }
20409
20410                      if (sequence_validator3_ptr->error_count())
20411                      {
20412                         sequence_validator3_ptr->clear_errors();
20413                      }
20414                   }
20415                }
20416
20417                return false;
20418             }
20419          }
20420
20421          return true;
20422       }
20423
20424       inline settings_store& settings()
20425       {
20426          return settings_;
20427       }
20428
20429       inline parser_error::type get_error(const std::size_t& index) const
20430       {
20431          if (index < error_list_.size())
20432             return error_list_[index];
20433          else
20434             throw std::invalid_argument("parser::get_error() - Invalid error index specificed");
20435       }
20436
20437       inline std::string error() const
20438       {
20439          if (!error_list_.empty())
20440          {
20441             return error_list_[0].diagnostic;
20442          }
20443          else
20444             return std::string("No Error");
20445       }
20446
20447       inline std::size_t error_count() const
20448       {
20449          return error_list_.size();
20450       }
20451
20452       inline dependent_entity_collector& dec()
20453       {
20454          return dec_;
20455       }
20456
20457       inline bool replace_symbol(const std::string& old_symbol, const std::string& new_symbol)
20458       {
20459          if (!settings_.replacer_enabled())
20460             return false;
20461          else if (details::is_reserved_word(old_symbol))
20462             return false;
20463          else
20464             return symbol_replacer_.add_replace(old_symbol,new_symbol,lexer::token::e_symbol);
20465       }
20466
20467       inline bool remove_replace_symbol(const std::string& symbol)
20468       {
20469          if (!settings_.replacer_enabled())
20470             return false;
20471          else if (details::is_reserved_word(symbol))
20472             return false;
20473          else
20474             return symbol_replacer_.remove(symbol);
20475       }
20476
20477       inline void enable_unknown_symbol_resolver(unknown_symbol_resolver* usr = reinterpret_cast<unknown_symbol_resolver*>(0))
20478       {
20479          resolve_unknown_symbol_ = true;
20480
20481          if (usr)
20482             unknown_symbol_resolver_ = usr;
20483          else
20484             unknown_symbol_resolver_ = &default_usr_;
20485       }
20486
20487       inline void enable_unknown_symbol_resolver(unknown_symbol_resolver& usr)
20488       {
20489          enable_unknown_symbol_resolver(&usr);
20490       }
20491
20492       inline void disable_unknown_symbol_resolver()
20493       {
20494          resolve_unknown_symbol_  = false;
20495          unknown_symbol_resolver_ = &default_usr_;
20496       }
20497
20498    private:
20499
20500       inline bool valid_base_operation(const std::string& symbol) const
20501       {
20502          const std::size_t length = symbol.size();
20503
20504          if (
20505               (length < 3) || // Shortest base op symbol length
20506               (length > 9)    // Longest base op symbol length
20507             )
20508             return false;
20509          else
20510             return settings_.function_enabled(symbol) &&
20511                    (base_ops_map_.end() != base_ops_map_.find(symbol));
20512       }
20513
20514       inline bool valid_vararg_operation(const std::string& symbol) const
20515       {
20516          static const std::string s_sum     = "sum" ;
20517          static const std::string s_mul     = "mul" ;
20518          static const std::string s_avg     = "avg" ;
20519          static const std::string s_min     = "min" ;
20520          static const std::string s_max     = "max" ;
20521          static const std::string s_mand    = "mand";
20522          static const std::string s_mor     = "mor" ;
20523          static const std::string s_multi   = "~"   ;
20524          static const std::string s_mswitch = "[*]" ;
20525
20526          return
20527                (
20528                   details::imatch(symbol,s_sum    ) ||
20529                   details::imatch(symbol,s_mul    ) ||
20530                   details::imatch(symbol,s_avg    ) ||
20531                   details::imatch(symbol,s_min    ) ||
20532                   details::imatch(symbol,s_max    ) ||
20533                   details::imatch(symbol,s_mand   ) ||
20534                   details::imatch(symbol,s_mor    ) ||
20535                   details::imatch(symbol,s_multi  ) ||
20536                   details::imatch(symbol,s_mswitch)
20537                ) &&
20538                settings_.function_enabled(symbol);
20539       }
20540
20541       bool is_invalid_logic_operation(const details::operator_type operation) const
20542       {
20543          return settings_.logic_disabled(operation);
20544       }
20545
20546       bool is_invalid_arithmetic_operation(const details::operator_type operation) const
20547       {
20548          return settings_.arithmetic_disabled(operation);
20549       }
20550
20551       bool is_invalid_assignment_operation(const details::operator_type operation) const
20552       {
20553          return settings_.assignment_disabled(operation);
20554       }
20555
20556       bool is_invalid_inequality_operation(const details::operator_type operation) const
20557       {
20558          return settings_.inequality_disabled(operation);
20559       }
20560
20561       #ifdef exprtk_enable_debugging
20562       inline void next_token()
20563       {
20564          const std::string ct_str = current_token().value;
20565          parser_helper::next_token();
20566          const std::string depth(2 * state_.scope_depth,' ');
20567          exprtk_debug(("%s"
20568                        "prev[%s] --> curr[%s]\n",
20569                        depth.c_str(),
20570                        ct_str.c_str(),
20571                        current_token().value.c_str()));
20572       }
20573       #endif
20574
20575       inline expression_node_ptr parse_corpus()
20576       {
20577          std::vector<expression_node_ptr> arg_list;
20578          std::vector<bool> side_effect_list;
20579
20580          scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
20581
20582          lexer::token begin_token;
20583          lexer::token   end_token;
20584
20585          for ( ; ; )
20586          {
20587             state_.side_effect_present = false;
20588
20589             begin_token = current_token();
20590
20591             expression_node_ptr arg = parse_expression();
20592
20593             if (0 == arg)
20594             {
20595                if (error_list_.empty())
20596                {
20597                   set_error(
20598                      make_error(parser_error::e_syntax,
20599                                 current_token(),
20600                                 "ERR008 - Invalid expression encountered",
20601                                 exprtk_error_location));
20602                }
20603
20604                return error_node();
20605             }
20606             else
20607             {
20608                arg_list.push_back(arg);
20609
20610                side_effect_list.push_back(state_.side_effect_present);
20611
20612                end_token = current_token();
20613
20614                const std::string sub_expr = construct_subexpr(begin_token, end_token);
20615
20616                exprtk_debug(("parse_corpus(%02d) Subexpr: %s\n",
20617                              static_cast<int>(arg_list.size() - 1),
20618                              sub_expr.c_str()));
20619
20620                exprtk_debug(("parse_corpus(%02d) - Side effect present: %s\n",
20621                              static_cast<int>(arg_list.size() - 1),
20622                              state_.side_effect_present ? "true" : "false"));
20623
20624                exprtk_debug(("-------------------------------------------------\n"));
20625             }
20626
20627             if (lexer().finished())
20628                break;
20629             else if (token_is(token_t::e_eof,prsrhlpr_t::e_hold))
20630             {
20631                if (lexer().finished())
20632                   break;
20633                else
20634                   next_token();
20635             }
20636          }
20637
20638          if (
20639               !arg_list.empty() &&
20640               is_return_node(arg_list.back())
20641             )
20642          {
20643             dec_.final_stmt_return_ = true;
20644          }
20645
20646          const expression_node_ptr result = simplify(arg_list,side_effect_list);
20647
20648          sdd.delete_ptr = (0 == result);
20649
20650          return result;
20651       }
20652
20653       std::string construct_subexpr(lexer::token& begin_token, lexer::token& end_token)
20654       {
20655          std::string result = lexer().substr(begin_token.position,end_token.position);
20656
20657          for (std::size_t i = 0; i < result.size(); ++i)
20658          {
20659             if (details::is_whitespace(result[i])) result[i] = ' ';
20660          }
20661
20662          return result;
20663       }
20664
20665       static const precedence_level default_precedence = e_level00;
20666
20667       struct state_t
20668       {
20669          inline void set(const precedence_level& l,
20670                          const precedence_level& r,
20671                          const details::operator_type& o)
20672          {
20673             left  = l;
20674             right = r;
20675             operation = o;
20676          }
20677
20678          inline void reset()
20679          {
20680             left      = e_level00;
20681             right     = e_level00;
20682             operation = details::e_default;
20683          }
20684
20685          precedence_level left;
20686          precedence_level right;
20687          details::operator_type operation;
20688       };
20689
20690       inline expression_node_ptr parse_expression(precedence_level precedence = e_level00)
20691       {
20692          expression_node_ptr expression = parse_branch(precedence);
20693
20694          if (0 == expression)
20695          {
20696             return error_node();
20697          }
20698
20699          bool break_loop = false;
20700
20701          state_t current_state;
20702
20703          for ( ; ; )
20704          {
20705             current_state.reset();
20706
20707             switch (current_token().type)
20708             {
20709                case token_t::e_assign : current_state.set(e_level00,e_level00, details::e_assign); break;
20710                case token_t::e_addass : current_state.set(e_level00,e_level00, details::e_addass); break;
20711                case token_t::e_subass : current_state.set(e_level00,e_level00, details::e_subass); break;
20712                case token_t::e_mulass : current_state.set(e_level00,e_level00, details::e_mulass); break;
20713                case token_t::e_divass : current_state.set(e_level00,e_level00, details::e_divass); break;
20714                case token_t::e_modass : current_state.set(e_level00,e_level00, details::e_modass); break;
20715                case token_t::e_swap   : current_state.set(e_level00,e_level00, details::e_swap  ); break;
20716                case token_t::e_lt     : current_state.set(e_level05,e_level06, details::    e_lt); break;
20717                case token_t::e_lte    : current_state.set(e_level05,e_level06, details::   e_lte); break;
20718                case token_t::e_eq     : current_state.set(e_level05,e_level06, details::    e_eq); break;
20719                case token_t::e_ne     : current_state.set(e_level05,e_level06, details::    e_ne); break;
20720                case token_t::e_gte    : current_state.set(e_level05,e_level06, details::   e_gte); break;
20721                case token_t::e_gt     : current_state.set(e_level05,e_level06, details::    e_gt); break;
20722                case token_t::e_add    : current_state.set(e_level07,e_level08, details::   e_add); break;
20723                case token_t::e_sub    : current_state.set(e_level07,e_level08, details::   e_sub); break;
20724                case token_t::e_div    : current_state.set(e_level10,e_level11, details::   e_div); break;
20725                case token_t::e_mul    : current_state.set(e_level10,e_level11, details::   e_mul); break;
20726                case token_t::e_mod    : current_state.set(e_level10,e_level11, details::   e_mod); break;
20727                case token_t::e_pow    : current_state.set(e_level12,e_level12, details::   e_pow); break;
20728                default                : if (token_t::e_symbol == current_token().type)
20729                                         {
20730                                            static const std::string s_and   =   "and";
20731                                            static const std::string s_nand  =  "nand";
20732                                            static const std::string s_or    =    "or";
20733                                            static const std::string s_nor   =   "nor";
20734                                            static const std::string s_xor   =   "xor";
20735                                            static const std::string s_xnor  =  "xnor";
20736                                            static const std::string s_in    =    "in";
20737                                            static const std::string s_like  =  "like";
20738                                            static const std::string s_ilike = "ilike";
20739                                            static const std::string s_and1  =     "&";
20740                                            static const std::string s_or1   =     "|";
20741                                            static const std::string s_not   =   "not";
20742
20743                                            if (details::imatch(current_token().value,s_and))
20744                                            {
20745                                               current_state.set(e_level03, e_level04, details::e_and);
20746                                               break;
20747                                            }
20748                                            else if (details::imatch(current_token().value,s_and1))
20749                                            {
20750                                               #ifndef exprtk_disable_sc_andor
20751                                               current_state.set(e_level03, e_level04, details::e_scand);
20752                                               #else
20753                                               current_state.set(e_level03, e_level04, details::e_and);
20754                                               #endif
20755                                               break;
20756                                            }
20757                                            else if (details::imatch(current_token().value,s_nand))
20758                                            {
20759                                               current_state.set(e_level03, e_level04, details::e_nand);
20760                                               break;
20761                                            }
20762                                            else if (details::imatch(current_token().value,s_or))
20763                                            {
20764                                               current_state.set(e_level01, e_level02, details::e_or);
20765                                               break;
20766                                            }
20767                                            else if (details::imatch(current_token().value,s_or1))
20768                                            {
20769                                               #ifndef exprtk_disable_sc_andor
20770                                               current_state.set(e_level01, e_level02, details::e_scor);
20771                                               #else
20772                                               current_state.set(e_level01, e_level02, details::e_or);
20773                                               #endif
20774                                               break;
20775                                            }
20776                                            else if (details::imatch(current_token().value,s_nor))
20777                                            {
20778                                               current_state.set(e_level01, e_level02, details::e_nor);
20779                                               break;
20780                                            }
20781                                            else if (details::imatch(current_token().value,s_xor))
20782                                            {
20783                                               current_state.set(e_level01, e_level02, details::e_xor);
20784                                               break;
20785                                            }
20786                                            else if (details::imatch(current_token().value,s_xnor))
20787                                            {
20788                                               current_state.set(e_level01, e_level02, details::e_xnor);
20789                                               break;
20790                                            }
20791                                            else if (details::imatch(current_token().value,s_in))
20792                                            {
20793                                               current_state.set(e_level04, e_level04, details::e_in);
20794                                               break;
20795                                            }
20796                                            else if (details::imatch(current_token().value,s_like))
20797                                            {
20798                                               current_state.set(e_level04, e_level04, details::e_like);
20799                                               break;
20800                                            }
20801                                            else if (details::imatch(current_token().value,s_ilike))
20802                                            {
20803                                               current_state.set(e_level04, e_level04, details::e_ilike);
20804                                               break;
20805                                            }
20806                                            else if (details::imatch(current_token().value,s_not))
20807                                            {
20808                                               break;
20809                                            }
20810                                         }
20811
20812                                         break_loop = true;
20813             }
20814
20815             if (break_loop)
20816             {
20817                parse_pending_string_rangesize(expression);
20818                break;
20819             }
20820             else if (current_state.left < precedence)
20821                break;
20822
20823             const lexer::token prev_token = current_token();
20824
20825             next_token();
20826
20827             expression_node_ptr right_branch   = error_node();
20828             expression_node_ptr new_expression = error_node();
20829
20830             if (is_invalid_logic_operation(current_state.operation))
20831             {
20832                free_node(node_allocator_,expression);
20833
20834                set_error(
20835                   make_error(parser_error::e_syntax,
20836                              prev_token,
20837                              "ERR009 - Invalid or disabled logic operation '" + details::to_str(current_state.operation) + "'",
20838                              exprtk_error_location));
20839
20840                return error_node();
20841             }
20842             else if (is_invalid_arithmetic_operation(current_state.operation))
20843             {
20844                free_node(node_allocator_,expression);
20845
20846                set_error(
20847                   make_error(parser_error::e_syntax,
20848                              prev_token,
20849                              "ERR010 - Invalid or disabled arithmetic operation '" + details::to_str(current_state.operation) + "'",
20850                              exprtk_error_location));
20851
20852                return error_node();
20853             }
20854             else if (is_invalid_inequality_operation(current_state.operation))
20855             {
20856                free_node(node_allocator_,expression);
20857
20858                set_error(
20859                   make_error(parser_error::e_syntax,
20860                              prev_token,
20861                              "ERR011 - Invalid inequality operation '" + details::to_str(current_state.operation) + "'",
20862                              exprtk_error_location));
20863
20864                return error_node();
20865             }
20866             else if (is_invalid_assignment_operation(current_state.operation))
20867             {
20868                free_node(node_allocator_,expression);
20869
20870                set_error(
20871                   make_error(parser_error::e_syntax,
20872                              prev_token,
20873                              "ERR012 - Invalid or disabled assignment operation '" + details::to_str(current_state.operation) + "'",
20874                              exprtk_error_location));
20875
20876                return error_node();
20877             }
20878
20879             if (0 != (right_branch = parse_expression(current_state.right)))
20880             {
20881                if (
20882                     details::is_return_node(  expression) ||
20883                     details::is_return_node(right_branch)
20884                   )
20885                {
20886                   free_node(node_allocator_,   expression);
20887                   free_node(node_allocator_, right_branch);
20888
20889                   set_error(
20890                      make_error(parser_error::e_syntax,
20891                                 prev_token,
20892                                 "ERR013 - Return statements cannot be part of sub-expressions",
20893                                 exprtk_error_location));
20894
20895                   return error_node();
20896                }
20897
20898                new_expression = expression_generator_
20899                                   (
20900                                     current_state.operation,
20901                                     expression,
20902                                     right_branch
20903                                   );
20904             }
20905
20906             if (0 == new_expression)
20907             {
20908                if (error_list_.empty())
20909                {
20910                   set_error(
20911                      make_error(parser_error::e_syntax,
20912                                 prev_token,
20913                                 !synthesis_error_.empty() ?
20914                                 synthesis_error_ :
20915                                 "ERR014 - General parsing error at token: '" + prev_token.value + "'",
20916                                 exprtk_error_location));
20917                }
20918
20919                free_node(node_allocator_,   expression);
20920                free_node(node_allocator_, right_branch);
20921
20922                return error_node();
20923             }
20924             else
20925             {
20926                if (
20927                     token_is(token_t::e_ternary,prsrhlpr_t::e_hold) &&
20928                     (precedence == e_level00)
20929                   )
20930                {
20931                   expression = parse_ternary_conditional_statement(new_expression);
20932                }
20933                else
20934                   expression = new_expression;
20935
20936                parse_pending_string_rangesize(expression);
20937             }
20938          }
20939
20940          return expression;
20941       }
20942
20943       bool simplify_unary_negation_branch(expression_node_ptr& node)
20944       {
20945          {
20946             typedef details::unary_branch_node<T,details::neg_op<T> > ubn_t;
20947             ubn_t* n = dynamic_cast<ubn_t*>(node);
20948
20949             if (n)
20950             {
20951                expression_node_ptr un_r = n->branch(0);
20952                n->release();
20953                free_node(node_allocator_,node);
20954                node = un_r;
20955
20956                return true;
20957             }
20958          }
20959
20960          {
20961             typedef details::unary_variable_node<T,details::neg_op<T> > uvn_t;
20962
20963             uvn_t* n = dynamic_cast<uvn_t*>(node);
20964
20965             if (n)
20966             {
20967                const T& v = n->v();
20968                expression_node_ptr return_node = error_node();
20969
20970                if (
20971                     (0 != (return_node = symtab_store_.get_variable(v))) ||
20972                     (0 != (return_node = sem_         .get_variable(v)))
20973                   )
20974                {
20975                   free_node(node_allocator_,node);
20976                   node = return_node;
20977
20978                   return true;
20979                }
20980                else
20981                {
20982                   set_error(
20983                      make_error(parser_error::e_syntax,
20984                                 current_token(),
20985                                 "ERR015 - Failed to find variable node in symbol table",
20986                                 exprtk_error_location));
20987
20988                   free_node(node_allocator_,node);
20989
20990                   return false;
20991                }
20992             }
20993          }
20994
20995          return false;
20996       }
20997
20998       static inline expression_node_ptr error_node()
20999       {
21000          return reinterpret_cast<expression_node_ptr>(0);
21001       }
21002
21003       template <typename Type, std::size_t N>
21004       struct scoped_delete
21005       {
21006          typedef Type* ptr_t;
21007
21008          scoped_delete(parser<T>& pr, ptr_t& p)
21009          : delete_ptr(true),
21010            parser_(pr),
21011            p_(&p)
21012          {}
21013
21014          scoped_delete(parser<T>& pr, ptr_t (&p)[N])
21015          : delete_ptr(true),
21016            parser_(pr),
21017            p_(&p[0])
21018          {}
21019
21020         ~scoped_delete()
21021          {
21022             if (delete_ptr)
21023             {
21024                for (std::size_t i = 0; i < N; ++i)
21025                {
21026                   free_node(parser_.node_allocator_,p_[i]);
21027                }
21028             }
21029          }
21030
21031          bool delete_ptr;
21032          parser<T>& parser_;
21033          ptr_t* p_;
21034
21035       private:
21036
21037          scoped_delete<Type,N>& operator=(const scoped_delete<Type,N>&);
21038       };
21039
21040       template <typename Type>
21041       struct scoped_deq_delete
21042       {
21043          typedef Type* ptr_t;
21044
21045          scoped_deq_delete(parser<T>& pr, std::deque<ptr_t>& deq)
21046          : delete_ptr(true),
21047            parser_(pr),
21048            deq_(deq)
21049          {}
21050
21051         ~scoped_deq_delete()
21052          {
21053             if (delete_ptr && !deq_.empty())
21054             {
21055                for (std::size_t i = 0; i < deq_.size(); ++i)
21056                {
21057                   free_node(parser_.node_allocator_,deq_[i]);
21058                }
21059
21060                deq_.clear();
21061             }
21062          }
21063
21064          bool delete_ptr;
21065          parser<T>& parser_;
21066          std::deque<ptr_t>& deq_;
21067
21068       private:
21069
21070          scoped_deq_delete<Type>& operator=(const scoped_deq_delete<Type>&);
21071       };
21072
21073       template <typename Type>
21074       struct scoped_vec_delete
21075       {
21076          typedef Type* ptr_t;
21077
21078          scoped_vec_delete(parser<T>& pr, std::vector<ptr_t>& vec)
21079          : delete_ptr(true),
21080            parser_(pr),
21081            vec_(vec)
21082          {}
21083
21084         ~scoped_vec_delete()
21085          {
21086             if (delete_ptr && !vec_.empty())
21087             {
21088                for (std::size_t i = 0; i < vec_.size(); ++i)
21089                {
21090                   free_node(parser_.node_allocator_,vec_[i]);
21091                }
21092
21093                vec_.clear();
21094             }
21095          }
21096
21097          bool delete_ptr;
21098          parser<T>& parser_;
21099          std::vector<ptr_t>& vec_;
21100
21101       private:
21102
21103          scoped_vec_delete<Type>& operator=(const scoped_vec_delete<Type>&);
21104       };
21105
21106       struct scoped_bool_negator
21107       {
21108          explicit scoped_bool_negator(bool& bb)
21109          : b(bb)
21110          { b = !b; }
21111
21112         ~scoped_bool_negator()
21113          { b = !b; }
21114
21115          bool& b;
21116       };
21117
21118       struct scoped_bool_or_restorer
21119       {
21120          explicit scoped_bool_or_restorer(bool& bb)
21121          : b(bb),
21122            original_value_(bb)
21123          {}
21124
21125         ~scoped_bool_or_restorer()
21126          {
21127             b = b || original_value_;
21128          }
21129
21130          bool& b;
21131          bool original_value_;
21132       };
21133
21134       inline expression_node_ptr parse_function_invocation(ifunction<T>* function, const std::string& function_name)
21135       {
21136          expression_node_ptr func_node = reinterpret_cast<expression_node_ptr>(0);
21137
21138          switch (function->param_count)
21139          {
21140             case  0 : func_node = parse_function_call_0  (function,function_name); break;
21141             case  1 : func_node = parse_function_call< 1>(function,function_name); break;
21142             case  2 : func_node = parse_function_call< 2>(function,function_name); break;
21143             case  3 : func_node = parse_function_call< 3>(function,function_name); break;
21144             case  4 : func_node = parse_function_call< 4>(function,function_name); break;
21145             case  5 : func_node = parse_function_call< 5>(function,function_name); break;
21146             case  6 : func_node = parse_function_call< 6>(function,function_name); break;
21147             case  7 : func_node = parse_function_call< 7>(function,function_name); break;
21148             case  8 : func_node = parse_function_call< 8>(function,function_name); break;
21149             case  9 : func_node = parse_function_call< 9>(function,function_name); break;
21150             case 10 : func_node = parse_function_call<10>(function,function_name); break;
21151             case 11 : func_node = parse_function_call<11>(function,function_name); break;
21152             case 12 : func_node = parse_function_call<12>(function,function_name); break;
21153             case 13 : func_node = parse_function_call<13>(function,function_name); break;
21154             case 14 : func_node = parse_function_call<14>(function,function_name); break;
21155             case 15 : func_node = parse_function_call<15>(function,function_name); break;
21156             case 16 : func_node = parse_function_call<16>(function,function_name); break;
21157             case 17 : func_node = parse_function_call<17>(function,function_name); break;
21158             case 18 : func_node = parse_function_call<18>(function,function_name); break;
21159             case 19 : func_node = parse_function_call<19>(function,function_name); break;
21160             case 20 : func_node = parse_function_call<20>(function,function_name); break;
21161             default : {
21162                          set_error(
21163                             make_error(parser_error::e_syntax,
21164                                        current_token(),
21165                                        "ERR016 - Invalid number of parameters for function: '" + function_name + "'",
21166                                        exprtk_error_location));
21167
21168                          return error_node();
21169                       }
21170          }
21171
21172          if (func_node)
21173             return func_node;
21174          else
21175          {
21176             set_error(
21177                make_error(parser_error::e_syntax,
21178                           current_token(),
21179                           "ERR017 - Failed to generate call to function: '" + function_name + "'",
21180                           exprtk_error_location));
21181
21182             return error_node();
21183          }
21184       }
21185
21186       template <std::size_t NumberofParameters>
21187       inline expression_node_ptr parse_function_call(ifunction<T>* function, const std::string& function_name)
21188       {
21189          #ifdef _MSC_VER
21190             #pragma warning(push)
21191             #pragma warning(disable: 4127)
21192          #endif
21193          if (0 == NumberofParameters)
21194          {
21195             set_error(
21196                make_error(parser_error::e_syntax,
21197                           current_token(),
21198                           "ERR018 - Expecting ifunction '" + function_name + "' to have non-zero parameter count",
21199                           exprtk_error_location));
21200
21201             return error_node();
21202          }
21203          #ifdef _MSC_VER
21204             #pragma warning(pop)
21205          #endif
21206
21207          expression_node_ptr branch[NumberofParameters];
21208          expression_node_ptr result  = error_node();
21209
21210          std::fill_n(branch, NumberofParameters, reinterpret_cast<expression_node_ptr>(0));
21211
21212          scoped_delete<expression_node_t,NumberofParameters> sd((*this),branch);
21213
21214          next_token();
21215
21216          if (!token_is(token_t::e_lbracket))
21217          {
21218             set_error(
21219                make_error(parser_error::e_syntax,
21220                           current_token(),
21221                           "ERR019 - Expecting argument list for function: '" + function_name + "'",
21222                           exprtk_error_location));
21223
21224             return error_node();
21225          }
21226
21227          for (int i = 0; i < static_cast<int>(NumberofParameters); ++i)
21228          {
21229             branch[i] = parse_expression();
21230
21231             if (0 == branch[i])
21232             {
21233                set_error(
21234                   make_error(parser_error::e_syntax,
21235                              current_token(),
21236                              "ERR020 - Failed to parse argument " + details::to_str(i) + " for function: '" + function_name + "'",
21237                              exprtk_error_location));
21238
21239                return error_node();
21240             }
21241             else if (i < static_cast<int>(NumberofParameters - 1))
21242             {
21243                if (!token_is(token_t::e_comma))
21244                {
21245                   set_error(
21246                      make_error(parser_error::e_syntax,
21247                                 current_token(),
21248                                 "ERR021 - Invalid number of arguments for function: '" + function_name + "'",
21249                                 exprtk_error_location));
21250
21251                   return error_node();
21252                }
21253             }
21254          }
21255
21256          if (!token_is(token_t::e_rbracket))
21257          {
21258             set_error(
21259                make_error(parser_error::e_syntax,
21260                           current_token(),
21261                           "ERR022 - Invalid number of arguments for function: '" + function_name + "'",
21262                           exprtk_error_location));
21263
21264             return error_node();
21265          }
21266          else
21267             result = expression_generator_.function(function,branch);
21268
21269          sd.delete_ptr = false;
21270
21271          return result;
21272       }
21273
21274       inline expression_node_ptr parse_function_call_0(ifunction<T>* function, const std::string& function_name)
21275       {
21276          expression_node_ptr result = expression_generator_.function(function);
21277
21278          state_.side_effect_present = function->has_side_effects();
21279
21280          next_token();
21281
21282          if (
21283                token_is(token_t::e_lbracket) &&
21284               !token_is(token_t::e_rbracket)
21285             )
21286          {
21287             set_error(
21288                make_error(parser_error::e_syntax,
21289                           current_token(),
21290                           "ERR023 - Expecting '()' to proceed call to function: '" + function_name + "'",
21291                           exprtk_error_location));
21292
21293             free_node(node_allocator_,result);
21294
21295             return error_node();
21296          }
21297          else
21298             return result;
21299       }
21300
21301       template <std::size_t MaxNumberofParameters>
21302       inline std::size_t parse_base_function_call(expression_node_ptr (&param_list)[MaxNumberofParameters], const std::string& function_name = "")
21303       {
21304          std::fill_n(param_list, MaxNumberofParameters, reinterpret_cast<expression_node_ptr>(0));
21305
21306          scoped_delete<expression_node_t,MaxNumberofParameters> sd((*this),param_list);
21307
21308          next_token();
21309
21310          if (!token_is(token_t::e_lbracket))
21311          {
21312             set_error(
21313                make_error(parser_error::e_syntax,
21314                           current_token(),
21315                           "ERR024 - Expected a '(' at start of function call to '" + function_name  +
21316                           "', instead got: '" + current_token().value + "'",
21317                           exprtk_error_location));
21318
21319             return 0;
21320          }
21321
21322          if (token_is(token_t::e_rbracket, e_hold))
21323          {
21324             set_error(
21325                make_error(parser_error::e_syntax,
21326                           current_token(),
21327                           "ERR025 - Expected at least one input parameter for function call '" + function_name + "'",
21328                           exprtk_error_location));
21329
21330             return 0;
21331          }
21332
21333          std::size_t param_index = 0;
21334
21335          for (; param_index < MaxNumberofParameters; ++param_index)
21336          {
21337             param_list[param_index] = parse_expression();
21338
21339             if (0 == param_list[param_index])
21340                return 0;
21341             else if (token_is(token_t::e_rbracket))
21342             {
21343                sd.delete_ptr = false;
21344                break;
21345             }
21346             else if (token_is(token_t::e_comma))
21347                continue;
21348             else
21349             {
21350                set_error(
21351                   make_error(parser_error::e_syntax,
21352                              current_token(),
21353                              "ERR026 - Expected a ',' between function input parameters, instead got: '" + current_token().value + "'",
21354                              exprtk_error_location));
21355
21356                return 0;
21357             }
21358          }
21359
21360          if (sd.delete_ptr)
21361          {
21362             set_error(
21363                make_error(parser_error::e_syntax,
21364                           current_token(),
21365                           "ERR027 - Invalid number of input parameters passed to function '" + function_name  + "'",
21366                           exprtk_error_location));
21367
21368             return 0;
21369          }
21370
21371          return (param_index + 1);
21372       }
21373
21374       inline expression_node_ptr parse_base_operation()
21375       {
21376          typedef std::pair<base_ops_map_t::iterator,base_ops_map_t::iterator> map_range_t;
21377
21378          const std::string operation_name   = current_token().value;
21379          const token_t     diagnostic_token = current_token();
21380
21381          map_range_t itr_range = base_ops_map_.equal_range(operation_name);
21382
21383          if (0 == std::distance(itr_range.first,itr_range.second))
21384          {
21385             set_error(
21386                make_error(parser_error::e_syntax,
21387                           diagnostic_token,
21388                           "ERR028 - No entry found for base operation: " + operation_name,
21389                           exprtk_error_location));
21390
21391             return error_node();
21392          }
21393
21394          static const std::size_t MaxNumberofParameters = 4;
21395          expression_node_ptr param_list[MaxNumberofParameters] = {0};
21396
21397          const std::size_t parameter_count = parse_base_function_call(param_list, operation_name);
21398
21399          if ((parameter_count > 0) && (parameter_count <= MaxNumberofParameters))
21400          {
21401             for (base_ops_map_t::iterator itr = itr_range.first; itr != itr_range.second; ++itr)
21402             {
21403                const details::base_operation_t& operation = itr->second;
21404
21405                if (operation.num_params == parameter_count)
21406                {
21407                   switch (parameter_count)
21408                   {
21409                      #define base_opr_case(N)                                         \
21410                      case N : {                                                       \
21411                                  expression_node_ptr pl##N[N] = {0};                  \
21412                                  std::copy(param_list, param_list + N, pl##N);        \
21413                                  lodge_symbol(operation_name, e_st_function);         \
21414                                  return expression_generator_(operation.type, pl##N); \
21415                               }                                                       \
21416
21417                      base_opr_case(1)
21418                      base_opr_case(2)
21419                      base_opr_case(3)
21420                      base_opr_case(4)
21421                      #undef base_opr_case
21422                   }
21423                }
21424             }
21425          }
21426
21427          for (std::size_t i = 0; i < MaxNumberofParameters; ++i)
21428          {
21429             free_node(node_allocator_, param_list[i]);
21430          }
21431
21432          set_error(
21433             make_error(parser_error::e_syntax,
21434                        diagnostic_token,
21435                        "ERR029 - Invalid number of input parameters for call to function: '" + operation_name + "'",
21436                        exprtk_error_location));
21437
21438          return error_node();
21439       }
21440
21441       inline expression_node_ptr parse_conditional_statement_01(expression_node_ptr condition)
21442       {
21443          // Parse: [if][(][condition][,][consequent][,][alternative][)]
21444
21445          expression_node_ptr consequent  = error_node();
21446          expression_node_ptr alternative = error_node();
21447
21448          bool result = true;
21449
21450          if (!token_is(token_t::e_comma))
21451          {
21452             set_error(
21453                make_error(parser_error::e_syntax,
21454                           current_token(),
21455                           "ERR030 - Expected ',' between if-statement condition and consequent",
21456                           exprtk_error_location));
21457             result = false;
21458          }
21459          else if (0 == (consequent = parse_expression()))
21460          {
21461             set_error(
21462                make_error(parser_error::e_syntax,
21463                           current_token(),
21464                           "ERR031 - Failed to parse consequent for if-statement",
21465                           exprtk_error_location));
21466             result = false;
21467          }
21468          else if (!token_is(token_t::e_comma))
21469          {
21470             set_error(
21471                make_error(parser_error::e_syntax,
21472                           current_token(),
21473                           "ERR032 - Expected ',' between if-statement consequent and alternative",
21474                           exprtk_error_location));
21475             result = false;
21476          }
21477          else if (0 == (alternative = parse_expression()))
21478          {
21479             set_error(
21480                make_error(parser_error::e_syntax,
21481                           current_token(),
21482                           "ERR033 - Failed to parse alternative for if-statement",
21483                           exprtk_error_location));
21484             result = false;
21485          }
21486          else if (!token_is(token_t::e_rbracket))
21487          {
21488             set_error(
21489                make_error(parser_error::e_syntax,
21490                           current_token(),
21491                           "ERR034 - Expected ')' at the end of if-statement",
21492                           exprtk_error_location));
21493             result = false;
21494          }
21495
21496          #ifndef exprtk_disable_string_capabilities
21497          if (result)
21498          {
21499             const bool consq_is_str = is_generally_string_node( consequent);
21500             const bool alter_is_str = is_generally_string_node(alternative);
21501
21502             if (consq_is_str || alter_is_str)
21503             {
21504                if (consq_is_str && alter_is_str)
21505                {
21506                   return expression_generator_
21507                            .conditional_string(condition, consequent, alternative);
21508                }
21509
21510                set_error(
21511                   make_error(parser_error::e_syntax,
21512                              current_token(),
21513                              "ERR035 - Return types of ternary if-statement differ",
21514                              exprtk_error_location));
21515
21516                result = false;
21517             }
21518          }
21519          #endif
21520
21521          if (!result)
21522          {
21523             free_node(node_allocator_,  condition);
21524             free_node(node_allocator_, consequent);
21525             free_node(node_allocator_,alternative);
21526
21527             return error_node();
21528          }
21529          else
21530             return expression_generator_
21531                       .conditional(condition, consequent, alternative);
21532       }
21533
21534       inline expression_node_ptr parse_conditional_statement_02(expression_node_ptr condition)
21535       {
21536          expression_node_ptr consequent  = error_node();
21537          expression_node_ptr alternative = error_node();
21538
21539          bool result = true;
21540
21541          if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
21542          {
21543             if (0 == (consequent = parse_multi_sequence("if-statement-01")))
21544             {
21545                set_error(
21546                   make_error(parser_error::e_syntax,
21547                              current_token(),
21548                              "ERR036 - Failed to parse body of consequent for if-statement",
21549                              exprtk_error_location));
21550
21551                result = false;
21552             }
21553          }
21554          else
21555          {
21556             if (
21557                  settings_.commutative_check_enabled() &&
21558                  token_is(token_t::e_mul,prsrhlpr_t::e_hold)
21559                )
21560             {
21561                next_token();
21562             }
21563
21564             if (0 != (consequent = parse_expression()))
21565             {
21566                if (!token_is(token_t::e_eof))
21567                {
21568                   set_error(
21569                      make_error(parser_error::e_syntax,
21570                                 current_token(),
21571                                 "ERR037 - Expected ';' at the end of the consequent for if-statement",
21572                                 exprtk_error_location));
21573
21574                   result = false;
21575                }
21576             }
21577             else
21578             {
21579                set_error(
21580                   make_error(parser_error::e_syntax,
21581                              current_token(),
21582                              "ERR038 - Failed to parse body of consequent for if-statement",
21583                              exprtk_error_location));
21584
21585                result = false;
21586             }
21587          }
21588
21589          if (result)
21590          {
21591             if (details::imatch(current_token().value,"else"))
21592             {
21593                next_token();
21594
21595                if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
21596                {
21597                   if (0 == (alternative = parse_multi_sequence("else-statement-01")))
21598                   {
21599                      set_error(
21600                         make_error(parser_error::e_syntax,
21601                                    current_token(),
21602                                    "ERR039 - Failed to parse body of the 'else' for if-statement",
21603                                    exprtk_error_location));
21604
21605                      result = false;
21606                   }
21607                }
21608                else if (details::imatch(current_token().value,"if"))
21609                {
21610                   if (0 == (alternative = parse_conditional_statement()))
21611                   {
21612                      set_error(
21613                         make_error(parser_error::e_syntax,
21614                                    current_token(),
21615                                    "ERR040 - Failed to parse body of if-else statement",
21616                                    exprtk_error_location));
21617
21618                      result = false;
21619                   }
21620                }
21621                else if (0 != (alternative = parse_expression()))
21622                {
21623                   if (!token_is(token_t::e_eof))
21624                   {
21625                      set_error(
21626                         make_error(parser_error::e_syntax,
21627                                    current_token(),
21628                                    "ERR041 - Expected ';' at the end of the 'else-if' for the if-statement",
21629                                    exprtk_error_location));
21630
21631                      result = false;
21632                   }
21633                }
21634                else
21635                {
21636                   set_error(
21637                      make_error(parser_error::e_syntax,
21638                                 current_token(),
21639                                 "ERR042 - Failed to parse body of the 'else' for if-statement",
21640                                 exprtk_error_location));
21641
21642                   result = false;
21643                }
21644             }
21645          }
21646
21647          #ifndef exprtk_disable_string_capabilities
21648          if (result)
21649          {
21650             const bool consq_is_str = is_generally_string_node( consequent);
21651             const bool alter_is_str = is_generally_string_node(alternative);
21652
21653             if (consq_is_str || alter_is_str)
21654             {
21655                if (consq_is_str && alter_is_str)
21656                {
21657                   return expression_generator_
21658                            .conditional_string(condition, consequent, alternative);
21659                }
21660
21661                set_error(
21662                   make_error(parser_error::e_syntax,
21663                              current_token(),
21664                              "ERR043 - Return types of ternary if-statement differ",
21665                              exprtk_error_location));
21666
21667                result = false;
21668             }
21669          }
21670          #endif
21671
21672          if (!result)
21673          {
21674             free_node(node_allocator_,   condition);
21675             free_node(node_allocator_,  consequent);
21676             free_node(node_allocator_, alternative);
21677
21678             return error_node();
21679          }
21680          else
21681             return expression_generator_
21682                       .conditional(condition, consequent, alternative);
21683       }
21684
21685       inline expression_node_ptr parse_conditional_statement()
21686       {
21687          expression_node_ptr condition = error_node();
21688
21689          next_token();
21690
21691          if (!token_is(token_t::e_lbracket))
21692          {
21693             set_error(
21694                make_error(parser_error::e_syntax,
21695                           current_token(),
21696                           "ERR044 - Expected '(' at start of if-statement, instead got: '" + current_token().value + "'",
21697                           exprtk_error_location));
21698
21699             return error_node();
21700          }
21701          else if (0 == (condition = parse_expression()))
21702          {
21703             set_error(
21704                make_error(parser_error::e_syntax,
21705                           current_token(),
21706                           "ERR045 - Failed to parse condition for if-statement",
21707                           exprtk_error_location));
21708
21709             return error_node();
21710          }
21711          else if (token_is(token_t::e_comma,prsrhlpr_t::e_hold))
21712          {
21713             // if (x,y,z)
21714             return parse_conditional_statement_01(condition);
21715          }
21716          else if (token_is(token_t::e_rbracket))
21717          {
21718             // 00. if (x) y;
21719             // 01. if (x) y; else z;
21720             // 02. if (x) y; else {z0; ... zn;}
21721             // 03. if (x) y; else if (z) w;
21722             // 04. if (x) y; else if (z) w; else u;
21723             // 05. if (x) y; else if (z) w; else {u0; ... un;}
21724             // 06. if (x) y; else if (z) {w0; ... wn;}
21725             // 07. if (x) {y0; ... yn;}
21726             // 08. if (x) {y0; ... yn;} else z;
21727             // 09. if (x) {y0; ... yn;} else {z0; ... zn;};
21728             // 10. if (x) {y0; ... yn;} else if (z) w;
21729             // 11. if (x) {y0; ... yn;} else if (z) w; else u;
21730             // 12. if (x) {y0; ... nex;} else if (z) w; else {u0 ... un;}
21731             // 13. if (x) {y0; ... yn;} else if (z) {w0; ... wn;}
21732             return parse_conditional_statement_02(condition);
21733          }
21734
21735          set_error(
21736             make_error(parser_error::e_syntax,
21737                        current_token(),
21738                        "ERR046 - Invalid if-statement",
21739                        exprtk_error_location));
21740
21741          free_node(node_allocator_,condition);
21742
21743          return error_node();
21744       }
21745
21746       inline expression_node_ptr parse_ternary_conditional_statement(expression_node_ptr condition)
21747       {
21748          // Parse: [condition][?][consequent][:][alternative]
21749          expression_node_ptr consequent  = error_node();
21750          expression_node_ptr alternative = error_node();
21751
21752          bool result = true;
21753
21754          if (0 == condition)
21755          {
21756             set_error(
21757                make_error(parser_error::e_syntax,
21758                           current_token(),
21759                           "ERR047 - Encountered invalid condition branch for ternary if-statement",
21760                           exprtk_error_location));
21761
21762             return error_node();
21763          }
21764          else if (!token_is(token_t::e_ternary))
21765          {
21766             set_error(
21767                make_error(parser_error::e_syntax,
21768                           current_token(),
21769                           "ERR048 - Expected '?' after condition of ternary if-statement",
21770                           exprtk_error_location));
21771
21772             result = false;
21773          }
21774          else if (0 == (consequent = parse_expression()))
21775          {
21776             set_error(
21777                make_error(parser_error::e_syntax,
21778                           current_token(),
21779                           "ERR049 - Failed to parse consequent for ternary if-statement",
21780                           exprtk_error_location));
21781
21782             result = false;
21783          }
21784          else if (!token_is(token_t::e_colon))
21785          {
21786             set_error(
21787                make_error(parser_error::e_syntax,
21788                           current_token(),
21789                           "ERR050 - Expected ':' between ternary if-statement consequent and alternative",
21790                           exprtk_error_location));
21791
21792             result = false;
21793          }
21794          else if (0 == (alternative = parse_expression()))
21795          {
21796             set_error(
21797                make_error(parser_error::e_syntax,
21798                           current_token(),
21799                           "ERR051 - Failed to parse alternative for ternary if-statement",
21800                           exprtk_error_location));
21801
21802             result = false;
21803          }
21804
21805          #ifndef exprtk_disable_string_capabilities
21806          if (result)
21807          {
21808             const bool consq_is_str = is_generally_string_node( consequent);
21809             const bool alter_is_str = is_generally_string_node(alternative);
21810
21811             if (consq_is_str || alter_is_str)
21812             {
21813                if (consq_is_str && alter_is_str)
21814                {
21815                   return expression_generator_
21816                            .conditional_string(condition, consequent, alternative);
21817                }
21818
21819                set_error(
21820                   make_error(parser_error::e_syntax,
21821                              current_token(),
21822                              "ERR052 - Return types of ternary if-statement differ",
21823                              exprtk_error_location));
21824
21825                result = false;
21826             }
21827          }
21828          #endif
21829
21830          if (!result)
21831          {
21832             free_node(node_allocator_,   condition);
21833             free_node(node_allocator_,  consequent);
21834             free_node(node_allocator_, alternative);
21835
21836             return error_node();
21837          }
21838          else
21839             return expression_generator_
21840                       .conditional(condition, consequent, alternative);
21841       }
21842
21843       inline expression_node_ptr parse_not_statement()
21844       {
21845          if (settings_.logic_disabled("not"))
21846          {
21847             set_error(
21848                make_error(parser_error::e_syntax,
21849                           current_token(),
21850                           "ERR053 - Invalid or disabled logic operation 'not'",
21851                           exprtk_error_location));
21852
21853             return error_node();
21854          }
21855
21856          return parse_base_operation();
21857       }
21858
21859       inline expression_node_ptr parse_while_loop()
21860       {
21861          // Parse: [while][(][test expr][)][{][expression][}]
21862          expression_node_ptr condition   = error_node();
21863          expression_node_ptr branch      = error_node();
21864          expression_node_ptr result_node = error_node();
21865
21866          bool result = true;
21867
21868          next_token();
21869
21870          if (!token_is(token_t::e_lbracket))
21871          {
21872             set_error(
21873                make_error(parser_error::e_syntax,
21874                           current_token(),
21875                           "ERR054 - Expected '(' at start of while-loop condition statement",
21876                           exprtk_error_location));
21877
21878             return error_node();
21879          }
21880          else if (0 == (condition = parse_expression()))
21881          {
21882             set_error(
21883                make_error(parser_error::e_syntax,
21884                           current_token(),
21885                           "ERR055 - Failed to parse condition for while-loop",
21886                           exprtk_error_location));
21887
21888             return error_node();
21889          }
21890          else if (!token_is(token_t::e_rbracket))
21891          {
21892             set_error(
21893                make_error(parser_error::e_syntax,
21894                           current_token(),
21895                           "ERR056 - Expected ')' at end of while-loop condition statement",
21896                           exprtk_error_location));
21897
21898             result = false;
21899          }
21900
21901          brkcnt_list_.push_front(false);
21902
21903          if (result)
21904          {
21905             if (0 == (branch = parse_multi_sequence("while-loop")))
21906             {
21907                set_error(
21908                   make_error(parser_error::e_syntax,
21909                              current_token(),
21910                              "ERR057 - Failed to parse body of while-loop"));
21911                result = false;
21912             }
21913             else if (0 == (result_node = expression_generator_.while_loop(condition,
21914                                                                           branch,
21915                                                                           brkcnt_list_.front())))
21916             {
21917                set_error(
21918                   make_error(parser_error::e_syntax,
21919                              current_token(),
21920                              "ERR058 - Failed to synthesize while-loop",
21921                              exprtk_error_location));
21922
21923                result = false;
21924             }
21925          }
21926
21927          if (!result)
21928          {
21929             free_node(node_allocator_,      branch);
21930             free_node(node_allocator_,   condition);
21931             free_node(node_allocator_, result_node);
21932
21933             brkcnt_list_.pop_front();
21934
21935             return error_node();
21936          }
21937          else
21938             return result_node;
21939       }
21940
21941       inline expression_node_ptr parse_repeat_until_loop()
21942       {
21943          // Parse: [repeat][{][expression][}][until][(][test expr][)]
21944          expression_node_ptr condition = error_node();
21945          expression_node_ptr branch    = error_node();
21946          next_token();
21947
21948          std::vector<expression_node_ptr> arg_list;
21949          std::vector<bool> side_effect_list;
21950
21951          scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
21952
21953          brkcnt_list_.push_front(false);
21954
21955          if (details::imatch(current_token().value,"until"))
21956          {
21957             next_token();
21958             branch = node_allocator_.allocate<details::null_node<T> >();
21959          }
21960          else
21961          {
21962             const token_t::token_type seperator = token_t::e_eof;
21963
21964             scope_handler sh(*this);
21965
21966             scoped_bool_or_restorer sbr(state_.side_effect_present);
21967
21968             for ( ; ; )
21969             {
21970                state_.side_effect_present = false;
21971
21972                expression_node_ptr arg = parse_expression();
21973
21974                if (0 == arg)
21975                   return error_node();
21976                else
21977                {
21978                   arg_list.push_back(arg);
21979                   side_effect_list.push_back(state_.side_effect_present);
21980                }
21981
21982                if (details::imatch(current_token().value,"until"))
21983                {
21984                   next_token();
21985                   break;
21986                }
21987
21988                const bool is_next_until = peek_token_is(token_t::e_symbol) &&
21989                                           peek_token_is("until");
21990
21991                if (!token_is(seperator) && is_next_until)
21992                {
21993                   set_error(
21994                      make_error(parser_error::e_syntax,
21995                                 current_token(),
21996                                 "ERR059 - Expected '" + token_t::to_str(seperator) + "' in body of repeat until loop",
21997                                 exprtk_error_location));
21998
21999                   return error_node();
22000                }
22001
22002                if (details::imatch(current_token().value,"until"))
22003                {
22004                   next_token();
22005                   break;
22006                }
22007             }
22008
22009             branch = simplify(arg_list,side_effect_list);
22010
22011             sdd.delete_ptr = (0 == branch);
22012
22013             if (sdd.delete_ptr)
22014             {
22015                brkcnt_list_.pop_front();
22016
22017                set_error(
22018                   make_error(parser_error::e_syntax,
22019                              current_token(),
22020                              "ERR060 - Failed to parse body of repeat until loop",
22021                              exprtk_error_location));
22022
22023                return error_node();
22024             }
22025          }
22026
22027          if (!token_is(token_t::e_lbracket))
22028          {
22029             brkcnt_list_.pop_front();
22030
22031             set_error(
22032                make_error(parser_error::e_syntax,
22033                           current_token(),
22034                           "ERR061 - Expected '(' before condition statement of repeat until loop",
22035                           exprtk_error_location));
22036
22037             free_node(node_allocator_,branch);
22038
22039             return error_node();
22040          }
22041          else if (0 == (condition = parse_expression()))
22042          {
22043             brkcnt_list_.pop_front();
22044
22045             set_error(
22046                make_error(parser_error::e_syntax,
22047                           current_token(),
22048                           "ERR062 - Failed to parse condition for repeat until loop",
22049                           exprtk_error_location));
22050
22051             free_node(node_allocator_,branch);
22052
22053             return error_node();
22054          }
22055          else if (!token_is(token_t::e_rbracket))
22056          {
22057             set_error(
22058                make_error(parser_error::e_syntax,
22059                           current_token(),
22060                           "ERR063 - Expected ')' after condition of repeat until loop",
22061                           exprtk_error_location));
22062
22063             free_node(node_allocator_,    branch);
22064             free_node(node_allocator_, condition);
22065
22066             brkcnt_list_.pop_front();
22067
22068             return error_node();
22069          }
22070
22071          expression_node_ptr result;
22072
22073          result = expression_generator_
22074                      .repeat_until_loop(condition, branch, brkcnt_list_.front());
22075
22076          if (0 == result)
22077          {
22078             set_error(
22079                make_error(parser_error::e_syntax,
22080                           current_token(),
22081                           "ERR064 - Failed to synthesize repeat until loop",
22082                           exprtk_error_location));
22083
22084             free_node(node_allocator_,condition);
22085
22086             brkcnt_list_.pop_front();
22087
22088             return error_node();
22089          }
22090          else
22091          {
22092             brkcnt_list_.pop_front();
22093             return result;
22094          }
22095       }
22096
22097       inline expression_node_ptr parse_for_loop()
22098       {
22099          expression_node_ptr initialiser = error_node();
22100          expression_node_ptr condition   = error_node();
22101          expression_node_ptr incrementor = error_node();
22102          expression_node_ptr loop_body   = error_node();
22103
22104          scope_element* se = 0;
22105          bool result       = true;
22106
22107          next_token();
22108
22109          scope_handler sh(*this);
22110
22111          if (!token_is(token_t::e_lbracket))
22112          {
22113             set_error(
22114                make_error(parser_error::e_syntax,
22115                           current_token(),
22116                           "ERR065 - Expected '(' at start of for-loop",
22117                           exprtk_error_location));
22118
22119             return error_node();
22120          }
22121
22122          if (!token_is(token_t::e_eof))
22123          {
22124             if (
22125                  !token_is(token_t::e_symbol,prsrhlpr_t::e_hold) &&
22126                  details::imatch(current_token().value,"var")
22127                )
22128             {
22129                next_token();
22130
22131                if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold))
22132                {
22133                   set_error(
22134                      make_error(parser_error::e_syntax,
22135                                 current_token(),
22136                                 "ERR066 - Expected a variable at the start of initialiser section of for-loop",
22137                                 exprtk_error_location));
22138
22139                   return error_node();
22140                }
22141                else if (!peek_token_is(token_t::e_assign))
22142                {
22143                   set_error(
22144                      make_error(parser_error::e_syntax,
22145                                 current_token(),
22146                                 "ERR067 - Expected variable assignment of initialiser section of for-loop",
22147                                 exprtk_error_location));
22148
22149                   return error_node();
22150                }
22151
22152                const std::string loop_counter_symbol = current_token().value;
22153
22154                se = &sem_.get_element(loop_counter_symbol);
22155
22156                if ((se->name == loop_counter_symbol) && se->active)
22157                {
22158                   set_error(
22159                      make_error(parser_error::e_syntax,
22160                                 current_token(),
22161                                 "ERR068 - For-loop variable '" + loop_counter_symbol+ "' is being shadowed by a previous declaration",
22162                                 exprtk_error_location));
22163
22164                   return error_node();
22165                }
22166                else if (!symtab_store_.is_variable(loop_counter_symbol))
22167                {
22168                   if (
22169                        !se->active &&
22170                        (se->name == loop_counter_symbol) &&
22171                        (se->type ==  scope_element::e_variable)
22172                      )
22173                   {
22174                      se->active = true;
22175                      se->ref_count++;
22176                   }
22177                   else
22178                   {
22179                      scope_element nse;
22180                      nse.name      = loop_counter_symbol;
22181                      nse.active    = true;
22182                      nse.ref_count = 1;
22183                      nse.type      = scope_element::e_variable;
22184                      nse.depth     = state_.scope_depth;
22185                      nse.data      = new T(T(0));
22186                      nse.var_node  = node_allocator_.allocate<variable_node_t>(*(T*)(nse.data));
22187
22188                      if (!sem_.add_element(nse))
22189                      {
22190                         set_error(
22191                            make_error(parser_error::e_syntax,
22192                                       current_token(),
22193                                       "ERR069 - Failed to add new local variable '" + loop_counter_symbol + "' to SEM",
22194                                       exprtk_error_location));
22195
22196                         sem_.free_element(nse);
22197
22198                         result = false;
22199                      }
22200                      else
22201                      {
22202                         exprtk_debug(("parse_for_loop() - INFO - Added new local variable: %s\n",nse.name.c_str()));
22203
22204                         state_.activate_side_effect("parse_for_loop()");
22205                      }
22206                   }
22207                }
22208             }
22209
22210             if (0 == (initialiser = parse_expression()))
22211             {
22212                set_error(
22213                   make_error(parser_error::e_syntax,
22214                              current_token(),
22215                              "ERR070 - Failed to parse initialiser of for-loop",
22216                              exprtk_error_location));
22217
22218                result = false;
22219             }
22220             else if (!token_is(token_t::e_eof))
22221             {
22222                set_error(
22223                   make_error(parser_error::e_syntax,
22224                              current_token(),
22225                              "ERR071 - Expected ';' after initialiser of for-loop",
22226                              exprtk_error_location));
22227
22228                result = false;
22229             }
22230          }
22231
22232          if (!token_is(token_t::e_eof))
22233          {
22234             if (0 == (condition = parse_expression()))
22235             {
22236                set_error(
22237                   make_error(parser_error::e_syntax,
22238                              current_token(),
22239                              "ERR072 - Failed to parse condition of for-loop",
22240                              exprtk_error_location));
22241
22242                result = false;
22243             }
22244             else if (!token_is(token_t::e_eof))
22245             {
22246                set_error(
22247                   make_error(parser_error::e_syntax,
22248                              current_token(),
22249                              "ERR073 - Expected ';' after condition section of for-loop",
22250                              exprtk_error_location));
22251
22252                result = false;
22253             }
22254          }
22255
22256          if (!token_is(token_t::e_rbracket))
22257          {
22258             if (0 == (incrementor = parse_expression()))
22259             {
22260                set_error(
22261                   make_error(parser_error::e_syntax,
22262                              current_token(),
22263                              "ERR074 - Failed to parse incrementor of for-loop",
22264                              exprtk_error_location));
22265
22266                result = false;
22267             }
22268             else if (!token_is(token_t::e_rbracket))
22269             {
22270                set_error(
22271                   make_error(parser_error::e_syntax,
22272                              current_token(),
22273                              "ERR075 - Expected ')' after incrementor section of for-loop",
22274                              exprtk_error_location));
22275
22276                result = false;
22277             }
22278          }
22279
22280          if (result)
22281          {
22282             brkcnt_list_.push_front(false);
22283
22284             if (0 == (loop_body = parse_multi_sequence("for-loop")))
22285             {
22286                set_error(
22287                   make_error(parser_error::e_syntax,
22288                              current_token(),
22289                              "ERR076 - Failed to parse body of for-loop",
22290                              exprtk_error_location));
22291
22292                result = false;
22293             }
22294          }
22295
22296          if (!result)
22297          {
22298             if (se)
22299             {
22300                se->ref_count--;
22301             }
22302
22303             free_node(node_allocator_, initialiser);
22304             free_node(node_allocator_,   condition);
22305             free_node(node_allocator_, incrementor);
22306             free_node(node_allocator_,   loop_body);
22307
22308             if (!brkcnt_list_.empty())
22309             {
22310                brkcnt_list_.pop_front();
22311             }
22312
22313             return error_node();
22314          }
22315          else
22316          {
22317             expression_node_ptr result_node =
22318                expression_generator_.for_loop(initialiser,
22319                                               condition,
22320                                               incrementor,
22321                                               loop_body,
22322                                               brkcnt_list_.front());
22323             brkcnt_list_.pop_front();
22324
22325             return result_node;
22326          }
22327       }
22328
22329       inline expression_node_ptr parse_switch_statement()
22330       {
22331          std::vector<expression_node_ptr> arg_list;
22332          expression_node_ptr result = error_node();
22333
22334          if (!details::imatch(current_token().value,"switch"))
22335          {
22336             set_error(
22337                make_error(parser_error::e_syntax,
22338                           current_token(),
22339                           "ERR077 - Expected keyword 'switch'",
22340                           exprtk_error_location));
22341
22342             return error_node();
22343          }
22344
22345          scoped_vec_delete<expression_node_t> svd((*this),arg_list);
22346
22347          next_token();
22348
22349          if (!token_is(token_t::e_lcrlbracket))
22350          {
22351             set_error(
22352                make_error(parser_error::e_syntax,
22353                           current_token(),
22354                           "ERR078 - Expected '{' for call to switch statement",
22355                           exprtk_error_location));
22356
22357             return error_node();
22358          }
22359
22360          for ( ; ; )
22361          {
22362             if (!details::imatch("case",current_token().value))
22363             {
22364                set_error(
22365                   make_error(parser_error::e_syntax,
22366                              current_token(),
22367                              "ERR079 - Expected either a 'case' or 'default' statement",
22368                              exprtk_error_location));
22369
22370                return error_node();
22371             }
22372
22373             next_token();
22374
22375             expression_node_ptr condition = parse_expression();
22376
22377             if (0 == condition)
22378                return error_node();
22379             else if (!token_is(token_t::e_colon))
22380             {
22381                set_error(
22382                   make_error(parser_error::e_syntax,
22383                              current_token(),
22384                              "ERR080 - Expected ':' for case of switch statement",
22385                              exprtk_error_location));
22386
22387                return error_node();
22388             }
22389
22390             expression_node_ptr consequent = parse_expression();
22391
22392             if (0 == consequent)
22393                return error_node();
22394             else if (!token_is(token_t::e_eof))
22395             {
22396                set_error(
22397                   make_error(parser_error::e_syntax,
22398                              current_token(),
22399                              "ERR081 - Expected ';' at end of case for switch statement",
22400                              exprtk_error_location));
22401
22402                return error_node();
22403             }
22404
22405             // Can we optimise away the case statement?
22406             if (is_constant_node(condition) && is_false(condition))
22407             {
22408                free_node(node_allocator_,  condition);
22409                free_node(node_allocator_, consequent);
22410             }
22411             else
22412             {
22413                arg_list.push_back( condition);
22414                arg_list.push_back(consequent);
22415             }
22416
22417             if (details::imatch("default",current_token().value))
22418             {
22419                next_token();
22420                if (!token_is(token_t::e_colon))
22421                {
22422                   set_error(
22423                      make_error(parser_error::e_syntax,
22424                                 current_token(),
22425                                 "ERR082 - Expected ':' for default of switch statement",
22426                                 exprtk_error_location));
22427
22428                   return error_node();
22429                }
22430
22431                expression_node_ptr default_statement = error_node();
22432
22433                if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
22434                   default_statement = parse_multi_sequence("switch-default");
22435                else
22436                   default_statement = parse_expression();
22437
22438                if (0 == default_statement)
22439                   return error_node();
22440                else if (!token_is(token_t::e_eof))
22441                {
22442                   free_node(node_allocator_,default_statement);
22443
22444                   set_error(
22445                      make_error(parser_error::e_syntax,
22446                                 current_token(),
22447                                 "ERR083 - Expected ';' at end of default for switch statement",
22448                                 exprtk_error_location));
22449
22450                   return error_node();
22451                }
22452
22453                arg_list.push_back(default_statement);
22454                break;
22455             }
22456          }
22457
22458          if (!token_is(token_t::e_rcrlbracket))
22459          {
22460             set_error(
22461                make_error(parser_error::e_syntax,
22462                           current_token(),
22463                           "ERR084 - Expected '}' at end of switch statement",
22464                           exprtk_error_location));
22465
22466             return error_node();
22467          }
22468
22469          result = expression_generator_.switch_statement(arg_list);
22470
22471          svd.delete_ptr = (0 == result);
22472
22473          return result;
22474       }
22475
22476       inline expression_node_ptr parse_multi_switch_statement()
22477       {
22478          std::vector<expression_node_ptr> arg_list;
22479
22480          if (!details::imatch(current_token().value,"[*]"))
22481          {
22482             set_error(
22483                make_error(parser_error::e_syntax,
22484                           current_token(),
22485                           "ERR085 - Expected token '[*]'",
22486                           exprtk_error_location));
22487
22488             return error_node();
22489          }
22490
22491          scoped_vec_delete<expression_node_t> svd((*this),arg_list);
22492
22493          next_token();
22494
22495          if (!token_is(token_t::e_lcrlbracket))
22496          {
22497             set_error(
22498                make_error(parser_error::e_syntax,
22499                           current_token(),
22500                           "ERR086 - Expected '{' for call to [*] statement",
22501                           exprtk_error_location));
22502
22503             return error_node();
22504          }
22505
22506          for ( ; ; )
22507          {
22508             if (!details::imatch("case",current_token().value))
22509             {
22510                set_error(
22511                   make_error(parser_error::e_syntax,
22512                              current_token(),
22513                              "ERR087 - Expected a 'case' statement for multi-switch",
22514                              exprtk_error_location));
22515
22516                return error_node();
22517             }
22518
22519             next_token();
22520
22521             expression_node_ptr condition = parse_expression();
22522
22523             if (0 == condition)
22524                return error_node();
22525
22526             if (!token_is(token_t::e_colon))
22527             {
22528                set_error(
22529                   make_error(parser_error::e_syntax,
22530                              current_token(),
22531                              "ERR088 - Expected ':' for case of [*] statement",
22532                              exprtk_error_location));
22533
22534                return error_node();
22535             }
22536
22537             expression_node_ptr consequent = parse_expression();
22538
22539             if (0 == consequent)
22540                return error_node();
22541
22542             if (!token_is(token_t::e_eof))
22543             {
22544                set_error(
22545                   make_error(parser_error::e_syntax,
22546                              current_token(),
22547                              "ERR089 - Expected ';' at end of case for [*] statement",
22548                              exprtk_error_location));
22549
22550                return error_node();
22551             }
22552
22553             // Can we optimise away the case statement?
22554             if (is_constant_node(condition) && is_false(condition))
22555             {
22556                free_node(node_allocator_,  condition);
22557                free_node(node_allocator_, consequent);
22558             }
22559             else
22560             {
22561                arg_list.push_back( condition);
22562                arg_list.push_back(consequent);
22563             }
22564
22565             if (token_is(token_t::e_rcrlbracket,prsrhlpr_t::e_hold))
22566             {
22567                break;
22568             }
22569          }
22570
22571          if (!token_is(token_t::e_rcrlbracket))
22572          {
22573             set_error(
22574                make_error(parser_error::e_syntax,
22575                           current_token(),
22576                           "ERR090 - Expected '}' at end of [*] statement",
22577                           exprtk_error_location));
22578
22579             return error_node();
22580          }
22581
22582          const expression_node_ptr result = expression_generator_.multi_switch_statement(arg_list);
22583
22584          svd.delete_ptr = (0 == result);
22585
22586          return result;
22587       }
22588
22589       inline expression_node_ptr parse_vararg_function()
22590       {
22591          std::vector<expression_node_ptr> arg_list;
22592
22593          details::operator_type opt_type = details::e_default;
22594          const std::string symbol = current_token().value;
22595
22596          if (details::imatch(symbol,"~"))
22597          {
22598             next_token();
22599             return parse_multi_sequence();
22600          }
22601          else if (details::imatch(symbol,"[*]"))
22602          {
22603             return parse_multi_switch_statement();
22604          }
22605          else if (details::imatch(symbol, "avg" )) opt_type = details::e_avg ;
22606          else if (details::imatch(symbol, "mand")) opt_type = details::e_mand;
22607          else if (details::imatch(symbol, "max" )) opt_type = details::e_max ;
22608          else if (details::imatch(symbol, "min" )) opt_type = details::e_min ;
22609          else if (details::imatch(symbol, "mor" )) opt_type = details::e_mor ;
22610          else if (details::imatch(symbol, "mul" )) opt_type = details::e_prod;
22611          else if (details::imatch(symbol, "sum" )) opt_type = details::e_sum ;
22612          else
22613          {
22614             set_error(
22615                make_error(parser_error::e_syntax,
22616                           current_token(),
22617                           "ERR091 - Unsupported vararg function: " + symbol,
22618                           exprtk_error_location));
22619
22620             return error_node();
22621          }
22622
22623          scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
22624
22625          lodge_symbol(symbol, e_st_function);
22626
22627          next_token();
22628
22629          if (!token_is(token_t::e_lbracket))
22630          {
22631             set_error(
22632                make_error(parser_error::e_syntax,
22633                           current_token(),
22634                           "ERR092 - Expected '(' for call to vararg function: " + symbol,
22635                           exprtk_error_location));
22636
22637             return error_node();
22638          }
22639
22640          for ( ; ; )
22641          {
22642             expression_node_ptr arg = parse_expression();
22643
22644             if (0 == arg)
22645                return error_node();
22646             else
22647                arg_list.push_back(arg);
22648
22649             if (token_is(token_t::e_rbracket))
22650                break;
22651             else if (!token_is(token_t::e_comma))
22652             {
22653                set_error(
22654                   make_error(parser_error::e_syntax,
22655                              current_token(),
22656                              "ERR093 - Expected ',' for call to vararg function: " + symbol,
22657                              exprtk_error_location));
22658
22659                return error_node();
22660             }
22661          }
22662
22663          const expression_node_ptr result = expression_generator_.vararg_function(opt_type,arg_list);
22664
22665          sdd.delete_ptr = (0 == result);
22666          return result;
22667       }
22668
22669       #ifndef exprtk_disable_string_capabilities
22670       inline expression_node_ptr parse_string_range_statement(expression_node_ptr& expression)
22671       {
22672          if (!token_is(token_t::e_lsqrbracket))
22673          {
22674             set_error(
22675                make_error(parser_error::e_syntax,
22676                           current_token(),
22677                           "ERR094 - Expected '[' as start of string range definition",
22678                           exprtk_error_location));
22679
22680             free_node(node_allocator_,expression);
22681
22682             return error_node();
22683          }
22684          else if (token_is(token_t::e_rsqrbracket))
22685          {
22686             return node_allocator_.allocate<details::string_size_node<T> >(expression);
22687          }
22688
22689          range_t rp;
22690
22691          if (!parse_range(rp,true))
22692          {
22693             free_node(node_allocator_,expression);
22694
22695             return error_node();
22696          }
22697
22698          expression_node_ptr result = expression_generator_(expression,rp);
22699
22700          if (0 == result)
22701          {
22702             set_error(
22703                make_error(parser_error::e_syntax,
22704                           current_token(),
22705                           "ERR095 - Failed to generate string range node",
22706                           exprtk_error_location));
22707
22708             free_node(node_allocator_,expression);
22709          }
22710
22711          rp.clear();
22712
22713          return result;
22714       }
22715       #else
22716       inline expression_node_ptr parse_string_range_statement(expression_node_ptr&)
22717       {
22718          return error_node();
22719       }
22720       #endif
22721
22722       inline void parse_pending_string_rangesize(expression_node_ptr& expression)
22723       {
22724          // Allow no more than 100 range calls, eg: s[][][]...[][]
22725          const std::size_t max_rangesize_parses = 100;
22726
22727          std::size_t i = 0;
22728
22729          while
22730             (
22731               (0 != expression)                     &&
22732               (i++ < max_rangesize_parses)          &&
22733               error_list_.empty()                   &&
22734               is_generally_string_node(expression)  &&
22735               token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold)
22736             )
22737          {
22738             expression = parse_string_range_statement(expression);
22739          }
22740       }
22741
22742       template <typename Allocator1,
22743                 typename Allocator2,
22744                 template <typename, typename> class Sequence>
22745       inline expression_node_ptr simplify(Sequence<expression_node_ptr,Allocator1>& expression_list,
22746                                           Sequence<bool,Allocator2>& side_effect_list,
22747                                           const bool specialise_on_final_type = false)
22748       {
22749          if (expression_list.empty())
22750             return error_node();
22751          else if (1 == expression_list.size())
22752             return expression_list[0];
22753
22754          Sequence<expression_node_ptr,Allocator1> tmp_expression_list;
22755
22756          bool return_node_present = false;
22757
22758          for (std::size_t i = 0; i < (expression_list.size() - 1); ++i)
22759          {
22760             if (is_variable_node(expression_list[i]))
22761                continue;
22762             else if (
22763                       is_return_node  (expression_list[i]) ||
22764                       is_break_node   (expression_list[i]) ||
22765                       is_continue_node(expression_list[i])
22766                     )
22767             {
22768                tmp_expression_list.push_back(expression_list[i]);
22769
22770                // Remove all subexpressions after first short-circuit
22771                // node has been encountered.
22772
22773                for (std::size_t j = i + 1; j < expression_list.size(); ++j)
22774                {
22775                   free_node(node_allocator_,expression_list[j]);
22776                }
22777
22778                return_node_present = true;
22779
22780                break;
22781             }
22782             else if (
22783                       is_constant_node(expression_list[i]) ||
22784                       is_null_node    (expression_list[i]) ||
22785                       !side_effect_list[i]
22786                     )
22787             {
22788                free_node(node_allocator_,expression_list[i]);
22789                continue;
22790             }
22791             else
22792                tmp_expression_list.push_back(expression_list[i]);
22793          }
22794
22795          if (!return_node_present)
22796          {
22797             tmp_expression_list.push_back(expression_list.back());
22798          }
22799
22800          expression_list.swap(tmp_expression_list);
22801
22802          if (tmp_expression_list.size() > expression_list.size())
22803          {
22804             exprtk_debug(("simplify() - Reduced subexpressions from %d to %d\n",
22805                           static_cast<int>(tmp_expression_list.size()),
22806                           static_cast<int>(expression_list    .size())));
22807          }
22808
22809          if (
22810               return_node_present          ||
22811               side_effect_list.back()      ||
22812               (expression_list.size() > 1)
22813             )
22814             state_.activate_side_effect("simplify()");
22815
22816          if (1 == expression_list.size())
22817             return expression_list[0];
22818          else if (specialise_on_final_type && is_generally_string_node(expression_list.back()))
22819             return expression_generator_.vararg_function(details::e_smulti,expression_list);
22820          else
22821             return expression_generator_.vararg_function(details::e_multi,expression_list);
22822       }
22823
22824       inline expression_node_ptr parse_multi_sequence(const std::string& source = "")
22825       {
22826          token_t::token_type close_bracket = token_t::e_rcrlbracket;
22827          token_t::token_type seperator     = token_t::e_eof;
22828
22829          if (!token_is(token_t::e_lcrlbracket))
22830          {
22831             if (token_is(token_t::e_lbracket))
22832             {
22833                close_bracket = token_t::e_rbracket;
22834                seperator     = token_t::e_comma;
22835             }
22836             else
22837             {
22838                set_error(
22839                   make_error(parser_error::e_syntax,
22840                              current_token(),
22841                              "ERR096 - Expected '" + token_t::to_str(close_bracket) + "' for call to multi-sequence" +
22842                              ((!source.empty()) ? std::string(" section of " + source): ""),
22843                              exprtk_error_location));
22844
22845                return error_node();
22846             }
22847          }
22848          else if (token_is(token_t::e_rcrlbracket))
22849          {
22850             return node_allocator_.allocate<details::null_node<T> >();
22851          }
22852
22853          std::vector<expression_node_ptr> arg_list;
22854          std::vector<bool> side_effect_list;
22855
22856          expression_node_ptr result = error_node();
22857
22858          scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
22859
22860          scope_handler sh(*this);
22861
22862          scoped_bool_or_restorer sbr(state_.side_effect_present);
22863
22864          for ( ; ; )
22865          {
22866             state_.side_effect_present = false;
22867
22868             expression_node_ptr arg = parse_expression();
22869
22870             if (0 == arg)
22871                return error_node();
22872             else
22873             {
22874                arg_list.push_back(arg);
22875                side_effect_list.push_back(state_.side_effect_present);
22876             }
22877
22878             if (token_is(close_bracket))
22879                break;
22880
22881             const bool is_next_close = peek_token_is(close_bracket);
22882
22883             if (!token_is(seperator) && is_next_close)
22884             {
22885                set_error(
22886                   make_error(parser_error::e_syntax,
22887                              current_token(),
22888                              "ERR097 - Expected '" + details::to_str(seperator) + "' for call to multi-sequence section of " + source,
22889                              exprtk_error_location));
22890
22891                return error_node();
22892             }
22893
22894             if (token_is(close_bracket))
22895                break;
22896          }
22897
22898          result = simplify(arg_list,side_effect_list,source.empty());
22899
22900          sdd.delete_ptr = (0 == result);
22901          return result;
22902       }
22903
22904       inline bool parse_range(range_t& rp, const bool skip_lsqr = false)
22905       {
22906          // Examples of valid ranges:
22907          // 1. [1:5]     -> 1..5
22908          // 2. [ :5]     -> 0..5
22909          // 3. [1: ]     -> 1..end
22910          // 4. [x:y]     -> x..y where x <= y
22911          // 5. [x+1:y/2] -> x+1..y/2 where x+1 <= y/2
22912          // 6. [ :y]     -> 0..y where 0 <= y
22913          // 7. [x: ]     -> x..end where x <= end
22914
22915          rp.clear();
22916
22917          if (!skip_lsqr && !token_is(token_t::e_lsqrbracket))
22918          {
22919             set_error(
22920                make_error(parser_error::e_syntax,
22921                           current_token(),
22922                           "ERR098 - Expected '[' for start of range",
22923                           exprtk_error_location));
22924
22925             return false;
22926          }
22927
22928          if (token_is(token_t::e_colon))
22929          {
22930             rp.n0_c.first  = true;
22931             rp.n0_c.second = 0;
22932             rp.cache.first = 0;
22933          }
22934          else
22935          {
22936             expression_node_ptr r0 = parse_expression();
22937
22938             if (0 == r0)
22939             {
22940                set_error(
22941                   make_error(parser_error::e_syntax,
22942                              current_token(),
22943                              "ERR099 - Failed parse begin section of range",
22944                              exprtk_error_location));
22945
22946                return false;
22947             }
22948             else if (is_constant_node(r0))
22949             {
22950                const T r0_value = r0->value();
22951
22952                if (r0_value >= T(0))
22953                {
22954                   rp.n0_c.first  = true;
22955                   rp.n0_c.second = static_cast<std::size_t>(details::numeric::to_int64(r0_value));
22956                   rp.cache.first = rp.n0_c.second;
22957                }
22958
22959                free_node(node_allocator_,r0);
22960
22961                if (r0_value < T(0))
22962                {
22963                   set_error(
22964                      make_error(parser_error::e_syntax,
22965                                 current_token(),
22966                                 "ERR100 - Range lower bound less than zero! Constraint: r0 >= 0",
22967                                 exprtk_error_location));
22968
22969                   return false;
22970                }
22971             }
22972             else
22973             {
22974                rp.n0_e.first  = true;
22975                rp.n0_e.second = r0;
22976             }
22977
22978             if (!token_is(token_t::e_colon))
22979             {
22980                set_error(
22981                   make_error(parser_error::e_syntax,
22982                              current_token(),
22983                              "ERR101 - Expected ':' for break  in range",
22984                              exprtk_error_location));
22985
22986                rp.free();
22987
22988                return false;
22989             }
22990          }
22991
22992          if (token_is(token_t::e_rsqrbracket))
22993          {
22994             rp.n1_c.first  = true;
22995             rp.n1_c.second = std::numeric_limits<std::size_t>::max();
22996          }
22997          else
22998          {
22999             expression_node_ptr r1 = parse_expression();
23000
23001             if (0 == r1)
23002             {
23003                set_error(
23004                   make_error(parser_error::e_syntax,
23005                              current_token(),
23006                              "ERR102 - Failed parse end section of range",
23007                              exprtk_error_location));
23008
23009                rp.free();
23010
23011                return false;
23012             }
23013             else if (is_constant_node(r1))
23014             {
23015                const T r1_value = r1->value();
23016
23017                if (r1_value >= T(0))
23018                {
23019                   rp.n1_c.first   = true;
23020                   rp.n1_c.second  = static_cast<std::size_t>(details::numeric::to_int64(r1_value));
23021                   rp.cache.second = rp.n1_c.second;
23022                }
23023
23024                free_node(node_allocator_,r1);
23025
23026                if (r1_value < T(0))
23027                {
23028                   set_error(
23029                      make_error(parser_error::e_syntax,
23030                                 current_token(),
23031                                 "ERR103 - Range upper bound less than zero! Constraint: r1 >= 0",
23032                                 exprtk_error_location));
23033
23034                   return false;
23035                }
23036             }
23037             else
23038             {
23039                rp.n1_e.first  = true;
23040                rp.n1_e.second = r1;
23041             }
23042
23043             if (!token_is(token_t::e_rsqrbracket))
23044             {
23045                set_error(
23046                   make_error(parser_error::e_syntax,
23047                              current_token(),
23048                              "ERR104 - Expected ']' for start of range",
23049                              exprtk_error_location));
23050
23051                rp.free();
23052
23053                return false;
23054             }
23055          }
23056
23057          if (rp.const_range())
23058          {
23059             std::size_t r0 = 0;
23060             std::size_t r1 = 0;
23061
23062             const bool rp_result = rp(r0,r1);
23063
23064             if (!rp_result || (r0 > r1))
23065             {
23066                set_error(
23067                   make_error(parser_error::e_syntax,
23068                              current_token(),
23069                              "ERR105 - Invalid range, Constraint: r0 <= r1",
23070                              exprtk_error_location));
23071
23072                return false;
23073             }
23074          }
23075
23076          return true;
23077       }
23078
23079       inline void lodge_symbol(const std::string& symbol,
23080                                const symbol_type st)
23081       {
23082          dec_.add_symbol(symbol,st);
23083       }
23084
23085       #ifndef exprtk_disable_string_capabilities
23086       inline expression_node_ptr parse_string()
23087       {
23088          const std::string symbol = current_token().value;
23089
23090          typedef details::stringvar_node<T>* strvar_node_t;
23091
23092          expression_node_ptr result   = error_node();
23093          strvar_node_t const_str_node = static_cast<strvar_node_t>(0);
23094
23095          scope_element& se = sem_.get_active_element(symbol);
23096
23097          if (scope_element::e_string == se.type)
23098          {
23099             se.active = true;
23100             result    = se.str_node;
23101             lodge_symbol(symbol, e_st_local_string);
23102          }
23103          else
23104          {
23105             if (!symtab_store_.is_conststr_stringvar(symbol))
23106             {
23107                set_error(
23108                   make_error(parser_error::e_syntax,
23109                              current_token(),
23110                              "ERR106 - Unknown string symbol",
23111                              exprtk_error_location));
23112
23113                return error_node();
23114             }
23115
23116             result = symtab_store_.get_stringvar(symbol);
23117
23118             if (symtab_store_.is_constant_string(symbol))
23119             {
23120                const_str_node = static_cast<strvar_node_t>(result);
23121                result = expression_generator_(const_str_node->str());
23122             }
23123
23124             lodge_symbol(symbol, e_st_string);
23125          }
23126
23127          if (peek_token_is(token_t::e_lsqrbracket))
23128          {
23129             next_token();
23130
23131             if (peek_token_is(token_t::e_rsqrbracket))
23132             {
23133                next_token();
23134                next_token();
23135
23136                if (const_str_node)
23137                {
23138                   free_node(node_allocator_,result);
23139
23140                   return expression_generator_(T(const_str_node->size()));
23141                }
23142                else
23143                   return node_allocator_.allocate<details::stringvar_size_node<T> >
23144                             (static_cast<details::stringvar_node<T>*>(result)->ref());
23145             }
23146
23147             range_t rp;
23148
23149             if (!parse_range(rp))
23150             {
23151                free_node(node_allocator_,result);
23152
23153                return error_node();
23154             }
23155             else if (const_str_node)
23156             {
23157                free_node(node_allocator_,result);
23158                result = expression_generator_(const_str_node->ref(),rp);
23159             }
23160             else
23161                result = expression_generator_(static_cast<details::stringvar_node<T>*>
23162                            (result)->ref(), rp);
23163
23164             if (result)
23165                rp.clear();
23166          }
23167          else
23168             next_token();
23169
23170          return result;
23171       }
23172       #else
23173       inline expression_node_ptr parse_string()
23174       {
23175          return error_node();
23176       }
23177       #endif
23178
23179       #ifndef exprtk_disable_string_capabilities
23180       inline expression_node_ptr parse_const_string()
23181       {
23182          const std::string   const_str = current_token().value;
23183          expression_node_ptr result    = expression_generator_(const_str);
23184
23185          if (peek_token_is(token_t::e_lsqrbracket))
23186          {
23187             next_token();
23188
23189             if (peek_token_is(token_t::e_rsqrbracket))
23190             {
23191                next_token();
23192                next_token();
23193
23194                free_node(node_allocator_,result);
23195
23196                return expression_generator_(T(const_str.size()));
23197             }
23198
23199             range_t rp;
23200
23201             if (!parse_range(rp))
23202             {
23203                free_node(node_allocator_,result);
23204
23205                return error_node();
23206             }
23207
23208             free_node(node_allocator_,result);
23209
23210             if (rp.n1_c.first && (rp.n1_c.second == std::numeric_limits<std::size_t>::max()))
23211             {
23212                rp.n1_c.second  = const_str.size() - 1;
23213                rp.cache.second = rp.n1_c.second;
23214             }
23215
23216             if (
23217                  (rp.n0_c.first && (rp.n0_c.second >= const_str.size())) ||
23218                  (rp.n1_c.first && (rp.n1_c.second >= const_str.size()))
23219                )
23220             {
23221                set_error(
23222                   make_error(parser_error::e_syntax,
23223                              current_token(),
23224                              "ERR107 - Overflow in range for string: '" + const_str + "'[" +
23225                              (rp.n0_c.first ? details::to_str(static_cast<int>(rp.n0_c.second)) : "?") + ":" +
23226                              (rp.n1_c.first ? details::to_str(static_cast<int>(rp.n1_c.second)) : "?") + "]",
23227                              exprtk_error_location));
23228
23229                return error_node();
23230             }
23231
23232             result = expression_generator_(const_str,rp);
23233
23234             if (result)
23235                rp.clear();
23236          }
23237          else
23238             next_token();
23239
23240          return result;
23241       }
23242       #else
23243       inline expression_node_ptr parse_const_string()
23244       {
23245          return error_node();
23246       }
23247       #endif
23248
23249       inline expression_node_ptr parse_vector()
23250       {
23251          const std::string symbol = current_token().value;
23252
23253          vector_holder_ptr vec = vector_holder_ptr(0);
23254
23255          const scope_element& se = sem_.get_active_element(symbol);
23256
23257          if (
23258               !details::imatch(se.name, symbol) ||
23259               (se.depth > state_.scope_depth)   ||
23260               (scope_element::e_vector != se.type)
23261             )
23262          {
23263             if (0 == (vec = symtab_store_.get_vector(symbol)))
23264             {
23265                set_error(
23266                   make_error(parser_error::e_syntax,
23267                              current_token(),
23268                              "ERR108 - Symbol '" + symbol+ " not a vector",
23269                              exprtk_error_location));
23270
23271                return error_node();
23272             }
23273          }
23274          else
23275             vec = se.vec_node;
23276
23277          expression_node_ptr index_expr = error_node();
23278
23279          next_token();
23280
23281          if (!token_is(token_t::e_lsqrbracket))
23282          {
23283             return node_allocator_.allocate<vector_node_t>(vec);
23284          }
23285          else if (token_is(token_t::e_rsqrbracket))
23286          {
23287             return expression_generator_(T(vec->size()));
23288          }
23289          else if (0 == (index_expr = parse_expression()))
23290          {
23291             set_error(
23292                make_error(parser_error::e_syntax,
23293                           current_token(),
23294                           "ERR109 - Failed to parse index for vector: '" + symbol + "'",
23295                           exprtk_error_location));
23296
23297             return error_node();
23298          }
23299          else if (!token_is(token_t::e_rsqrbracket))
23300          {
23301             set_error(
23302                make_error(parser_error::e_syntax,
23303                           current_token(),
23304                           "ERR110 - Expected ']' for index of vector: '" + symbol + "'",
23305                           exprtk_error_location));
23306
23307             free_node(node_allocator_,index_expr);
23308
23309             return error_node();
23310          }
23311
23312          // Perform compile-time range check
23313          if (details::is_constant_node(index_expr))
23314          {
23315             const std::size_t index    = static_cast<std::size_t>(details::numeric::to_int32(index_expr->value()));
23316             const std::size_t vec_size = vec->size();
23317
23318             if (index >= vec_size)
23319             {
23320                set_error(
23321                   make_error(parser_error::e_syntax,
23322                              current_token(),
23323                              "ERR111 - Index of " + details::to_str(index) + " out of range for "
23324                              "vector '" + symbol + "' of size " + details::to_str(vec_size),
23325                              exprtk_error_location));
23326
23327                free_node(node_allocator_,index_expr);
23328
23329                return error_node();
23330             }
23331          }
23332
23333          return expression_generator_.vector_element(symbol, vec, index_expr);
23334       }
23335
23336       inline expression_node_ptr parse_vararg_function_call(ivararg_function<T>* vararg_function, const std::string& vararg_function_name)
23337       {
23338          std::vector<expression_node_ptr> arg_list;
23339
23340          expression_node_ptr result = error_node();
23341
23342          scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
23343
23344          next_token();
23345
23346          if (token_is(token_t::e_lbracket))
23347          {
23348             if (token_is(token_t::e_rbracket))
23349             {
23350                if (!vararg_function->allow_zero_parameters())
23351                {
23352                   set_error(
23353                      make_error(parser_error::e_syntax,
23354                                 current_token(),
23355                                 "ERR112 - Zero parameter call to vararg function: "
23356                                 + vararg_function_name + " not allowed",
23357                                 exprtk_error_location));
23358
23359                   return error_node();
23360                }
23361             }
23362             else
23363             {
23364                for ( ; ; )
23365                {
23366                   expression_node_ptr arg = parse_expression();
23367
23368                   if (0 == arg)
23369                      return error_node();
23370                   else
23371                      arg_list.push_back(arg);
23372
23373                   if (token_is(token_t::e_rbracket))
23374                      break;
23375                   else if (!token_is(token_t::e_comma))
23376                   {
23377                      set_error(
23378                         make_error(parser_error::e_syntax,
23379                                    current_token(),
23380                                    "ERR113 - Expected ',' for call to vararg function: "
23381                                    + vararg_function_name,
23382                                    exprtk_error_location));
23383
23384                      return error_node();
23385                   }
23386                }
23387             }
23388          }
23389          else if (!vararg_function->allow_zero_parameters())
23390          {
23391             set_error(
23392                make_error(parser_error::e_syntax,
23393                           current_token(),
23394                           "ERR114 - Zero parameter call to vararg function: "
23395                           + vararg_function_name + " not allowed",
23396                           exprtk_error_location));
23397
23398             return error_node();
23399          }
23400
23401          if (arg_list.size() < vararg_function->min_num_args())
23402          {
23403             set_error(
23404                make_error(parser_error::e_syntax,
23405                           current_token(),
23406                           "ERR115 - Invalid number of parameters to call to vararg function: "
23407                           + vararg_function_name + ", require at least "
23408                           + details::to_str(static_cast<int>(vararg_function->min_num_args())) + " parameters",
23409                           exprtk_error_location));
23410
23411             return error_node();
23412          }
23413          else if (arg_list.size() > vararg_function->max_num_args())
23414          {
23415             set_error(
23416                make_error(parser_error::e_syntax,
23417                           current_token(),
23418                           "ERR116 - Invalid number of parameters to call to vararg function: "
23419                           + vararg_function_name + ", require no more than "
23420                           + details::to_str(static_cast<int>(vararg_function->max_num_args())) + " parameters",
23421                           exprtk_error_location));
23422
23423             return error_node();
23424          }
23425
23426          result = expression_generator_.vararg_function_call(vararg_function,arg_list);
23427
23428          sdd.delete_ptr = (0 == result);
23429
23430          return result;
23431       }
23432
23433       class type_checker
23434       {
23435       public:
23436
23437          enum return_type_t
23438          {
23439             e_overload = ' ',
23440             e_numeric  = 'T',
23441             e_string   = 'S'
23442          };
23443
23444          struct function_prototype_t
23445          {
23446              return_type_t return_type;
23447              std::string   param_seq;
23448          };
23449
23450          typedef parser<T> parser_t;
23451          typedef std::vector<function_prototype_t> function_definition_list_t;
23452
23453          type_checker(parser_t& p,
23454                       const std::string& func_name,
23455                       const std::string& func_prototypes,
23456                       const return_type_t default_return_type)
23457          : invalid_state_(true),
23458            parser_(p),
23459            function_name_(func_name),
23460            default_return_type_(default_return_type)
23461          {
23462             parse_function_prototypes(func_prototypes);
23463          }
23464
23465          void set_default_return_type(const std::string& return_type)
23466          {
23467             default_return_type_ = return_type;
23468          }
23469
23470          bool verify(const std::string& param_seq, std::size_t& pseq_index)
23471          {
23472             if (function_definition_list_.empty())
23473                return true;
23474
23475             std::vector<std::pair<std::size_t,char> > error_list;
23476
23477             for (std::size_t i = 0; i < function_definition_list_.size(); ++i)
23478             {
23479                details::char_t diff_value = 0;
23480                std::size_t     diff_index = 0;
23481
23482                const bool result = details::sequence_match(function_definition_list_[i].param_seq,
23483                                                            param_seq,
23484                                                            diff_index, diff_value);
23485
23486               if (result)
23487               {
23488                  pseq_index = i;
23489                  return true;
23490               }
23491               else
23492                  error_list.push_back(std::make_pair(diff_index, diff_value));
23493             }
23494
23495             if (1 == error_list.size())
23496             {
23497                parser_.
23498                   set_error(
23499                      make_error(parser_error::e_syntax,
23500                                 parser_.current_token(),
23501                                 "ERR117 - Failed parameter type check for function '" + function_name_ + "', "
23502                                 "Expected '" + function_definition_list_[0].param_seq +
23503                                 "'  call set: '" + param_seq + "'",
23504                                 exprtk_error_location));
23505             }
23506             else
23507             {
23508                // find first with largest diff_index;
23509                std::size_t max_diff_index = 0;
23510
23511                for (std::size_t i = 1; i < error_list.size(); ++i)
23512                {
23513                   if (error_list[i].first > error_list[max_diff_index].first)
23514                   {
23515                      max_diff_index = i;
23516                   }
23517                }
23518
23519                parser_.
23520                   set_error(
23521                      make_error(parser_error::e_syntax,
23522                                 parser_.current_token(),
23523                                 "ERR118 - Failed parameter type check for function '" + function_name_ + "', "
23524                                 "Best match: '" + function_definition_list_[max_diff_index].param_seq +
23525                                 "'  call set: '" + param_seq + "'",
23526                                 exprtk_error_location));
23527             }
23528
23529             return false;
23530          }
23531
23532          std::size_t paramseq_count() const
23533          {
23534             return function_definition_list_.size();
23535          }
23536
23537          std::string paramseq(const std::size_t& index) const
23538          {
23539             return function_definition_list_[index].param_seq;
23540          }
23541
23542          return_type_t return_type(const std::size_t& index) const
23543          {
23544             return function_definition_list_[index].return_type;
23545          }
23546
23547          bool invalid() const
23548          {
23549             return !invalid_state_;
23550          }
23551
23552          bool allow_zero_parameters() const
23553          {
23554
23555             for (std::size_t i = 0; i < function_definition_list_.size(); ++i)
23556             {
23557                if (std::string::npos != function_definition_list_[i].param_seq.find("Z"))
23558                {
23559                   return true;
23560                }
23561             }
23562
23563             return false;
23564          }
23565
23566       private:
23567
23568          std::vector<std::string> split_param_seq(const std::string& param_seq, const details::char_t delimiter = '|') const
23569          {
23570              std::string::const_iterator current_begin = param_seq.begin();
23571              std::string::const_iterator iter          = param_seq.begin();
23572
23573              std::vector<std::string> result;
23574
23575              while (iter != param_seq.end())
23576              {
23577                  if (*iter == delimiter)
23578                  {
23579                      result.push_back(std::string(current_begin, iter));
23580                      current_begin = ++iter;
23581                  }
23582                  else
23583                      ++iter;
23584              }
23585
23586              if (current_begin != iter)
23587              {
23588                  result.push_back(std::string(current_begin, iter));
23589              }
23590
23591              return result;
23592          }
23593
23594          inline bool is_valid_token(std::string param_seq,
23595                                     function_prototype_t& funcproto) const
23596          {
23597             // Determine return type
23598             funcproto.return_type = default_return_type_;
23599
23600             if (param_seq.size() > 2)
23601             {
23602                if (':' == param_seq[1])
23603                {
23604                   // Note: Only overloaded igeneric functions can have return
23605                   // type definitions.
23606                   if (type_checker::e_overload != default_return_type_)
23607                      return false;
23608
23609                   switch (param_seq[0])
23610                   {
23611                      case 'T' : funcproto.return_type = type_checker::e_numeric;
23612                                 break;
23613
23614                      case 'S' : funcproto.return_type = type_checker::e_string;
23615                                 break;
23616
23617                      default  : return false;
23618                   }
23619
23620                   param_seq.erase(0,2);
23621                }
23622             }
23623
23624             if (
23625                  (std::string::npos != param_seq.find("?*")) ||
23626                  (std::string::npos != param_seq.find("**"))
23627                )
23628             {
23629                return false;
23630             }
23631             else if (
23632                       (std::string::npos == param_seq.find_first_not_of("STV*?|")) ||
23633                       ("Z" == param_seq)
23634                     )
23635             {
23636                funcproto.param_seq = param_seq;
23637                return true;
23638             }
23639
23640             return false;
23641          }
23642
23643          void parse_function_prototypes(const std::string& func_prototypes)
23644          {
23645             if (func_prototypes.empty())
23646                return;
23647
23648             std::vector<std::string> param_seq_list = split_param_seq(func_prototypes);
23649
23650             typedef std::map<std::string,std::size_t> param_seq_map_t;
23651             param_seq_map_t param_seq_map;
23652
23653             for (std::size_t i = 0; i < param_seq_list.size(); ++i)
23654             {
23655                function_prototype_t func_proto;
23656
23657                if (!is_valid_token(param_seq_list[i], func_proto))
23658                {
23659                   invalid_state_ = false;
23660
23661                   parser_.
23662                      set_error(
23663                         make_error(parser_error::e_syntax,
23664                                    parser_.current_token(),
23665                                    "ERR119 - Invalid parameter sequence of '" + param_seq_list[i] +
23666                                    "' for function: " + function_name_,
23667                                    exprtk_error_location));
23668                   return;
23669                }
23670
23671                param_seq_map_t::const_iterator seq_itr = param_seq_map.find(param_seq_list[i]);
23672
23673                if (param_seq_map.end() != seq_itr)
23674                {
23675                   invalid_state_ = false;
23676
23677                   parser_.
23678                      set_error(
23679                         make_error(parser_error::e_syntax,
23680                                    parser_.current_token(),
23681                                    "ERR120 - Function '" + function_name_ + "' has a parameter sequence conflict between " +
23682                                    "pseq_idx[" + details::to_str(seq_itr->second) + "] and" +
23683                                    "pseq_idx[" + details::to_str(i) + "] " +
23684                                    "param seq: " + param_seq_list[i],
23685                                    exprtk_error_location));
23686                   return;
23687                }
23688
23689                function_definition_list_.push_back(func_proto);
23690             }
23691          }
23692
23693          type_checker(const type_checker&);
23694          type_checker& operator=(const type_checker&);
23695
23696          bool invalid_state_;
23697          parser_t& parser_;
23698          std::string function_name_;
23699          const return_type_t default_return_type_;
23700          function_definition_list_t function_definition_list_;
23701       };
23702
23703       inline expression_node_ptr parse_generic_function_call(igeneric_function<T>* function, const std::string& function_name)
23704       {
23705          std::vector<expression_node_ptr> arg_list;
23706
23707          scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
23708
23709          next_token();
23710
23711          std::string param_type_list;
23712
23713          type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_string);
23714
23715          if (tc.invalid())
23716          {
23717             set_error(
23718                make_error(parser_error::e_syntax,
23719                           current_token(),
23720                           "ERR121 - Type checker instantiation failure for generic function: " + function_name,
23721                           exprtk_error_location));
23722
23723             return error_node();
23724          }
23725
23726          if (token_is(token_t::e_lbracket))
23727          {
23728             if (token_is(token_t::e_rbracket))
23729             {
23730                if (
23731                     !function->allow_zero_parameters() &&
23732                     !tc       .allow_zero_parameters()
23733                   )
23734                {
23735                   set_error(
23736                      make_error(parser_error::e_syntax,
23737                                 current_token(),
23738                                 "ERR122 - Zero parameter call to generic function: "
23739                                 + function_name + " not allowed",
23740                                 exprtk_error_location));
23741
23742                   return error_node();
23743                }
23744             }
23745             else
23746             {
23747                for ( ; ; )
23748                {
23749                   expression_node_ptr arg = parse_expression();
23750
23751                   if (0 == arg)
23752                      return error_node();
23753
23754                   if (is_ivector_node(arg))
23755                      param_type_list += 'V';
23756                   else if (is_generally_string_node(arg))
23757                      param_type_list += 'S';
23758                   else // Everything else is assumed to be a scalar returning expression
23759                      param_type_list += 'T';
23760
23761                   arg_list.push_back(arg);
23762
23763                   if (token_is(token_t::e_rbracket))
23764                      break;
23765                   else if (!token_is(token_t::e_comma))
23766                   {
23767                      set_error(
23768                         make_error(parser_error::e_syntax,
23769                                    current_token(),
23770                                    "ERR123 - Expected ',' for call to generic function: " + function_name,
23771                                    exprtk_error_location));
23772
23773                      return error_node();
23774                   }
23775                }
23776             }
23777          }
23778          else if (
23779                    !function->parameter_sequence.empty() &&
23780                    function->allow_zero_parameters    () &&
23781                    !tc      .allow_zero_parameters    ()
23782                  )
23783          {
23784             set_error(
23785                make_error(parser_error::e_syntax,
23786                           current_token(),
23787                           "ERR124 - Zero parameter call to generic function: "
23788                           + function_name + " not allowed",
23789                           exprtk_error_location));
23790
23791             return error_node();
23792          }
23793
23794          std::size_t param_seq_index = 0;
23795
23796          if (
23797               state_.type_check_enabled &&
23798               !tc.verify(param_type_list, param_seq_index)
23799             )
23800          {
23801             set_error(
23802                make_error(parser_error::e_syntax,
23803                           current_token(),
23804                           "ERR125 - Invalid input parameter sequence for call to generic function: " + function_name,
23805                           exprtk_error_location));
23806
23807             return error_node();
23808          }
23809
23810          expression_node_ptr result = error_node();
23811
23812          if (tc.paramseq_count() <= 1)
23813             result = expression_generator_
23814                        .generic_function_call(function, arg_list);
23815          else
23816             result = expression_generator_
23817                        .generic_function_call(function, arg_list, param_seq_index);
23818
23819          sdd.delete_ptr = (0 == result);
23820
23821          return result;
23822       }
23823
23824       inline bool parse_igeneric_function_params(std::string& param_type_list,
23825                                                  std::vector<expression_node_ptr>& arg_list,
23826                                                  const std::string& function_name,
23827                                                  igeneric_function<T>* function,
23828                                                  const type_checker& tc)
23829       {
23830          if (token_is(token_t::e_lbracket))
23831          {
23832             if (token_is(token_t::e_rbracket))
23833             {
23834                if (
23835                     !function->allow_zero_parameters() &&
23836                     !tc       .allow_zero_parameters()
23837                   )
23838                {
23839                   set_error(
23840                      make_error(parser_error::e_syntax,
23841                                 current_token(),
23842                                 "ERR126 - Zero parameter call to generic function: "
23843                                 + function_name + " not allowed",
23844                                 exprtk_error_location));
23845
23846                   return false;
23847                }
23848             }
23849             else
23850             {
23851                for ( ; ; )
23852                {
23853                   expression_node_ptr arg = parse_expression();
23854
23855                   if (0 == arg)
23856                      return false;
23857
23858                   if (is_ivector_node(arg))
23859                      param_type_list += 'V';
23860                   else if (is_generally_string_node(arg))
23861                      param_type_list += 'S';
23862                   else // Everything else is a scalar returning expression
23863                      param_type_list += 'T';
23864
23865                   arg_list.push_back(arg);
23866
23867                   if (token_is(token_t::e_rbracket))
23868                      break;
23869                   else if (!token_is(token_t::e_comma))
23870                   {
23871                      set_error(
23872                         make_error(parser_error::e_syntax,
23873                                    current_token(),
23874                                    "ERR127 - Expected ',' for call to string function: " + function_name,
23875                                    exprtk_error_location));
23876
23877                      return false;
23878                   }
23879                }
23880             }
23881
23882             return true;
23883          }
23884          else
23885             return false;
23886       }
23887
23888       #ifndef exprtk_disable_string_capabilities
23889       inline expression_node_ptr parse_string_function_call(igeneric_function<T>* function, const std::string& function_name)
23890       {
23891          // Move pass the function name
23892          next_token();
23893
23894          std::string param_type_list;
23895
23896          type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_string);
23897
23898          if (
23899               (!function->parameter_sequence.empty()) &&
23900               (0 == tc.paramseq_count())
23901             )
23902          {
23903             return error_node();
23904          }
23905
23906          std::vector<expression_node_ptr> arg_list;
23907          scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
23908
23909          if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc))
23910          {
23911             return error_node();
23912          }
23913
23914          std::size_t param_seq_index = 0;
23915
23916          if (!tc.verify(param_type_list, param_seq_index))
23917          {
23918             set_error(
23919                make_error(parser_error::e_syntax,
23920                           current_token(),
23921                           "ERR128 - Invalid input parameter sequence for call to string function: " + function_name,
23922                           exprtk_error_location));
23923
23924             return error_node();
23925          }
23926
23927          expression_node_ptr result = error_node();
23928
23929          if (tc.paramseq_count() <= 1)
23930             result = expression_generator_
23931                        .string_function_call(function, arg_list);
23932          else
23933             result = expression_generator_
23934                        .string_function_call(function, arg_list, param_seq_index);
23935
23936          sdd.delete_ptr = (0 == result);
23937
23938          return result;
23939       }
23940
23941       inline expression_node_ptr parse_overload_function_call(igeneric_function<T>* function, const std::string& function_name)
23942       {
23943          // Move pass the function name
23944          next_token();
23945
23946          std::string param_type_list;
23947
23948          type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_overload);
23949
23950          if (
23951               (!function->parameter_sequence.empty()) &&
23952               (0 == tc.paramseq_count())
23953             )
23954          {
23955             return error_node();
23956          }
23957
23958          std::vector<expression_node_ptr> arg_list;
23959          scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
23960
23961          if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc))
23962          {
23963             return error_node();
23964          }
23965
23966          std::size_t param_seq_index = 0;
23967
23968          if (!tc.verify(param_type_list, param_seq_index))
23969          {
23970             set_error(
23971                make_error(parser_error::e_syntax,
23972                           current_token(),
23973                           "ERR129 - Invalid input parameter sequence for call to overloaded function: " + function_name,
23974                           exprtk_error_location));
23975
23976             return error_node();
23977          }
23978
23979          expression_node_ptr result = error_node();
23980
23981          if (type_checker::e_numeric == tc.return_type(param_seq_index))
23982          {
23983             if (tc.paramseq_count() <= 1)
23984                result = expression_generator_
23985                           .generic_function_call(function, arg_list);
23986             else
23987                result = expression_generator_
23988                           .generic_function_call(function, arg_list, param_seq_index);
23989          }
23990          else if (type_checker::e_string == tc.return_type(param_seq_index))
23991          {
23992             if (tc.paramseq_count() <= 1)
23993                result = expression_generator_
23994                           .string_function_call(function, arg_list);
23995             else
23996                result = expression_generator_
23997                           .string_function_call(function, arg_list, param_seq_index);
23998          }
23999          else
24000          {
24001             set_error(
24002                make_error(parser_error::e_syntax,
24003                           current_token(),
24004                           "ERR130 - Invalid return type for call to overloaded function: " + function_name,
24005                           exprtk_error_location));
24006          }
24007
24008          sdd.delete_ptr = (0 == result);
24009          return result;
24010       }
24011       #endif
24012
24013       template <typename Type, std::size_t NumberOfParameters>
24014       struct parse_special_function_impl
24015       {
24016          static inline expression_node_ptr process(parser<Type>& p, const details::operator_type opt_type, const std::string& sf_name)
24017          {
24018             expression_node_ptr branch[NumberOfParameters];
24019             expression_node_ptr result = error_node();
24020
24021             std::fill_n(branch,NumberOfParameters,reinterpret_cast<expression_node_ptr>(0));
24022
24023             scoped_delete<expression_node_t,NumberOfParameters> sd(p,branch);
24024
24025             p.next_token();
24026
24027             if (!p.token_is(token_t::e_lbracket))
24028             {
24029                p.set_error(
24030                     make_error(parser_error::e_syntax,
24031                                p.current_token(),
24032                                "ERR131 - Expected '(' for special function '" + sf_name + "'",
24033                                exprtk_error_location));
24034
24035                return error_node();
24036             }
24037
24038             for (std::size_t i = 0; i < NumberOfParameters; ++i)
24039             {
24040                branch[i] = p.parse_expression();
24041
24042                if (0 == branch[i])
24043                {
24044                   return p.error_node();
24045                }
24046                else if (i < (NumberOfParameters - 1))
24047                {
24048                   if (!p.token_is(token_t::e_comma))
24049                   {
24050                      p.set_error(
24051                           make_error(parser_error::e_syntax,
24052                                      p.current_token(),
24053                                      "ERR132 - Expected ',' before next parameter of special function '" + sf_name + "'",
24054                                      exprtk_error_location));
24055
24056                      return p.error_node();
24057                   }
24058                }
24059             }
24060
24061             if (!p.token_is(token_t::e_rbracket))
24062             {
24063                p.set_error(
24064                     make_error(parser_error::e_syntax,
24065                                p.current_token(),
24066                                "ERR133 - Invalid number of parameters for special function '" + sf_name + "'",
24067                                exprtk_error_location));
24068
24069                return p.error_node();
24070             }
24071             else
24072                result = p.expression_generator_.special_function(opt_type,branch);
24073
24074             sd.delete_ptr = (0 == result);
24075
24076             return result;
24077          }
24078       };
24079
24080       inline expression_node_ptr parse_special_function()
24081       {
24082          const std::string sf_name = current_token().value;
24083
24084          // Expect: $fDD(expr0,expr1,expr2) or $fDD(expr0,expr1,expr2,expr3)
24085          if (
24086               !details::is_digit(sf_name[2]) ||
24087               !details::is_digit(sf_name[3])
24088             )
24089          {
24090             set_error(
24091                make_error(parser_error::e_token,
24092                           current_token(),
24093                           "ERR134 - Invalid special function[1]: " + sf_name,
24094                           exprtk_error_location));
24095
24096             return error_node();
24097          }
24098
24099          const int id = (sf_name[2] - '0') * 10 +
24100                         (sf_name[3] - '0');
24101
24102          if (id >= details::e_sffinal)
24103          {
24104             set_error(
24105                make_error(parser_error::e_token,
24106                           current_token(),
24107                           "ERR135 - Invalid special function[2]: " + sf_name,
24108                           exprtk_error_location));
24109
24110             return error_node();
24111          }
24112
24113          const int sf_3_to_4                   = details::e_sf48;
24114          const details::operator_type opt_type = details::operator_type(id + 1000);
24115          const std::size_t NumberOfParameters  = (id < (sf_3_to_4 - 1000)) ? 3U : 4U;
24116
24117          switch (NumberOfParameters)
24118          {
24119             case 3  : return parse_special_function_impl<T,3>::process((*this), opt_type, sf_name);
24120             case 4  : return parse_special_function_impl<T,4>::process((*this), opt_type, sf_name);
24121             default : return error_node();
24122          }
24123       }
24124
24125       inline expression_node_ptr parse_null_statement()
24126       {
24127          next_token();
24128          return node_allocator_.allocate<details::null_node<T> >();
24129       }
24130
24131       #ifndef exprtk_disable_break_continue
24132       inline expression_node_ptr parse_break_statement()
24133       {
24134          if (state_.parsing_break_stmt)
24135          {
24136             set_error(
24137                make_error(parser_error::e_syntax,
24138                           current_token(),
24139                           "ERR136 - Break call within a break call is not allowed",
24140                           exprtk_error_location));
24141
24142             return error_node();
24143          }
24144
24145          scoped_bool_negator sbn(state_.parsing_break_stmt);
24146
24147          if (!brkcnt_list_.empty())
24148          {
24149             next_token();
24150
24151             brkcnt_list_.front() = true;
24152
24153             expression_node_ptr return_expr = error_node();
24154
24155             if (token_is(token_t::e_lsqrbracket))
24156             {
24157                if (0 == (return_expr = parse_expression()))
24158                {
24159                   set_error(
24160                      make_error(parser_error::e_syntax,
24161                                 current_token(),
24162                                 "ERR137 - Failed to parse return expression for 'break' statement",
24163                                 exprtk_error_location));
24164
24165                   return error_node();
24166                }
24167                else if (!token_is(token_t::e_rsqrbracket))
24168                {
24169                   set_error(
24170                      make_error(parser_error::e_syntax,
24171                                 current_token(),
24172                                 "ERR138 - Expected ']' at the completion of break's return expression",
24173                                 exprtk_error_location));
24174
24175                   free_node(node_allocator_,return_expr);
24176
24177                   return error_node();
24178                }
24179             }
24180
24181             state_.activate_side_effect("parse_break_statement()");
24182
24183             return node_allocator_.allocate<details::break_node<T> >(return_expr);
24184          }
24185          else
24186          {
24187             set_error(
24188                make_error(parser_error::e_syntax,
24189                           current_token(),
24190                           "ERR139 - Invalid use of 'break', allowed only in the scope of a loop",
24191                           exprtk_error_location));
24192          }
24193
24194          return error_node();
24195       }
24196
24197       inline expression_node_ptr parse_continue_statement()
24198       {
24199          if (!brkcnt_list_.empty())
24200          {
24201             next_token();
24202
24203             brkcnt_list_.front() = true;
24204             state_.activate_side_effect("parse_continue_statement()");
24205
24206             return node_allocator_.allocate<details::continue_node<T> >();
24207          }
24208          else
24209          {
24210             set_error(
24211                make_error(parser_error::e_syntax,
24212                           current_token(),
24213                           "ERR140 - Invalid use of 'continue', allowed only in the scope of a loop",
24214                           exprtk_error_location));
24215
24216             return error_node();
24217          }
24218       }
24219       #endif
24220
24221       inline expression_node_ptr parse_define_vector_statement(const std::string& vec_name)
24222       {
24223          expression_node_ptr size_expr = error_node();
24224
24225          if (!token_is(token_t::e_lsqrbracket))
24226          {
24227             set_error(
24228                make_error(parser_error::e_syntax,
24229                           current_token(),
24230                           "ERR141 - Expected '[' as part of vector size definition",
24231                           exprtk_error_location));
24232
24233             return error_node();
24234          }
24235          else if (0 == (size_expr = parse_expression()))
24236          {
24237             set_error(
24238                make_error(parser_error::e_syntax,
24239                           current_token(),
24240                           "ERR142 - Failed to determine size of vector '" + vec_name + "'",
24241                           exprtk_error_location));
24242
24243             return error_node();
24244          }
24245          else if (!is_constant_node(size_expr))
24246          {
24247             free_node(node_allocator_,size_expr);
24248
24249             set_error(
24250                make_error(parser_error::e_syntax,
24251                           current_token(),
24252                           "ERR143 - Expected a literal number as size of vector '" + vec_name + "'",
24253                           exprtk_error_location));
24254
24255             return error_node();
24256          }
24257
24258          const T vector_size = size_expr->value();
24259
24260          free_node(node_allocator_,size_expr);
24261
24262          const T max_vector_size = T(2000000000.0);
24263
24264          if (
24265               (vector_size <= T(0)) ||
24266               std::not_equal_to<T>()
24267               (T(0),vector_size - details::numeric::trunc(vector_size)) ||
24268               (vector_size > max_vector_size)
24269             )
24270          {
24271             set_error(
24272                make_error(parser_error::e_syntax,
24273                           current_token(),
24274                           "ERR144 - Invalid vector size. Must be an integer in the range [0,2e9], size: " +
24275                           details::to_str(details::numeric::to_int32(vector_size)),
24276                           exprtk_error_location));
24277
24278             return error_node();
24279          }
24280
24281          std::vector<expression_node_ptr> vec_initilizer_list;
24282
24283          scoped_vec_delete<expression_node_t> svd((*this),vec_initilizer_list);
24284
24285          bool single_value_initialiser = false;
24286          bool vec_to_vec_initialiser   = false;
24287          bool null_initialisation      = false;
24288
24289          if (!token_is(token_t::e_rsqrbracket))
24290          {
24291             set_error(
24292                make_error(parser_error::e_syntax,
24293                           current_token(),
24294                           "ERR145 - Expected ']' as part of vector size definition",
24295                           exprtk_error_location));
24296
24297             return error_node();
24298          }
24299          else if (!token_is(token_t::e_eof))
24300          {
24301             if (!token_is(token_t::e_assign))
24302             {
24303                set_error(
24304                   make_error(parser_error::e_syntax,
24305                              current_token(),
24306                              "ERR146 - Expected ':=' as part of vector definition",
24307                              exprtk_error_location));
24308
24309                return error_node();
24310             }
24311             else if (token_is(token_t::e_lsqrbracket))
24312             {
24313                expression_node_ptr initialiser = parse_expression();
24314
24315                if (0 == initialiser)
24316                {
24317                   set_error(
24318                      make_error(parser_error::e_syntax,
24319                                 current_token(),
24320                                 "ERR147 - Failed to parse single vector initialiser",
24321                                 exprtk_error_location));
24322
24323                   return error_node();
24324                }
24325
24326                vec_initilizer_list.push_back(initialiser);
24327
24328                if (!token_is(token_t::e_rsqrbracket))
24329                {
24330                   set_error(
24331                      make_error(parser_error::e_syntax,
24332                                 current_token(),
24333                                 "ERR148 - Expected ']' to close single value vector initialiser",
24334                                 exprtk_error_location));
24335
24336                   return error_node();
24337                }
24338
24339                single_value_initialiser = true;
24340             }
24341             else if (!token_is(token_t::e_lcrlbracket))
24342             {
24343                expression_node_ptr initialiser = error_node();
24344
24345                // Is this a vector to vector assignment and initialisation?
24346                if (token_t::e_symbol == current_token().type)
24347                {
24348                   // Is it a locally defined vector?
24349                   scope_element& se = sem_.get_active_element(current_token().value);
24350
24351                   if (scope_element::e_vector == se.type)
24352                   {
24353                      if (0 != (initialiser = parse_expression()))
24354                         vec_initilizer_list.push_back(initialiser);
24355                      else
24356                         return error_node();
24357                   }
24358                   // Are we dealing with a user defined vector?
24359                   else if (symtab_store_.is_vector(current_token().value))
24360                   {
24361                      lodge_symbol(current_token().value, e_st_vector);
24362
24363                      if (0 != (initialiser = parse_expression()))
24364                         vec_initilizer_list.push_back(initialiser);
24365                      else
24366                         return error_node();
24367                   }
24368                   // Are we dealing with a null initialisation vector definition?
24369                   else if (token_is(token_t::e_symbol,"null"))
24370                      null_initialisation = true;
24371                }
24372
24373                if (!null_initialisation)
24374                {
24375                   if (0 == initialiser)
24376                   {
24377                      set_error(
24378                         make_error(parser_error::e_syntax,
24379                                    current_token(),
24380                                    "ERR149 - Expected '{' as part of vector initialiser list",
24381                                    exprtk_error_location));
24382
24383                      return error_node();
24384                   }
24385                   else
24386                      vec_to_vec_initialiser = true;
24387                }
24388             }
24389             else if (!token_is(token_t::e_rcrlbracket))
24390             {
24391                for ( ; ; )
24392                {
24393                   expression_node_ptr initialiser = parse_expression();
24394
24395                   if (0 == initialiser)
24396                   {
24397                      set_error(
24398                         make_error(parser_error::e_syntax,
24399                                    current_token(),
24400                                    "ERR150 - Expected '{' as part of vector initialiser list",
24401                                    exprtk_error_location));
24402
24403                      return error_node();
24404                   }
24405                   else
24406                      vec_initilizer_list.push_back(initialiser);
24407
24408                   if (token_is(token_t::e_rcrlbracket))
24409                      break;
24410
24411                   const bool is_next_close = peek_token_is(token_t::e_rcrlbracket);
24412
24413                   if (!token_is(token_t::e_comma) && is_next_close)
24414                   {
24415                      set_error(
24416                         make_error(parser_error::e_syntax,
24417                                    current_token(),
24418                                    "ERR151 - Expected ',' between vector initialisers",
24419                                    exprtk_error_location));
24420
24421                      return error_node();
24422                   }
24423
24424                   if (token_is(token_t::e_rcrlbracket))
24425                      break;
24426                }
24427             }
24428
24429             if (
24430                  !token_is(token_t::e_rbracket   , prsrhlpr_t::e_hold) &&
24431                  !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) &&
24432                  !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold)
24433                )
24434             {
24435                if (!token_is(token_t::e_eof))
24436                {
24437                   set_error(
24438                      make_error(parser_error::e_syntax,
24439                                 current_token(),
24440                                 "ERR152 - Expected ';' at end of vector definition",
24441                                 exprtk_error_location));
24442
24443                   return error_node();
24444                }
24445             }
24446
24447             if (vec_initilizer_list.size() > vector_size)
24448             {
24449                set_error(
24450                   make_error(parser_error::e_syntax,
24451                              current_token(),
24452                              "ERR153 - Initialiser list larger than the number of elements in the vector: '" + vec_name + "'",
24453                              exprtk_error_location));
24454
24455                return error_node();
24456             }
24457          }
24458
24459          typename symbol_table_t::vector_holder_ptr vec_holder = typename symbol_table_t::vector_holder_ptr(0);
24460
24461          const std::size_t vec_size = static_cast<std::size_t>(details::numeric::to_int32(vector_size));
24462
24463          scope_element& se = sem_.get_element(vec_name);
24464
24465          if (se.name == vec_name)
24466          {
24467             if (se.active)
24468             {
24469                set_error(
24470                   make_error(parser_error::e_syntax,
24471                              current_token(),
24472                              "ERR154 - Illegal redefinition of local vector: '" + vec_name + "'",
24473                              exprtk_error_location));
24474
24475                return error_node();
24476             }
24477             else if (
24478                       (se.size == vec_size) &&
24479                       (scope_element::e_vector == se.type)
24480                     )
24481             {
24482                vec_holder = se.vec_node;
24483                se.active  = true;
24484                se.depth   = state_.scope_depth;
24485                se.ref_count++;
24486             }
24487          }
24488
24489          if (0 == vec_holder)
24490          {
24491             scope_element nse;
24492             nse.name      = vec_name;
24493             nse.active    = true;
24494             nse.ref_count = 1;
24495             nse.type      = scope_element::e_vector;
24496             nse.depth     = state_.scope_depth;
24497             nse.size      = vec_size;
24498             nse.data      = new T[vec_size];
24499             nse.vec_node  = new typename scope_element::vector_holder_t((T*)(nse.data),nse.size);
24500
24501             if (!sem_.add_element(nse))
24502             {
24503                set_error(
24504                   make_error(parser_error::e_syntax,
24505                              current_token(),
24506                              "ERR155 - Failed to add new local vector '" + vec_name + "' to SEM",
24507                              exprtk_error_location));
24508
24509                sem_.free_element(nse);
24510
24511                return error_node();
24512             }
24513
24514             vec_holder = nse.vec_node;
24515
24516             exprtk_debug(("parse_define_vector_statement() - INFO - Added new local vector: %s[%d]\n",
24517                           nse.name.c_str(),
24518                           static_cast<int>(nse.size)));
24519          }
24520
24521          state_.activate_side_effect("parse_define_vector_statement()");
24522
24523          lodge_symbol(vec_name, e_st_local_vector);
24524
24525          expression_node_ptr result = error_node();
24526
24527          if (null_initialisation)
24528             result = expression_generator_(T(0.0));
24529          else if (vec_to_vec_initialiser)
24530          {
24531             expression_node_ptr vec_node = node_allocator_.allocate<vector_node_t>(vec_holder);
24532
24533             result = expression_generator_(
24534                         details::e_assign,
24535                         vec_node,
24536                         vec_initilizer_list[0]);
24537          }
24538          else
24539             result = node_allocator_
24540                         .allocate<details::vector_assignment_node<T> >(
24541                            (*vec_holder)[0],
24542                            vec_size,
24543                            vec_initilizer_list,
24544                            single_value_initialiser);
24545
24546          svd.delete_ptr = (0 == result);
24547
24548          return result;
24549       }
24550
24551       #ifndef exprtk_disable_string_capabilities
24552       inline expression_node_ptr parse_define_string_statement(const std::string& str_name, expression_node_ptr initialisation_expression)
24553       {
24554          stringvar_node_t* str_node = reinterpret_cast<stringvar_node_t*>(0);
24555
24556          scope_element& se = sem_.get_element(str_name);
24557
24558          if (se.name == str_name)
24559          {
24560             if (se.active)
24561             {
24562                set_error(
24563                   make_error(parser_error::e_syntax,
24564                              current_token(),
24565                              "ERR156 - Illegal redefinition of local variable: '" + str_name + "'",
24566                              exprtk_error_location));
24567
24568                free_node(node_allocator_,initialisation_expression);
24569
24570                return error_node();
24571             }
24572             else if (scope_element::e_string == se.type)
24573             {
24574                str_node  = se.str_node;
24575                se.active = true;
24576                se.depth  = state_.scope_depth;
24577                se.ref_count++;
24578             }
24579          }
24580
24581          if (0 == str_node)
24582          {
24583             scope_element nse;
24584             nse.name      = str_name;
24585             nse.active    = true;
24586             nse.ref_count = 1;
24587             nse.type      = scope_element::e_string;
24588             nse.depth     = state_.scope_depth;
24589             nse.data      = new std::string;
24590             nse.str_node  = new stringvar_node_t(*(std::string*)(nse.data));
24591
24592             if (!sem_.add_element(nse))
24593             {
24594                set_error(
24595                   make_error(parser_error::e_syntax,
24596                              current_token(),
24597                              "ERR157 - Failed to add new local string variable '" + str_name + "' to SEM",
24598                              exprtk_error_location));
24599
24600                free_node(node_allocator_,initialisation_expression);
24601
24602                sem_.free_element(nse);
24603
24604                return error_node();
24605             }
24606
24607             str_node = nse.str_node;
24608
24609             exprtk_debug(("parse_define_string_statement() - INFO - Added new local string variable: %s\n",nse.name.c_str()));
24610          }
24611
24612          lodge_symbol(str_name, e_st_local_string);
24613
24614          state_.activate_side_effect("parse_define_string_statement()");
24615
24616          expression_node_ptr branch[2] = {0};
24617
24618          branch[0] = str_node;
24619          branch[1] = initialisation_expression;
24620
24621          return expression_generator_(details::e_assign,branch);
24622       }
24623       #else
24624       inline expression_node_ptr parse_define_string_statement(const std::string&, expression_node_ptr)
24625       {
24626          return error_node();
24627       }
24628       #endif
24629
24630       inline bool local_variable_is_shadowed(const std::string& symbol)
24631       {
24632          const scope_element& se = sem_.get_element(symbol);
24633          return (se.name == symbol) && se.active;
24634       }
24635
24636       inline expression_node_ptr parse_define_var_statement()
24637       {
24638          if (settings_.vardef_disabled())
24639          {
24640             set_error(
24641                make_error(parser_error::e_syntax,
24642                           current_token(),
24643                           "ERR158 - Illegal variable definition",
24644                           exprtk_error_location));
24645
24646             return error_node();
24647          }
24648          else if (!details::imatch(current_token().value,"var"))
24649          {
24650             return error_node();
24651          }
24652          else
24653             next_token();
24654
24655          const std::string var_name = current_token().value;
24656
24657          expression_node_ptr initialisation_expression = error_node();
24658
24659          if (!token_is(token_t::e_symbol))
24660          {
24661             set_error(
24662                make_error(parser_error::e_syntax,
24663                           current_token(),
24664                           "ERR159 - Expected a symbol for variable definition",
24665                           exprtk_error_location));
24666
24667             return error_node();
24668          }
24669          else if (details::is_reserved_symbol(var_name))
24670          {
24671             set_error(
24672                make_error(parser_error::e_syntax,
24673                           current_token(),
24674                           "ERR160 - Illegal redefinition of reserved keyword: '" + var_name + "'",
24675                           exprtk_error_location));
24676
24677             return error_node();
24678          }
24679          else if (symtab_store_.symbol_exists(var_name))
24680          {
24681             set_error(
24682                make_error(parser_error::e_syntax,
24683                           current_token(),
24684                           "ERR161 - Illegal redefinition of variable '" + var_name + "'",
24685                           exprtk_error_location));
24686
24687             return error_node();
24688          }
24689          else if (local_variable_is_shadowed(var_name))
24690          {
24691             set_error(
24692                make_error(parser_error::e_syntax,
24693                           current_token(),
24694                           "ERR162 - Illegal redefinition of local variable: '" + var_name + "'",
24695                           exprtk_error_location));
24696
24697             return error_node();
24698          }
24699          else if (token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold))
24700          {
24701             return parse_define_vector_statement(var_name);
24702          }
24703          else if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
24704          {
24705             return parse_uninitialised_var_statement(var_name);
24706          }
24707          else if (token_is(token_t::e_assign))
24708          {
24709             if (0 == (initialisation_expression = parse_expression()))
24710             {
24711                set_error(
24712                   make_error(parser_error::e_syntax,
24713                              current_token(),
24714                              "ERR163 - Failed to parse initialisation expression",
24715                              exprtk_error_location));
24716
24717                return error_node();
24718             }
24719          }
24720
24721          if (
24722               !token_is(token_t::e_rbracket   , prsrhlpr_t::e_hold) &&
24723               !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) &&
24724               !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold)
24725             )
24726          {
24727             if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold))
24728             {
24729                set_error(
24730                   make_error(parser_error::e_syntax,
24731                              current_token(),
24732                              "ERR164 - Expected ';' after variable definition",
24733                              exprtk_error_location));
24734
24735                free_node(node_allocator_,initialisation_expression);
24736
24737                return error_node();
24738             }
24739          }
24740
24741          if (
24742               (0 != initialisation_expression) &&
24743               details::is_generally_string_node(initialisation_expression)
24744             )
24745          {
24746             return parse_define_string_statement(var_name,initialisation_expression);
24747          }
24748
24749          expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0);
24750
24751          scope_element& se = sem_.get_element(var_name);
24752
24753          if (se.name == var_name)
24754          {
24755             if (se.active)
24756             {
24757                set_error(
24758                   make_error(parser_error::e_syntax,
24759                              current_token(),
24760                              "ERR165 - Illegal redefinition of local variable: '" + var_name + "'",
24761                              exprtk_error_location));
24762
24763                free_node(node_allocator_, initialisation_expression);
24764
24765                return error_node();
24766             }
24767             else if (scope_element::e_variable == se.type)
24768             {
24769                var_node  = se.var_node;
24770                se.active = true;
24771                se.depth  = state_.scope_depth;
24772                se.ref_count++;
24773             }
24774          }
24775
24776          if (0 == var_node)
24777          {
24778             scope_element nse;
24779             nse.name      = var_name;
24780             nse.active    = true;
24781             nse.ref_count = 1;
24782             nse.type      = scope_element::e_variable;
24783             nse.depth     = state_.scope_depth;
24784             nse.data      = new T(T(0));
24785             nse.var_node  = node_allocator_.allocate<variable_node_t>(*(T*)(nse.data));
24786
24787             if (!sem_.add_element(nse))
24788             {
24789                set_error(
24790                   make_error(parser_error::e_syntax,
24791                              current_token(),
24792                              "ERR166 - Failed to add new local variable '" + var_name + "' to SEM",
24793                              exprtk_error_location));
24794
24795                free_node(node_allocator_, initialisation_expression);
24796
24797                sem_.free_element(nse);
24798
24799                return error_node();
24800             }
24801
24802             var_node = nse.var_node;
24803
24804             exprtk_debug(("parse_define_var_statement() - INFO - Added new local variable: %s\n",nse.name.c_str()));
24805          }
24806
24807          state_.activate_side_effect("parse_define_var_statement()");
24808
24809          lodge_symbol(var_name, e_st_local_variable);
24810
24811          expression_node_ptr branch[2] = {0};
24812
24813          branch[0] = var_node;
24814          branch[1] = initialisation_expression ? initialisation_expression : expression_generator_(T(0));
24815
24816          return expression_generator_(details::e_assign,branch);
24817       }
24818
24819       inline expression_node_ptr parse_uninitialised_var_statement(const std::string& var_name)
24820       {
24821          if (
24822               !token_is(token_t::e_lcrlbracket) ||
24823               !token_is(token_t::e_rcrlbracket)
24824             )
24825          {
24826             set_error(
24827                make_error(parser_error::e_syntax,
24828                           current_token(),
24829                           "ERR167 - Expected a '{}' for uninitialised var definition",
24830                           exprtk_error_location));
24831
24832             return error_node();
24833          }
24834          else if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold))
24835          {
24836             set_error(
24837                make_error(parser_error::e_syntax,
24838                           current_token(),
24839                           "ERR168 - Expected ';' after uninitialised variable definition",
24840                           exprtk_error_location));
24841
24842             return error_node();
24843          }
24844
24845          expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0);
24846
24847          scope_element& se = sem_.get_element(var_name);
24848
24849          if (se.name == var_name)
24850          {
24851             if (se.active)
24852             {
24853                set_error(
24854                   make_error(parser_error::e_syntax,
24855                              current_token(),
24856                              "ERR169 - Illegal redefinition of local variable: '" + var_name + "'",
24857                              exprtk_error_location));
24858
24859                return error_node();
24860             }
24861             else if (scope_element::e_variable == se.type)
24862             {
24863                var_node  = se.var_node;
24864                se.active = true;
24865                se.ref_count++;
24866             }
24867          }
24868
24869          if (0 == var_node)
24870          {
24871             scope_element nse;
24872             nse.name      = var_name;
24873             nse.active    = true;
24874             nse.ref_count = 1;
24875             nse.type      = scope_element::e_variable;
24876             nse.depth     = state_.scope_depth;
24877             nse.ip_index  = sem_.next_ip_index();
24878             nse.data      = new T(T(0));
24879             nse.var_node  = node_allocator_.allocate<variable_node_t>(*(T*)(nse.data));
24880
24881             if (!sem_.add_element(nse))
24882             {
24883                set_error(
24884                   make_error(parser_error::e_syntax,
24885                              current_token(),
24886                              "ERR170 - Failed to add new local variable '" + var_name + "' to SEM",
24887                              exprtk_error_location));
24888
24889                sem_.free_element(nse);
24890
24891                return error_node();
24892             }
24893
24894             exprtk_debug(("parse_uninitialised_var_statement() - INFO - Added new local variable: %s\n",
24895                           nse.name.c_str()));
24896          }
24897
24898          lodge_symbol(var_name, e_st_local_variable);
24899
24900          state_.activate_side_effect("parse_uninitialised_var_statement()");
24901
24902          return expression_generator_(T(0));
24903       }
24904
24905       inline expression_node_ptr parse_swap_statement()
24906       {
24907          if (!details::imatch(current_token().value,"swap"))
24908          {
24909             return error_node();
24910          }
24911          else
24912             next_token();
24913
24914          if (!token_is(token_t::e_lbracket))
24915          {
24916             set_error(
24917                make_error(parser_error::e_syntax,
24918                           current_token(),
24919                           "ERR171 - Expected '(' at start of swap statement",
24920                           exprtk_error_location));
24921
24922             return error_node();
24923          }
24924
24925          expression_node_ptr variable0 = error_node();
24926          expression_node_ptr variable1 = error_node();
24927
24928          bool variable0_generated = false;
24929          bool variable1_generated = false;
24930
24931          const std::string var0_name = current_token().value;
24932
24933          if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold))
24934          {
24935             set_error(
24936                make_error(parser_error::e_syntax,
24937                           current_token(),
24938                           "ERR172 - Expected a symbol for variable or vector element definition",
24939                           exprtk_error_location));
24940
24941             return error_node();
24942          }
24943          else if (peek_token_is(token_t::e_lsqrbracket))
24944          {
24945             if (0 == (variable0 = parse_vector()))
24946             {
24947                set_error(
24948                   make_error(parser_error::e_syntax,
24949                              current_token(),
24950                              "ERR173 - First parameter to swap is an invalid vector element: '" + var0_name + "'",
24951                              exprtk_error_location));
24952
24953                return error_node();
24954             }
24955
24956             variable0_generated = true;
24957          }
24958          else
24959          {
24960             if (symtab_store_.is_variable(var0_name))
24961             {
24962                variable0 = symtab_store_.get_variable(var0_name);
24963             }
24964
24965             scope_element& se = sem_.get_element(var0_name);
24966
24967             if (
24968                  (se.active)            &&
24969                  (se.name == var0_name) &&
24970                  (scope_element::e_variable == se.type)
24971                )
24972             {
24973                variable0 = se.var_node;
24974             }
24975
24976             lodge_symbol(var0_name, e_st_variable);
24977
24978             if (0 == variable0)
24979             {
24980                set_error(
24981                   make_error(parser_error::e_syntax,
24982                              current_token(),
24983                              "ERR174 - First parameter to swap is an invalid variable: '" + var0_name + "'",
24984                              exprtk_error_location));
24985
24986                return error_node();
24987             }
24988             else
24989                next_token();
24990          }
24991
24992          if (!token_is(token_t::e_comma))
24993          {
24994             set_error(
24995                 make_error(parser_error::e_syntax,
24996                            current_token(),
24997                            "ERR175 - Expected ',' between parameters to swap",
24998                            exprtk_error_location));
24999
25000             if (variable0_generated)
25001             {
25002                free_node(node_allocator_,variable0);
25003             }
25004
25005             return error_node();
25006          }
25007
25008          const std::string var1_name = current_token().value;
25009
25010          if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold))
25011          {
25012             set_error(
25013                make_error(parser_error::e_syntax,
25014                           current_token(),
25015                           "ERR176 - Expected a symbol for variable or vector element definition",
25016                           exprtk_error_location));
25017
25018             if (variable0_generated)
25019             {
25020                free_node(node_allocator_,variable0);
25021             }
25022
25023             return error_node();
25024          }
25025          else if (peek_token_is(token_t::e_lsqrbracket))
25026          {
25027             if (0 == (variable1 = parse_vector()))
25028             {
25029                set_error(
25030                   make_error(parser_error::e_syntax,
25031                              current_token(),
25032                              "ERR177 - Second parameter to swap is an invalid vector element: '" + var1_name + "'",
25033                              exprtk_error_location));
25034
25035                if (variable0_generated)
25036                {
25037                   free_node(node_allocator_,variable0);
25038                }
25039
25040                return error_node();
25041             }
25042
25043             variable1_generated = true;
25044          }
25045          else
25046          {
25047             if (symtab_store_.is_variable(var1_name))
25048             {
25049                variable1 = symtab_store_.get_variable(var1_name);
25050             }
25051
25052             scope_element& se = sem_.get_element(var1_name);
25053
25054             if (
25055                  (se.active) &&
25056                  (se.name == var1_name) &&
25057                  (scope_element::e_variable == se.type)
25058                )
25059             {
25060                variable1 = se.var_node;
25061             }
25062
25063             lodge_symbol(var1_name, e_st_variable);
25064
25065             if (0 == variable1)
25066             {
25067                set_error(
25068                   make_error(parser_error::e_syntax,
25069                              current_token(),
25070                              "ERR178 - Second parameter to swap is an invalid variable: '" + var1_name + "'",
25071                              exprtk_error_location));
25072
25073                if (variable0_generated)
25074                {
25075                   free_node(node_allocator_,variable0);
25076                }
25077
25078                return error_node();
25079             }
25080             else
25081                next_token();
25082          }
25083
25084          if (!token_is(token_t::e_rbracket))
25085          {
25086             set_error(
25087                make_error(parser_error::e_syntax,
25088                           current_token(),
25089                           "ERR179 - Expected ')' at end of swap statement",
25090                           exprtk_error_location));
25091
25092             if (variable0_generated)
25093             {
25094                free_node(node_allocator_,variable0);
25095             }
25096
25097             if (variable1_generated)
25098             {
25099                free_node(node_allocator_,variable1);
25100             }
25101
25102             return error_node();
25103          }
25104
25105          typedef details::variable_node<T>* variable_node_ptr;
25106
25107          variable_node_ptr v0 = variable_node_ptr(0);
25108          variable_node_ptr v1 = variable_node_ptr(0);
25109
25110          expression_node_ptr result = error_node();
25111
25112          if (
25113               (0 != (v0 = dynamic_cast<variable_node_ptr>(variable0))) &&
25114               (0 != (v1 = dynamic_cast<variable_node_ptr>(variable1)))
25115             )
25116          {
25117             result = node_allocator_.allocate<details::swap_node<T> >(v0, v1);
25118
25119             if (variable0_generated)
25120             {
25121                free_node(node_allocator_,variable0);
25122             }
25123
25124             if (variable1_generated)
25125             {
25126                free_node(node_allocator_,variable1);
25127             }
25128          }
25129          else
25130             result = node_allocator_.allocate<details::swap_generic_node<T> >
25131                         (variable0, variable1);
25132
25133          state_.activate_side_effect("parse_swap_statement()");
25134
25135          return result;
25136       }
25137
25138       #ifndef exprtk_disable_return_statement
25139       inline expression_node_ptr parse_return_statement()
25140       {
25141          if (state_.parsing_return_stmt)
25142          {
25143             set_error(
25144                make_error(parser_error::e_syntax,
25145                           current_token(),
25146                           "ERR180 - Return call within a return call is not allowed",
25147                           exprtk_error_location));
25148
25149             return error_node();
25150          }
25151
25152          scoped_bool_negator sbn(state_.parsing_return_stmt);
25153
25154          std::vector<expression_node_ptr> arg_list;
25155
25156          scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
25157
25158          if (!details::imatch(current_token().value,"return"))
25159          {
25160             return error_node();
25161          }
25162          else
25163             next_token();
25164
25165          if (!token_is(token_t::e_lsqrbracket))
25166          {
25167             set_error(
25168                make_error(parser_error::e_syntax,
25169                           current_token(),
25170                           "ERR181 - Expected '[' at start of return statement",
25171                           exprtk_error_location));
25172
25173             return error_node();
25174          }
25175          else if (!token_is(token_t::e_rsqrbracket))
25176          {
25177             for ( ; ; )
25178             {
25179                expression_node_ptr arg = parse_expression();
25180
25181                if (0 == arg)
25182                   return error_node();
25183
25184                arg_list.push_back(arg);
25185
25186                if (token_is(token_t::e_rsqrbracket))
25187                   break;
25188                else if (!token_is(token_t::e_comma))
25189                {
25190                   set_error(
25191                      make_error(parser_error::e_syntax,
25192                                 current_token(),
25193                                 "ERR182 - Expected ',' between values during call to return",
25194                                 exprtk_error_location));
25195
25196                   return error_node();
25197                }
25198             }
25199          }
25200          else if (settings_.zero_return_disabled())
25201          {
25202             set_error(
25203                make_error(parser_error::e_syntax,
25204                           current_token(),
25205                           "ERR183 - Zero parameter return statement not allowed",
25206                           exprtk_error_location));
25207
25208             return error_node();
25209          }
25210
25211          const lexer::token prev_token = current_token();
25212
25213          if (token_is(token_t::e_rsqrbracket))
25214          {
25215             if (!arg_list.empty())
25216             {
25217                set_error(
25218                   make_error(parser_error::e_syntax,
25219                              prev_token,
25220                              "ERR184 - Invalid ']' found during return call",
25221                              exprtk_error_location));
25222
25223                return error_node();
25224             }
25225          }
25226
25227          std::string ret_param_type_list;
25228
25229          for (std::size_t i = 0; i < arg_list.size(); ++i)
25230          {
25231             if (0 == arg_list[i])
25232                return error_node();
25233             else if (is_ivector_node(arg_list[i]))
25234                ret_param_type_list += 'V';
25235             else if (is_generally_string_node(arg_list[i]))
25236                ret_param_type_list += 'S';
25237             else
25238                ret_param_type_list += 'T';
25239          }
25240
25241          dec_.retparam_list_.push_back(ret_param_type_list);
25242
25243          expression_node_ptr result = expression_generator_.return_call(arg_list);
25244
25245          sdd.delete_ptr = (0 == result);
25246
25247          state_.return_stmt_present = true;
25248
25249          state_.activate_side_effect("parse_return_statement()");
25250
25251          return result;
25252       }
25253       #else
25254       inline expression_node_ptr parse_return_statement()
25255       {
25256          return error_node();
25257       }
25258       #endif
25259
25260       inline bool post_variable_process(const std::string& symbol)
25261       {
25262          if (
25263               peek_token_is(token_t::e_lbracket   ) ||
25264               peek_token_is(token_t::e_lcrlbracket) ||
25265               peek_token_is(token_t::e_lsqrbracket)
25266             )
25267          {
25268             if (!settings_.commutative_check_enabled())
25269             {
25270                set_error(
25271                   make_error(parser_error::e_syntax,
25272                              current_token(),
25273                              "ERR185 - Invalid sequence of variable '"+ symbol + "' and bracket",
25274                              exprtk_error_location));
25275
25276                return false;
25277             }
25278
25279             lexer().insert_front(token_t::e_mul);
25280          }
25281
25282          return true;
25283       }
25284
25285       inline bool post_bracket_process(const typename token_t::token_type& token, expression_node_ptr& branch)
25286       {
25287          bool implied_mul = false;
25288
25289          if (is_generally_string_node(branch))
25290             return true;
25291
25292          const lexer::parser_helper::token_advance_mode hold = prsrhlpr_t::e_hold;
25293
25294          switch (token)
25295          {
25296             case token_t::e_lcrlbracket : implied_mul = token_is(token_t::e_lbracket   ,hold) ||
25297                                                         token_is(token_t::e_lcrlbracket,hold) ||
25298                                                         token_is(token_t::e_lsqrbracket,hold) ;
25299                                           break;
25300
25301             case token_t::e_lbracket    : implied_mul = token_is(token_t::e_lbracket   ,hold) ||
25302                                                         token_is(token_t::e_lcrlbracket,hold) ||
25303                                                         token_is(token_t::e_lsqrbracket,hold) ;
25304                                           break;
25305
25306             case token_t::e_lsqrbracket : implied_mul = token_is(token_t::e_lbracket   ,hold) ||
25307                                                         token_is(token_t::e_lcrlbracket,hold) ||
25308                                                         token_is(token_t::e_lsqrbracket,hold) ;
25309                                           break;
25310
25311             default                     : return true;
25312          }
25313
25314          if (implied_mul)
25315          {
25316             if (!settings_.commutative_check_enabled())
25317             {
25318                set_error(
25319                   make_error(parser_error::e_syntax,
25320                              current_token(),
25321                              "ERR186 - Invalid sequence of brackets",
25322                              exprtk_error_location));
25323
25324                return false;
25325             }
25326             else if (token_t::e_eof != current_token().type)
25327             {
25328                lexer().insert_front(current_token().type);
25329                lexer().insert_front(token_t::e_mul);
25330                next_token();
25331             }
25332          }
25333
25334          return true;
25335       }
25336
25337       inline expression_node_ptr parse_symtab_symbol()
25338       {
25339          const std::string symbol = current_token().value;
25340
25341          // Are we dealing with a variable or a special constant?
25342          expression_node_ptr variable = symtab_store_.get_variable(symbol);
25343
25344          if (variable)
25345          {
25346             if (symtab_store_.is_constant_node(symbol))
25347             {
25348                variable = expression_generator_(variable->value());
25349             }
25350
25351             if (!post_variable_process(symbol))
25352                return error_node();
25353
25354             lodge_symbol(symbol, e_st_variable);
25355             next_token();
25356
25357             return variable;
25358          }
25359
25360          // Are we dealing with a locally defined variable, vector or string?
25361          if (!sem_.empty())
25362          {
25363             scope_element& se = sem_.get_active_element(symbol);
25364
25365             if (se.active && details::imatch(se.name, symbol))
25366             {
25367                if (scope_element::e_variable == se.type)
25368                {
25369                   se.active = true;
25370                   lodge_symbol(symbol, e_st_local_variable);
25371
25372                   if (!post_variable_process(symbol))
25373                      return error_node();
25374
25375                   next_token();
25376
25377                   return se.var_node;
25378                }
25379                else if (scope_element::e_vector == se.type)
25380                {
25381                   return parse_vector();
25382                }
25383                #ifndef exprtk_disable_string_capabilities
25384                else if (scope_element::e_string == se.type)
25385                {
25386                   return parse_string();
25387                }
25388                #endif
25389             }
25390          }
25391
25392          #ifndef exprtk_disable_string_capabilities
25393          // Are we dealing with a string variable?
25394          if (symtab_store_.is_stringvar(symbol))
25395          {
25396             return parse_string();
25397          }
25398          #endif
25399
25400          {
25401             // Are we dealing with a function?
25402             ifunction<T>* function = symtab_store_.get_function(symbol);
25403
25404             if (function)
25405             {
25406                lodge_symbol(symbol, e_st_function);
25407
25408                expression_node_ptr func_node =
25409                                       parse_function_invocation(function,symbol);
25410
25411                if (func_node)
25412                   return func_node;
25413                else
25414                {
25415                   set_error(
25416                      make_error(parser_error::e_syntax,
25417                                 current_token(),
25418                                 "ERR187 - Failed to generate node for function: '" + symbol + "'",
25419                                 exprtk_error_location));
25420
25421                   return error_node();
25422                }
25423             }
25424          }
25425
25426          {
25427             // Are we dealing with a vararg function?
25428             ivararg_function<T>* vararg_function = symtab_store_.get_vararg_function(symbol);
25429
25430             if (vararg_function)
25431             {
25432                lodge_symbol(symbol, e_st_function);
25433
25434                expression_node_ptr vararg_func_node =
25435                                       parse_vararg_function_call(vararg_function, symbol);
25436
25437                if (vararg_func_node)
25438                   return vararg_func_node;
25439                else
25440                {
25441                   set_error(
25442                      make_error(parser_error::e_syntax,
25443                                 current_token(),
25444                                 "ERR188 - Failed to generate node for vararg function: '" + symbol + "'",
25445                                 exprtk_error_location));
25446
25447                   return error_node();
25448                }
25449             }
25450          }
25451
25452          {
25453             // Are we dealing with a vararg generic function?
25454             igeneric_function<T>* generic_function = symtab_store_.get_generic_function(symbol);
25455
25456             if (generic_function)
25457             {
25458                lodge_symbol(symbol, e_st_function);
25459
25460                expression_node_ptr genericfunc_node =
25461                                       parse_generic_function_call(generic_function, symbol);
25462
25463                if (genericfunc_node)
25464                   return genericfunc_node;
25465                else
25466                {
25467                   set_error(
25468                      make_error(parser_error::e_syntax,
25469                                 current_token(),
25470                                 "ERR189 - Failed to generate node for generic function: '" + symbol + "'",
25471                                 exprtk_error_location));
25472
25473                   return error_node();
25474                }
25475             }
25476          }
25477
25478          #ifndef exprtk_disable_string_capabilities
25479          {
25480             // Are we dealing with a vararg string returning function?
25481             igeneric_function<T>* string_function = symtab_store_.get_string_function(symbol);
25482
25483             if (string_function)
25484             {
25485                lodge_symbol(symbol, e_st_function);
25486
25487                expression_node_ptr stringfunc_node =
25488                                       parse_string_function_call(string_function, symbol);
25489
25490                if (stringfunc_node)
25491                   return stringfunc_node;
25492                else
25493                {
25494                   set_error(
25495                      make_error(parser_error::e_syntax,
25496                                 current_token(),
25497                                 "ERR190 - Failed to generate node for string function: '" + symbol + "'",
25498                                 exprtk_error_location));
25499
25500                   return error_node();
25501                }
25502             }
25503          }
25504
25505          {
25506             // Are we dealing with a vararg overloaded scalar/string returning function?
25507             igeneric_function<T>* overload_function = symtab_store_.get_overload_function(symbol);
25508
25509             if (overload_function)
25510             {
25511                lodge_symbol(symbol, e_st_function);
25512
25513                expression_node_ptr overloadfunc_node =
25514                                       parse_overload_function_call(overload_function, symbol);
25515
25516                if (overloadfunc_node)
25517                   return overloadfunc_node;
25518                else
25519                {
25520                   set_error(
25521                      make_error(parser_error::e_syntax,
25522                                 current_token(),
25523                                 "ERR191 - Failed to generate node for overload function: '" + symbol + "'",
25524                                 exprtk_error_location));
25525
25526                   return error_node();
25527                }
25528             }
25529          }
25530          #endif
25531
25532          // Are we dealing with a vector?
25533          if (symtab_store_.is_vector(symbol))
25534          {
25535             lodge_symbol(symbol, e_st_vector);
25536             return parse_vector();
25537          }
25538
25539          if (details::is_reserved_symbol(symbol))
25540          {
25541                if (
25542                     settings_.function_enabled(symbol) ||
25543                     !details::is_base_function(symbol)
25544                   )
25545                {
25546                   set_error(
25547                      make_error(parser_error::e_syntax,
25548                                 current_token(),
25549                                 "ERR192 - Invalid use of reserved symbol '" + symbol + "'",
25550                                 exprtk_error_location));
25551
25552                   return error_node();
25553                }
25554          }
25555
25556          // Should we handle unknown symbols?
25557          if (resolve_unknown_symbol_ && unknown_symbol_resolver_)
25558          {
25559             if (!(settings_.rsrvd_sym_usr_disabled() && details::is_reserved_symbol(symbol)))
25560             {
25561                symbol_table_t& symtab = symtab_store_.get_symbol_table();
25562
25563                std::string error_message;
25564
25565                if (unknown_symbol_resolver::e_usrmode_default == unknown_symbol_resolver_->mode)
25566                {
25567                   T default_value = T(0);
25568
25569                   typename unknown_symbol_resolver::usr_symbol_type usr_symbol_type = unknown_symbol_resolver::e_usr_unknown_type;
25570
25571                   if (unknown_symbol_resolver_->process(symbol, usr_symbol_type, default_value, error_message))
25572                   {
25573                      bool create_result = false;
25574
25575                      switch (usr_symbol_type)
25576                      {
25577                         case unknown_symbol_resolver::e_usr_variable_type : create_result = symtab.create_variable(symbol, default_value);
25578                                                                             break;
25579
25580                         case unknown_symbol_resolver::e_usr_constant_type : create_result = symtab.add_constant(symbol, default_value);
25581                                                                             break;
25582
25583                         default                                           : create_result = false;
25584                      }
25585
25586                      if (create_result)
25587                      {
25588                         expression_node_ptr var = symtab_store_.get_variable(symbol);
25589
25590                         if (var)
25591                         {
25592                            if (symtab_store_.is_constant_node(symbol))
25593                            {
25594                               var = expression_generator_(var->value());
25595                            }
25596
25597                            lodge_symbol(symbol, e_st_variable);
25598
25599                            if (!post_variable_process(symbol))
25600                               return error_node();
25601
25602                            next_token();
25603
25604                            return var;
25605                         }
25606                      }
25607                   }
25608
25609                   set_error(
25610                      make_error(parser_error::e_symtab,
25611                                 current_token(),
25612                                 "ERR193 - Failed to create variable: '" + symbol + "'" +
25613                                 (error_message.empty() ? "" : " - " + error_message),
25614                                 exprtk_error_location));
25615
25616                }
25617                else if (unknown_symbol_resolver::e_usrmode_extended == unknown_symbol_resolver_->mode)
25618                {
25619                   if (unknown_symbol_resolver_->process(symbol, symtab, error_message))
25620                   {
25621                      expression_node_ptr result = parse_symtab_symbol();
25622
25623                      if (result)
25624                      {
25625                         return result;
25626                      }
25627                   }
25628
25629                   set_error(
25630                      make_error(parser_error::e_symtab,
25631                                 current_token(),
25632                                 "ERR194 - Failed to resolve symbol: '" + symbol + "'" +
25633                                 (error_message.empty() ? "" : " - " + error_message),
25634                                 exprtk_error_location));
25635                }
25636
25637                return error_node();
25638             }
25639          }
25640
25641          set_error(
25642             make_error(parser_error::e_syntax,
25643                        current_token(),
25644                        "ERR195 - Undefined symbol: '" + symbol + "'",
25645                        exprtk_error_location));
25646
25647          return error_node();
25648       }
25649
25650       inline expression_node_ptr parse_symbol()
25651       {
25652          static const std::string symbol_if       = "if"      ;
25653          static const std::string symbol_while    = "while"   ;
25654          static const std::string symbol_repeat   = "repeat"  ;
25655          static const std::string symbol_for      = "for"     ;
25656          static const std::string symbol_switch   = "switch"  ;
25657          static const std::string symbol_null     = "null"    ;
25658          static const std::string symbol_break    = "break"   ;
25659          static const std::string symbol_continue = "continue";
25660          static const std::string symbol_var      = "var"     ;
25661          static const std::string symbol_swap     = "swap"    ;
25662          static const std::string symbol_return   = "return"  ;
25663          static const std::string symbol_not      = "not"     ;
25664
25665          if (valid_vararg_operation(current_token().value))
25666          {
25667             return parse_vararg_function();
25668          }
25669          else if (details::imatch(current_token().value, symbol_not))
25670          {
25671             return parse_not_statement();
25672          }
25673          else if (valid_base_operation(current_token().value))
25674          {
25675             return parse_base_operation();
25676          }
25677          else if (
25678                    details::imatch(current_token().value, symbol_if) &&
25679                    settings_.control_struct_enabled(current_token().value)
25680                  )
25681          {
25682             return parse_conditional_statement();
25683          }
25684          else if (
25685                    details::imatch(current_token().value, symbol_while) &&
25686                    settings_.control_struct_enabled(current_token().value)
25687                  )
25688          {
25689             return parse_while_loop();
25690          }
25691          else if (
25692                    details::imatch(current_token().value, symbol_repeat) &&
25693                    settings_.control_struct_enabled(current_token().value)
25694                  )
25695          {
25696             return parse_repeat_until_loop();
25697          }
25698          else if (
25699                    details::imatch(current_token().value, symbol_for) &&
25700                    settings_.control_struct_enabled(current_token().value)
25701                  )
25702          {
25703             return parse_for_loop();
25704          }
25705          else if (
25706                    details::imatch(current_token().value, symbol_switch) &&
25707                    settings_.control_struct_enabled(current_token().value)
25708                  )
25709          {
25710             return parse_switch_statement();
25711          }
25712          else if (details::is_valid_sf_symbol(current_token().value))
25713          {
25714             return parse_special_function();
25715          }
25716          else if (details::imatch(current_token().value, symbol_null))
25717          {
25718             return parse_null_statement();
25719          }
25720          #ifndef exprtk_disable_break_continue
25721          else if (details::imatch(current_token().value, symbol_break))
25722          {
25723             return parse_break_statement();
25724          }
25725          else if (details::imatch(current_token().value, symbol_continue))
25726          {
25727             return parse_continue_statement();
25728          }
25729          #endif
25730          else if (details::imatch(current_token().value, symbol_var))
25731          {
25732             return parse_define_var_statement();
25733          }
25734          else if (details::imatch(current_token().value, symbol_swap))
25735          {
25736             return parse_swap_statement();
25737          }
25738          #ifndef exprtk_disable_return_statement
25739          else if (
25740                    details::imatch(current_token().value, symbol_return) &&
25741                    settings_.control_struct_enabled(current_token().value)
25742                  )
25743          {
25744             return parse_return_statement();
25745          }
25746          #endif
25747          else if (symtab_store_.valid() || !sem_.empty())
25748          {
25749             return parse_symtab_symbol();
25750          }
25751          else
25752          {
25753             set_error(
25754                make_error(parser_error::e_symtab,
25755                           current_token(),
25756                           "ERR196 - Variable or function detected, yet symbol-table is invalid, Symbol: " + current_token().value,
25757                           exprtk_error_location));
25758
25759             return error_node();
25760          }
25761       }
25762
25763       inline expression_node_ptr parse_branch(precedence_level precedence = e_level00)
25764       {
25765          expression_node_ptr branch = error_node();
25766
25767          if (token_t::e_number == current_token().type)
25768          {
25769             T numeric_value = T(0);
25770
25771             if (details::string_to_real(current_token().value, numeric_value))
25772             {
25773                expression_node_ptr literal_exp = expression_generator_(numeric_value);
25774
25775                if (0 == literal_exp)
25776                {
25777                   set_error(
25778                      make_error(parser_error::e_numeric,
25779                                 current_token(),
25780                                 "ERR197 - Failed generate node for scalar: '" + current_token().value + "'",
25781                                 exprtk_error_location));
25782
25783                   return error_node();
25784                }
25785
25786                next_token();
25787                branch = literal_exp;
25788             }
25789             else
25790             {
25791                set_error(
25792                   make_error(parser_error::e_numeric,
25793                              current_token(),
25794                              "ERR198 - Failed to convert '" + current_token().value + "' to a number",
25795                              exprtk_error_location));
25796
25797                return error_node();
25798             }
25799          }
25800          else if (token_t::e_symbol == current_token().type)
25801          {
25802             branch = parse_symbol();
25803          }
25804          #ifndef exprtk_disable_string_capabilities
25805          else if (token_t::e_string == current_token().type)
25806          {
25807             branch = parse_const_string();
25808          }
25809          #endif
25810          else if (token_t::e_lbracket == current_token().type)
25811          {
25812             next_token();
25813
25814             if (0 == (branch = parse_expression()))
25815                return error_node();
25816             else if (!token_is(token_t::e_rbracket))
25817             {
25818                set_error(
25819                   make_error(parser_error::e_syntax,
25820                              current_token(),
25821                              "ERR199 - Expected ')' instead of: '" + current_token().value + "'",
25822                              exprtk_error_location));
25823
25824                free_node(node_allocator_,branch);
25825
25826                return error_node();
25827             }
25828             else if (!post_bracket_process(token_t::e_lbracket,branch))
25829             {
25830                free_node(node_allocator_,branch);
25831
25832                return error_node();
25833             }
25834          }
25835          else if (token_t::e_lsqrbracket == current_token().type)
25836          {
25837             next_token();
25838
25839             if (0 == (branch = parse_expression()))
25840                return error_node();
25841             else if (!token_is(token_t::e_rsqrbracket))
25842             {
25843                set_error(
25844                   make_error(parser_error::e_syntax,
25845                              current_token(),
25846                              "ERR200 - Expected ']' instead of: '" + current_token().value + "'",
25847                              exprtk_error_location));
25848
25849                free_node(node_allocator_,branch);
25850
25851                return error_node();
25852             }
25853             else if (!post_bracket_process(token_t::e_lsqrbracket,branch))
25854             {
25855                free_node(node_allocator_,branch);
25856
25857                return error_node();
25858             }
25859          }
25860          else if (token_t::e_lcrlbracket == current_token().type)
25861          {
25862             next_token();
25863
25864             if (0 == (branch = parse_expression()))
25865                return error_node();
25866             else if (!token_is(token_t::e_rcrlbracket))
25867             {
25868                set_error(
25869                   make_error(parser_error::e_syntax,
25870                              current_token(),
25871                              "ERR201 - Expected '}' instead of: '" + current_token().value + "'",
25872                              exprtk_error_location));
25873
25874                free_node(node_allocator_,branch);
25875
25876                return error_node();
25877             }
25878             else if (!post_bracket_process(token_t::e_lcrlbracket,branch))
25879             {
25880                free_node(node_allocator_,branch);
25881
25882                return error_node();
25883             }
25884          }
25885          else if (token_t::e_sub == current_token().type)
25886          {
25887             next_token();
25888             branch = parse_expression(e_level11);
25889
25890             if (
25891                  branch &&
25892                  !(
25893                     details::is_neg_unary_node    (branch) &&
25894                     simplify_unary_negation_branch(branch)
25895                   )
25896                )
25897             {
25898                branch = expression_generator_(details::e_neg,branch);
25899             }
25900          }
25901          else if (token_t::e_add == current_token().type)
25902          {
25903             next_token();
25904             branch = parse_expression(e_level13);
25905          }
25906          else if (token_t::e_eof == current_token().type)
25907          {
25908             set_error(
25909                make_error(parser_error::e_syntax,
25910                           current_token(),
25911                           "ERR202 - Premature end of expression[1]",
25912                           exprtk_error_location));
25913
25914             return error_node();
25915          }
25916          else
25917          {
25918             set_error(
25919                make_error(parser_error::e_syntax,
25920                           current_token(),
25921                           "ERR203 - Premature end of expression[2]",
25922                           exprtk_error_location));
25923
25924             return error_node();
25925          }
25926
25927          if (
25928               branch                    &&
25929               (e_level00 == precedence) &&
25930               token_is(token_t::e_ternary,prsrhlpr_t::e_hold)
25931             )
25932          {
25933             branch = parse_ternary_conditional_statement(branch);
25934          }
25935
25936          parse_pending_string_rangesize(branch);
25937
25938          return branch;
25939       }
25940
25941       template <typename Type>
25942       class expression_generator
25943       {
25944       public:
25945
25946          typedef details::expression_node<Type>* expression_node_ptr;
25947          typedef expression_node_ptr (*synthesize_functor_t)(expression_generator<T>&, const details::operator_type& operation, expression_node_ptr (&branch)[2]);
25948          typedef std::map<std::string,synthesize_functor_t> synthesize_map_t;
25949          typedef typename exprtk::parser<Type> parser_t;
25950          typedef const Type& vtype;
25951          typedef const Type  ctype;
25952
25953          inline void init_synthesize_map()
25954          {
25955             #ifndef exprtk_disable_enhanced_features
25956             synthesize_map_["(v)o(v)"] = synthesize_vov_expression::process;
25957             synthesize_map_["(c)o(v)"] = synthesize_cov_expression::process;
25958             synthesize_map_["(v)o(c)"] = synthesize_voc_expression::process;
25959
25960             #define register_synthezier(S)                      \
25961             synthesize_map_[S ::node_type::id()] = S ::process; \
25962
25963             register_synthezier(synthesize_vovov_expression0)
25964             register_synthezier(synthesize_vovov_expression1)
25965             register_synthezier(synthesize_vovoc_expression0)
25966             register_synthezier(synthesize_vovoc_expression1)
25967             register_synthezier(synthesize_vocov_expression0)
25968             register_synthezier(synthesize_vocov_expression1)
25969             register_synthezier(synthesize_covov_expression0)
25970             register_synthezier(synthesize_covov_expression1)
25971             register_synthezier(synthesize_covoc_expression0)
25972             register_synthezier(synthesize_covoc_expression1)
25973             register_synthezier(synthesize_cocov_expression1)
25974             register_synthezier(synthesize_vococ_expression0)
25975
25976             register_synthezier(synthesize_vovovov_expression0)
25977             register_synthezier(synthesize_vovovoc_expression0)
25978             register_synthezier(synthesize_vovocov_expression0)
25979             register_synthezier(synthesize_vocovov_expression0)
25980             register_synthezier(synthesize_covovov_expression0)
25981             register_synthezier(synthesize_covocov_expression0)
25982             register_synthezier(synthesize_vocovoc_expression0)
25983             register_synthezier(synthesize_covovoc_expression0)
25984             register_synthezier(synthesize_vococov_expression0)
25985
25986             register_synthezier(synthesize_vovovov_expression1)
25987             register_synthezier(synthesize_vovovoc_expression1)
25988             register_synthezier(synthesize_vovocov_expression1)
25989             register_synthezier(synthesize_vocovov_expression1)
25990             register_synthezier(synthesize_covovov_expression1)
25991             register_synthezier(synthesize_covocov_expression1)
25992             register_synthezier(synthesize_vocovoc_expression1)
25993             register_synthezier(synthesize_covovoc_expression1)
25994             register_synthezier(synthesize_vococov_expression1)
25995
25996             register_synthezier(synthesize_vovovov_expression2)
25997             register_synthezier(synthesize_vovovoc_expression2)
25998             register_synthezier(synthesize_vovocov_expression2)
25999             register_synthezier(synthesize_vocovov_expression2)
26000             register_synthezier(synthesize_covovov_expression2)
26001             register_synthezier(synthesize_covocov_expression2)
26002             register_synthezier(synthesize_vocovoc_expression2)
26003             register_synthezier(synthesize_covovoc_expression2)
26004
26005             register_synthezier(synthesize_vovovov_expression3)
26006             register_synthezier(synthesize_vovovoc_expression3)
26007             register_synthezier(synthesize_vovocov_expression3)
26008             register_synthezier(synthesize_vocovov_expression3)
26009             register_synthezier(synthesize_covovov_expression3)
26010             register_synthezier(synthesize_covocov_expression3)
26011             register_synthezier(synthesize_vocovoc_expression3)
26012             register_synthezier(synthesize_covovoc_expression3)
26013             register_synthezier(synthesize_vococov_expression3)
26014
26015             register_synthezier(synthesize_vovovov_expression4)
26016             register_synthezier(synthesize_vovovoc_expression4)
26017             register_synthezier(synthesize_vovocov_expression4)
26018             register_synthezier(synthesize_vocovov_expression4)
26019             register_synthezier(synthesize_covovov_expression4)
26020             register_synthezier(synthesize_covocov_expression4)
26021             register_synthezier(synthesize_vocovoc_expression4)
26022             register_synthezier(synthesize_covovoc_expression4)
26023             #endif
26024          }
26025
26026          inline void set_parser(parser_t& p)
26027          {
26028             parser_ = &p;
26029          }
26030
26031          inline void set_uom(unary_op_map_t& unary_op_map)
26032          {
26033             unary_op_map_ = &unary_op_map;
26034          }
26035
26036          inline void set_bom(binary_op_map_t& binary_op_map)
26037          {
26038             binary_op_map_ = &binary_op_map;
26039          }
26040
26041          inline void set_ibom(inv_binary_op_map_t& inv_binary_op_map)
26042          {
26043             inv_binary_op_map_ = &inv_binary_op_map;
26044          }
26045
26046          inline void set_sf3m(sf3_map_t& sf3_map)
26047          {
26048             sf3_map_ = &sf3_map;
26049          }
26050
26051          inline void set_sf4m(sf4_map_t& sf4_map)
26052          {
26053             sf4_map_ = &sf4_map;
26054          }
26055
26056          inline void set_allocator(details::node_allocator& na)
26057          {
26058             node_allocator_ = &na;
26059          }
26060
26061          inline void set_strength_reduction_state(const bool enabled)
26062          {
26063             strength_reduction_enabled_ = enabled;
26064          }
26065
26066          inline bool strength_reduction_enabled() const
26067          {
26068             return strength_reduction_enabled_;
26069          }
26070
26071          inline bool valid_operator(const details::operator_type& operation, binary_functor_t& bop)
26072          {
26073             typename binary_op_map_t::iterator bop_itr = binary_op_map_->find(operation);
26074
26075             if ((*binary_op_map_).end() == bop_itr)
26076                return false;
26077
26078             bop = bop_itr->second;
26079
26080             return true;
26081          }
26082
26083          inline bool valid_operator(const details::operator_type& operation, unary_functor_t& uop)
26084          {
26085             typename unary_op_map_t::iterator uop_itr = unary_op_map_->find(operation);
26086
26087             if ((*unary_op_map_).end() == uop_itr)
26088                return false;
26089
26090             uop = uop_itr->second;
26091
26092             return true;
26093          }
26094
26095          inline details::operator_type get_operator(const binary_functor_t& bop) const
26096          {
26097             return (*inv_binary_op_map_).find(bop)->second;
26098          }
26099
26100          inline expression_node_ptr operator() (const Type& v) const
26101          {
26102             return node_allocator_->allocate<literal_node_t>(v);
26103          }
26104
26105          #ifndef exprtk_disable_string_capabilities
26106          inline expression_node_ptr operator() (const std::string& s) const
26107          {
26108             return node_allocator_->allocate<string_literal_node_t>(s);
26109          }
26110
26111          inline expression_node_ptr operator() (std::string& s, range_t& rp) const
26112          {
26113             return node_allocator_->allocate_rr<string_range_node_t>(s,rp);
26114          }
26115
26116          inline expression_node_ptr operator() (const std::string& s, range_t& rp) const
26117          {
26118             return node_allocator_->allocate_tt<const_string_range_node_t>(s,rp);
26119          }
26120
26121          inline expression_node_ptr operator() (expression_node_ptr branch, range_t& rp) const
26122          {
26123             if (is_generally_string_node(branch))
26124                return node_allocator_->allocate_tt<generic_string_range_node_t>(branch,rp);
26125             else
26126                return error_node();
26127          }
26128          #endif
26129
26130          inline bool unary_optimisable(const details::operator_type& operation) const
26131          {
26132             return (details::e_abs   == operation) || (details::e_acos  == operation) ||
26133                    (details::e_acosh == operation) || (details::e_asin  == operation) ||
26134                    (details::e_asinh == operation) || (details::e_atan  == operation) ||
26135                    (details::e_atanh == operation) || (details::e_ceil  == operation) ||
26136                    (details::e_cos   == operation) || (details::e_cosh  == operation) ||
26137                    (details::e_exp   == operation) || (details::e_expm1 == operation) ||
26138                    (details::e_floor == operation) || (details::e_log   == operation) ||
26139                    (details::e_log10 == operation) || (details::e_log2  == operation) ||
26140                    (details::e_log1p == operation) || (details::e_neg   == operation) ||
26141                    (details::e_pos   == operation) || (details::e_round == operation) ||
26142                    (details::e_sin   == operation) || (details::e_sinc  == operation) ||
26143                    (details::e_sinh  == operation) || (details::e_sqrt  == operation) ||
26144                    (details::e_tan   == operation) || (details::e_tanh  == operation) ||
26145                    (details::e_cot   == operation) || (details::e_sec   == operation) ||
26146                    (details::e_csc   == operation) || (details::e_r2d   == operation) ||
26147                    (details::e_d2r   == operation) || (details::e_d2g   == operation) ||
26148                    (details::e_g2d   == operation) || (details::e_notl  == operation) ||
26149                    (details::e_sgn   == operation) || (details::e_erf   == operation) ||
26150                    (details::e_erfc  == operation) || (details::e_ncdf  == operation) ||
26151                    (details::e_frac  == operation) || (details::e_trunc == operation) ;
26152          }
26153
26154          inline bool sf3_optimisable(const std::string& sf3id, trinary_functor_t& tfunc) const
26155          {
26156             typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id);
26157
26158             if (sf3_map_->end() == itr)
26159                return false;
26160             else
26161                tfunc = itr->second.first;
26162
26163             return true;
26164          }
26165
26166          inline bool sf4_optimisable(const std::string& sf4id, quaternary_functor_t& qfunc) const
26167          {
26168             typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id);
26169
26170             if (sf4_map_->end() == itr)
26171                return false;
26172             else
26173                qfunc = itr->second.first;
26174
26175             return true;
26176          }
26177
26178          inline bool sf3_optimisable(const std::string& sf3id, details::operator_type& operation) const
26179          {
26180             typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id);
26181
26182             if (sf3_map_->end() == itr)
26183                return false;
26184             else
26185                operation = itr->second.second;
26186
26187             return true;
26188          }
26189
26190          inline bool sf4_optimisable(const std::string& sf4id, details::operator_type& operation) const
26191          {
26192             typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id);
26193
26194             if (sf4_map_->end() == itr)
26195                return false;
26196             else
26197                operation = itr->second.second;
26198
26199             return true;
26200          }
26201
26202          inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[1])
26203          {
26204             if (0 == branch[0])
26205             {
26206                return error_node();
26207             }
26208             else if (details::is_null_node(branch[0]))
26209             {
26210                return branch[0];
26211             }
26212             else if (details::is_break_node(branch[0]))
26213             {
26214                return error_node();
26215             }
26216             else if (details::is_continue_node(branch[0]))
26217             {
26218                return error_node();
26219             }
26220             else if (details::is_constant_node(branch[0]))
26221             {
26222                return synthesize_expression<unary_node_t,1>(operation,branch);
26223             }
26224             else if (unary_optimisable(operation) && details::is_variable_node(branch[0]))
26225             {
26226                return synthesize_uv_expression(operation,branch);
26227             }
26228             else if (unary_optimisable(operation) && details::is_ivector_node(branch[0]))
26229             {
26230                return synthesize_uvec_expression(operation,branch);
26231             }
26232             else
26233                return synthesize_unary_expression(operation,branch);
26234          }
26235
26236          inline bool is_assignment_operation(const details::operator_type& operation) const
26237          {
26238             return (
26239                      (details::e_addass == operation) ||
26240                      (details::e_subass == operation) ||
26241                      (details::e_mulass == operation) ||
26242                      (details::e_divass == operation) ||
26243                      (details::e_modass == operation)
26244                    ) &&
26245                    parser_->settings_.assignment_enabled(operation);
26246          }
26247
26248          #ifndef exprtk_disable_string_capabilities
26249          inline bool valid_string_operation(const details::operator_type& operation) const
26250          {
26251             return (details::e_add    == operation) ||
26252                    (details::e_lt     == operation) ||
26253                    (details::e_lte    == operation) ||
26254                    (details::e_gt     == operation) ||
26255                    (details::e_gte    == operation) ||
26256                    (details::e_eq     == operation) ||
26257                    (details::e_ne     == operation) ||
26258                    (details::e_in     == operation) ||
26259                    (details::e_like   == operation) ||
26260                    (details::e_ilike  == operation) ||
26261                    (details::e_assign == operation) ||
26262                    (details::e_addass == operation) ||
26263                    (details::e_swap   == operation) ;
26264          }
26265          #else
26266          inline bool valid_string_operation(const details::operator_type&) const
26267          {
26268             return false;
26269          }
26270          #endif
26271
26272          inline std::string to_str(const details::operator_type& operation) const
26273          {
26274             switch (operation)
26275             {
26276                case details::e_add  : return "+"      ;
26277                case details::e_sub  : return "-"      ;
26278                case details::e_mul  : return "*"      ;
26279                case details::e_div  : return "/"      ;
26280                case details::e_mod  : return "%"      ;
26281                case details::e_pow  : return "^"      ;
26282                case details::e_lt   : return "<"      ;
26283                case details::e_lte  : return "<="     ;
26284                case details::e_gt   : return ">"      ;
26285                case details::e_gte  : return ">="     ;
26286                case details::e_eq   : return "=="     ;
26287                case details::e_ne   : return "!="     ;
26288                case details::e_and  : return "and"    ;
26289                case details::e_nand : return "nand"   ;
26290                case details::e_or   : return "or"     ;
26291                case details::e_nor  : return "nor"    ;
26292                case details::e_xor  : return "xor"    ;
26293                case details::e_xnor : return "xnor"   ;
26294                default              : return "UNKNOWN";
26295             }
26296          }
26297
26298          inline bool operation_optimisable(const details::operator_type& operation) const
26299          {
26300             return (details::e_add  == operation) ||
26301                    (details::e_sub  == operation) ||
26302                    (details::e_mul  == operation) ||
26303                    (details::e_div  == operation) ||
26304                    (details::e_mod  == operation) ||
26305                    (details::e_pow  == operation) ||
26306                    (details::e_lt   == operation) ||
26307                    (details::e_lte  == operation) ||
26308                    (details::e_gt   == operation) ||
26309                    (details::e_gte  == operation) ||
26310                    (details::e_eq   == operation) ||
26311                    (details::e_ne   == operation) ||
26312                    (details::e_and  == operation) ||
26313                    (details::e_nand == operation) ||
26314                    (details::e_or   == operation) ||
26315                    (details::e_nor  == operation) ||
26316                    (details::e_xor  == operation) ||
26317                    (details::e_xnor == operation) ;
26318          }
26319
26320          inline std::string branch_to_id(expression_node_ptr branch) const
26321          {
26322             static const std::string null_str   ("(null)" );
26323             static const std::string const_str  ("(c)"    );
26324             static const std::string var_str    ("(v)"    );
26325             static const std::string vov_str    ("(vov)"  );
26326             static const std::string cov_str    ("(cov)"  );
26327             static const std::string voc_str    ("(voc)"  );
26328             static const std::string str_str    ("(s)"    );
26329             static const std::string strrng_str ("(rngs)" );
26330             static const std::string cs_str     ("(cs)"   );
26331             static const std::string cstrrng_str("(crngs)");
26332
26333             if (details::is_null_node(branch))
26334                return null_str;
26335             else if (details::is_constant_node(branch))
26336                return const_str;
26337             else if (details::is_variable_node(branch))
26338                return var_str;
26339             else if (details::is_vov_node(branch))
26340                return vov_str;
26341             else if (details::is_cov_node(branch))
26342                return cov_str;
26343             else if (details::is_voc_node(branch))
26344                return voc_str;
26345             else if (details::is_string_node(branch))
26346                return str_str;
26347             else if (details::is_const_string_node(branch))
26348                return cs_str;
26349             else if (details::is_string_range_node(branch))
26350                return strrng_str;
26351             else if (details::is_const_string_range_node(branch))
26352                return cstrrng_str;
26353             else if (details::is_t0ot1ot2_node(branch))
26354                return "(" + dynamic_cast<details::T0oT1oT2_base_node<T>*>(branch)->type_id() + ")";
26355             else if (details::is_t0ot1ot2ot3_node(branch))
26356                return "(" + dynamic_cast<details::T0oT1oT2oT3_base_node<T>*>(branch)->type_id() + ")";
26357             else
26358                return "ERROR";
26359          }
26360
26361          inline std::string branch_to_id(expression_node_ptr (&branch)[2]) const
26362          {
26363             return branch_to_id(branch[0]) + std::string("o") + branch_to_id(branch[1]);
26364          }
26365
26366          inline bool cov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26367          {
26368             if (!operation_optimisable(operation))
26369                return false;
26370             else
26371                return details::is_constant_node(branch[0]) &&
26372                       details::is_variable_node(branch[1]) ;
26373          }
26374
26375          inline bool voc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26376          {
26377             if (!operation_optimisable(operation))
26378                return false;
26379             else
26380                return details::is_variable_node(branch[0]) &&
26381                       details::is_constant_node(branch[1]) ;
26382          }
26383
26384          inline bool vov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26385          {
26386             if (!operation_optimisable(operation))
26387                return false;
26388             else
26389                return details::is_variable_node(branch[0]) &&
26390                       details::is_variable_node(branch[1]) ;
26391          }
26392
26393          inline bool cob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26394          {
26395             if (!operation_optimisable(operation))
26396                return false;
26397             else
26398                return details::is_constant_node(branch[0]) &&
26399                      !details::is_constant_node(branch[1]) ;
26400          }
26401
26402          inline bool boc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26403          {
26404             if (!operation_optimisable(operation))
26405                return false;
26406             else
26407                return !details::is_constant_node(branch[0]) &&
26408                        details::is_constant_node(branch[1]) ;
26409          }
26410
26411          inline bool cocob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26412          {
26413             if (
26414                  (details::e_add == operation) ||
26415                  (details::e_sub == operation) ||
26416                  (details::e_mul == operation) ||
26417                  (details::e_div == operation)
26418                )
26419             {
26420                return (details::is_constant_node(branch[0]) && details::is_cob_node(branch[1])) ||
26421                       (details::is_constant_node(branch[1]) && details::is_cob_node(branch[0])) ;
26422             }
26423             else
26424                return false;
26425          }
26426
26427          inline bool coboc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26428          {
26429             if (
26430                  (details::e_add == operation) ||
26431                  (details::e_sub == operation) ||
26432                  (details::e_mul == operation) ||
26433                  (details::e_div == operation)
26434                )
26435             {
26436                return (details::is_constant_node(branch[0]) && details::is_boc_node(branch[1])) ||
26437                       (details::is_constant_node(branch[1]) && details::is_boc_node(branch[0])) ;
26438             }
26439             else
26440                return false;
26441          }
26442
26443          inline bool uvouv_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26444          {
26445             if (!operation_optimisable(operation))
26446                return false;
26447             else
26448                return details::is_uv_node(branch[0]) &&
26449                       details::is_uv_node(branch[1]) ;
26450          }
26451
26452          inline bool vob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26453          {
26454             if (!operation_optimisable(operation))
26455                return false;
26456             else
26457                return details::is_variable_node(branch[0]) &&
26458                      !details::is_variable_node(branch[1]) ;
26459          }
26460
26461          inline bool bov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26462          {
26463             if (!operation_optimisable(operation))
26464                return false;
26465             else
26466                return !details::is_variable_node(branch[0]) &&
26467                        details::is_variable_node(branch[1]) ;
26468          }
26469
26470          inline bool binext_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26471          {
26472             if (!operation_optimisable(operation))
26473                return false;
26474             else
26475                return !details::is_constant_node(branch[0]) ||
26476                       !details::is_constant_node(branch[1]) ;
26477          }
26478
26479          inline bool is_invalid_assignment_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26480          {
26481             if (is_assignment_operation(operation))
26482             {
26483                const bool b1_is_genstring = details::is_generally_string_node(branch[1]);
26484
26485                if (details::is_string_node(branch[0]))
26486                   return !b1_is_genstring;
26487                else
26488                   return (
26489                            !details::is_variable_node          (branch[0]) &&
26490                            !details::is_vector_elem_node       (branch[0]) &&
26491                            !details::is_rebasevector_elem_node (branch[0]) &&
26492                            !details::is_rebasevector_celem_node(branch[0]) &&
26493                            !details::is_vector_node            (branch[0])
26494                          )
26495                          || b1_is_genstring;
26496             }
26497             else
26498                return false;
26499          }
26500
26501          inline bool is_constpow_operation(const details::operator_type& operation, expression_node_ptr(&branch)[2]) const
26502          {
26503             if (
26504                  !details::is_constant_node(branch[1]) ||
26505                   details::is_constant_node(branch[0]) ||
26506                   details::is_variable_node(branch[0]) ||
26507                   details::is_vector_node  (branch[0]) ||
26508                   details::is_generally_string_node(branch[0])
26509                )
26510                return false;
26511
26512             const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
26513
26514             return cardinal_pow_optimisable(operation, c);
26515          }
26516
26517          inline bool is_invalid_break_continue_op(expression_node_ptr (&branch)[2]) const
26518          {
26519             return (
26520                      details::is_break_node   (branch[0]) ||
26521                      details::is_break_node   (branch[1]) ||
26522                      details::is_continue_node(branch[0]) ||
26523                      details::is_continue_node(branch[1])
26524                    );
26525          }
26526
26527          inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26528          {
26529             const bool b0_string = is_generally_string_node(branch[0]);
26530             const bool b1_string = is_generally_string_node(branch[1]);
26531
26532             bool result = false;
26533
26534             if (b0_string != b1_string)
26535                result = true;
26536             else if (!valid_string_operation(operation) && b0_string && b1_string)
26537                result = true;
26538
26539             if (result)
26540             {
26541                parser_->set_synthesis_error("Invalid string operation");
26542             }
26543
26544             return result;
26545          }
26546
26547          inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[3]) const
26548          {
26549             const bool b0_string = is_generally_string_node(branch[0]);
26550             const bool b1_string = is_generally_string_node(branch[1]);
26551             const bool b2_string = is_generally_string_node(branch[2]);
26552
26553             bool result = false;
26554
26555             if ((b0_string != b1_string) || (b1_string != b2_string))
26556                result = true;
26557             else if ((details::e_inrange != operation) && b0_string && b1_string && b2_string)
26558                result = true;
26559
26560             if (result)
26561             {
26562                parser_->set_synthesis_error("Invalid string operation");
26563             }
26564
26565             return result;
26566          }
26567
26568          inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26569          {
26570             const bool b0_string = is_generally_string_node(branch[0]);
26571             const bool b1_string = is_generally_string_node(branch[1]);
26572
26573             return (b0_string && b1_string && valid_string_operation(operation));
26574          }
26575
26576          inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[3]) const
26577          {
26578             const bool b0_string = is_generally_string_node(branch[0]);
26579             const bool b1_string = is_generally_string_node(branch[1]);
26580             const bool b2_string = is_generally_string_node(branch[2]);
26581
26582             return (b0_string && b1_string && b2_string && (details::e_inrange == operation));
26583          }
26584
26585          #ifndef exprtk_disable_sc_andor
26586          inline bool is_shortcircuit_expression(const details::operator_type& operation) const
26587          {
26588             return (
26589                      (details::e_scand == operation) ||
26590                      (details::e_scor  == operation)
26591                    );
26592          }
26593          #else
26594          inline bool is_shortcircuit_expression(const details::operator_type&) const
26595          {
26596             return false;
26597          }
26598          #endif
26599
26600          inline bool is_null_present(expression_node_ptr (&branch)[2]) const
26601          {
26602             return (
26603                      details::is_null_node(branch[0]) ||
26604                      details::is_null_node(branch[1])
26605                    );
26606          }
26607
26608          inline bool is_vector_eqineq_logic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26609          {
26610             if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1]))
26611                return false;
26612             else
26613                return (
26614                         (details::e_lt    == operation) ||
26615                         (details::e_lte   == operation) ||
26616                         (details::e_gt    == operation) ||
26617                         (details::e_gte   == operation) ||
26618                         (details::e_eq    == operation) ||
26619                         (details::e_ne    == operation) ||
26620                         (details::e_equal == operation) ||
26621                         (details::e_and   == operation) ||
26622                         (details::e_nand  == operation) ||
26623                         (details::  e_or  == operation) ||
26624                         (details:: e_nor  == operation) ||
26625                         (details:: e_xor  == operation) ||
26626                         (details::e_xnor  == operation)
26627                       );
26628          }
26629
26630          inline bool is_vector_arithmetic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26631          {
26632             if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1]))
26633                return false;
26634             else
26635                return (
26636                         (details::e_add == operation) ||
26637                         (details::e_sub == operation) ||
26638                         (details::e_mul == operation) ||
26639                         (details::e_div == operation) ||
26640                         (details::e_pow == operation)
26641                       );
26642          }
26643
26644          inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[2])
26645          {
26646             if ((0 == branch[0]) || (0 == branch[1]))
26647             {
26648                return error_node();
26649             }
26650             else if (is_invalid_string_op(operation,branch))
26651             {
26652                return error_node();
26653             }
26654             else if (is_invalid_assignment_op(operation,branch))
26655             {
26656                return error_node();
26657             }
26658             else if (is_invalid_break_continue_op(branch))
26659             {
26660                return error_node();
26661             }
26662             else if (details::e_assign == operation)
26663             {
26664                return synthesize_assignment_expression(operation, branch);
26665             }
26666             else if (details::e_swap == operation)
26667             {
26668                return synthesize_swap_expression(branch);
26669             }
26670             else if (is_assignment_operation(operation))
26671             {
26672                return synthesize_assignment_operation_expression(operation, branch);
26673             }
26674             else if (is_vector_eqineq_logic_operation(operation, branch))
26675             {
26676                return synthesize_veceqineqlogic_operation_expression(operation, branch);
26677             }
26678             else if (is_vector_arithmetic_operation(operation, branch))
26679             {
26680                return synthesize_vecarithmetic_operation_expression(operation, branch);
26681             }
26682             else if (is_shortcircuit_expression(operation))
26683             {
26684                return synthesize_shortcircuit_expression(operation, branch);
26685             }
26686             else if (is_string_operation(operation, branch))
26687             {
26688                return synthesize_string_expression(operation, branch);
26689             }
26690             else if (is_null_present(branch))
26691             {
26692                return synthesize_null_expression(operation, branch);
26693             }
26694             #ifndef exprtk_disable_cardinal_pow_optimisation
26695             else if (is_constpow_operation(operation, branch))
26696             {
26697                return cardinal_pow_optimisation(branch);
26698             }
26699             #endif
26700
26701             expression_node_ptr result = error_node();
26702
26703             #ifndef exprtk_disable_enhanced_features
26704             if (synthesize_expression(operation, branch, result))
26705             {
26706                return result;
26707             }
26708             else
26709             #endif
26710
26711             {
26712                /*
26713                   Possible reductions:
26714                   1. c o cob -> cob
26715                   2. cob o c -> cob
26716                   3. c o boc -> boc
26717                   4. boc o c -> boc
26718                */
26719                result = error_node();
26720
26721                if (cocob_optimisable(operation, branch))
26722                {
26723                   result = synthesize_cocob_expression::process((*this), operation, branch);
26724                }
26725                else if (coboc_optimisable(operation, branch) && (0 == result))
26726                {
26727                   result = synthesize_coboc_expression::process((*this), operation, branch);
26728                }
26729
26730                if (result)
26731                   return result;
26732             }
26733
26734             if (uvouv_optimisable(operation, branch))
26735             {
26736                return synthesize_uvouv_expression(operation, branch);
26737             }
26738             else if (vob_optimisable(operation, branch))
26739             {
26740                return synthesize_vob_expression::process((*this), operation, branch);
26741             }
26742             else if (bov_optimisable(operation, branch))
26743             {
26744                return synthesize_bov_expression::process((*this), operation, branch);
26745             }
26746             else if (cob_optimisable(operation, branch))
26747             {
26748                return synthesize_cob_expression::process((*this), operation, branch);
26749             }
26750             else if (boc_optimisable(operation, branch))
26751             {
26752                return synthesize_boc_expression::process((*this), operation, branch);
26753             }
26754             #ifndef exprtk_disable_enhanced_features
26755             else if (cov_optimisable(operation, branch))
26756             {
26757                return synthesize_cov_expression::process((*this), operation, branch);
26758             }
26759             #endif
26760             else if (binext_optimisable(operation, branch))
26761             {
26762                return synthesize_binary_ext_expression::process((*this), operation, branch);
26763             }
26764             else
26765                return synthesize_expression<binary_node_t,2>(operation, branch);
26766          }
26767
26768          inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[3])
26769          {
26770             if (
26771                  (0 == branch[0]) ||
26772                  (0 == branch[1]) ||
26773                  (0 == branch[2])
26774                )
26775             {
26776                details::free_all_nodes(*node_allocator_,branch);
26777
26778                return error_node();
26779             }
26780             else if (is_invalid_string_op(operation, branch))
26781             {
26782                return error_node();
26783             }
26784             else if (is_string_operation(operation, branch))
26785             {
26786                return synthesize_string_expression(operation, branch);
26787             }
26788             else
26789                return synthesize_expression<trinary_node_t,3>(operation, branch);
26790          }
26791
26792          inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[4])
26793          {
26794             return synthesize_expression<quaternary_node_t,4>(operation,branch);
26795          }
26796
26797          inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr b0)
26798          {
26799             expression_node_ptr branch[1] = { b0 };
26800             return (*this)(operation,branch);
26801          }
26802
26803          inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr& b0, expression_node_ptr& b1)
26804          {
26805             expression_node_ptr result = error_node();
26806
26807             if ((0 != b0) && (0 != b1))
26808             {
26809                expression_node_ptr branch[2] = { b0, b1 };
26810                result = expression_generator<Type>::operator()(operation, branch);
26811                b0 = branch[0];
26812                b1 = branch[1];
26813             }
26814
26815             return result;
26816          }
26817
26818          inline expression_node_ptr conditional(expression_node_ptr condition,
26819                                                 expression_node_ptr consequent,
26820                                                 expression_node_ptr alternative) const
26821          {
26822             if ((0 == condition) || (0 == consequent))
26823             {
26824                free_node(*node_allocator_,   condition);
26825                free_node(*node_allocator_,  consequent);
26826                free_node(*node_allocator_, alternative);
26827
26828                return error_node();
26829             }
26830             // Can the condition be immediately evaluated? if so optimise.
26831             else if (details::is_constant_node(condition))
26832             {
26833                // True branch
26834                if (details::is_true(condition))
26835                {
26836                   free_node(*node_allocator_,   condition);
26837                   free_node(*node_allocator_, alternative);
26838
26839                   return consequent;
26840                }
26841                // False branch
26842                else
26843                {
26844                   free_node(*node_allocator_,  condition);
26845                   free_node(*node_allocator_, consequent);
26846
26847                   if (alternative)
26848                      return alternative;
26849                   else
26850                      return node_allocator_->allocate<details::null_node<T> >();
26851                }
26852             }
26853             else if ((0 != consequent) && (0 != alternative))
26854             {
26855                return node_allocator_->
26856                         allocate<conditional_node_t>(condition, consequent, alternative);
26857             }
26858             else
26859                return node_allocator_->
26860                         allocate<cons_conditional_node_t>(condition, consequent);
26861          }
26862
26863          #ifndef exprtk_disable_string_capabilities
26864          inline expression_node_ptr conditional_string(expression_node_ptr condition,
26865                                                        expression_node_ptr consequent,
26866                                                        expression_node_ptr alternative) const
26867          {
26868             if ((0 == condition) || (0 == consequent))
26869             {
26870                free_node(*node_allocator_,   condition);
26871                free_node(*node_allocator_,  consequent);
26872                free_node(*node_allocator_, alternative);
26873
26874                return error_node();
26875             }
26876             // Can the condition be immediately evaluated? if so optimise.
26877             else if (details::is_constant_node(condition))
26878             {
26879                // True branch
26880                if (details::is_true(condition))
26881                {
26882                   free_node(*node_allocator_,   condition);
26883                   free_node(*node_allocator_, alternative);
26884
26885                   return consequent;
26886                }
26887                // False branch
26888                else
26889                {
26890                   free_node(*node_allocator_,  condition);
26891                   free_node(*node_allocator_, consequent);
26892
26893                   if (alternative)
26894                      return alternative;
26895                   else
26896                      return node_allocator_->
26897                               allocate_c<details::string_literal_node<Type> >("");
26898                }
26899             }
26900             else if ((0 != consequent) && (0 != alternative))
26901                return node_allocator_->
26902                         allocate<conditional_string_node_t>(condition, consequent, alternative);
26903             else
26904                return error_node();
26905          }
26906          #else
26907          inline expression_node_ptr conditional_string(expression_node_ptr,
26908                                                        expression_node_ptr,
26909                                                        expression_node_ptr) const
26910          {
26911             return error_node();
26912          }
26913          #endif
26914
26915          inline expression_node_ptr while_loop(expression_node_ptr& condition,
26916                                                expression_node_ptr& branch,
26917                                                const bool brkcont = false) const
26918          {
26919             if (!brkcont && details::is_constant_node(condition))
26920             {
26921                expression_node_ptr result = error_node();
26922                if (details::is_true(condition))
26923                   // Infinite loops are not allowed.
26924                   result = error_node();
26925                else
26926                   result = node_allocator_->allocate<details::null_node<Type> >();
26927
26928                free_node(*node_allocator_, condition);
26929                free_node(*node_allocator_,    branch);
26930
26931                return result;
26932             }
26933             else if (details::is_null_node(condition))
26934             {
26935                free_node(*node_allocator_,condition);
26936
26937                return branch;
26938             }
26939             else if (!brkcont)
26940                return node_allocator_->allocate<while_loop_node_t>(condition,branch);
26941             #ifndef exprtk_disable_break_continue
26942             else
26943                return node_allocator_->allocate<while_loop_bc_node_t>(condition,branch);
26944             #else
26945                return error_node();
26946             #endif
26947          }
26948
26949          inline expression_node_ptr repeat_until_loop(expression_node_ptr& condition,
26950                                                       expression_node_ptr& branch,
26951                                                       const bool brkcont = false) const
26952          {
26953             if (!brkcont && details::is_constant_node(condition))
26954             {
26955                if (
26956                     details::is_true(condition) &&
26957                     details::is_constant_node(branch)
26958                   )
26959                {
26960                   free_node(*node_allocator_,condition);
26961
26962                   return branch;
26963                }
26964
26965                free_node(*node_allocator_, condition);
26966                free_node(*node_allocator_,    branch);
26967
26968                return error_node();
26969             }
26970             else if (details::is_null_node(condition))
26971             {
26972                free_node(*node_allocator_,condition);
26973
26974                return branch;
26975             }
26976             else if (!brkcont)
26977                return node_allocator_->allocate<repeat_until_loop_node_t>(condition,branch);
26978             #ifndef exprtk_disable_break_continue
26979             else
26980                return node_allocator_->allocate<repeat_until_loop_bc_node_t>(condition,branch);
26981             #else
26982                return error_node();
26983             #endif
26984          }
26985
26986          inline expression_node_ptr for_loop(expression_node_ptr& initialiser,
26987                                              expression_node_ptr& condition,
26988                                              expression_node_ptr& incrementor,
26989                                              expression_node_ptr& loop_body,
26990                                              bool brkcont = false) const
26991          {
26992             if (!brkcont && details::is_constant_node(condition))
26993             {
26994                expression_node_ptr result = error_node();
26995
26996                if (details::is_true(condition))
26997                   // Infinite loops are not allowed.
26998                   result = error_node();
26999                else
27000                   result = node_allocator_->allocate<details::null_node<Type> >();
27001
27002                free_node(*node_allocator_, initialiser);
27003                free_node(*node_allocator_,   condition);
27004                free_node(*node_allocator_, incrementor);
27005                free_node(*node_allocator_,   loop_body);
27006
27007                return result;
27008             }
27009             else if (details::is_null_node(condition) || (0 == condition))
27010             {
27011                free_node(*node_allocator_, initialiser);
27012                free_node(*node_allocator_,   condition);
27013                free_node(*node_allocator_, incrementor);
27014
27015                return loop_body;
27016             }
27017             else if (!brkcont)
27018                return node_allocator_->allocate<for_loop_node_t>
27019                                        (
27020                                          initialiser,
27021                                          condition,
27022                                          incrementor,
27023                                          loop_body
27024                                        );
27025
27026             #ifndef exprtk_disable_break_continue
27027             else
27028                return node_allocator_->allocate<for_loop_bc_node_t>
27029                                        (
27030                                          initialiser,
27031                                          condition,
27032                                          incrementor,
27033                                          loop_body
27034                                        );
27035             #else
27036             return error_node();
27037             #endif
27038          }
27039
27040          template <typename Allocator,
27041                    template <typename, typename> class Sequence>
27042          inline expression_node_ptr const_optimise_switch(Sequence<expression_node_ptr,Allocator>& arg_list)
27043          {
27044             expression_node_ptr result = error_node();
27045
27046             for (std::size_t i = 0; i < (arg_list.size() / 2); ++i)
27047             {
27048                expression_node_ptr condition  = arg_list[(2 * i)    ];
27049                expression_node_ptr consequent = arg_list[(2 * i) + 1];
27050
27051                if ((0 == result) && details::is_true(condition))
27052                {
27053                   result = consequent;
27054                   break;
27055                }
27056             }
27057
27058             if (0 == result)
27059             {
27060                result = arg_list.back();
27061             }
27062
27063             for (std::size_t i = 0; i < arg_list.size(); ++i)
27064             {
27065                expression_node_ptr current_expr = arg_list[i];
27066
27067                if (current_expr && (current_expr != result))
27068                {
27069                   free_node(*node_allocator_,current_expr);
27070                }
27071             }
27072
27073             return result;
27074          }
27075
27076          template <typename Allocator,
27077                    template <typename, typename> class Sequence>
27078          inline expression_node_ptr const_optimise_mswitch(Sequence<expression_node_ptr,Allocator>& arg_list)
27079          {
27080             expression_node_ptr result = error_node();
27081
27082             for (std::size_t i = 0; i < (arg_list.size() / 2); ++i)
27083             {
27084                expression_node_ptr condition  = arg_list[(2 * i)    ];
27085                expression_node_ptr consequent = arg_list[(2 * i) + 1];
27086
27087                if (details::is_true(condition))
27088                {
27089                   result = consequent;
27090                }
27091             }
27092
27093             if (0 == result)
27094             {
27095                T zero = T(0);
27096                result = node_allocator_->allocate<literal_node_t>(zero);
27097             }
27098
27099             for (std::size_t i = 0; i < arg_list.size(); ++i)
27100             {
27101                expression_node_ptr& current_expr = arg_list[i];
27102
27103                if (current_expr && (current_expr != result))
27104                {
27105                   free_node(*node_allocator_,current_expr);
27106                }
27107             }
27108
27109             return result;
27110          }
27111
27112          struct switch_nodes
27113          {
27114             typedef std::vector<expression_node_ptr> arg_list_t;
27115
27116             #define case_stmt(N)                                             \
27117             if (is_true(arg[(2 * N)])) { return arg[(2 * N) + 1]->value(); } \
27118
27119             struct switch_1
27120             {
27121                static inline T process(const arg_list_t& arg)
27122                {
27123                   case_stmt(0)
27124
27125                   return arg.back()->value();
27126                }
27127             };
27128
27129             struct switch_2
27130             {
27131                static inline T process(const arg_list_t& arg)
27132                {
27133                   case_stmt(0) case_stmt(1)
27134
27135                   return arg.back()->value();
27136                }
27137             };
27138
27139             struct switch_3
27140             {
27141                static inline T process(const arg_list_t& arg)
27142                {
27143                   case_stmt(0) case_stmt(1)
27144                   case_stmt(2)
27145
27146                   return arg.back()->value();
27147                }
27148             };
27149
27150             struct switch_4
27151             {
27152                static inline T process(const arg_list_t& arg)
27153                {
27154                   case_stmt(0) case_stmt(1)
27155                   case_stmt(2) case_stmt(3)
27156
27157                   return arg.back()->value();
27158                }
27159             };
27160
27161             struct switch_5
27162             {
27163                static inline T process(const arg_list_t& arg)
27164                {
27165                   case_stmt(0) case_stmt(1)
27166                   case_stmt(2) case_stmt(3)
27167                   case_stmt(4)
27168
27169                   return arg.back()->value();
27170                }
27171             };
27172
27173             struct switch_6
27174             {
27175                static inline T process(const arg_list_t& arg)
27176                {
27177                   case_stmt(0) case_stmt(1)
27178                   case_stmt(2) case_stmt(3)
27179                   case_stmt(4) case_stmt(5)
27180
27181                   return arg.back()->value();
27182                }
27183             };
27184
27185             struct switch_7
27186             {
27187                static inline T process(const arg_list_t& arg)
27188                {
27189                   case_stmt(0) case_stmt(1)
27190                   case_stmt(2) case_stmt(3)
27191                   case_stmt(4) case_stmt(5)
27192                   case_stmt(6)
27193
27194                   return arg.back()->value();
27195                }
27196             };
27197
27198             #undef case_stmt
27199          };
27200
27201          template <typename Allocator,
27202                    template <typename, typename> class Sequence>
27203          inline expression_node_ptr switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list)
27204          {
27205             if (arg_list.empty())
27206                return error_node();
27207             else if (
27208                       !all_nodes_valid(arg_list)   ||
27209                       (arg_list.size() < 3)        ||
27210                       ((arg_list.size() % 2) != 1)
27211                     )
27212             {
27213                details::free_all_nodes(*node_allocator_,arg_list);
27214
27215                return error_node();
27216             }
27217             else if (is_constant_foldable(arg_list))
27218                return const_optimise_switch(arg_list);
27219
27220             switch ((arg_list.size() - 1) / 2)
27221             {
27222                #define case_stmt(N)                                                 \
27223                case N :                                                             \
27224                   return node_allocator_->                                          \
27225                             allocate<details::switch_n_node                         \
27226                               <Type,typename switch_nodes::switch_##N> >(arg_list); \
27227
27228                case_stmt(1)
27229                case_stmt(2)
27230                case_stmt(3)
27231                case_stmt(4)
27232                case_stmt(5)
27233                case_stmt(6)
27234                case_stmt(7)
27235                #undef case_stmt
27236
27237                default : return node_allocator_->allocate<details::switch_node<Type> >(arg_list);
27238             }
27239          }
27240
27241          template <typename Allocator,
27242                    template <typename, typename> class Sequence>
27243          inline expression_node_ptr multi_switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list)
27244          {
27245             if (!all_nodes_valid(arg_list))
27246             {
27247                details::free_all_nodes(*node_allocator_,arg_list);
27248
27249                return error_node();
27250             }
27251             else if (is_constant_foldable(arg_list))
27252                return const_optimise_mswitch(arg_list);
27253             else
27254                return node_allocator_->allocate<details::multi_switch_node<Type> >(arg_list);
27255          }
27256
27257          #define unary_opr_switch_statements            \
27258          case_stmt(details::  e_abs, details::  abs_op) \
27259          case_stmt(details:: e_acos, details:: acos_op) \
27260          case_stmt(details::e_acosh, details::acosh_op) \
27261          case_stmt(details:: e_asin, details:: asin_op) \
27262          case_stmt(details::e_asinh, details::asinh_op) \
27263          case_stmt(details:: e_atan, details:: atan_op) \
27264          case_stmt(details::e_atanh, details::atanh_op) \
27265          case_stmt(details:: e_ceil, details:: ceil_op) \
27266          case_stmt(details::  e_cos, details::  cos_op) \
27267          case_stmt(details:: e_cosh, details:: cosh_op) \
27268          case_stmt(details::  e_exp, details::  exp_op) \
27269          case_stmt(details::e_expm1, details::expm1_op) \
27270          case_stmt(details::e_floor, details::floor_op) \
27271          case_stmt(details::  e_log, details::  log_op) \
27272          case_stmt(details::e_log10, details::log10_op) \
27273          case_stmt(details:: e_log2, details:: log2_op) \
27274          case_stmt(details::e_log1p, details::log1p_op) \
27275          case_stmt(details::  e_neg, details::  neg_op) \
27276          case_stmt(details::  e_pos, details::  pos_op) \
27277          case_stmt(details::e_round, details::round_op) \
27278          case_stmt(details::  e_sin, details::  sin_op) \
27279          case_stmt(details:: e_sinc, details:: sinc_op) \
27280          case_stmt(details:: e_sinh, details:: sinh_op) \
27281          case_stmt(details:: e_sqrt, details:: sqrt_op) \
27282          case_stmt(details::  e_tan, details::  tan_op) \
27283          case_stmt(details:: e_tanh, details:: tanh_op) \
27284          case_stmt(details::  e_cot, details::  cot_op) \
27285          case_stmt(details::  e_sec, details::  sec_op) \
27286          case_stmt(details::  e_csc, details::  csc_op) \
27287          case_stmt(details::  e_r2d, details::  r2d_op) \
27288          case_stmt(details::  e_d2r, details::  d2r_op) \
27289          case_stmt(details::  e_d2g, details::  d2g_op) \
27290          case_stmt(details::  e_g2d, details::  g2d_op) \
27291          case_stmt(details:: e_notl, details:: notl_op) \
27292          case_stmt(details::  e_sgn, details::  sgn_op) \
27293          case_stmt(details::  e_erf, details::  erf_op) \
27294          case_stmt(details:: e_erfc, details:: erfc_op) \
27295          case_stmt(details:: e_ncdf, details:: ncdf_op) \
27296          case_stmt(details:: e_frac, details:: frac_op) \
27297          case_stmt(details::e_trunc, details::trunc_op) \
27298
27299          inline expression_node_ptr synthesize_uv_expression(const details::operator_type& operation,
27300                                                              expression_node_ptr (&branch)[1])
27301          {
27302             T& v = static_cast<details::variable_node<T>*>(branch[0])->ref();
27303
27304             switch (operation)
27305             {
27306                #define case_stmt(op0,op1)                                                          \
27307                case op0 : return node_allocator_->                                                 \
27308                              allocate<typename details::unary_variable_node<Type,op1<Type> > >(v); \
27309
27310                unary_opr_switch_statements
27311                #undef case_stmt
27312                default : return error_node();
27313             }
27314          }
27315
27316          inline expression_node_ptr synthesize_uvec_expression(const details::operator_type& operation,
27317                                                                expression_node_ptr (&branch)[1])
27318          {
27319             switch (operation)
27320             {
27321                #define case_stmt(op0,op1)                                                    \
27322                case op0 : return node_allocator_->                                           \
27323                              allocate<typename details::unary_vector_node<Type,op1<Type> > > \
27324                                 (operation, branch[0]);                                      \
27325
27326                unary_opr_switch_statements
27327                #undef case_stmt
27328                default : return error_node();
27329             }
27330          }
27331
27332          inline expression_node_ptr synthesize_unary_expression(const details::operator_type& operation,
27333                                                                 expression_node_ptr (&branch)[1])
27334          {
27335             switch (operation)
27336             {
27337                #define case_stmt(op0,op1)                                                                \
27338                case op0 : return node_allocator_->                                                       \
27339                              allocate<typename details::unary_branch_node<Type,op1<Type> > >(branch[0]); \
27340
27341                unary_opr_switch_statements
27342                #undef case_stmt
27343                default : return error_node();
27344             }
27345          }
27346
27347          inline expression_node_ptr const_optimise_sf3(const details::operator_type& operation,
27348                                                        expression_node_ptr (&branch)[3])
27349          {
27350             expression_node_ptr temp_node = error_node();
27351
27352             switch (operation)
27353             {
27354                #define case_stmt(op)                                                        \
27355                case details::e_sf##op : temp_node = node_allocator_->                       \
27356                              allocate<details::sf3_node<Type,details::sf##op##_op<Type> > > \
27357                                 (operation, branch);                                        \
27358                              break;                                                         \
27359
27360                case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
27361                case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
27362                case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
27363                case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
27364                case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
27365                case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
27366                case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
27367                case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31)
27368                case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35)
27369                case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39)
27370                case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43)
27371                case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47)
27372                #undef case_stmt
27373                default : return error_node();
27374             }
27375
27376             const T v = temp_node->value();
27377
27378             details::free_node(*node_allocator_,temp_node);
27379
27380             return node_allocator_->allocate<literal_node_t>(v);
27381          }
27382
27383          inline expression_node_ptr varnode_optimise_sf3(const details::operator_type& operation, expression_node_ptr (&branch)[3])
27384          {
27385             typedef details::variable_node<Type>* variable_ptr;
27386
27387             const Type& v0 = static_cast<variable_ptr>(branch[0])->ref();
27388             const Type& v1 = static_cast<variable_ptr>(branch[1])->ref();
27389             const Type& v2 = static_cast<variable_ptr>(branch[2])->ref();
27390
27391             switch (operation)
27392             {
27393                #define case_stmt(op)                                                                \
27394                case details::e_sf##op : return node_allocator_->                                    \
27395                              allocate_rrr<details::sf3_var_node<Type,details::sf##op##_op<Type> > > \
27396                                 (v0, v1, v2);                                                       \
27397
27398                case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
27399                case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
27400                case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
27401                case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
27402                case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
27403                case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
27404                case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
27405                case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31)
27406                case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35)
27407                case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39)
27408                case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43)
27409                case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47)
27410                #undef case_stmt
27411                default : return error_node();
27412             }
27413          }
27414
27415          inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[3])
27416          {
27417             if (!all_nodes_valid(branch))
27418                return error_node();
27419             else if (is_constant_foldable(branch))
27420                return const_optimise_sf3(operation,branch);
27421             else if (all_nodes_variables(branch))
27422                return varnode_optimise_sf3(operation,branch);
27423             else
27424             {
27425                switch (operation)
27426                {
27427                   #define case_stmt(op)                                                        \
27428                   case details::e_sf##op : return node_allocator_->                            \
27429                                 allocate<details::sf3_node<Type,details::sf##op##_op<Type> > > \
27430                                    (operation, branch);                                        \
27431
27432                   case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
27433                   case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
27434                   case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
27435                   case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
27436                   case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
27437                   case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
27438                   case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
27439                   case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31)
27440                   case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35)
27441                   case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39)
27442                   case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43)
27443                   case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47)
27444                   #undef case_stmt
27445                   default : return error_node();
27446                }
27447             }
27448          }
27449
27450          inline expression_node_ptr const_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4])
27451          {
27452             expression_node_ptr temp_node = error_node();
27453
27454             switch (operation)
27455             {
27456                #define case_stmt(op)                                                                    \
27457                case details::e_sf##op : temp_node = node_allocator_->                                   \
27458                                          allocate<details::sf4_node<Type,details::sf##op##_op<Type> > > \
27459                                             (operation, branch);                                        \
27460                                         break;                                                          \
27461
27462                case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51)
27463                case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55)
27464                case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59)
27465                case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63)
27466                case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67)
27467                case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71)
27468                case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75)
27469                case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79)
27470                case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83)
27471                case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87)
27472                case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91)
27473                case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95)
27474                case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99)
27475                #undef case_stmt
27476                default : return error_node();
27477             }
27478
27479             const T v = temp_node->value();
27480
27481             details::free_node(*node_allocator_,temp_node);
27482
27483             return node_allocator_->allocate<literal_node_t>(v);
27484          }
27485
27486          inline expression_node_ptr varnode_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4])
27487          {
27488             typedef details::variable_node<Type>* variable_ptr;
27489
27490             const Type& v0 = static_cast<variable_ptr>(branch[0])->ref();
27491             const Type& v1 = static_cast<variable_ptr>(branch[1])->ref();
27492             const Type& v2 = static_cast<variable_ptr>(branch[2])->ref();
27493             const Type& v3 = static_cast<variable_ptr>(branch[3])->ref();
27494
27495             switch (operation)
27496             {
27497                #define case_stmt(op)                                                                 \
27498                case details::e_sf##op : return node_allocator_->                                     \
27499                              allocate_rrrr<details::sf4_var_node<Type,details::sf##op##_op<Type> > > \
27500                                 (v0, v1, v2, v3);                                                    \
27501
27502                case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51)
27503                case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55)
27504                case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59)
27505                case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63)
27506                case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67)
27507                case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71)
27508                case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75)
27509                case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79)
27510                case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83)
27511                case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87)
27512                case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91)
27513                case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95)
27514                case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99)
27515                #undef case_stmt
27516                default : return error_node();
27517             }
27518          }
27519
27520          inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[4])
27521          {
27522             if (!all_nodes_valid(branch))
27523                return error_node();
27524             else if (is_constant_foldable(branch))
27525                return const_optimise_sf4(operation,branch);
27526             else if (all_nodes_variables(branch))
27527                return varnode_optimise_sf4(operation,branch);
27528             switch (operation)
27529             {
27530                #define case_stmt(op)                                                        \
27531                case details::e_sf##op : return node_allocator_->                            \
27532                              allocate<details::sf4_node<Type,details::sf##op##_op<Type> > > \
27533                                 (operation, branch);                                        \
27534
27535                case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51)
27536                case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55)
27537                case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59)
27538                case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63)
27539                case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67)
27540                case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71)
27541                case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75)
27542                case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79)
27543                case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83)
27544                case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87)
27545                case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91)
27546                case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95)
27547                case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99)
27548                #undef case_stmt
27549                default : return error_node();
27550             }
27551          }
27552
27553          template <typename Allocator,
27554                    template <typename, typename> class Sequence>
27555          inline expression_node_ptr const_optimise_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
27556          {
27557             expression_node_ptr temp_node = error_node();
27558
27559             switch (operation)
27560             {
27561                #define case_stmt(op0,op1)                                                 \
27562                case op0 : temp_node = node_allocator_->                                   \
27563                                          allocate<details::vararg_node<Type,op1<Type> > > \
27564                                             (arg_list);                                   \
27565                           break;                                                          \
27566
27567                case_stmt(details::e_sum   , details::vararg_add_op  )
27568                case_stmt(details::e_prod  , details::vararg_mul_op  )
27569                case_stmt(details::e_avg   , details::vararg_avg_op  )
27570                case_stmt(details::e_min   , details::vararg_min_op  )
27571                case_stmt(details::e_max   , details::vararg_max_op  )
27572                case_stmt(details::e_mand  , details::vararg_mand_op )
27573                case_stmt(details::e_mor   , details::vararg_mor_op  )
27574                case_stmt(details::e_multi , details::vararg_multi_op)
27575                #undef case_stmt
27576                default : return error_node();
27577             }
27578
27579             const T v = temp_node->value();
27580
27581             details::free_node(*node_allocator_,temp_node);
27582
27583             return node_allocator_->allocate<literal_node_t>(v);
27584          }
27585
27586          inline bool special_one_parameter_vararg(const details::operator_type& operation) const
27587          {
27588             return (
27589                      (details::e_sum  == operation) ||
27590                      (details::e_prod == operation) ||
27591                      (details::e_avg  == operation) ||
27592                      (details::e_min  == operation) ||
27593                      (details::e_max  == operation)
27594                    );
27595          }
27596
27597          template <typename Allocator,
27598                    template <typename, typename> class Sequence>
27599          inline expression_node_ptr varnode_optimise_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
27600          {
27601             switch (operation)
27602             {
27603                #define case_stmt(op0,op1)                                                   \
27604                case op0 : return node_allocator_->                                          \
27605                              allocate<details::vararg_varnode<Type,op1<Type> > >(arg_list); \
27606
27607                case_stmt(details::e_sum   , details::vararg_add_op  )
27608                case_stmt(details::e_prod  , details::vararg_mul_op  )
27609                case_stmt(details::e_avg   , details::vararg_avg_op  )
27610                case_stmt(details::e_min   , details::vararg_min_op  )
27611                case_stmt(details::e_max   , details::vararg_max_op  )
27612                case_stmt(details::e_mand  , details::vararg_mand_op )
27613                case_stmt(details::e_mor   , details::vararg_mor_op  )
27614                case_stmt(details::e_multi , details::vararg_multi_op)
27615                #undef case_stmt
27616                default : return error_node();
27617             }
27618          }
27619
27620          template <typename Allocator,
27621                    template <typename, typename> class Sequence>
27622          inline expression_node_ptr vectorize_func(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
27623          {
27624             if (1 == arg_list.size())
27625             {
27626                switch (operation)
27627                {
27628                   #define case_stmt(op0,op1)                                                      \
27629                   case op0 : return node_allocator_->                                             \
27630                                 allocate<details::vectorize_node<Type,op1<Type> > >(arg_list[0]); \
27631
27632                   case_stmt(details::e_sum  , details::vec_add_op)
27633                   case_stmt(details::e_prod , details::vec_mul_op)
27634                   case_stmt(details::e_avg  , details::vec_avg_op)
27635                   case_stmt(details::e_min  , details::vec_min_op)
27636                   case_stmt(details::e_max  , details::vec_max_op)
27637                   #undef case_stmt
27638                   default : return error_node();
27639                }
27640             }
27641             else
27642                return error_node();
27643          }
27644
27645          template <typename Allocator,
27646                    template <typename, typename> class Sequence>
27647          inline expression_node_ptr vararg_function(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
27648          {
27649             if (!all_nodes_valid(arg_list))
27650             {
27651                details::free_all_nodes(*node_allocator_,arg_list);
27652
27653                return error_node();
27654             }
27655             else if (is_constant_foldable(arg_list))
27656                return const_optimise_varargfunc(operation,arg_list);
27657             else if ((arg_list.size() == 1) && details::is_ivector_node(arg_list[0]))
27658                return vectorize_func(operation,arg_list);
27659             else if ((arg_list.size() == 1) && special_one_parameter_vararg(operation))
27660                return arg_list[0];
27661             else if (all_nodes_variables(arg_list))
27662                return varnode_optimise_varargfunc(operation,arg_list);
27663
27664             #ifndef exprtk_disable_string_capabilities
27665             if (details::e_smulti == operation)
27666             {
27667                return node_allocator_->
27668                  allocate<details::str_vararg_node<Type,details::vararg_multi_op<Type> > >(arg_list);
27669             }
27670             else
27671             #endif
27672             {
27673                switch (operation)
27674                {
27675                   #define case_stmt(op0,op1)                                                \
27676                   case op0 : return node_allocator_->                                       \
27677                                 allocate<details::vararg_node<Type,op1<Type> > >(arg_list); \
27678
27679                   case_stmt(details::e_sum   , details::vararg_add_op  )
27680                   case_stmt(details::e_prod  , details::vararg_mul_op  )
27681                   case_stmt(details::e_avg   , details::vararg_avg_op  )
27682                   case_stmt(details::e_min   , details::vararg_min_op  )
27683                   case_stmt(details::e_max   , details::vararg_max_op  )
27684                   case_stmt(details::e_mand  , details::vararg_mand_op )
27685                   case_stmt(details::e_mor   , details::vararg_mor_op  )
27686                   case_stmt(details::e_multi , details::vararg_multi_op)
27687                   #undef case_stmt
27688                   default : return error_node();
27689                }
27690             }
27691          }
27692
27693          template <std::size_t N>
27694          inline expression_node_ptr function(ifunction_t* f, expression_node_ptr (&b)[N])
27695          {
27696             typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t;
27697             expression_node_ptr result = synthesize_expression<function_N_node_t,N>(f,b);
27698
27699             if (0 == result)
27700                return error_node();
27701             else
27702             {
27703                // Can the function call be completely optimised?
27704                if (details::is_constant_node(result))
27705                   return result;
27706                else if (!all_nodes_valid(b))
27707                   return error_node();
27708                else if (N != f->param_count)
27709                {
27710                   details::free_all_nodes(*node_allocator_,b);
27711
27712                   return error_node();
27713                }
27714
27715                function_N_node_t* func_node_ptr = static_cast<function_N_node_t*>(result);
27716
27717                if (func_node_ptr->init_branches(b))
27718                   return result;
27719                else
27720                {
27721                   details::free_all_nodes(*node_allocator_,b);
27722
27723                   return error_node();
27724                }
27725             }
27726          }
27727
27728          inline expression_node_ptr function(ifunction_t* f)
27729          {
27730             typedef typename details::function_N_node<Type,ifunction_t,0> function_N_node_t;
27731             return node_allocator_->allocate<function_N_node_t>(f);
27732          }
27733
27734          inline expression_node_ptr vararg_function_call(ivararg_function_t* vaf,
27735                                                          std::vector<expression_node_ptr>& arg_list)
27736          {
27737             if (!all_nodes_valid(arg_list))
27738             {
27739                details::free_all_nodes(*node_allocator_,arg_list);
27740
27741                return error_node();
27742             }
27743
27744             typedef details::vararg_function_node<Type,ivararg_function_t> alloc_type;
27745
27746             expression_node_ptr result = node_allocator_->allocate<alloc_type>(vaf,arg_list);
27747
27748             if (
27749                  !arg_list.empty()        &&
27750                  !vaf->has_side_effects() &&
27751                  is_constant_foldable(arg_list)
27752                )
27753             {
27754                const Type v = result->value();
27755                details::free_node(*node_allocator_,result);
27756                result = node_allocator_->allocate<literal_node_t>(v);
27757             }
27758
27759             parser_->state_.activate_side_effect("vararg_function_call()");
27760
27761             return result;
27762          }
27763
27764          inline expression_node_ptr generic_function_call(igeneric_function_t* gf,
27765                                                           std::vector<expression_node_ptr>& arg_list,
27766                                                           const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max())
27767          {
27768             if (!all_nodes_valid(arg_list))
27769             {
27770                details::free_all_nodes(*node_allocator_,arg_list);
27771                return error_node();
27772             }
27773
27774             typedef details::generic_function_node     <Type,igeneric_function_t> alloc_type1;
27775             typedef details::multimode_genfunction_node<Type,igeneric_function_t> alloc_type2;
27776
27777             const std::size_t no_psi = std::numeric_limits<std::size_t>::max();
27778
27779             expression_node_ptr result = error_node();
27780
27781             if (no_psi == param_seq_index)
27782                result = node_allocator_->allocate<alloc_type1>(arg_list,gf);
27783             else
27784                result = node_allocator_->allocate<alloc_type2>(gf, param_seq_index, arg_list);
27785
27786             alloc_type1* genfunc_node_ptr = static_cast<alloc_type1*>(result);
27787
27788             if (
27789                  !arg_list.empty()                  &&
27790                  !gf->has_side_effects()            &&
27791                  parser_->state_.type_check_enabled &&
27792                  is_constant_foldable(arg_list)
27793                )
27794             {
27795                genfunc_node_ptr->init_branches();
27796
27797                const Type v = result->value();
27798
27799                details::free_node(*node_allocator_,result);
27800
27801                return node_allocator_->allocate<literal_node_t>(v);
27802             }
27803             else if (genfunc_node_ptr->init_branches())
27804             {
27805                parser_->state_.activate_side_effect("generic_function_call()");
27806
27807                return result;
27808             }
27809             else
27810             {
27811                details::free_node(*node_allocator_, result);
27812                details::free_all_nodes(*node_allocator_, arg_list);
27813
27814                return error_node();
27815             }
27816          }
27817
27818          #ifndef exprtk_disable_string_capabilities
27819          inline expression_node_ptr string_function_call(igeneric_function_t* gf,
27820                                                          std::vector<expression_node_ptr>& arg_list,
27821                                                          const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max())
27822          {
27823             if (!all_nodes_valid(arg_list))
27824             {
27825                details::free_all_nodes(*node_allocator_,arg_list);
27826                return error_node();
27827             }
27828
27829             typedef details::string_function_node      <Type,igeneric_function_t> alloc_type1;
27830             typedef details::multimode_strfunction_node<Type,igeneric_function_t> alloc_type2;
27831
27832             const std::size_t no_psi = std::numeric_limits<std::size_t>::max();
27833
27834             expression_node_ptr result = error_node();
27835
27836             if (no_psi == param_seq_index)
27837                result = node_allocator_->allocate<alloc_type1>(gf,arg_list);
27838             else
27839                result = node_allocator_->allocate<alloc_type2>(gf, param_seq_index, arg_list);
27840
27841             alloc_type1* strfunc_node_ptr = static_cast<alloc_type1*>(result);
27842
27843             if (
27844                  !arg_list.empty()       &&
27845                  !gf->has_side_effects() &&
27846                  is_constant_foldable(arg_list)
27847                )
27848             {
27849                strfunc_node_ptr->init_branches();
27850
27851                const Type v = result->value();
27852
27853                details::free_node(*node_allocator_,result);
27854
27855                return node_allocator_->allocate<literal_node_t>(v);
27856             }
27857             else if (strfunc_node_ptr->init_branches())
27858             {
27859                parser_->state_.activate_side_effect("string_function_call()");
27860
27861                return result;
27862             }
27863             else
27864             {
27865                details::free_node     (*node_allocator_,result  );
27866                details::free_all_nodes(*node_allocator_,arg_list);
27867
27868                return error_node();
27869             }
27870          }
27871          #endif
27872
27873          #ifndef exprtk_disable_return_statement
27874          inline expression_node_ptr return_call(std::vector<expression_node_ptr>& arg_list)
27875          {
27876             if (!all_nodes_valid(arg_list))
27877             {
27878                details::free_all_nodes(*node_allocator_,arg_list);
27879                return error_node();
27880             }
27881
27882             typedef details::return_node<Type> alloc_type;
27883
27884             expression_node_ptr result = node_allocator_->
27885                                             allocate_rr<alloc_type>(arg_list,parser_->results_ctx());
27886
27887             alloc_type* return_node_ptr = static_cast<alloc_type*>(result);
27888
27889             if (return_node_ptr->init_branches())
27890             {
27891                parser_->state_.activate_side_effect("return_call()");
27892
27893                return result;
27894             }
27895             else
27896             {
27897                details::free_node     (*node_allocator_,result  );
27898                details::free_all_nodes(*node_allocator_,arg_list);
27899
27900                return error_node();
27901             }
27902          }
27903
27904          inline expression_node_ptr return_envelope(expression_node_ptr body,
27905                                                     results_context_t* rc,
27906                                                     bool*& return_invoked)
27907          {
27908             typedef details::return_envelope_node<Type> alloc_type;
27909
27910             expression_node_ptr result = node_allocator_->
27911                                             allocate_cr<alloc_type>(body,(*rc));
27912
27913             return_invoked = static_cast<alloc_type*>(result)->retinvk_ptr();
27914
27915             return result;
27916          }
27917          #else
27918          inline expression_node_ptr return_call(std::vector<expression_node_ptr>&)
27919          {
27920             return error_node();
27921          }
27922
27923          inline expression_node_ptr return_envelope(expression_node_ptr,
27924                                                     results_context_t*,
27925                                                     bool*&)
27926          {
27927             return error_node();
27928          }
27929          #endif
27930
27931          inline expression_node_ptr vector_element(const std::string& symbol,
27932                                                    vector_holder_ptr vector_base,
27933                                                    expression_node_ptr index)
27934          {
27935             expression_node_ptr result = error_node();
27936
27937             if (details::is_constant_node(index))
27938             {
27939                std::size_t i = static_cast<std::size_t>(details::numeric::to_int64(index->value()));
27940
27941                details::free_node(*node_allocator_,index);
27942
27943                if (vector_base->rebaseable())
27944                {
27945                   return node_allocator_->allocate<rebasevector_celem_node_t>(i,vector_base);
27946                }
27947
27948                scope_element& se = parser_->sem_.get_element(symbol,i);
27949
27950                if (se.index == i)
27951                {
27952                   result = se.var_node;
27953                }
27954                else
27955                {
27956                   scope_element nse;
27957                   nse.name      = symbol;
27958                   nse.active    = true;
27959                   nse.ref_count = 1;
27960                   nse.type      = scope_element::e_vecelem;
27961                   nse.index     = i;
27962                   nse.depth     = parser_->state_.scope_depth;
27963                   nse.data      = 0;
27964                   nse.var_node  = node_allocator_->allocate<variable_node_t>((*(*vector_base)[i]));
27965
27966                   if (!parser_->sem_.add_element(nse))
27967                   {
27968                      parser_->set_synthesis_error("Failed to add new local vector element to SEM [1]");
27969
27970                      parser_->sem_.free_element(nse);
27971
27972                      result = error_node();
27973                   }
27974
27975                   exprtk_debug(("vector_element() - INFO - Added new local vector element: %s\n",nse.name.c_str()));
27976
27977                   parser_->state_.activate_side_effect("vector_element()");
27978
27979                   result = nse.var_node;
27980                }
27981             }
27982             else if (vector_base->rebaseable())
27983                result = node_allocator_->allocate<rebasevector_elem_node_t>(index,vector_base);
27984             else
27985                result = node_allocator_->allocate<vector_elem_node_t>(index,vector_base);
27986
27987             return result;
27988          }
27989
27990       private:
27991
27992          template <std::size_t N, typename NodePtr>
27993          inline bool is_constant_foldable(NodePtr (&b)[N]) const
27994          {
27995             for (std::size_t i = 0; i < N; ++i)
27996             {
27997                if (0 == b[i])
27998                   return false;
27999                else if (!details::is_constant_node(b[i]))
28000                   return false;
28001             }
28002
28003             return true;
28004          }
28005
28006          template <typename NodePtr,
28007                    typename Allocator,
28008                    template <typename, typename> class Sequence>
28009          inline bool is_constant_foldable(const Sequence<NodePtr,Allocator>& b) const
28010          {
28011             for (std::size_t i = 0; i < b.size(); ++i)
28012             {
28013                if (0 == b[i])
28014                   return false;
28015                else if (!details::is_constant_node(b[i]))
28016                   return false;
28017             }
28018
28019             return true;
28020          }
28021
28022          void lodge_assignment(symbol_type cst, expression_node_ptr node)
28023          {
28024             parser_->state_.activate_side_effect("lodge_assignment()");
28025
28026             if (!parser_->dec_.collect_assignments())
28027                return;
28028
28029             std::string symbol_name;
28030
28031             switch (cst)
28032             {
28033                case e_st_variable : symbol_name = parser_->symtab_store_
28034                                                      .get_variable_name(node);
28035                                     break;
28036
28037                #ifndef exprtk_disable_string_capabilities
28038                case e_st_string   : symbol_name = parser_->symtab_store_
28039                                                      .get_stringvar_name(node);
28040                                     break;
28041                #endif
28042
28043                case e_st_vector   : {
28044                                        typedef details::vector_holder<T> vector_holder_t;
28045
28046                                        vector_holder_t& vh = static_cast<vector_node_t*>(node)->vec_holder();
28047
28048                                        symbol_name = parser_->symtab_store_.get_vector_name(&vh);
28049                                     }
28050                                     break;
28051
28052                case e_st_vecelem  : {
28053                                        typedef details::vector_holder<T> vector_holder_t;
28054
28055                                        vector_holder_t& vh = static_cast<vector_elem_node_t*>(node)->vec_holder();
28056
28057                                        symbol_name = parser_->symtab_store_.get_vector_name(&vh);
28058
28059                                        cst = e_st_vector;
28060                                     }
28061                                     break;
28062
28063                default            : return;
28064             }
28065
28066             if (!symbol_name.empty())
28067             {
28068                parser_->dec_.add_assignment(symbol_name,cst);
28069             }
28070          }
28071
28072          inline expression_node_ptr synthesize_assignment_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
28073          {
28074             if (details::is_variable_node(branch[0]))
28075             {
28076                lodge_assignment(e_st_variable,branch[0]);
28077
28078                return synthesize_expression<assignment_node_t,2>(operation,branch);
28079             }
28080             else if (details::is_vector_elem_node(branch[0]))
28081             {
28082                lodge_assignment(e_st_vecelem,branch[0]);
28083
28084                return synthesize_expression<assignment_vec_elem_node_t, 2>(operation, branch);
28085             }
28086             else if (details::is_rebasevector_elem_node(branch[0]))
28087             {
28088                lodge_assignment(e_st_vecelem,branch[0]);
28089
28090                return synthesize_expression<assignment_rebasevec_elem_node_t, 2>(operation, branch);
28091             }
28092             else if (details::is_rebasevector_celem_node(branch[0]))
28093             {
28094                lodge_assignment(e_st_vecelem,branch[0]);
28095
28096                return synthesize_expression<assignment_rebasevec_celem_node_t, 2>(operation, branch);
28097             }
28098             #ifndef exprtk_disable_string_capabilities
28099             else if (details::is_string_node(branch[0]))
28100             {
28101                lodge_assignment(e_st_string,branch[0]);
28102
28103                return synthesize_expression<assignment_string_node_t,2>(operation, branch);
28104             }
28105             else if (details::is_string_range_node(branch[0]))
28106             {
28107                lodge_assignment(e_st_string,branch[0]);
28108
28109                return synthesize_expression<assignment_string_range_node_t,2>(operation, branch);
28110             }
28111             #endif
28112             else if (details::is_vector_node(branch[0]))
28113             {
28114                lodge_assignment(e_st_vector,branch[0]);
28115
28116                if (details::is_ivector_node(branch[1]))
28117                   return synthesize_expression<assignment_vecvec_node_t,2>(operation, branch);
28118               else
28119                   return synthesize_expression<assignment_vec_node_t,2>(operation, branch);
28120             }
28121             else
28122             {
28123                parser_->set_synthesis_error("Invalid assignment operation.[1]");
28124
28125                return error_node();
28126             }
28127          }
28128
28129          inline expression_node_ptr synthesize_assignment_operation_expression(const details::operator_type& operation,
28130                                                                                expression_node_ptr (&branch)[2])
28131          {
28132             if (details::is_variable_node(branch[0]))
28133             {
28134                lodge_assignment(e_st_variable,branch[0]);
28135
28136                switch (operation)
28137                {
28138                   #define case_stmt(op0,op1)                                                                  \
28139                   case op0 : return node_allocator_->                                                         \
28140                                 template allocate_rrr<typename details::assignment_op_node<Type,op1<Type> > > \
28141                                    (operation, branch[0], branch[1]);                                         \
28142
28143                   case_stmt(details::e_addass,details::add_op)
28144                   case_stmt(details::e_subass,details::sub_op)
28145                   case_stmt(details::e_mulass,details::mul_op)
28146                   case_stmt(details::e_divass,details::div_op)
28147                   case_stmt(details::e_modass,details::mod_op)
28148                   #undef case_stmt
28149                   default : return error_node();
28150                }
28151             }
28152             else if (details::is_vector_elem_node(branch[0]))
28153             {
28154                lodge_assignment(e_st_vecelem,branch[0]);
28155
28156                switch (operation)
28157                {
28158                   #define case_stmt(op0,op1)                                                                            \
28159                   case op0 : return node_allocator_->                                                                   \
28160                                  template allocate_rrr<typename details::assignment_vec_elem_op_node<Type,op1<Type> > > \
28161                                     (operation, branch[0], branch[1]);                                                  \
28162
28163                   case_stmt(details::e_addass,details::add_op)
28164                   case_stmt(details::e_subass,details::sub_op)
28165                   case_stmt(details::e_mulass,details::mul_op)
28166                   case_stmt(details::e_divass,details::div_op)
28167                   case_stmt(details::e_modass,details::mod_op)
28168                   #undef case_stmt
28169                   default : return error_node();
28170                }
28171             }
28172             else if (details::is_rebasevector_elem_node(branch[0]))
28173             {
28174                lodge_assignment(e_st_vecelem,branch[0]);
28175
28176                switch (operation)
28177                {
28178                   #define case_stmt(op0,op1)                                                                                  \
28179                   case op0 : return node_allocator_->                                                                         \
28180                                  template allocate_rrr<typename details::assignment_rebasevec_elem_op_node<Type,op1<Type> > > \
28181                                     (operation, branch[0], branch[1]);                                                        \
28182
28183                   case_stmt(details::e_addass,details::add_op)
28184                   case_stmt(details::e_subass,details::sub_op)
28185                   case_stmt(details::e_mulass,details::mul_op)
28186                   case_stmt(details::e_divass,details::div_op)
28187                   case_stmt(details::e_modass,details::mod_op)
28188                   #undef case_stmt
28189                   default : return error_node();
28190                }
28191             }
28192             else if (details::is_rebasevector_celem_node(branch[0]))
28193             {
28194                lodge_assignment(e_st_vecelem,branch[0]);
28195
28196                switch (operation)
28197                {
28198                   #define case_stmt(op0,op1)                                                                                   \
28199                   case op0 : return node_allocator_->                                                                          \
28200                                  template allocate_rrr<typename details::assignment_rebasevec_celem_op_node<Type,op1<Type> > > \
28201                                     (operation, branch[0], branch[1]);                                                         \
28202
28203                   case_stmt(details::e_addass,details::add_op)
28204                   case_stmt(details::e_subass,details::sub_op)
28205                   case_stmt(details::e_mulass,details::mul_op)
28206                   case_stmt(details::e_divass,details::div_op)
28207                   case_stmt(details::e_modass,details::mod_op)
28208                   #undef case_stmt
28209                   default : return error_node();
28210                }
28211             }
28212             else if (details::is_vector_node(branch[0]))
28213             {
28214                lodge_assignment(e_st_vector,branch[0]);
28215
28216                if (details::is_ivector_node(branch[1]))
28217                {
28218                   switch (operation)
28219                   {
28220                      #define case_stmt(op0,op1)                                                                         \
28221                      case op0 : return node_allocator_->                                                                \
28222                                    template allocate_rrr<typename details::assignment_vecvec_op_node<Type,op1<Type> > > \
28223                                       (operation, branch[0], branch[1]);                                                \
28224
28225                      case_stmt(details::e_addass,details::add_op)
28226                      case_stmt(details::e_subass,details::sub_op)
28227                      case_stmt(details::e_mulass,details::mul_op)
28228                      case_stmt(details::e_divass,details::div_op)
28229                      case_stmt(details::e_modass,details::mod_op)
28230                      #undef case_stmt
28231                      default : return error_node();
28232                   }
28233                }
28234                else
28235                {
28236                   switch (operation)
28237                   {
28238                      #define case_stmt(op0,op1)                                                                      \
28239                      case op0 : return node_allocator_->                                                             \
28240                                    template allocate_rrr<typename details::assignment_vec_op_node<Type,op1<Type> > > \
28241                                       (operation, branch[0], branch[1]);                                             \
28242
28243                      case_stmt(details::e_addass,details::add_op)
28244                      case_stmt(details::e_subass,details::sub_op)
28245                      case_stmt(details::e_mulass,details::mul_op)
28246                      case_stmt(details::e_divass,details::div_op)
28247                      case_stmt(details::e_modass,details::mod_op)
28248                      #undef case_stmt
28249                      default : return error_node();
28250                   }
28251                }
28252             }
28253             #ifndef exprtk_disable_string_capabilities
28254             else if (
28255                       (details::e_addass == operation) &&
28256                       details::is_string_node(branch[0])
28257                     )
28258             {
28259                typedef details::assignment_string_node<T,details::asn_addassignment> addass_t;
28260
28261                lodge_assignment(e_st_string,branch[0]);
28262
28263                return synthesize_expression<addass_t,2>(operation,branch);
28264             }
28265             #endif
28266             else
28267             {
28268                parser_->set_synthesis_error("Invalid assignment operation[2]");
28269
28270                return error_node();
28271             }
28272          }
28273
28274          inline expression_node_ptr synthesize_veceqineqlogic_operation_expression(const details::operator_type& operation,
28275                                                                                    expression_node_ptr (&branch)[2])
28276          {
28277             const bool is_b0_ivec = details::is_ivector_node(branch[0]);
28278             const bool is_b1_ivec = details::is_ivector_node(branch[1]);
28279
28280             #define batch_eqineq_logic_case                \
28281             case_stmt(details::   e_lt, details::   lt_op) \
28282             case_stmt(details::  e_lte, details::  lte_op) \
28283             case_stmt(details::   e_gt, details::   gt_op) \
28284             case_stmt(details::  e_gte, details::  gte_op) \
28285             case_stmt(details::   e_eq, details::   eq_op) \
28286             case_stmt(details::   e_ne, details::   ne_op) \
28287             case_stmt(details::e_equal, details::equal_op) \
28288             case_stmt(details::  e_and, details::  and_op) \
28289             case_stmt(details:: e_nand, details:: nand_op) \
28290             case_stmt(details::   e_or, details::   or_op) \
28291             case_stmt(details::  e_nor, details::  nor_op) \
28292             case_stmt(details::  e_xor, details::  xor_op) \
28293             case_stmt(details:: e_xnor, details:: xnor_op) \
28294
28295             if (is_b0_ivec && is_b1_ivec)
28296             {
28297                switch (operation)
28298                {
28299                   #define case_stmt(op0,op1)                                                                     \
28300                   case op0 : return node_allocator_->                                                            \
28301                                 template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \
28302                                    (operation, branch[0], branch[1]);                                            \
28303
28304                   batch_eqineq_logic_case
28305                   #undef case_stmt
28306                   default : return error_node();
28307                }
28308             }
28309             else if (is_b0_ivec && !is_b1_ivec)
28310             {
28311                switch (operation)
28312                {
28313                   #define case_stmt(op0,op1)                                                                     \
28314                   case op0 : return node_allocator_->                                                            \
28315                                 template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \
28316                                    (operation, branch[0], branch[1]);                                            \
28317
28318                   batch_eqineq_logic_case
28319                   #undef case_stmt
28320                   default : return error_node();
28321                }
28322             }
28323             else if (!is_b0_ivec && is_b1_ivec)
28324             {
28325                switch (operation)
28326                {
28327                   #define case_stmt(op0,op1)                                                                     \
28328                   case op0 : return node_allocator_->                                                            \
28329                                 template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \
28330                                    (operation, branch[0], branch[1]);                                            \
28331
28332                   batch_eqineq_logic_case
28333                   #undef case_stmt
28334                   default : return error_node();
28335                }
28336             }
28337             else
28338                return error_node();
28339
28340             #undef batch_eqineq_logic_case
28341          }
28342
28343          inline expression_node_ptr synthesize_vecarithmetic_operation_expression(const details::operator_type& operation,
28344                                                                                   expression_node_ptr (&branch)[2])
28345          {
28346             const bool is_b0_ivec = details::is_ivector_node(branch[0]);
28347             const bool is_b1_ivec = details::is_ivector_node(branch[1]);
28348
28349             #define vector_ops                        \
28350             case_stmt(details::e_add,details::add_op) \
28351             case_stmt(details::e_sub,details::sub_op) \
28352             case_stmt(details::e_mul,details::mul_op) \
28353             case_stmt(details::e_div,details::div_op) \
28354             case_stmt(details::e_mod,details::mod_op) \
28355
28356             if (is_b0_ivec && is_b1_ivec)
28357             {
28358                switch (operation)
28359                {
28360                   #define case_stmt(op0,op1)                                                                     \
28361                   case op0 : return node_allocator_->                                                            \
28362                                 template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \
28363                                    (operation, branch[0], branch[1]);                                            \
28364
28365                   vector_ops
28366                   case_stmt(details::e_pow,details:: pow_op)
28367                   #undef case_stmt
28368                   default : return error_node();
28369                }
28370             }
28371             else if (is_b0_ivec && !is_b1_ivec)
28372             {
28373                switch (operation)
28374                {
28375                   #define case_stmt(op0,op1)                                                                     \
28376                   case op0 : return node_allocator_->                                                            \
28377                                 template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \
28378                                    (operation, branch[0], branch[1]);                                            \
28379
28380                   vector_ops
28381                   case_stmt(details::e_pow,details:: pow_op)
28382                   #undef case_stmt
28383                   default : return error_node();
28384                }
28385             }
28386             else if (!is_b0_ivec && is_b1_ivec)
28387             {
28388                switch (operation)
28389                {
28390                   #define case_stmt(op0,op1)                                                                     \
28391                   case op0 : return node_allocator_->                                                            \
28392                                 template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \
28393                                    (operation, branch[0], branch[1]);                                            \
28394
28395                   vector_ops
28396                   #undef case_stmt
28397                   default : return error_node();
28398                }
28399             }
28400             else
28401                return error_node();
28402
28403             #undef vector_ops
28404          }
28405
28406          inline expression_node_ptr synthesize_swap_expression(expression_node_ptr (&branch)[2])
28407          {
28408             const bool v0_is_ivar = details::is_ivariable_node(branch[0]);
28409             const bool v1_is_ivar = details::is_ivariable_node(branch[1]);
28410
28411             const bool v0_is_ivec = details::is_ivector_node  (branch[0]);
28412             const bool v1_is_ivec = details::is_ivector_node  (branch[1]);
28413
28414             #ifndef exprtk_disable_string_capabilities
28415             const bool v0_is_str = details::is_generally_string_node(branch[0]);
28416             const bool v1_is_str = details::is_generally_string_node(branch[1]);
28417             #endif
28418
28419             expression_node_ptr result = error_node();
28420
28421             if (v0_is_ivar && v1_is_ivar)
28422             {
28423                typedef details::variable_node<T>* variable_node_ptr;
28424
28425                variable_node_ptr v0 = variable_node_ptr(0);
28426                variable_node_ptr v1 = variable_node_ptr(0);
28427
28428                if (
28429                     (0 != (v0 = dynamic_cast<variable_node_ptr>(branch[0]))) &&
28430                     (0 != (v1 = dynamic_cast<variable_node_ptr>(branch[1])))
28431                   )
28432                {
28433                   result = node_allocator_->allocate<details::swap_node<T> >(v0,v1);
28434                }
28435                else
28436                   result = node_allocator_->allocate<details::swap_generic_node<T> >(branch[0],branch[1]);
28437             }
28438             else if (v0_is_ivec && v1_is_ivec)
28439             {
28440                result = node_allocator_->allocate<details::swap_vecvec_node<T> >(branch[0],branch[1]);
28441             }
28442             #ifndef exprtk_disable_string_capabilities
28443             else if (v0_is_str && v1_is_str)
28444             {
28445                if (is_string_node(branch[0]) && is_string_node(branch[1]))
28446                   result = node_allocator_->allocate<details::swap_string_node<T> >
28447                                                (branch[0], branch[1]);
28448                else
28449                   result = node_allocator_->allocate<details::swap_genstrings_node<T> >
28450                                                (branch[0], branch[1]);
28451             }
28452             #endif
28453             else
28454             {
28455                parser_->set_synthesis_error("Only variables, strings, vectors or vector elements can be swapped");
28456
28457                return error_node();
28458             }
28459
28460             parser_->state_.activate_side_effect("synthesize_swap_expression()");
28461
28462             return result;
28463          }
28464
28465          #ifndef exprtk_disable_sc_andor
28466          inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
28467          {
28468             expression_node_ptr result = error_node();
28469
28470             if (details::is_constant_node(branch[0]))
28471             {
28472                if (
28473                     (details::e_scand == operation) &&
28474                     std::equal_to<T>()(T(0),branch[0]->value())
28475                   )
28476                   result = node_allocator_->allocate_c<literal_node_t>(T(0));
28477                else if (
28478                          (details::e_scor == operation) &&
28479                          std::not_equal_to<T>()(T(0),branch[0]->value())
28480                        )
28481                   result = node_allocator_->allocate_c<literal_node_t>(T(1));
28482             }
28483
28484             if (details::is_constant_node(branch[1]) && (0 == result))
28485             {
28486                if (
28487                     (details::e_scand == operation) &&
28488                     std::equal_to<T>()(T(0),branch[1]->value())
28489                   )
28490                   result = node_allocator_->allocate_c<literal_node_t>(T(0));
28491                else if (
28492                          (details::e_scor == operation) &&
28493                          std::not_equal_to<T>()(T(0),branch[1]->value())
28494                        )
28495                   result = node_allocator_->allocate_c<literal_node_t>(T(1));
28496             }
28497
28498             if (result)
28499             {
28500                free_node(*node_allocator_, branch[0]);
28501                free_node(*node_allocator_, branch[1]);
28502
28503                return result;
28504             }
28505             else if (details::e_scand == operation)
28506             {
28507                return synthesize_expression<scand_node_t,2>(operation, branch);
28508             }
28509             else if (details::e_scor == operation)
28510             {
28511                return synthesize_expression<scor_node_t,2>(operation, branch);
28512             }
28513             else
28514                return error_node();
28515          }
28516          #else
28517          inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type&, expression_node_ptr (&)[2])
28518          {
28519             return error_node();
28520          }
28521          #endif
28522
28523          #define basic_opr_switch_statements        \
28524          case_stmt(details::e_add, details::add_op) \
28525          case_stmt(details::e_sub, details::sub_op) \
28526          case_stmt(details::e_mul, details::mul_op) \
28527          case_stmt(details::e_div, details::div_op) \
28528          case_stmt(details::e_mod, details::mod_op) \
28529          case_stmt(details::e_pow, details::pow_op) \
28530
28531          #define extended_opr_switch_statements       \
28532          case_stmt(details::  e_lt, details::  lt_op) \
28533          case_stmt(details:: e_lte, details:: lte_op) \
28534          case_stmt(details::  e_gt, details::  gt_op) \
28535          case_stmt(details:: e_gte, details:: gte_op) \
28536          case_stmt(details::  e_eq, details::  eq_op) \
28537          case_stmt(details::  e_ne, details::  ne_op) \
28538          case_stmt(details:: e_and, details:: and_op) \
28539          case_stmt(details::e_nand, details::nand_op) \
28540          case_stmt(details::  e_or, details::  or_op) \
28541          case_stmt(details:: e_nor, details:: nor_op) \
28542          case_stmt(details:: e_xor, details:: xor_op) \
28543          case_stmt(details::e_xnor, details::xnor_op) \
28544
28545          #ifndef exprtk_disable_cardinal_pow_optimisation
28546          template <typename TType, template <typename, typename> class IPowNode>
28547          inline expression_node_ptr cardinal_pow_optimisation_impl(const TType& v, const unsigned int& p)
28548          {
28549             switch (p)
28550             {
28551                #define case_stmt(cp)                                                     \
28552                case cp : return node_allocator_->                                        \
28553                             allocate<IPowNode<T,details::numeric::fast_exp<T,cp> > >(v); \
28554
28555                case_stmt( 1) case_stmt( 2) case_stmt( 3) case_stmt( 4)
28556                case_stmt( 5) case_stmt( 6) case_stmt( 7) case_stmt( 8)
28557                case_stmt( 9) case_stmt(10) case_stmt(11) case_stmt(12)
28558                case_stmt(13) case_stmt(14) case_stmt(15) case_stmt(16)
28559                case_stmt(17) case_stmt(18) case_stmt(19) case_stmt(20)
28560                case_stmt(21) case_stmt(22) case_stmt(23) case_stmt(24)
28561                case_stmt(25) case_stmt(26) case_stmt(27) case_stmt(28)
28562                case_stmt(29) case_stmt(30) case_stmt(31) case_stmt(32)
28563                case_stmt(33) case_stmt(34) case_stmt(35) case_stmt(36)
28564                case_stmt(37) case_stmt(38) case_stmt(39) case_stmt(40)
28565                case_stmt(41) case_stmt(42) case_stmt(43) case_stmt(44)
28566                case_stmt(45) case_stmt(46) case_stmt(47) case_stmt(48)
28567                case_stmt(49) case_stmt(50) case_stmt(51) case_stmt(52)
28568                case_stmt(53) case_stmt(54) case_stmt(55) case_stmt(56)
28569                case_stmt(57) case_stmt(58) case_stmt(59) case_stmt(60)
28570                #undef case_stmt
28571                default : return error_node();
28572             }
28573          }
28574
28575          inline expression_node_ptr cardinal_pow_optimisation(const T& v, const T& c)
28576          {
28577             const bool not_recipricol = (c >= T(0));
28578             const unsigned int p = static_cast<unsigned int>(details::numeric::to_int32(details::numeric::abs(c)));
28579
28580             if (0 == p)
28581                return node_allocator_->allocate_c<literal_node_t>(T(1));
28582             else if (std::equal_to<T>()(T(2),c))
28583             {
28584                return node_allocator_->
28585                   template allocate_rr<typename details::vov_node<Type,details::mul_op<Type> > >(v,v);
28586             }
28587             else
28588             {
28589                if (not_recipricol)
28590                   return cardinal_pow_optimisation_impl<T,details::ipow_node>(v,p);
28591                else
28592                   return cardinal_pow_optimisation_impl<T,details::ipowinv_node>(v,p);
28593             }
28594          }
28595
28596          inline bool cardinal_pow_optimisable(const details::operator_type& operation, const T& c) const
28597          {
28598             return (details::e_pow == operation) && (details::numeric::abs(c) <= T(60)) && details::numeric::is_integer(c);
28599          }
28600
28601          inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr (&branch)[2])
28602          {
28603             const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
28604             const bool not_recipricol = (c >= T(0));
28605             const unsigned int p = static_cast<unsigned int>(details::numeric::to_int32(details::numeric::abs(c)));
28606
28607             node_allocator_->free(branch[1]);
28608
28609             if (0 == p)
28610             {
28611                details::free_all_nodes(*node_allocator_, branch);
28612
28613                return node_allocator_->allocate_c<literal_node_t>(T(1));
28614             }
28615             else if (not_recipricol)
28616                return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipow_node>(branch[0],p);
28617             else
28618                return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipowninv_node>(branch[0],p);
28619          }
28620          #else
28621          inline expression_node_ptr cardinal_pow_optimisation(T&, const T&)
28622          {
28623             return error_node();
28624          }
28625
28626          inline bool cardinal_pow_optimisable(const details::operator_type&, const T&)
28627          {
28628             return false;
28629          }
28630
28631          inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr(&)[2])
28632          {
28633             return error_node();
28634          }
28635          #endif
28636
28637          struct synthesize_binary_ext_expression
28638          {
28639             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
28640                                                       const details::operator_type& operation,
28641                                                       expression_node_ptr (&branch)[2])
28642             {
28643                const bool left_neg  = is_neg_unary_node(branch[0]);
28644                const bool right_neg = is_neg_unary_node(branch[1]);
28645
28646                if (left_neg && right_neg)
28647                {
28648                   if (
28649                        (details::e_add == operation) ||
28650                        (details::e_sub == operation) ||
28651                        (details::e_mul == operation) ||
28652                        (details::e_div == operation)
28653                      )
28654                   {
28655                      if (
28656                           !expr_gen.parser_->simplify_unary_negation_branch(branch[0]) ||
28657                           !expr_gen.parser_->simplify_unary_negation_branch(branch[1])
28658                         )
28659                      {
28660                         details::free_all_nodes(*expr_gen.node_allocator_,branch);
28661
28662                         return error_node();
28663                      }
28664                   }
28665
28666                   switch (operation)
28667                   {
28668                                            // -f(x + 1) + -g(y + 1) --> -(f(x + 1) + g(y + 1))
28669                      case details::e_add : return expr_gen(details::e_neg,
28670                                               expr_gen.node_allocator_->
28671                                                  template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >
28672                                                     (branch[0],branch[1]));
28673
28674                                            // -f(x + 1) - -g(y + 1) --> g(y + 1) - f(x + 1)
28675                      case details::e_sub : return expr_gen.node_allocator_->
28676                                               template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >
28677                                                  (branch[1],branch[0]);
28678
28679                      default             : break;
28680                   }
28681                }
28682                else if (left_neg && !right_neg)
28683                {
28684                   if (
28685                        (details::e_add == operation) ||
28686                        (details::e_sub == operation) ||
28687                        (details::e_mul == operation) ||
28688                        (details::e_div == operation)
28689                      )
28690                   {
28691                      if (!expr_gen.parser_->simplify_unary_negation_branch(branch[0]))
28692                      {
28693                         details::free_all_nodes(*expr_gen.node_allocator_,branch);
28694
28695                         return error_node();
28696                      }
28697
28698                      switch (operation)
28699                      {
28700                                               // -f(x + 1) + g(y + 1) --> g(y + 1) - f(x + 1)
28701                         case details::e_add : return expr_gen.node_allocator_->
28702                                                  template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >
28703                                                    (branch[1], branch[0]);
28704
28705                                               // -f(x + 1) - g(y + 1) --> -(f(x + 1) + g(y + 1))
28706                         case details::e_sub : return expr_gen(details::e_neg,
28707                                                  expr_gen.node_allocator_->
28708                                                     template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >
28709                                                        (branch[0], branch[1]));
28710
28711                                               // -f(x + 1) * g(y + 1) --> -(f(x + 1) * g(y + 1))
28712                         case details::e_mul : return expr_gen(details::e_neg,
28713                                                  expr_gen.node_allocator_->
28714                                                     template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > >
28715                                                        (branch[0], branch[1]));
28716
28717                                               // -f(x + 1) / g(y + 1) --> -(f(x + 1) / g(y + 1))
28718                         case details::e_div : return expr_gen(details::e_neg,
28719                                                  expr_gen.node_allocator_->
28720                                                     template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > >
28721                                                        (branch[0], branch[1]));
28722
28723                         default             : return error_node();
28724                      }
28725                   }
28726                }
28727                else if (!left_neg && right_neg)
28728                {
28729                   if (
28730                        (details::e_add == operation) ||
28731                        (details::e_sub == operation) ||
28732                        (details::e_mul == operation) ||
28733                        (details::e_div == operation)
28734                      )
28735                   {
28736                      if (!expr_gen.parser_->simplify_unary_negation_branch(branch[1]))
28737                      {
28738                         details::free_all_nodes(*expr_gen.node_allocator_,branch);
28739
28740                         return error_node();
28741                      }
28742
28743                      switch (operation)
28744                      {
28745                                               // f(x + 1) + -g(y + 1) --> f(x + 1) - g(y + 1)
28746                         case details::e_add : return expr_gen.node_allocator_->
28747                                                  template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >
28748                                                    (branch[0], branch[1]);
28749
28750                                               // f(x + 1) - - g(y + 1) --> f(x + 1) + g(y + 1)
28751                         case details::e_sub : return expr_gen.node_allocator_->
28752                                                  template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >
28753                                                    (branch[0], branch[1]);
28754
28755                                               // f(x + 1) * -g(y + 1) --> -(f(x + 1) * g(y + 1))
28756                         case details::e_mul : return expr_gen(details::e_neg,
28757                                                  expr_gen.node_allocator_->
28758                                                     template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > >
28759                                                        (branch[0], branch[1]));
28760
28761                                               // f(x + 1) / -g(y + 1) --> -(f(x + 1) / g(y + 1))
28762                         case details::e_div : return expr_gen(details::e_neg,
28763                                                  expr_gen.node_allocator_->
28764                                                     template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > >
28765                                                        (branch[0], branch[1]));
28766
28767                         default             : return error_node();
28768                      }
28769                   }
28770                }
28771
28772                switch (operation)
28773                {
28774                   #define case_stmt(op0,op1)                                                           \
28775                   case op0 : return expr_gen.node_allocator_->                                         \
28776                                 template allocate<typename details::binary_ext_node<Type,op1<Type> > > \
28777                                    (branch[0], branch[1]);                                             \
28778
28779                   basic_opr_switch_statements
28780                   extended_opr_switch_statements
28781                   #undef case_stmt
28782                   default : return error_node();
28783                }
28784             }
28785          };
28786
28787          struct synthesize_vob_expression
28788          {
28789             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
28790                                                       const details::operator_type& operation,
28791                                                       expression_node_ptr (&branch)[2])
28792             {
28793                const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref();
28794
28795                #ifndef exprtk_disable_enhanced_features
28796                if (details::is_sf3ext_node(branch[1]))
28797                {
28798                   expression_node_ptr result = error_node();
28799
28800                   const bool synthesis_result =
28801                      synthesize_sf4ext_expression::template compile_right<vtype>
28802                         (expr_gen, v, operation, branch[1], result);
28803
28804                   if (synthesis_result)
28805                   {
28806                      free_node(*expr_gen.node_allocator_,branch[1]);
28807                      return result;
28808                   }
28809                }
28810                #endif
28811
28812                if (
28813                     (details::e_mul == operation) ||
28814                     (details::e_div == operation)
28815                   )
28816                {
28817                   if (details::is_uv_node(branch[1]))
28818                   {
28819                      typedef details::uv_base_node<Type>* uvbn_ptr_t;
28820
28821                      details::operator_type o = static_cast<uvbn_ptr_t>(branch[1])->operation();
28822
28823                      if (details::e_neg == o)
28824                      {
28825                         const Type& v1 = static_cast<uvbn_ptr_t>(branch[1])->v();
28826
28827                         free_node(*expr_gen.node_allocator_,branch[1]);
28828
28829                         switch (operation)
28830                         {
28831                            case details::e_mul : return expr_gen(details::e_neg,
28832                                                     expr_gen.node_allocator_->
28833                                                        template allocate_rr<typename details::
28834                                                           vov_node<Type,details::mul_op<Type> > >(v,v1));
28835
28836                            case details::e_div : return expr_gen(details::e_neg,
28837                                                     expr_gen.node_allocator_->
28838                                                        template allocate_rr<typename details::
28839                                                           vov_node<Type,details::div_op<Type> > >(v,v1));
28840
28841                            default             : break;
28842                         }
28843                      }
28844                   }
28845                }
28846
28847                switch (operation)
28848                {
28849                   #define case_stmt(op0,op1)                                                       \
28850                   case op0 : return expr_gen.node_allocator_->                                     \
28851                                 template allocate_rc<typename details::vob_node<Type,op1<Type> > > \
28852                                    (v, branch[1]);                                                 \
28853
28854                   basic_opr_switch_statements
28855                   extended_opr_switch_statements
28856                   #undef case_stmt
28857                   default : return error_node();
28858                }
28859             }
28860          };
28861
28862          struct synthesize_bov_expression
28863          {
28864             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
28865                                                       const details::operator_type& operation,
28866                                                       expression_node_ptr (&branch)[2])
28867             {
28868                const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref();
28869
28870                #ifndef exprtk_disable_enhanced_features
28871                if (details::is_sf3ext_node(branch[0]))
28872                {
28873                   expression_node_ptr result = error_node();
28874
28875                   const bool synthesis_result =
28876                      synthesize_sf4ext_expression::template compile_left<vtype>
28877                         (expr_gen, v, operation, branch[0], result);
28878
28879                   if (synthesis_result)
28880                   {
28881                      free_node(*expr_gen.node_allocator_, branch[0]);
28882
28883                      return result;
28884                   }
28885                }
28886                #endif
28887
28888                if (
28889                     (details::e_add == operation) ||
28890                     (details::e_sub == operation) ||
28891                     (details::e_mul == operation) ||
28892                     (details::e_div == operation)
28893                   )
28894                {
28895                   if (details::is_uv_node(branch[0]))
28896                   {
28897                      typedef details::uv_base_node<Type>* uvbn_ptr_t;
28898
28899                      details::operator_type o = static_cast<uvbn_ptr_t>(branch[0])->operation();
28900
28901                      if (details::e_neg == o)
28902                      {
28903                         const Type& v0 = static_cast<uvbn_ptr_t>(branch[0])->v();
28904
28905                         free_node(*expr_gen.node_allocator_,branch[0]);
28906
28907                         switch (operation)
28908                         {
28909                            case details::e_add : return expr_gen.node_allocator_->
28910                                                     template allocate_rr<typename details::
28911                                                        vov_node<Type,details::sub_op<Type> > >(v,v0);
28912
28913                            case details::e_sub : return expr_gen(details::e_neg,
28914                                                     expr_gen.node_allocator_->
28915                                                        template allocate_rr<typename details::
28916                                                           vov_node<Type,details::add_op<Type> > >(v0,v));
28917
28918                            case details::e_mul : return expr_gen(details::e_neg,
28919                                                     expr_gen.node_allocator_->
28920                                                        template allocate_rr<typename details::
28921                                                           vov_node<Type,details::mul_op<Type> > >(v0,v));
28922
28923                            case details::e_div : return expr_gen(details::e_neg,
28924                                                     expr_gen.node_allocator_->
28925                                                        template allocate_rr<typename details::
28926                                                           vov_node<Type,details::div_op<Type> > >(v0,v));
28927                            default : break;
28928                         }
28929                      }
28930                   }
28931                }
28932
28933                switch (operation)
28934                {
28935                   #define case_stmt(op0,op1)                                                       \
28936                   case op0 : return expr_gen.node_allocator_->                                     \
28937                                 template allocate_cr<typename details::bov_node<Type,op1<Type> > > \
28938                                    (branch[0], v);                                                 \
28939
28940                   basic_opr_switch_statements
28941                   extended_opr_switch_statements
28942                   #undef case_stmt
28943                   default : return error_node();
28944                }
28945             }
28946          };
28947
28948          struct synthesize_cob_expression
28949          {
28950             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
28951                                                       const details::operator_type& operation,
28952                                                       expression_node_ptr (&branch)[2])
28953             {
28954                const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
28955
28956                free_node(*expr_gen.node_allocator_,branch[0]);
28957
28958                if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
28959                {
28960                   free_node(*expr_gen.node_allocator_,branch[1]);
28961
28962                   return expr_gen(T(0));
28963                }
28964                else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
28965                {
28966                   free_node(*expr_gen.node_allocator_, branch[1]);
28967
28968                   return expr_gen(T(0));
28969                }
28970                else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
28971                   return branch[1];
28972                else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
28973                   return branch[1];
28974
28975                if (details::is_cob_node(branch[1]))
28976                {
28977                   // Simplify expressions of the form:
28978                   // 1. (1 * (2 * (3 * (4 * (5 * (6 * (7 * (8 * (9 + x))))))))) --> 40320 * (9 + x)
28979                   // 2. (1 + (2 + (3 + (4 + (5 + (6 + (7 + (8 + (9 + x))))))))) --> 45 + x
28980                   if (
28981                        (operation == details::e_mul) ||
28982                        (operation == details::e_add)
28983                      )
28984                   {
28985                      details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
28986
28987                      if (operation == cobnode->operation())
28988                      {
28989                         switch (operation)
28990                         {
28991                            case details::e_add : cobnode->set_c(c + cobnode->c()); break;
28992                            case details::e_mul : cobnode->set_c(c * cobnode->c()); break;
28993                            default             : return error_node();
28994                         }
28995
28996                         return cobnode;
28997                      }
28998                   }
28999
29000                   if (operation == details::e_mul)
29001                   {
29002                      details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
29003                      details::operator_type cob_opr = cobnode->operation();
29004
29005                      if (
29006                           (details::e_div == cob_opr) ||
29007                           (details::e_mul == cob_opr)
29008                         )
29009                      {
29010                         switch (cob_opr)
29011                         {
29012                            case details::e_div : cobnode->set_c(c * cobnode->c()); break;
29013                            case details::e_mul : cobnode->set_c(cobnode->c() / c); break;
29014                            default             : return error_node();
29015                         }
29016
29017                         return cobnode;
29018                      }
29019                   }
29020                   else if (operation == details::e_div)
29021                   {
29022                      details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
29023                      details::operator_type cob_opr = cobnode->operation();
29024
29025                      if (
29026                           (details::e_div == cob_opr) ||
29027                           (details::e_mul == cob_opr)
29028                         )
29029                      {
29030                         details::expression_node<Type>* new_cobnode = error_node();
29031
29032                         switch (cob_opr)
29033                         {
29034                            case details::e_div : new_cobnode = expr_gen.node_allocator_->
29035                                                     template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > >
29036                                                        (c / cobnode->c(), cobnode->move_branch(0));
29037                                                  break;
29038
29039                            case details::e_mul : new_cobnode = expr_gen.node_allocator_->
29040                                                     template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
29041                                                        (c / cobnode->c(), cobnode->move_branch(0));
29042                                                  break;
29043
29044                            default             : return error_node();
29045                         }
29046
29047                         free_node(*expr_gen.node_allocator_,branch[1]);
29048
29049                         return new_cobnode;
29050                      }
29051                   }
29052                }
29053                #ifndef exprtk_disable_enhanced_features
29054                else if (details::is_sf3ext_node(branch[1]))
29055                {
29056                   expression_node_ptr result = error_node();
29057
29058                   const bool synthesis_result =
29059                      synthesize_sf4ext_expression::template compile_right<ctype>
29060                         (expr_gen, c, operation, branch[1], result);
29061
29062                   if (synthesis_result)
29063                   {
29064                      free_node(*expr_gen.node_allocator_,branch[1]);
29065
29066                      return result;
29067                   }
29068                }
29069                #endif
29070
29071                switch (operation)
29072                {
29073                   #define case_stmt(op0,op1)                                                       \
29074                   case op0 : return expr_gen.node_allocator_->                                     \
29075                                 template allocate_tt<typename details::cob_node<Type,op1<Type> > > \
29076                                    (c,  branch[1]);                                                \
29077
29078                   basic_opr_switch_statements
29079                   extended_opr_switch_statements
29080                   #undef case_stmt
29081                   default : return error_node();
29082                }
29083             }
29084          };
29085
29086          struct synthesize_boc_expression
29087          {
29088             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
29089                                                       const details::operator_type& operation,
29090                                                       expression_node_ptr (&branch)[2])
29091             {
29092                const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
29093
29094                details::free_node(*(expr_gen.node_allocator_), branch[1]);
29095
29096                if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
29097                {
29098                   free_node(*expr_gen.node_allocator_, branch[0]);
29099
29100                   return expr_gen(T(0));
29101                }
29102                else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
29103                {
29104                   free_node(*expr_gen.node_allocator_, branch[0]);
29105
29106                   return expr_gen(std::numeric_limits<T>::quiet_NaN());
29107                }
29108                else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
29109                   return branch[0];
29110                else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
29111                   return branch[0];
29112
29113                if (details::is_boc_node(branch[0]))
29114                {
29115                   // Simplify expressions of the form:
29116                   // 1. (((((((((x + 9) * 8) * 7) * 6) * 5) * 4) * 3) * 2) * 1) --> (x + 9) * 40320
29117                   // 2. (((((((((x + 9) + 8) + 7) + 6) + 5) + 4) + 3) + 2) + 1) --> x + 45
29118                   if (
29119                        (operation == details::e_mul) ||
29120                        (operation == details::e_add)
29121                      )
29122                   {
29123                      details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
29124
29125                      if (operation == bocnode->operation())
29126                      {
29127                         switch (operation)
29128                         {
29129                            case details::e_add : bocnode->set_c(c + bocnode->c()); break;
29130                            case details::e_mul : bocnode->set_c(c * bocnode->c()); break;
29131                            default             : return error_node();
29132                         }
29133
29134                         return bocnode;
29135                      }
29136                   }
29137                   else if (operation == details::e_div)
29138                   {
29139                      details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
29140                      details::operator_type        boc_opr = bocnode->operation();
29141
29142                      if (
29143                           (details::e_div == boc_opr) ||
29144                           (details::e_mul == boc_opr)
29145                         )
29146                      {
29147                         switch (boc_opr)
29148                         {
29149                            case details::e_div : bocnode->set_c(c * bocnode->c()); break;
29150                            case details::e_mul : bocnode->set_c(bocnode->c() / c); break;
29151                            default             : return error_node();
29152                         }
29153
29154                         return bocnode;
29155                      }
29156                   }
29157                   else if (operation == details::e_pow)
29158                   {
29159                      // (v ^ c0) ^ c1 --> v ^(c0 * c1)
29160                      details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
29161                      details::operator_type        boc_opr = bocnode->operation();
29162
29163                      if (details::e_pow == boc_opr)
29164                      {
29165                         bocnode->set_c(bocnode->c() * c);
29166
29167                         return bocnode;
29168                      }
29169                   }
29170                }
29171
29172                #ifndef exprtk_disable_enhanced_features
29173                if (details::is_sf3ext_node(branch[0]))
29174                {
29175                   expression_node_ptr result = error_node();
29176
29177                   const bool synthesis_result =
29178                      synthesize_sf4ext_expression::template compile_left<ctype>
29179                         (expr_gen, c, operation, branch[0], result);
29180
29181                   if (synthesis_result)
29182                   {
29183                      free_node(*expr_gen.node_allocator_, branch[0]);
29184
29185                      return result;
29186                   }
29187                }
29188                #endif
29189
29190                switch (operation)
29191                {
29192                   #define case_stmt(op0,op1)                                                       \
29193                   case op0 : return expr_gen.node_allocator_->                                     \
29194                                 template allocate_cr<typename details::boc_node<Type,op1<Type> > > \
29195                                    (branch[0], c);                                                 \
29196
29197                   basic_opr_switch_statements
29198                   extended_opr_switch_statements
29199                   #undef case_stmt
29200                   default : return error_node();
29201                }
29202             }
29203          };
29204
29205          struct synthesize_cocob_expression
29206          {
29207             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
29208                                                       const details::operator_type& operation,
29209                                                       expression_node_ptr (&branch)[2])
29210             {
29211                expression_node_ptr result = error_node();
29212
29213                // (cob) o c --> cob
29214                if (details::is_cob_node(branch[0]))
29215                {
29216                   details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[0]);
29217
29218                   const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
29219
29220                   if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
29221                   {
29222                      free_node(*expr_gen.node_allocator_, branch[0]);
29223                      free_node(*expr_gen.node_allocator_, branch[1]);
29224
29225                      return expr_gen(T(0));
29226                   }
29227                   else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
29228                   {
29229                      free_node(*expr_gen.node_allocator_, branch[0]);
29230                      free_node(*expr_gen.node_allocator_, branch[1]);
29231
29232                      return expr_gen(T(std::numeric_limits<T>::quiet_NaN()));
29233                   }
29234                   else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
29235                   {
29236                      free_node(*expr_gen.node_allocator_, branch[1]);
29237
29238                      return branch[0];
29239                   }
29240                   else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
29241                   {
29242                      free_node(*expr_gen.node_allocator_, branch[1]);
29243
29244                      return branch[0];
29245                   }
29246                   else if (std::equal_to<T>()(T(1),c) && (details::e_div == operation))
29247                   {
29248                      free_node(*expr_gen.node_allocator_, branch[1]);
29249
29250                      return branch[0];
29251                   }
29252
29253                   const bool op_addsub = (details::e_add == cobnode->operation()) ||
29254                                          (details::e_sub == cobnode->operation()) ;
29255
29256                   if (op_addsub)
29257                   {
29258                      switch (operation)
29259                      {
29260                         case details::e_add : cobnode->set_c(cobnode->c() + c); break;
29261                         case details::e_sub : cobnode->set_c(cobnode->c() - c); break;
29262                         default             : return error_node();
29263                      }
29264
29265                      result = cobnode;
29266                   }
29267                   else if (details::e_mul == cobnode->operation())
29268                   {
29269                      switch (operation)
29270                      {
29271                         case details::e_mul : cobnode->set_c(cobnode->c() * c); break;
29272                         case details::e_div : cobnode->set_c(cobnode->c() / c); break;
29273                         default             : return error_node();
29274                      }
29275
29276                      result = cobnode;
29277                   }
29278                   else if (details::e_div == cobnode->operation())
29279                   {
29280                      if (details::e_mul == operation)
29281                      {
29282                         cobnode->set_c(cobnode->c() * c);
29283                         result = cobnode;
29284                      }
29285                      else if (details::e_div == operation)
29286                      {
29287                         result = expr_gen.node_allocator_->
29288                                     template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
29289                                        (cobnode->c() / c, cobnode->move_branch(0));
29290
29291                         free_node(*expr_gen.node_allocator_, branch[0]);
29292                      }
29293                   }
29294
29295                   if (result)
29296                   {
29297                      free_node(*expr_gen.node_allocator_,branch[1]);
29298                   }
29299                }
29300
29301                // c o (cob) --> cob
29302                else if (details::is_cob_node(branch[1]))
29303                {
29304                   details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
29305
29306                   const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
29307
29308                   if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
29309                   {
29310                      free_node(*expr_gen.node_allocator_, branch[0]);
29311                      free_node(*expr_gen.node_allocator_, branch[1]);
29312
29313                      return expr_gen(T(0));
29314                   }
29315                   else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
29316                   {
29317                      free_node(*expr_gen.node_allocator_, branch[0]);
29318                      free_node(*expr_gen.node_allocator_, branch[1]);
29319
29320                      return expr_gen(T(0));
29321                   }
29322                   else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
29323                   {
29324                      free_node(*expr_gen.node_allocator_, branch[0]);
29325
29326                      return branch[1];
29327                   }
29328                   else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
29329                   {
29330                      free_node(*expr_gen.node_allocator_, branch[0]);
29331
29332                      return branch[1];
29333                   }
29334
29335                   if (details::e_add == cobnode->operation())
29336                   {
29337                      if (details::e_add == operation)
29338                      {
29339                         cobnode->set_c(c + cobnode->c());
29340                         result = cobnode;
29341                      }
29342                      else if (details::e_sub == operation)
29343                      {
29344                         result = expr_gen.node_allocator_->
29345                                     template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
29346                                        (c - cobnode->c(), cobnode->move_branch(0));
29347
29348                         free_node(*expr_gen.node_allocator_,branch[1]);
29349                      }
29350                   }
29351                   else if (details::e_sub == cobnode->operation())
29352                   {
29353                      if (details::e_add == operation)
29354                      {
29355                         cobnode->set_c(c + cobnode->c());
29356                         result = cobnode;
29357                      }
29358                      else if (details::e_sub == operation)
29359                      {
29360                         result = expr_gen.node_allocator_->
29361                                     template allocate_tt<typename details::cob_node<Type,details::add_op<Type> > >
29362                                        (c - cobnode->c(), cobnode->move_branch(0));
29363
29364                         free_node(*expr_gen.node_allocator_,branch[1]);
29365                      }
29366                   }
29367                   else if (details::e_mul == cobnode->operation())
29368                   {
29369                      if (details::e_mul == operation)
29370                      {
29371                         cobnode->set_c(c * cobnode->c());
29372                         result = cobnode;
29373                      }
29374                      else if (details::e_div == operation)
29375                      {
29376                         result = expr_gen.node_allocator_->
29377                                     template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
29378                                        (c / cobnode->c(), cobnode->move_branch(0));
29379
29380                         free_node(*expr_gen.node_allocator_,branch[1]);
29381                      }
29382                   }
29383                   else if (details::e_div == cobnode->operation())
29384                   {
29385                      if (details::e_mul == operation)
29386                      {
29387                         cobnode->set_c(c * cobnode->c());
29388                         result = cobnode;
29389                      }
29390                      else if (details::e_div == operation)
29391                      {
29392                         result = expr_gen.node_allocator_->
29393                                     template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > >
29394                                        (c / cobnode->c(), cobnode->move_branch(0));
29395
29396                         free_node(*expr_gen.node_allocator_,branch[1]);
29397                      }
29398                   }
29399
29400                   if (result)
29401                   {
29402                      free_node(*expr_gen.node_allocator_,branch[0]);
29403                   }
29404                }
29405
29406                return result;
29407             }
29408          };
29409
29410          struct synthesize_coboc_expression
29411          {
29412             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
29413                                                       const details::operator_type& operation,
29414                                                       expression_node_ptr (&branch)[2])
29415             {
29416                expression_node_ptr result = error_node();
29417
29418                // (boc) o c --> boc
29419                if (details::is_boc_node(branch[0]))
29420                {
29421                   details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
29422
29423                   const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
29424
29425                   if (details::e_add == bocnode->operation())
29426                   {
29427                      switch (operation)
29428                      {
29429                         case details::e_add : bocnode->set_c(bocnode->c() + c); break;
29430                         case details::e_sub : bocnode->set_c(bocnode->c() - c); break;
29431                         default             : return error_node();
29432                      }
29433
29434                      result = bocnode;
29435                   }
29436                   else if (details::e_mul == bocnode->operation())
29437                   {
29438                      switch (operation)
29439                      {
29440                         case details::e_mul : bocnode->set_c(bocnode->c() * c); break;
29441                         case details::e_div : bocnode->set_c(bocnode->c() / c); break;
29442                         default             : return error_node();
29443                      }
29444
29445                      result = bocnode;
29446                   }
29447                   else if (details::e_sub == bocnode->operation())
29448                   {
29449                      if (details::e_add == operation)
29450                      {
29451                         result = expr_gen.node_allocator_->
29452                                     template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > >
29453                                        (bocnode->move_branch(0), c - bocnode->c());
29454
29455                         free_node(*expr_gen.node_allocator_,branch[0]);
29456                      }
29457                      else if (details::e_sub == operation)
29458                      {
29459                         bocnode->set_c(bocnode->c() + c);
29460                         result = bocnode;
29461                      }
29462                   }
29463                   else if (details::e_div == bocnode->operation())
29464                   {
29465                      switch (operation)
29466                      {
29467                         case details::e_div : bocnode->set_c(bocnode->c() * c); break;
29468                         case details::e_mul : bocnode->set_c(bocnode->c() / c); break;
29469                         default             : return error_node();
29470                      }
29471
29472                      result = bocnode;
29473                   }
29474
29475                   if (result)
29476                   {
29477                      free_node(*expr_gen.node_allocator_, branch[1]);
29478                   }
29479                }
29480
29481                // c o (boc) --> boc
29482                else if (details::is_boc_node(branch[1]))
29483                {
29484                   details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[1]);
29485
29486                   const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
29487
29488                   if (details::e_add == bocnode->operation())
29489                   {
29490                      if (details::e_add == operation)
29491                      {
29492                         bocnode->set_c(c + bocnode->c());
29493                         result = bocnode;
29494                      }
29495                      else if (details::e_sub == operation)
29496                      {
29497                         result = expr_gen.node_allocator_->
29498                                     template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
29499                                        (c - bocnode->c(), bocnode->move_branch(0));
29500
29501                         free_node(*expr_gen.node_allocator_,branch[1]);
29502                      }
29503                   }
29504                   else if (details::e_sub == bocnode->operation())
29505                   {
29506                      if (details::e_add == operation)
29507                      {
29508                         result = expr_gen.node_allocator_->
29509                                     template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > >
29510                                        (bocnode->move_branch(0), c - bocnode->c());
29511
29512                         free_node(*expr_gen.node_allocator_,branch[1]);
29513                      }
29514                      else if (details::e_sub == operation)
29515                      {
29516                         result = expr_gen.node_allocator_->
29517                                     template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
29518                                        (c + bocnode->c(), bocnode->move_branch(0));
29519
29520                         free_node(*expr_gen.node_allocator_,branch[1]);
29521                      }
29522                   }
29523                   else if (details::e_mul == bocnode->operation())
29524                   {
29525                      if (details::e_mul == operation)
29526                      {
29527                         bocnode->set_c(c * bocnode->c());
29528                         result = bocnode;
29529                      }
29530                      else if (details::e_div == operation)
29531                      {
29532                         result = expr_gen.node_allocator_->
29533                                     template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
29534                                        (c / bocnode->c(), bocnode->move_branch(0));
29535
29536                         free_node(*expr_gen.node_allocator_,branch[1]);
29537                      }
29538                   }
29539                   else if (details::e_div == bocnode->operation())
29540                   {
29541                      if (details::e_mul == operation)
29542                      {
29543                         bocnode->set_c(bocnode->c() / c);
29544                         result = bocnode;
29545                      }
29546                      else if (details::e_div == operation)
29547                      {
29548                         result = expr_gen.node_allocator_->
29549                                     template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
29550                                        (c * bocnode->c(), bocnode->move_branch(0));
29551
29552                         free_node(*expr_gen.node_allocator_,branch[1]);
29553                      }
29554                   }
29555
29556                   if (result)
29557                   {
29558                      free_node(*expr_gen.node_allocator_,branch[0]);
29559                   }
29560                }
29561
29562                return result;
29563             }
29564          };
29565
29566          #ifndef exprtk_disable_enhanced_features
29567          inline bool synthesize_expression(const details::operator_type& operation,
29568                                            expression_node_ptr (&branch)[2],
29569                                            expression_node_ptr& result)
29570          {
29571             result = error_node();
29572
29573             if (!operation_optimisable(operation))
29574                return false;
29575
29576             const std::string node_id = branch_to_id(branch);
29577
29578             const typename synthesize_map_t::iterator itr = synthesize_map_.find(node_id);
29579
29580             if (synthesize_map_.end() != itr)
29581             {
29582                result = itr->second((*this), operation, branch);
29583
29584                return true;
29585             }
29586             else
29587                return false;
29588          }
29589
29590          struct synthesize_vov_expression
29591          {
29592             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
29593                                                       const details::operator_type& operation,
29594                                                       expression_node_ptr (&branch)[2])
29595             {
29596                const Type& v1 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
29597                const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
29598
29599                switch (operation)
29600                {
29601                   #define case_stmt(op0,op1)                                                       \
29602                   case op0 : return expr_gen.node_allocator_->                                     \
29603                                 template allocate_rr<typename details::vov_node<Type,op1<Type> > > \
29604                                    (v1, v2);                                                       \
29605
29606                   basic_opr_switch_statements
29607                   extended_opr_switch_statements
29608                   #undef case_stmt
29609                   default : return error_node();
29610                }
29611             }
29612          };
29613
29614          struct synthesize_cov_expression
29615          {
29616             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
29617                                                       const details::operator_type& operation,
29618                                                       expression_node_ptr (&branch)[2])
29619             {
29620                const Type  c = static_cast<details::literal_node<Type>*> (branch[0])->value();
29621                const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref  ();
29622
29623                details::free_node(*(expr_gen.node_allocator_),branch[0]);
29624
29625                if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
29626                   return expr_gen(T(0));
29627                else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
29628                   return expr_gen(T(0));
29629                else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
29630                   return static_cast<details::variable_node<Type>*>(branch[1]);
29631                else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
29632                   return static_cast<details::variable_node<Type>*>(branch[1]);
29633
29634                switch (operation)
29635                {
29636                   #define case_stmt(op0,op1)                                                       \
29637                   case op0 : return expr_gen.node_allocator_->                                     \
29638                                 template allocate_cr<typename details::cov_node<Type,op1<Type> > > \
29639                                    (c, v);                                                         \
29640
29641                   basic_opr_switch_statements
29642                   extended_opr_switch_statements
29643                   #undef case_stmt
29644                   default : return error_node();
29645                }
29646             }
29647          };
29648
29649          struct synthesize_voc_expression
29650          {
29651             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
29652                                                       const details::operator_type& operation,
29653                                                       expression_node_ptr (&branch)[2])
29654             {
29655                const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref  ();
29656                const Type  c = static_cast<details::literal_node<Type>*> (branch[1])->value();
29657
29658                details::free_node(*(expr_gen.node_allocator_), branch[1]);
29659
29660                if (expr_gen.cardinal_pow_optimisable(operation,c))
29661                {
29662                   if (std::equal_to<T>()(T(1),c))
29663                      return branch[0];
29664                   else
29665                      return expr_gen.cardinal_pow_optimisation(v,c);
29666                }
29667                else if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
29668                   return expr_gen(T(0));
29669                else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
29670                   return expr_gen(std::numeric_limits<T>::quiet_NaN());
29671                else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
29672                   return static_cast<details::variable_node<Type>*>(branch[0]);
29673                else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
29674                   return static_cast<details::variable_node<Type>*>(branch[0]);
29675                else if (std::equal_to<T>()(T(1),c) && (details::e_div == operation))
29676                   return static_cast<details::variable_node<Type>*>(branch[0]);
29677
29678                switch (operation)
29679                {
29680                   #define case_stmt(op0,op1)                                                       \
29681                   case op0 : return expr_gen.node_allocator_->                                     \
29682                                 template allocate_rc<typename details::voc_node<Type,op1<Type> > > \
29683                                    (v, c);                                                         \
29684
29685                   basic_opr_switch_statements
29686                   extended_opr_switch_statements
29687                   #undef case_stmt
29688                   default : return error_node();
29689                }
29690             }
29691          };
29692
29693          struct synthesize_sf3ext_expression
29694          {
29695             template <typename T0, typename T1, typename T2>
29696             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
29697                                                       const details::operator_type& sf3opr,
29698                                                       T0 t0, T1 t1, T2 t2)
29699             {
29700                switch (sf3opr)
29701                {
29702                   #define case_stmt(op)                                                                              \
29703                   case details::e_sf##op : return details::T0oT1oT2_sf3ext<T,T0,T1,T2,details::sf##op##_op<Type> >:: \
29704                                 allocate(*(expr_gen.node_allocator_), t0, t1, t2);                                   \
29705
29706                   case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
29707                   case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
29708                   case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
29709                   case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
29710                   case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
29711                   case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
29712                   case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
29713                   case_stmt(28) case_stmt(29) case_stmt(30)
29714                   #undef case_stmt
29715                   default : return error_node();
29716                }
29717             }
29718
29719             template <typename T0, typename T1, typename T2>
29720             static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id,
29721                                        T0 t0, T1 t1, T2 t2,
29722                                        expression_node_ptr& result)
29723             {
29724                details::operator_type sf3opr;
29725
29726                if (!expr_gen.sf3_optimisable(id,sf3opr))
29727                   return false;
29728                else
29729                   result = synthesize_sf3ext_expression::template process<T0, T1, T2>
29730                               (expr_gen, sf3opr, t0, t1, t2);
29731
29732                return true;
29733             }
29734          };
29735
29736          struct synthesize_sf4ext_expression
29737          {
29738             template <typename T0, typename T1, typename T2, typename T3>
29739             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
29740                                                       const details::operator_type& sf4opr,
29741                                                       T0 t0, T1 t1, T2 t2, T3 t3)
29742             {
29743                switch (sf4opr)
29744                {
29745                   #define case_stmt0(op)                                                                                      \
29746                   case details::e_sf##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sf##op##_op<Type> >:: \
29747                                 allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3);                                        \
29748
29749
29750                   #define case_stmt1(op)                                                                                             \
29751                   case details::e_sf4ext##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sfext##op##_op<Type> >:: \
29752                                 allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3);                                               \
29753
29754                   case_stmt0(48) case_stmt0(49) case_stmt0(50) case_stmt0(51)
29755                   case_stmt0(52) case_stmt0(53) case_stmt0(54) case_stmt0(55)
29756                   case_stmt0(56) case_stmt0(57) case_stmt0(58) case_stmt0(59)
29757                   case_stmt0(60) case_stmt0(61) case_stmt0(62) case_stmt0(63)
29758                   case_stmt0(64) case_stmt0(65) case_stmt0(66) case_stmt0(67)
29759                   case_stmt0(68) case_stmt0(69) case_stmt0(70) case_stmt0(71)
29760                   case_stmt0(72) case_stmt0(73) case_stmt0(74) case_stmt0(75)
29761                   case_stmt0(76) case_stmt0(77) case_stmt0(78) case_stmt0(79)
29762                   case_stmt0(80) case_stmt0(81) case_stmt0(82) case_stmt0(83)
29763
29764                   case_stmt1(00) case_stmt1(01) case_stmt1(02) case_stmt1(03)
29765                   case_stmt1(04) case_stmt1(05) case_stmt1(06) case_stmt1(07)
29766                   case_stmt1(08) case_stmt1(09) case_stmt1(10) case_stmt1(11)
29767                   case_stmt1(12) case_stmt1(13) case_stmt1(14) case_stmt1(15)
29768                   case_stmt1(16) case_stmt1(17) case_stmt1(18) case_stmt1(19)
29769                   case_stmt1(20) case_stmt1(21) case_stmt1(22) case_stmt1(23)
29770                   case_stmt1(24) case_stmt1(25) case_stmt1(26) case_stmt1(27)
29771                   case_stmt1(28) case_stmt1(29) case_stmt1(30) case_stmt1(31)
29772                   case_stmt1(32) case_stmt1(33) case_stmt1(34) case_stmt1(35)
29773                   case_stmt1(36) case_stmt1(37) case_stmt1(38) case_stmt1(39)
29774                   case_stmt1(40) case_stmt1(41) case_stmt1(42) case_stmt1(43)
29775                   case_stmt1(44) case_stmt1(45) case_stmt1(46) case_stmt1(47)
29776                   case_stmt1(48) case_stmt1(49) case_stmt1(50) case_stmt1(51)
29777                   case_stmt1(52) case_stmt1(53) case_stmt1(54) case_stmt1(55)
29778                   case_stmt1(56) case_stmt1(57) case_stmt1(58) case_stmt1(59)
29779                   case_stmt1(60) case_stmt1(61)
29780
29781                   #undef case_stmt0
29782                   #undef case_stmt1
29783                   default : return error_node();
29784                }
29785             }
29786
29787             template <typename T0, typename T1, typename T2, typename T3>
29788             static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id,
29789                                        T0 t0, T1 t1, T2 t2, T3 t3,
29790                                        expression_node_ptr& result)
29791             {
29792                details::operator_type sf4opr;
29793
29794                if (!expr_gen.sf4_optimisable(id,sf4opr))
29795                   return false;
29796                else
29797                   result = synthesize_sf4ext_expression::template process<T0, T1, T2, T3>
29798                               (expr_gen, sf4opr, t0, t1, t2, t3);
29799
29800                return true;
29801             }
29802
29803             // T o (sf3ext)
29804             template <typename ExternalType>
29805             static inline bool compile_right(expression_generator<Type>& expr_gen,
29806                                              ExternalType t,
29807                                              const details::operator_type& operation,
29808                                              expression_node_ptr& sf3node,
29809                                              expression_node_ptr& result)
29810             {
29811                if (!details::is_sf3ext_node(sf3node))
29812                   return false;
29813
29814                typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr;
29815
29816                sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node);
29817                const std::string id = "t" + expr_gen.to_str(operation) + "(" + n->type_id() + ")";
29818
29819                switch (n->type())
29820                {
29821                   case details::expression_node<Type>::e_covoc : return compile_right_impl
29822                                                                     <typename covoc_t::sf3_type_node,ExternalType, ctype, vtype, ctype>
29823                                                                        (expr_gen, id, t, sf3node, result);
29824
29825                   case details::expression_node<Type>::e_covov : return compile_right_impl
29826                                                                     <typename covov_t::sf3_type_node,ExternalType, ctype, vtype, vtype>
29827                                                                        (expr_gen, id, t, sf3node, result);
29828
29829                   case details::expression_node<Type>::e_vocov : return compile_right_impl
29830                                                                     <typename vocov_t::sf3_type_node,ExternalType, vtype, ctype, vtype>
29831                                                                        (expr_gen, id, t, sf3node, result);
29832
29833                   case details::expression_node<Type>::e_vovoc : return compile_right_impl
29834                                                                     <typename vovoc_t::sf3_type_node,ExternalType, vtype, vtype, ctype>
29835                                                                        (expr_gen, id, t, sf3node, result);
29836
29837                   case details::expression_node<Type>::e_vovov : return compile_right_impl
29838                                                                     <typename vovov_t::sf3_type_node,ExternalType, vtype, vtype, vtype>
29839                                                                        (expr_gen, id, t, sf3node, result);
29840
29841                   default                                      : return false;
29842                }
29843             }
29844
29845             // (sf3ext) o T
29846             template <typename ExternalType>
29847             static inline bool compile_left(expression_generator<Type>& expr_gen,
29848                                             ExternalType t,
29849                                             const details::operator_type& operation,
29850                                             expression_node_ptr& sf3node,
29851                                             expression_node_ptr& result)
29852             {
29853                if (!details::is_sf3ext_node(sf3node))
29854                   return false;
29855
29856                typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr;
29857
29858                sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node);
29859
29860                const std::string id = "(" + n->type_id() + ")" + expr_gen.to_str(operation) + "t";
29861
29862                switch (n->type())
29863                {
29864                   case details::expression_node<Type>::e_covoc : return compile_left_impl
29865                                                                     <typename covoc_t::sf3_type_node,ExternalType, ctype, vtype, ctype>
29866                                                                        (expr_gen, id, t, sf3node, result);
29867
29868                   case details::expression_node<Type>::e_covov : return compile_left_impl
29869                                                                     <typename covov_t::sf3_type_node,ExternalType, ctype, vtype, vtype>
29870                                                                        (expr_gen, id, t, sf3node, result);
29871
29872                   case details::expression_node<Type>::e_vocov : return compile_left_impl
29873                                                                     <typename vocov_t::sf3_type_node,ExternalType, vtype, ctype, vtype>
29874                                                                        (expr_gen, id, t, sf3node, result);
29875
29876                   case details::expression_node<Type>::e_vovoc : return compile_left_impl
29877                                                                     <typename vovoc_t::sf3_type_node,ExternalType, vtype, vtype, ctype>
29878                                                                        (expr_gen, id, t, sf3node, result);
29879
29880                   case details::expression_node<Type>::e_vovov : return compile_left_impl
29881                                                                     <typename vovov_t::sf3_type_node,ExternalType, vtype, vtype, vtype>
29882                                                                        (expr_gen, id, t, sf3node, result);
29883
29884                   default                                      : return false;
29885                }
29886             }
29887
29888             template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2>
29889             static inline bool compile_right_impl(expression_generator<Type>& expr_gen,
29890                                                   const std::string& id,
29891                                                   ExternalType t,
29892                                                   expression_node_ptr& node,
29893                                                   expression_node_ptr& result)
29894             {
29895                SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node);
29896
29897                if (n)
29898                {
29899                   T0 t0 = n->t0();
29900                   T1 t1 = n->t1();
29901                   T2 t2 = n->t2();
29902
29903                   return synthesize_sf4ext_expression::template compile<ExternalType, T0, T1, T2>
29904                             (expr_gen, id, t, t0, t1, t2, result);
29905                }
29906                else
29907                   return false;
29908             }
29909
29910             template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2>
29911             static inline bool compile_left_impl(expression_generator<Type>& expr_gen,
29912                                                  const std::string& id,
29913                                                  ExternalType t,
29914                                                  expression_node_ptr& node,
29915                                                  expression_node_ptr& result)
29916             {
29917                SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node);
29918
29919                if (n)
29920                {
29921                   T0 t0 = n->t0();
29922                   T1 t1 = n->t1();
29923                   T2 t2 = n->t2();
29924
29925                   return synthesize_sf4ext_expression::template compile<T0, T1, T2, ExternalType>
29926                             (expr_gen, id, t0, t1, t2, t, result);
29927                }
29928                else
29929                   return false;
29930             }
29931          };
29932
29933          struct synthesize_vovov_expression0
29934          {
29935             typedef typename vovov_t::type0 node_type;
29936             typedef typename vovov_t::sf3_type sf3_type;
29937
29938             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
29939                                                       const details::operator_type& operation,
29940                                                       expression_node_ptr (&branch)[2])
29941             {
29942                // (v0 o0 v1) o1 (v2)
29943                const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
29944                const Type& v0 = vov->v0();
29945                const Type& v1 = vov->v1();
29946                const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
29947                const details::operator_type o0 = vov->operation();
29948                const details::operator_type o1 = operation;
29949
29950                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
29951                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
29952
29953                details::free_node(*(expr_gen.node_allocator_),branch[0]);
29954
29955                expression_node_ptr result = error_node();
29956
29957                if (expr_gen.parser_->settings_.strength_reduction_enabled())
29958                {
29959                   // (v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)
29960                   if ((details::e_div == o0) && (details::e_div == o1))
29961                   {
29962                      const bool synthesis_result =
29963                         synthesize_sf3ext_expression::
29964                            template compile<vtype,vtype,vtype>(expr_gen, "t/(t*t)", v0, v1, v2, result);
29965
29966                      exprtk_debug(("(v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)\n"));
29967
29968                      return (synthesis_result) ? result : error_node();
29969                   }
29970                }
29971
29972                const bool synthesis_result =
29973                   synthesize_sf3ext_expression::template compile<vtype, vtype, vtype>
29974                      (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result);
29975
29976                if (synthesis_result)
29977                   return result;
29978                else if (!expr_gen.valid_operator(o0,f0))
29979                   return error_node();
29980                else if (!expr_gen.valid_operator(o1,f1))
29981                   return error_node();
29982                else
29983                   return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1);
29984             }
29985
29986             static inline std::string id(expression_generator<Type>& expr_gen,
29987                                          const details::operator_type o0, const details::operator_type o1)
29988             {
29989                return details::build_string()
29990                          << "(t" << expr_gen.to_str(o0)
29991                          << "t)" << expr_gen.to_str(o1)
29992                          << "t";
29993             }
29994          };
29995
29996          struct synthesize_vovov_expression1
29997          {
29998             typedef typename vovov_t::type1 node_type;
29999             typedef typename vovov_t::sf3_type sf3_type;
30000
30001             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30002                                                       const details::operator_type& operation,
30003                                                       expression_node_ptr (&branch)[2])
30004             {
30005                // (v0) o0 (v1 o1 v2)
30006                const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
30007                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
30008                const Type& v1 = vov->v0();
30009                const Type& v2 = vov->v1();
30010                const details::operator_type o0 = operation;
30011                const details::operator_type o1 = vov->operation();
30012
30013                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30014                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30015
30016                details::free_node(*(expr_gen.node_allocator_),branch[1]);
30017
30018                expression_node_ptr result = error_node();
30019
30020                if (expr_gen.parser_->settings_.strength_reduction_enabled())
30021                {
30022                   // v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1
30023                   if ((details::e_div == o0) && (details::e_div == o1))
30024                   {
30025                      const bool synthesis_result =
30026                         synthesize_sf3ext_expression::
30027                            template compile<vtype,vtype,vtype>(expr_gen, "(t*t)/t", v0, v2, v1, result);
30028
30029                      exprtk_debug(("v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1\n"));
30030
30031                      return (synthesis_result) ? result : error_node();
30032                   }
30033                }
30034
30035                const bool synthesis_result =
30036                   synthesize_sf3ext_expression::template compile<vtype, vtype, vtype>
30037                      (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result);
30038
30039                if (synthesis_result)
30040                   return result;
30041                else if (!expr_gen.valid_operator(o0,f0))
30042                   return error_node();
30043                else if (!expr_gen.valid_operator(o1,f1))
30044                   return error_node();
30045                else
30046                   return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1);
30047             }
30048
30049             static inline std::string id(expression_generator<Type>& expr_gen,
30050                                          const details::operator_type o0, const details::operator_type o1)
30051             {
30052                return details::build_string()
30053                          << "t"  << expr_gen.to_str(o0)
30054                          << "(t" << expr_gen.to_str(o1)
30055                          << "t)";
30056             }
30057          };
30058
30059          struct synthesize_vovoc_expression0
30060          {
30061             typedef typename vovoc_t::type0 node_type;
30062             typedef typename vovoc_t::sf3_type sf3_type;
30063
30064             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30065                                                       const details::operator_type& operation,
30066                                                       expression_node_ptr (&branch)[2])
30067             {
30068                // (v0 o0 v1) o1 (c)
30069                const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
30070                const Type& v0 = vov->v0();
30071                const Type& v1 = vov->v1();
30072                const Type   c = static_cast<details::literal_node<Type>*>(branch[1])->value();
30073                const details::operator_type o0 = vov->operation();
30074                const details::operator_type o1 = operation;
30075
30076                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30077                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30078
30079                details::free_node(*(expr_gen.node_allocator_),branch[0]);
30080                details::free_node(*(expr_gen.node_allocator_),branch[1]);
30081
30082                expression_node_ptr result = error_node();
30083
30084                if (expr_gen.parser_->settings_.strength_reduction_enabled())
30085                {
30086                   // (v0 / v1) / c --> (vovoc) v0 / (v1 * c)
30087                   if ((details::e_div == o0) && (details::e_div == o1))
30088                   {
30089                      const bool synthesis_result =
30090                         synthesize_sf3ext_expression::
30091                            template compile<vtype,vtype,ctype>(expr_gen, "t/(t*t)", v0, v1, c, result);
30092
30093                      exprtk_debug(("(v0 / v1) / c --> (vovoc) v0 / (v1 * c)\n"));
30094
30095                      return (synthesis_result) ? result : error_node();
30096                   }
30097                }
30098
30099                const bool synthesis_result =
30100                   synthesize_sf3ext_expression::template compile<vtype, vtype, ctype>
30101                      (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result);
30102
30103                if (synthesis_result)
30104                   return result;
30105                else if (!expr_gen.valid_operator(o0,f0))
30106                   return error_node();
30107                else if (!expr_gen.valid_operator(o1,f1))
30108                   return error_node();
30109                else
30110                   return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1);
30111             }
30112
30113             static inline std::string id(expression_generator<Type>& expr_gen,
30114                                          const details::operator_type o0, const details::operator_type o1)
30115             {
30116                return details::build_string()
30117                          << "(t" << expr_gen.to_str(o0)
30118                          << "t)" << expr_gen.to_str(o1)
30119                          << "t";
30120             }
30121          };
30122
30123          struct synthesize_vovoc_expression1
30124          {
30125             typedef typename vovoc_t::type1 node_type;
30126             typedef typename vovoc_t::sf3_type sf3_type;
30127
30128             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30129                                                       const details::operator_type& operation,
30130                                                       expression_node_ptr (&branch)[2])
30131             {
30132                // (v0) o0 (v1 o1 c)
30133                const details::voc_base_node<Type>* voc = static_cast<const details::voc_base_node<Type>*>(branch[1]);
30134                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
30135                const Type& v1 = voc->v();
30136                const Type   c = voc->c();
30137                const details::operator_type o0 = operation;
30138                const details::operator_type o1 = voc->operation();
30139
30140                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30141                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30142
30143                details::free_node(*(expr_gen.node_allocator_),branch[1]);
30144
30145                expression_node_ptr result = error_node();
30146
30147                if (expr_gen.parser_->settings_.strength_reduction_enabled())
30148                {
30149                   // v0 / (v1 / c) --> (vocov) (v0 * c) / v1
30150                   if ((details::e_div == o0) && (details::e_div == o1))
30151                   {
30152                      const bool synthesis_result =
30153                         synthesize_sf3ext_expression::
30154                            template compile<vtype,ctype,vtype>(expr_gen, "(t*t)/t", v0, c, v1, result);
30155
30156                      exprtk_debug(("v0 / (v1 / c) --> (vocov) (v0 * c) / v1\n"));
30157
30158                      return (synthesis_result) ? result : error_node();
30159                   }
30160                }
30161
30162                const bool synthesis_result =
30163                   synthesize_sf3ext_expression::template compile<vtype, vtype, ctype>
30164                      (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result);
30165
30166                if (synthesis_result)
30167                   return result;
30168                else if (!expr_gen.valid_operator(o0,f0))
30169                   return error_node();
30170                else if (!expr_gen.valid_operator(o1,f1))
30171                   return error_node();
30172                else
30173                   return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1);
30174             }
30175
30176             static inline std::string id(expression_generator<Type>& expr_gen,
30177                                          const details::operator_type o0, const details::operator_type o1)
30178             {
30179                return details::build_string()
30180                          << "t"  << expr_gen.to_str(o0)
30181                          << "(t" << expr_gen.to_str(o1)
30182                          << "t)";
30183             }
30184          };
30185
30186          struct synthesize_vocov_expression0
30187          {
30188             typedef typename vocov_t::type0 node_type;
30189             typedef typename vocov_t::sf3_type sf3_type;
30190
30191             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30192                                                       const details::operator_type& operation,
30193                                                       expression_node_ptr (&branch)[2])
30194             {
30195                // (v0 o0 c) o1 (v1)
30196                const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
30197                const Type& v0 = voc->v();
30198                const Type   c = voc->c();
30199                const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
30200                const details::operator_type o0 = voc->operation();
30201                const details::operator_type o1 = operation;
30202
30203                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30204                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30205
30206                details::free_node(*(expr_gen.node_allocator_),branch[0]);
30207
30208                expression_node_ptr result = error_node();
30209
30210                if (expr_gen.parser_->settings_.strength_reduction_enabled())
30211                {
30212                   // (v0 / c) / v1 --> (vovoc) v0 / (v1 * c)
30213                   if ((details::e_div == o0) && (details::e_div == o1))
30214                   {
30215                      const bool synthesis_result =
30216                         synthesize_sf3ext_expression::
30217                            template compile<vtype,vtype,ctype>(expr_gen, "t/(t*t)", v0, v1, c, result);
30218
30219                      exprtk_debug(("(v0 / c) / v1 --> (vovoc) v0 / (v1 * c)\n"));
30220
30221                      return (synthesis_result) ? result : error_node();
30222                   }
30223                }
30224
30225                const bool synthesis_result =
30226                   synthesize_sf3ext_expression::template compile<vtype, ctype, vtype>
30227                      (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result);
30228
30229                if (synthesis_result)
30230                   return result;
30231                else if (!expr_gen.valid_operator(o0,f0))
30232                   return error_node();
30233                else if (!expr_gen.valid_operator(o1,f1))
30234                   return error_node();
30235                else
30236                   return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1);
30237             }
30238
30239             static inline std::string id(expression_generator<Type>& expr_gen,
30240                                          const details::operator_type o0, const details::operator_type o1)
30241             {
30242                return details::build_string()
30243                          << "(t" << expr_gen.to_str(o0)
30244                          << "t)" << expr_gen.to_str(o1)
30245                          << "t";
30246             }
30247          };
30248
30249          struct synthesize_vocov_expression1
30250          {
30251             typedef typename vocov_t::type1 node_type;
30252             typedef typename vocov_t::sf3_type sf3_type;
30253
30254             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30255                                                       const details::operator_type& operation,
30256                                                       expression_node_ptr (&branch)[2])
30257             {
30258                // (v0) o0 (c o1 v1)
30259                const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
30260                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
30261                const Type   c = cov->c();
30262                const Type& v1 = cov->v();
30263                const details::operator_type o0 = operation;
30264                const details::operator_type o1 = cov->operation();
30265
30266                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30267                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30268
30269                details::free_node(*(expr_gen.node_allocator_),branch[1]);
30270
30271                expression_node_ptr result = error_node();
30272
30273                if (expr_gen.parser_->settings_.strength_reduction_enabled())
30274                {
30275                   // v0 / (c / v1) --> (vovoc) (v0 * v1) / c
30276                   if ((details::e_div == o0) && (details::e_div == o1))
30277                   {
30278                      const bool synthesis_result =
30279                         synthesize_sf3ext_expression::
30280                            template compile<vtype, vtype, ctype>(expr_gen, "(t*t)/t", v0, v1, c, result);
30281
30282                      exprtk_debug(("v0 / (c / v1) --> (vovoc) (v0 * v1) / c\n"));
30283
30284                      return (synthesis_result) ? result : error_node();
30285                   }
30286                }
30287
30288                const bool synthesis_result =
30289                   synthesize_sf3ext_expression::template compile<vtype, ctype, vtype>
30290                      (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result);
30291
30292                if (synthesis_result)
30293                   return result;
30294                else if (!expr_gen.valid_operator(o0,f0))
30295                   return error_node();
30296                else if (!expr_gen.valid_operator(o1,f1))
30297                   return error_node();
30298                else
30299                   return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1);
30300             }
30301
30302             static inline std::string id(expression_generator<Type>& expr_gen,
30303                                          const details::operator_type o0, const details::operator_type o1)
30304             {
30305                return details::build_string()
30306                          << "t"  << expr_gen.to_str(o0)
30307                          << "(t" << expr_gen.to_str(o1)
30308                          << "t)";
30309             }
30310          };
30311
30312          struct synthesize_covov_expression0
30313          {
30314             typedef typename covov_t::type0 node_type;
30315             typedef typename covov_t::sf3_type sf3_type;
30316
30317             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30318                                                       const details::operator_type& operation,
30319                                                       expression_node_ptr (&branch)[2])
30320             {
30321                // (c o0 v0) o1 (v1)
30322                const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
30323                const Type   c = cov->c();
30324                const Type& v0 = cov->v();
30325                const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
30326                const details::operator_type o0 = cov->operation();
30327                const details::operator_type o1 = operation;
30328
30329                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30330                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30331
30332                details::free_node(*(expr_gen.node_allocator_),branch[0]);
30333
30334                expression_node_ptr result = error_node();
30335
30336                if (expr_gen.parser_->settings_.strength_reduction_enabled())
30337                {
30338                   // (c / v0) / v1 --> (covov) c / (v0 * v1)
30339                   if ((details::e_div == o0) && (details::e_div == o1))
30340                   {
30341                      const bool synthesis_result =
30342                         synthesize_sf3ext_expression::
30343                            template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", c, v0, v1, result);
30344
30345                      exprtk_debug(("(c / v0) / v1 --> (covov) c / (v0 * v1)\n"));
30346
30347                      return (synthesis_result) ? result : error_node();
30348                   }
30349                }
30350
30351                const bool synthesis_result =
30352                   synthesize_sf3ext_expression::template compile<ctype, vtype, vtype>
30353                      (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result);
30354
30355                if (synthesis_result)
30356                   return result;
30357                else if (!expr_gen.valid_operator(o0,f0))
30358                   return error_node();
30359                else if (!expr_gen.valid_operator(o1,f1))
30360                   return error_node();
30361                else
30362                   return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1);
30363             }
30364
30365             static inline std::string id(expression_generator<Type>& expr_gen,
30366                                          const details::operator_type o0, const details::operator_type o1)
30367             {
30368                return details::build_string()
30369                          << "(t" << expr_gen.to_str(o0)
30370                          << "t)" << expr_gen.to_str(o1)
30371                          << "t";
30372             }
30373          };
30374
30375          struct synthesize_covov_expression1
30376          {
30377             typedef typename covov_t::type1 node_type;
30378             typedef typename covov_t::sf3_type sf3_type;
30379
30380             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30381                                                       const details::operator_type& operation,
30382                                                       expression_node_ptr (&branch)[2])
30383             {
30384                // (c) o0 (v0 o1 v1)
30385                const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
30386                const Type   c = static_cast<details::literal_node<Type>*>(branch[0])->value();
30387                const Type& v0 = vov->v0();
30388                const Type& v1 = vov->v1();
30389                const details::operator_type o0 = operation;
30390                const details::operator_type o1 = vov->operation();
30391
30392                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30393                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30394
30395                details::free_node(*(expr_gen.node_allocator_),branch[0]);
30396                details::free_node(*(expr_gen.node_allocator_),branch[1]);
30397
30398                expression_node_ptr result = error_node();
30399
30400                if (expr_gen.parser_->settings_.strength_reduction_enabled())
30401                {
30402                   // c / (v0 / v1) --> (covov) (c * v1) / v0
30403                   if ((details::e_div == o0) && (details::e_div == o1))
30404                   {
30405                      const bool synthesis_result =
30406                         synthesize_sf3ext_expression::
30407                            template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", c, v1, v0, result);
30408
30409                      exprtk_debug(("c / (v0 / v1) --> (covov) (c * v1) / v0\n"));
30410
30411                      return (synthesis_result) ? result : error_node();
30412                   }
30413                }
30414
30415                const bool synthesis_result =
30416                   synthesize_sf3ext_expression::template compile<ctype, vtype, vtype>
30417                      (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result);
30418
30419                if (synthesis_result)
30420                   return result;
30421                else if (!expr_gen.valid_operator(o0,f0))
30422                   return error_node();
30423                else if (!expr_gen.valid_operator(o1,f1))
30424                   return error_node();
30425                else
30426                   return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1);
30427             }
30428
30429             static inline std::string id(expression_generator<Type>& expr_gen, const details::operator_type o0, const details::operator_type o1)
30430             {
30431                return details::build_string()
30432                          << "t"  << expr_gen.to_str(o0)
30433                          << "(t" << expr_gen.to_str(o1)
30434                          << "t)";
30435             }
30436          };
30437
30438          struct synthesize_covoc_expression0
30439          {
30440             typedef typename covoc_t::type0 node_type;
30441             typedef typename covoc_t::sf3_type sf3_type;
30442
30443             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30444                                                       const details::operator_type& operation,
30445                                                       expression_node_ptr (&branch)[2])
30446             {
30447                // (c0 o0 v) o1 (c1)
30448                const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
30449                const Type  c0 = cov->c();
30450                const Type&  v = cov->v();
30451                const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
30452                const details::operator_type o0 = cov->operation();
30453                const details::operator_type o1 = operation;
30454
30455                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30456                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30457
30458                details::free_node(*(expr_gen.node_allocator_),branch[0]);
30459                details::free_node(*(expr_gen.node_allocator_),branch[1]);
30460
30461                expression_node_ptr result = error_node();
30462
30463                if (expr_gen.parser_->settings_.strength_reduction_enabled())
30464                {
30465                   // (c0 + v) + c1 --> (cov) (c0 + c1) + v
30466                   if ((details::e_add == o0) && (details::e_add == o1))
30467                   {
30468                      exprtk_debug(("(c0 + v) + c1 --> (cov) (c0 + c1) + v\n"));
30469
30470                      return expr_gen.node_allocator_->
30471                                template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v);
30472                   }
30473                   // (c0 + v) - c1 --> (cov) (c0 - c1) + v
30474                   else if ((details::e_add == o0) && (details::e_sub == o1))
30475                   {
30476                      exprtk_debug(("(c0 + v) - c1 --> (cov) (c0 - c1) + v\n"));
30477
30478                      return expr_gen.node_allocator_->
30479                                template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v);
30480                   }
30481                   // (c0 - v) + c1 --> (cov) (c0 + c1) - v
30482                   else if ((details::e_sub == o0) && (details::e_add == o1))
30483                   {
30484                      exprtk_debug(("(c0 - v) + c1 --> (cov) (c0 + c1) - v\n"));
30485
30486                      return expr_gen.node_allocator_->
30487                                template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v);
30488                   }
30489                   // (c0 - v) - c1 --> (cov) (c0 - c1) - v
30490                   else if ((details::e_sub == o0) && (details::e_sub == o1))
30491                   {
30492                      exprtk_debug(("(c0 - v) - c1 --> (cov) (c0 - c1) - v\n"));
30493
30494                      return expr_gen.node_allocator_->
30495                                template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v);
30496                   }
30497                   // (c0 * v) * c1 --> (cov) (c0 * c1) * v
30498                   else if ((details::e_mul == o0) && (details::e_mul == o1))
30499                   {
30500                      exprtk_debug(("(c0 * v) * c1 --> (cov) (c0 * c1) * v\n"));
30501
30502                      return expr_gen.node_allocator_->
30503                                template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v);
30504                   }
30505                   // (c0 * v) / c1 --> (cov) (c0 / c1) * v
30506                   else if ((details::e_mul == o0) && (details::e_div == o1))
30507                   {
30508                      exprtk_debug(("(c0 * v) / c1 --> (cov) (c0 / c1) * v\n"));
30509
30510                      return expr_gen.node_allocator_->
30511                                template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v);
30512                   }
30513                   // (c0 / v) * c1 --> (cov) (c0 * c1) / v
30514                   else if ((details::e_div == o0) && (details::e_mul == o1))
30515                   {
30516                      exprtk_debug(("(c0 / v) * c1 --> (cov) (c0 * c1) / v\n"));
30517
30518                      return expr_gen.node_allocator_->
30519                                template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v);
30520                   }
30521                   // (c0 / v) / c1 --> (cov) (c0 / c1) / v
30522                   else if ((details::e_div == o0) && (details::e_div == o1))
30523                   {
30524                      exprtk_debug(("(c0 / v) / c1 --> (cov) (c0 / c1) / v\n"));
30525
30526                      return expr_gen.node_allocator_->
30527                                template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v);
30528                   }
30529                }
30530
30531                const bool synthesis_result =
30532                   synthesize_sf3ext_expression::template compile<ctype, vtype, ctype>
30533                      (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result);
30534
30535                if (synthesis_result)
30536                   return result;
30537                else if (!expr_gen.valid_operator(o0,f0))
30538                   return error_node();
30539                else if (!expr_gen.valid_operator(o1,f1))
30540                   return error_node();
30541                else
30542                   return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1);
30543             }
30544
30545             static inline std::string id(expression_generator<Type>& expr_gen,
30546                                          const details::operator_type o0, const details::operator_type o1)
30547             {
30548                return details::build_string()
30549                          << "(t" << expr_gen.to_str(o0)
30550                          << "t)" << expr_gen.to_str(o1)
30551                          << "t";
30552             }
30553          };
30554
30555          struct synthesize_covoc_expression1
30556          {
30557             typedef typename covoc_t::type1 node_type;
30558             typedef typename covoc_t::sf3_type sf3_type;
30559
30560             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30561                                                       const details::operator_type& operation,
30562                                                       expression_node_ptr (&branch)[2])
30563             {
30564                // (c0) o0 (v o1 c1)
30565                const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);
30566                const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
30567                const Type&  v = voc->v();
30568                const Type  c1 = voc->c();
30569                const details::operator_type o0 = operation;
30570                const details::operator_type o1 = voc->operation();
30571
30572                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30573                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30574
30575                details::free_node(*(expr_gen.node_allocator_),branch[0]);
30576                details::free_node(*(expr_gen.node_allocator_),branch[1]);
30577
30578                expression_node_ptr result = error_node();
30579
30580                if (expr_gen.parser_->settings_.strength_reduction_enabled())
30581                {
30582                   // (c0) + (v + c1) --> (cov) (c0 + c1) + v
30583                   if ((details::e_add == o0) && (details::e_add == o1))
30584                   {
30585                      exprtk_debug(("(c0) + (v + c1) --> (cov) (c0 + c1) + v\n"));
30586
30587                      return expr_gen.node_allocator_->
30588                                template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v);
30589                   }
30590                   // (c0) + (v - c1) --> (cov) (c0 - c1) + v
30591                   else if ((details::e_add == o0) && (details::e_sub == o1))
30592                   {
30593                      exprtk_debug(("(c0) + (v - c1) --> (cov) (c0 - c1) + v\n"));
30594
30595                      return expr_gen.node_allocator_->
30596                                template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v);
30597                   }
30598                   // (c0) - (v + c1) --> (cov) (c0 - c1) - v
30599                   else if ((details::e_sub == o0) && (details::e_add == o1))
30600                   {
30601                      exprtk_debug(("(c0) - (v + c1) --> (cov) (c0 - c1) - v\n"));
30602
30603                      return expr_gen.node_allocator_->
30604                                template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v);
30605                   }
30606                   // (c0) - (v - c1) --> (cov) (c0 + c1) - v
30607                   else if ((details::e_sub == o0) && (details::e_sub == o1))
30608                   {
30609                      exprtk_debug(("(c0) - (v - c1) --> (cov) (c0 + c1) - v\n"));
30610
30611                      return expr_gen.node_allocator_->
30612                                template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v);
30613                   }
30614                   // (c0) * (v * c1) --> (voc) v * (c0 * c1)
30615                   else if ((details::e_mul == o0) && (details::e_mul == o1))
30616                   {
30617                      exprtk_debug(("(c0) * (v * c1) --> (voc) v * (c0 * c1)\n"));
30618
30619                      return expr_gen.node_allocator_->
30620                                template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v);
30621                   }
30622                   // (c0) * (v / c1) --> (cov) (c0 / c1) * v
30623                   else if ((details::e_mul == o0) && (details::e_div == o1))
30624                   {
30625                      exprtk_debug(("(c0) * (v / c1) --> (cov) (c0 / c1) * v\n"));
30626
30627                      return expr_gen.node_allocator_->
30628                                template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v);
30629                   }
30630                   // (c0) / (v * c1) --> (cov) (c0 / c1) / v
30631                   else if ((details::e_div == o0) && (details::e_mul == o1))
30632                   {
30633                      exprtk_debug(("(c0) / (v * c1) --> (cov) (c0 / c1) / v\n"));
30634
30635                      return expr_gen.node_allocator_->
30636                                template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v);
30637                   }
30638                   // (c0) / (v / c1) --> (cov) (c0 * c1) / v
30639                   else if ((details::e_div == o0) && (details::e_div == o1))
30640                   {
30641                      exprtk_debug(("(c0) / (v / c1) --> (cov) (c0 * c1) / v\n"));
30642
30643                      return expr_gen.node_allocator_->
30644                                template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v);
30645                   }
30646                }
30647
30648                const bool synthesis_result =
30649                   synthesize_sf3ext_expression::template compile<ctype, vtype, ctype>
30650                      (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result);
30651
30652                if (synthesis_result)
30653                   return result;
30654                else if (!expr_gen.valid_operator(o0,f0))
30655                   return error_node();
30656                else if (!expr_gen.valid_operator(o1,f1))
30657                   return error_node();
30658                else
30659                   return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1);
30660             }
30661
30662             static inline std::string id(expression_generator<Type>& expr_gen,
30663                                          const details::operator_type o0, const details::operator_type o1)
30664             {
30665                return details::build_string()
30666                          << "t"  << expr_gen.to_str(o0)
30667                          << "(t" << expr_gen.to_str(o1)
30668                          << "t)";
30669             }
30670          };
30671
30672          struct synthesize_cocov_expression0
30673          {
30674             typedef typename cocov_t::type0 node_type;
30675             static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
30676             {
30677                // (c0 o0 c1) o1 (v) - Not possible.
30678                return error_node();
30679             }
30680          };
30681
30682          struct synthesize_cocov_expression1
30683          {
30684             typedef typename cocov_t::type1 node_type;
30685             typedef typename cocov_t::sf3_type sf3_type;
30686
30687             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30688                                                       const details::operator_type& operation,
30689                                                       expression_node_ptr (&branch)[2])
30690             {
30691                // (c0) o0 (c1 o1 v)
30692                const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
30693                const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
30694                const Type  c1 = cov->c();
30695                const Type&  v = cov->v();
30696                const details::operator_type o0 = operation;
30697                const details::operator_type o1 = cov->operation();
30698
30699                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30700                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30701
30702                details::free_node(*(expr_gen.node_allocator_),branch[0]);
30703                details::free_node(*(expr_gen.node_allocator_),branch[1]);
30704
30705                expression_node_ptr result = error_node();
30706
30707                if (expr_gen.parser_->settings_.strength_reduction_enabled())
30708                {
30709                   // (c0) + (c1 + v) --> (cov) (c0 + c1) + v
30710                   if ((details::e_add == o0) && (details::e_add == o1))
30711                   {
30712                      exprtk_debug(("(c0) + (c1 + v) --> (cov) (c0 + c1) + v\n"));
30713
30714                      return expr_gen.node_allocator_->
30715                                template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v);
30716                   }
30717                   // (c0) + (c1 - v) --> (cov) (c0 + c1) - v
30718                   else if ((details::e_add == o0) && (details::e_sub == o1))
30719                   {
30720                      exprtk_debug(("(c0) + (c1 - v) --> (cov) (c0 + c1) - v\n"));
30721
30722                      return expr_gen.node_allocator_->
30723                                template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v);
30724                   }
30725                   // (c0) - (c1 + v) --> (cov) (c0 - c1) - v
30726                   else if ((details::e_sub == o0) && (details::e_add == o1))
30727                   {
30728                      exprtk_debug(("(c0) - (c1 + v) --> (cov) (c0 - c1) - v\n"));
30729
30730                      return expr_gen.node_allocator_->
30731                                template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v);
30732                   }
30733                   // (c0) - (c1 - v) --> (cov) (c0 - c1) + v
30734                   else if ((details::e_sub == o0) && (details::e_sub == o1))
30735                   {
30736                      exprtk_debug(("(c0) - (c1 - v) --> (cov) (c0 - c1) + v\n"));
30737
30738                      return expr_gen.node_allocator_->
30739                                template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v);
30740                   }
30741                   // (c0) * (c1 * v) --> (cov) (c0 * c1) * v
30742                   else if ((details::e_mul == o0) && (details::e_mul == o1))
30743                   {
30744                      exprtk_debug(("(c0) * (c1 * v) --> (cov) (c0 * c1) * v\n"));
30745
30746                      return expr_gen.node_allocator_->
30747                                template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v);
30748                   }
30749                   // (c0) * (c1 / v) --> (cov) (c0 * c1) / v
30750                   else if ((details::e_mul == o0) && (details::e_div == o1))
30751                   {
30752                      exprtk_debug(("(c0) * (c1 / v) --> (cov) (c0 * c1) / v\n"));
30753
30754                      return expr_gen.node_allocator_->
30755                                template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v);
30756                   }
30757                   // (c0) / (c1 * v) --> (cov) (c0 / c1) / v
30758                   else if ((details::e_div == o0) && (details::e_mul == o1))
30759                   {
30760                      exprtk_debug(("(c0) / (c1 * v) --> (cov) (c0 / c1) / v\n"));
30761
30762                      return expr_gen.node_allocator_->
30763                                template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v);
30764                   }
30765                   // (c0) / (c1 / v) --> (cov) (c0 / c1) * v
30766                   else if ((details::e_div == o0) && (details::e_div == o1))
30767                   {
30768                      exprtk_debug(("(c0) / (c1 / v) --> (cov) (c0 / c1) * v\n"));
30769
30770                      return expr_gen.node_allocator_->
30771                                template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v);
30772                   }
30773                }
30774
30775                const bool synthesis_result =
30776                   synthesize_sf3ext_expression::template compile<ctype, ctype, vtype>
30777                      (expr_gen, id(expr_gen, o0, o1), c0, c1, v, result);
30778
30779                if (synthesis_result)
30780                   return result;
30781                else if (!expr_gen.valid_operator(o0,f0))
30782                   return error_node();
30783                else if (!expr_gen.valid_operator(o1,f1))
30784                   return error_node();
30785                else
30786                   return node_type::allocate(*(expr_gen.node_allocator_), c0, c1, v, f0, f1);
30787             }
30788
30789             static inline std::string id(expression_generator<Type>& expr_gen, const details::operator_type o0, const details::operator_type o1)
30790             {
30791                return details::build_string()
30792                          << "t"  << expr_gen.to_str(o0)
30793                          << "(t" << expr_gen.to_str(o1)
30794                          << "t)";
30795             }
30796          };
30797
30798          struct synthesize_vococ_expression0
30799          {
30800             typedef typename vococ_t::type0 node_type;
30801             typedef typename vococ_t::sf3_type sf3_type;
30802
30803             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30804                                                       const details::operator_type& operation,
30805                                                       expression_node_ptr (&branch)[2])
30806             {
30807                // (v o0 c0) o1 (c1)
30808                const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
30809                const Type&  v = voc->v();
30810                const Type& c0 = voc->c();
30811                const Type& c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
30812                const details::operator_type o0 = voc->operation();
30813                const details::operator_type o1 = operation;
30814
30815                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30816                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30817
30818                details::free_node(*(expr_gen.node_allocator_),branch[0]);
30819                details::free_node(*(expr_gen.node_allocator_),branch[1]);
30820
30821                expression_node_ptr result = error_node();
30822
30823                if (expr_gen.parser_->settings_.strength_reduction_enabled())
30824                {
30825                   // (v + c0) + c1 --> (voc) v + (c0 + c1)
30826                   if ((details::e_add == o0) && (details::e_add == o1))
30827                   {
30828                      exprtk_debug(("(v + c0) + c1 --> (voc) v + (c0 + c1)\n"));
30829
30830                      return expr_gen.node_allocator_->
30831                                template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c0 + c1);
30832                   }
30833                   // (v + c0) - c1 --> (voc) v + (c0 - c1)
30834                   else if ((details::e_add == o0) && (details::e_sub == o1))
30835                   {
30836                      exprtk_debug(("(v + c0) - c1 --> (voc) v + (c0 - c1)\n"));
30837
30838                      return expr_gen.node_allocator_->
30839                                template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c0 - c1);
30840                   }
30841                   // (v - c0) + c1 --> (voc) v - (c0 + c1)
30842                   else if ((details::e_sub == o0) && (details::e_add == o1))
30843                   {
30844                      exprtk_debug(("(v - c0) + c1 --> (voc) v - (c0 + c1)\n"));
30845
30846                      return expr_gen.node_allocator_->
30847                                template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c1 - c0);
30848                   }
30849                   // (v - c0) - c1 --> (voc) v - (c0 + c1)
30850                   else if ((details::e_sub == o0) && (details::e_sub == o1))
30851                   {
30852                      exprtk_debug(("(v - c0) - c1 --> (voc) v - (c0 + c1)\n"));
30853
30854                      return expr_gen.node_allocator_->
30855                                template allocate_rc<typename details::voc_node<Type,details::sub_op<Type> > >(v, c0 + c1);
30856                   }
30857                   // (v * c0) * c1 --> (voc) v * (c0 * c1)
30858                   else if ((details::e_mul == o0) && (details::e_mul == o1))
30859                   {
30860                      exprtk_debug(("(v * c0) * c1 --> (voc) v * (c0 * c1)\n"));
30861
30862                      return expr_gen.node_allocator_->
30863                                template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c0 * c1);
30864                   }
30865                   // (v * c0) / c1 --> (voc) v * (c0 / c1)
30866                   else if ((details::e_mul == o0) && (details::e_div == o1))
30867                   {
30868                      exprtk_debug(("(v * c0) / c1 --> (voc) v * (c0 / c1)\n"));
30869
30870                      return expr_gen.node_allocator_->
30871                                template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c0 / c1);
30872                   }
30873                   // (v / c0) * c1 --> (voc) v * (c1 / c0)
30874                   else if ((details::e_div == o0) && (details::e_mul == o1))
30875                   {
30876                      exprtk_debug(("(v / c0) * c1 --> (voc) v * (c1 / c0)\n"));
30877
30878                      return expr_gen.node_allocator_->
30879                                template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c1 / c0);
30880                   }
30881                   // (v / c0) / c1 --> (voc) v / (c0 * c1)
30882                   else if ((details::e_div == o0) && (details::e_div == o1))
30883                   {
30884                      exprtk_debug(("(v / c0) / c1 --> (voc) v / (c0 * c1)\n"));
30885
30886                      return expr_gen.node_allocator_->
30887                                template allocate_rc<typename details::voc_node<Type,details::div_op<Type> > >(v, c0 * c1);
30888                   }
30889                   // (v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1)
30890                   else if ((details::e_pow == o0) && (details::e_pow == o1))
30891                   {
30892                      exprtk_debug(("(v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1)\n"));
30893
30894                      return expr_gen.node_allocator_->
30895                                template allocate_rc<typename details::voc_node<Type,details::pow_op<Type> > >(v, c0 * c1);
30896                   }
30897                }
30898
30899                const bool synthesis_result =
30900                   synthesize_sf3ext_expression::template compile<vtype, ctype, ctype>
30901                      (expr_gen, id(expr_gen, o0, o1), v, c0, c1, result);
30902
30903                if (synthesis_result)
30904                   return result;
30905                else if (!expr_gen.valid_operator(o0,f0))
30906                   return error_node();
30907                else if (!expr_gen.valid_operator(o1,f1))
30908                   return error_node();
30909                else
30910                   return node_type::allocate(*(expr_gen.node_allocator_), v, c0, c1, f0, f1);
30911             }
30912
30913             static inline std::string id(expression_generator<Type>& expr_gen,
30914                                          const details::operator_type o0, const details::operator_type o1)
30915             {
30916                return details::build_string()
30917                          << "(t" << expr_gen.to_str(o0)
30918                          << "t)" << expr_gen.to_str(o1)
30919                          << "t";
30920             }
30921          };
30922
30923          struct synthesize_vococ_expression1
30924          {
30925             typedef typename vococ_t::type0 node_type;
30926
30927             static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
30928             {
30929                // (v) o0 (c0 o1 c1) - Not possible.
30930                exprtk_debug(("(v) o0 (c0 o1 c1) - Not possible.\n"));
30931                return error_node();
30932             }
30933          };
30934
30935          struct synthesize_vovovov_expression0
30936          {
30937             typedef typename vovovov_t::type0 node_type;
30938             typedef typename vovovov_t::sf4_type sf4_type;
30939             typedef typename node_type::T0 T0;
30940             typedef typename node_type::T1 T1;
30941             typedef typename node_type::T2 T2;
30942             typedef typename node_type::T3 T3;
30943
30944             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
30945                                                       const details::operator_type& operation,
30946                                                       expression_node_ptr (&branch)[2])
30947             {
30948                // (v0 o0 v1) o1 (v2 o2 v3)
30949                const details::vov_base_node<Type>* vov0 = static_cast<details::vov_base_node<Type>*>(branch[0]);
30950                const details::vov_base_node<Type>* vov1 = static_cast<details::vov_base_node<Type>*>(branch[1]);
30951                const Type& v0 = vov0->v0();
30952                const Type& v1 = vov0->v1();
30953                const Type& v2 = vov1->v0();
30954                const Type& v3 = vov1->v1();
30955                const details::operator_type o0 = vov0->operation();
30956                const details::operator_type o1 = operation;
30957                const details::operator_type o2 = vov1->operation();
30958
30959                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30960                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30961                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
30962
30963                details::free_node(*(expr_gen.node_allocator_),branch[0]);
30964                details::free_node(*(expr_gen.node_allocator_),branch[1]);
30965
30966                expression_node_ptr result = error_node();
30967
30968                if (expr_gen.parser_->settings_.strength_reduction_enabled())
30969                {
30970                   // (v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)
30971                   if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
30972                   {
30973                      const bool synthesis_result =
30974                         synthesize_sf4ext_expression::
30975                            template compile<vtype,vtype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, v3, result);
30976
30977                      exprtk_debug(("(v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)\n"));
30978
30979                      return (synthesis_result) ? result : error_node();
30980                   }
30981                   // (v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)
30982                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
30983                   {
30984                      const bool synthesis_result =
30985                         synthesize_sf4ext_expression::
30986                            template compile<vtype,vtype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", v0, v3, v1, v2, result);
30987
30988                      exprtk_debug(("(v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)\n"));
30989
30990                      return (synthesis_result) ? result : error_node();
30991                   }
30992                   // (v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)
30993                   else if ((details::e_add == o0) && (details::e_div == o1) && (details::e_div == o2))
30994                   {
30995                      const bool synthesis_result =
30996                         synthesize_sf4ext_expression::
30997                            template compile<vtype,vtype,vtype,vtype>(expr_gen, "(t+t)*(t/t)", v0, v1, v3, v2, result);
30998
30999                      exprtk_debug(("(v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)\n"));
31000
31001                      return (synthesis_result) ? result : error_node();
31002                   }
31003                   // (v0 - v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)
31004                   else if ((details::e_sub == o0) && (details::e_div == o1) && (details::e_div == o2))
31005                   {
31006                      const bool synthesis_result =
31007                         synthesize_sf4ext_expression::
31008                            template compile<vtype,vtype,vtype,vtype>(expr_gen, "(t-t)*(t/t)", v0, v1, v3, v2, result);
31009
31010                      exprtk_debug(("(v0 - v1) / (v2 / v3) --> (vovovov) (v0 - v1) * (v3 / v2)\n"));
31011
31012                      return (synthesis_result) ? result : error_node();
31013                   }
31014                   // (v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2
31015                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
31016                   {
31017                      const bool synthesis_result =
31018                         synthesize_sf4ext_expression::
31019                            template compile<vtype,vtype,vtype,vtype>(expr_gen, "((t*t)*t)/t", v0, v1, v3, v2, result);
31020
31021                      exprtk_debug(("(v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2\n"));
31022
31023                      return (synthesis_result) ? result : error_node();
31024                   }
31025                }
31026
31027                const bool synthesis_result =
31028                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
31029                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
31030
31031                if (synthesis_result)
31032                   return result;
31033                else if (!expr_gen.valid_operator(o0,f0))
31034                   return error_node();
31035                else if (!expr_gen.valid_operator(o1,f1))
31036                   return error_node();
31037                else if (!expr_gen.valid_operator(o2,f2))
31038                   return error_node();
31039                else
31040                   return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
31041             }
31042
31043             static inline std::string id(expression_generator<Type>& expr_gen,
31044                                          const details::operator_type o0,
31045                                          const details::operator_type o1,
31046                                          const details::operator_type o2)
31047             {
31048                return details::build_string()
31049                          << "(t" << expr_gen.to_str(o0)
31050                          << "t)" << expr_gen.to_str(o1)
31051                          << "(t" << expr_gen.to_str(o2)
31052                          << "t)";
31053             }
31054          };
31055
31056          struct synthesize_vovovoc_expression0
31057          {
31058             typedef typename vovovoc_t::type0 node_type;
31059             typedef typename vovovoc_t::sf4_type sf4_type;
31060             typedef typename node_type::T0 T0;
31061             typedef typename node_type::T1 T1;
31062             typedef typename node_type::T2 T2;
31063             typedef typename node_type::T3 T3;
31064
31065             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
31066                                                       const details::operator_type& operation,
31067                                                       expression_node_ptr (&branch)[2])
31068             {
31069                // (v0 o0 v1) o1 (v2 o2 c)
31070                const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
31071                const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);
31072                const Type& v0 = vov->v0();
31073                const Type& v1 = vov->v1();
31074                const Type& v2 = voc->v ();
31075                const Type   c = voc->c ();
31076                const details::operator_type o0 = vov->operation();
31077                const details::operator_type o1 = operation;
31078                const details::operator_type o2 = voc->operation();
31079
31080                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31081                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31082                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
31083
31084                details::free_node(*(expr_gen.node_allocator_),branch[0]);
31085                details::free_node(*(expr_gen.node_allocator_),branch[1]);
31086
31087                expression_node_ptr result = error_node();
31088
31089                if (expr_gen.parser_->settings_.strength_reduction_enabled())
31090                {
31091                   // (v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c)
31092                   if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
31093                   {
31094                      const bool synthesis_result =
31095                         synthesize_sf4ext_expression::
31096                            template compile<vtype,vtype,vtype,ctype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result);
31097
31098                      exprtk_debug(("(v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c)\n"));
31099
31100                      return (synthesis_result) ? result : error_node();
31101                   }
31102                   // (v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2)
31103                   if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
31104                   {
31105                      const bool synthesis_result =
31106                         synthesize_sf4ext_expression::
31107                            template compile<vtype,ctype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result);
31108
31109                      exprtk_debug(("(v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2)\n"));
31110
31111                      return (synthesis_result) ? result : error_node();
31112                   }
31113                }
31114
31115                const bool synthesis_result =
31116                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
31117                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
31118
31119                if (synthesis_result)
31120                   return result;
31121                else if (!expr_gen.valid_operator(o0,f0))
31122                   return error_node();
31123                else if (!expr_gen.valid_operator(o1,f1))
31124                   return error_node();
31125                else if (!expr_gen.valid_operator(o2,f2))
31126                   return error_node();
31127                else
31128                   return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
31129             }
31130
31131             static inline std::string id(expression_generator<Type>& expr_gen,
31132                                          const details::operator_type o0,
31133                                          const details::operator_type o1,
31134                                          const details::operator_type o2)
31135             {
31136                return details::build_string()
31137                          << "(t" << expr_gen.to_str(o0)
31138                          << "t)" << expr_gen.to_str(o1)
31139                          << "(t" << expr_gen.to_str(o2)
31140                          << "t)";
31141             }
31142          };
31143
31144          struct synthesize_vovocov_expression0
31145          {
31146             typedef typename vovocov_t::type0 node_type;
31147             typedef typename vovocov_t::sf4_type sf4_type;
31148             typedef typename node_type::T0 T0;
31149             typedef typename node_type::T1 T1;
31150             typedef typename node_type::T2 T2;
31151             typedef typename node_type::T3 T3;
31152
31153             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
31154                                                       const details::operator_type& operation,
31155                                                       expression_node_ptr (&branch)[2])
31156             {
31157                // (v0 o0 v1) o1 (c o2 v2)
31158                const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
31159                const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
31160                const Type& v0 = vov->v0();
31161                const Type& v1 = vov->v1();
31162                const Type& v2 = cov->v ();
31163                const Type   c = cov->c ();
31164                const details::operator_type o0 = vov->operation();
31165                const details::operator_type o1 = operation;
31166                const details::operator_type o2 = cov->operation();
31167
31168                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31169                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31170                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
31171
31172                details::free_node(*(expr_gen.node_allocator_),branch[0]);
31173                details::free_node(*(expr_gen.node_allocator_),branch[1]);
31174
31175                expression_node_ptr result = error_node();
31176
31177                if (expr_gen.parser_->settings_.strength_reduction_enabled())
31178                {
31179                   // (v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2)
31180                   if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
31181                   {
31182                      const bool synthesis_result =
31183                         synthesize_sf4ext_expression::
31184                            template compile<vtype,ctype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result);
31185
31186                      exprtk_debug(("(v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2)\n"));
31187
31188                      return (synthesis_result) ? result : error_node();
31189                   }
31190                   // (v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c)
31191                   if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
31192                   {
31193                      const bool synthesis_result =
31194                         synthesize_sf4ext_expression::
31195                            template compile<vtype,vtype,vtype,ctype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result);
31196
31197                      exprtk_debug(("(v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c)\n"));
31198
31199                      return (synthesis_result) ? result : error_node();
31200                   }
31201                }
31202
31203                const bool synthesis_result =
31204                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
31205                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
31206
31207                if (synthesis_result)
31208                   return result;
31209                else if (!expr_gen.valid_operator(o0,f0))
31210                   return error_node();
31211                else if (!expr_gen.valid_operator(o1,f1))
31212                   return error_node();
31213                else if (!expr_gen.valid_operator(o2,f2))
31214                   return error_node();
31215                else
31216                   return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
31217             }
31218
31219             static inline std::string id(expression_generator<Type>& expr_gen,
31220                                          const details::operator_type o0,
31221                                          const details::operator_type o1,
31222                                          const details::operator_type o2)
31223             {
31224                return details::build_string()
31225                          << "(t" << expr_gen.to_str(o0)
31226                          << "t)" << expr_gen.to_str(o1)
31227                          << "(t" << expr_gen.to_str(o2)
31228                          << "t)";
31229             }
31230          };
31231
31232          struct synthesize_vocovov_expression0
31233          {
31234             typedef typename vocovov_t::type0 node_type;
31235             typedef typename vocovov_t::sf4_type sf4_type;
31236             typedef typename node_type::T0 T0;
31237             typedef typename node_type::T1 T1;
31238             typedef typename node_type::T2 T2;
31239             typedef typename node_type::T3 T3;
31240
31241             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
31242                                                       const details::operator_type& operation,
31243                                                       expression_node_ptr (&branch)[2])
31244             {
31245                // (v0 o0 c) o1 (v1 o2 v2)
31246                const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
31247                const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
31248                const Type   c = voc->c ();
31249                const Type& v0 = voc->v ();
31250                const Type& v1 = vov->v0();
31251                const Type& v2 = vov->v1();
31252                const details::operator_type o0 = voc->operation();
31253                const details::operator_type o1 = operation;
31254                const details::operator_type o2 = vov->operation();
31255
31256                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31257                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31258                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
31259
31260                details::free_node(*(expr_gen.node_allocator_),branch[0]);
31261                details::free_node(*(expr_gen.node_allocator_),branch[1]);
31262
31263                expression_node_ptr result = error_node();
31264
31265                if (expr_gen.parser_->settings_.strength_reduction_enabled())
31266                {
31267                   // (v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2)
31268                   if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
31269                   {
31270                      const bool synthesis_result =
31271                         synthesize_sf4ext_expression::
31272                            template compile<vtype,vtype,ctype,vtype>(expr_gen, "(t*t)/(t*t)", v0, v1, c, v2, result);
31273
31274                      exprtk_debug(("(v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2)\n"));
31275
31276                      return (synthesis_result) ? result : error_node();
31277                   }
31278                   // (v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1)
31279                   if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
31280                   {
31281                      const bool synthesis_result =
31282                         synthesize_sf4ext_expression::
31283                            template compile<vtype,vtype,ctype,vtype>(expr_gen, "(t*t)/(t*t)", v0, v2, c, v1, result);
31284
31285                      exprtk_debug(("(v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1)\n"));
31286
31287                      return (synthesis_result) ? result : error_node();
31288                   }
31289                }
31290
31291                const bool synthesis_result =
31292                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
31293                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
31294
31295                if (synthesis_result)
31296                   return result;
31297                else if (!expr_gen.valid_operator(o0,f0))
31298                   return error_node();
31299                else if (!expr_gen.valid_operator(o1,f1))
31300                   return error_node();
31301                else if (!expr_gen.valid_operator(o2,f2))
31302                   return error_node();
31303                else
31304                   return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
31305             }
31306
31307             static inline std::string id(expression_generator<Type>& expr_gen,
31308                                          const details::operator_type o0,
31309                                          const details::operator_type o1,
31310                                          const details::operator_type o2)
31311             {
31312                return details::build_string()
31313                          << "(t" << expr_gen.to_str(o0)
31314                          << "t)" << expr_gen.to_str(o1)
31315                          << "(t" << expr_gen.to_str(o2)
31316                          << "t)";
31317             }
31318          };
31319
31320          struct synthesize_covovov_expression0
31321          {
31322             typedef typename covovov_t::type0 node_type;
31323             typedef typename covovov_t::sf4_type sf4_type;
31324             typedef typename node_type::T0 T0;
31325             typedef typename node_type::T1 T1;
31326             typedef typename node_type::T2 T2;
31327             typedef typename node_type::T3 T3;
31328
31329             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
31330                                                       const details::operator_type& operation,
31331                                                       expression_node_ptr (&branch)[2])
31332             {
31333                // (c o0 v0) o1 (v1 o2 v2)
31334                const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
31335                const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
31336                const Type   c = cov->c ();
31337                const Type& v0 = cov->v ();
31338                const Type& v1 = vov->v0();
31339                const Type& v2 = vov->v1();
31340                const details::operator_type o0 = cov->operation();
31341                const details::operator_type o1 = operation;
31342                const details::operator_type o2 = vov->operation();
31343
31344                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31345                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31346                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
31347
31348                details::free_node(*(expr_gen.node_allocator_),branch[0]);
31349                details::free_node(*(expr_gen.node_allocator_),branch[1]);
31350
31351                expression_node_ptr result = error_node();
31352
31353                if (expr_gen.parser_->settings_.strength_reduction_enabled())
31354                {
31355                   // (c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2)
31356                   if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
31357                   {
31358                      const bool synthesis_result =
31359                         synthesize_sf4ext_expression::
31360                            template compile<ctype,vtype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", c, v1, v0, v2, result);
31361
31362                      exprtk_debug(("(c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2)\n"));
31363
31364                      return (synthesis_result) ? result : error_node();
31365                   }
31366                   // (c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1)
31367                   if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
31368                   {
31369                      const bool synthesis_result =
31370                         synthesize_sf4ext_expression::
31371                            template compile<ctype,vtype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", c, v2, v0, v1, result);
31372
31373                      exprtk_debug(("(c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1)\n"));
31374
31375                      return (synthesis_result) ? result : error_node();
31376                   }
31377                }
31378
31379                const bool synthesis_result =
31380                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
31381                      (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
31382
31383                if (synthesis_result)
31384                   return result;
31385                else if (!expr_gen.valid_operator(o0,f0))
31386                   return error_node();
31387                else if (!expr_gen.valid_operator(o1,f1))
31388                   return error_node();
31389                else if (!expr_gen.valid_operator(o2,f2))
31390                   return error_node();
31391                else
31392                   return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
31393             }
31394
31395             static inline std::string id(expression_generator<Type>& expr_gen,
31396                                          const details::operator_type o0,
31397                                          const details::operator_type o1,
31398                                          const details::operator_type o2)
31399             {
31400                return details::build_string()
31401                          << "(t" << expr_gen.to_str(o0)
31402                          << "t)" << expr_gen.to_str(o1)
31403                          << "(t" << expr_gen.to_str(o2)
31404                          << "t)";
31405             }
31406          };
31407
31408          struct synthesize_covocov_expression0
31409          {
31410             typedef typename covocov_t::type0 node_type;
31411             typedef typename covocov_t::sf4_type sf4_type;
31412             typedef typename node_type::T0 T0;
31413             typedef typename node_type::T1 T1;
31414             typedef typename node_type::T2 T2;
31415             typedef typename node_type::T3 T3;
31416
31417             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
31418                                                       const details::operator_type& operation,
31419                                                       expression_node_ptr (&branch)[2])
31420             {
31421                // (c0 o0 v0) o1 (c1 o2 v1)
31422                const details::cov_base_node<Type>* cov0 = static_cast<details::cov_base_node<Type>*>(branch[0]);
31423                const details::cov_base_node<Type>* cov1 = static_cast<details::cov_base_node<Type>*>(branch[1]);
31424                const Type  c0 = cov0->c();
31425                const Type& v0 = cov0->v();
31426                const Type  c1 = cov1->c();
31427                const Type& v1 = cov1->v();
31428                const details::operator_type o0 = cov0->operation();
31429                const details::operator_type o1 = operation;
31430                const details::operator_type o2 = cov1->operation();
31431
31432                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31433                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31434                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
31435
31436                details::free_node(*(expr_gen.node_allocator_),branch[0]);
31437                details::free_node(*(expr_gen.node_allocator_),branch[1]);
31438
31439                expression_node_ptr result = error_node();
31440
31441                if (expr_gen.parser_->settings_.strength_reduction_enabled())
31442                {
31443                   // (c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1
31444                   if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
31445                   {
31446                      const bool synthesis_result =
31447                         synthesize_sf3ext_expression::
31448                            template compile<ctype,vtype,vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
31449
31450                      exprtk_debug(("(c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n"));
31451
31452                      return (synthesis_result) ? result : error_node();
31453                   }
31454                   // (c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1
31455                   else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
31456                   {
31457                      const bool synthesis_result =
31458                         synthesize_sf3ext_expression::
31459                            template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
31460
31461                      exprtk_debug(("(c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n"));
31462
31463                      return (synthesis_result) ? result : error_node();
31464                   }
31465                   // (c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1
31466                   else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
31467                   {
31468                      const bool synthesis_result =
31469                         synthesize_sf3ext_expression::
31470                            template compile<ctype,vtype,vtype>(expr_gen, "(t-t)+t", (c0 - c1), v0, v1, result);
31471
31472                      exprtk_debug(("(c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1\n"));
31473
31474                      return (synthesis_result) ? result : error_node();
31475                   }
31476                   // (c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1
31477                   else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
31478                   {
31479                      const bool synthesis_result =
31480                         synthesize_sf3ext_expression::
31481                            template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
31482
31483                      exprtk_debug(("(c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n"));
31484
31485                      return (synthesis_result) ? result : error_node();
31486                   }
31487                   // (c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)
31488                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
31489                   {
31490                      const bool synthesis_result =
31491                         synthesize_sf3ext_expression::
31492                            template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
31493
31494                      exprtk_debug(("(c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
31495
31496                      return (synthesis_result) ? result : error_node();
31497                   }
31498                   // (c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)
31499                   else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
31500                   {
31501                      const bool synthesis_result =
31502                         synthesize_sf3ext_expression::
31503                            template compile<ctype,vtype,vtype>(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result);
31504
31505                      exprtk_debug(("(c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)\n"));
31506
31507                      return (synthesis_result) ? result : error_node();
31508                   }
31509                   // (c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0
31510                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
31511                   {
31512                      const bool synthesis_result =
31513                         synthesize_sf3ext_expression::
31514                            template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v1, v0, result);
31515
31516                      exprtk_debug(("(c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0\n"));
31517
31518                      return (synthesis_result) ? result : error_node();
31519                   }
31520                   // (c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)
31521                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
31522                   {
31523                      const bool synthesis_result =
31524                         synthesize_sf3ext_expression::
31525                            template compile<ctype,vtype,vtype>(expr_gen, "t*(t*t)", (c0 / c1), v0, v1, result);
31526
31527                      exprtk_debug(("(c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
31528
31529                      return (synthesis_result) ? result : error_node();
31530                   }
31531                   // (c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)
31532                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
31533                   {
31534                      const bool synthesis_result =
31535                         synthesize_sf3ext_expression::
31536                            template compile<ctype,vtype,vtype>(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result);
31537
31538                      exprtk_debug(("(c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)\n"));
31539
31540                      return (synthesis_result) ? result : error_node();
31541                   }
31542                   // (c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1)
31543                   else if (
31544                             (std::equal_to<T>()(c0,c1)) &&
31545                             (details::e_mul == o0)      &&
31546                             (details::e_mul == o2)      &&
31547                             (
31548                               (details::e_add == o1) ||
31549                               (details::e_sub == o1)
31550                             )
31551                           )
31552                   {
31553                      std::string specfunc;
31554
31555                      switch (o1)
31556                      {
31557                         case details::e_add : specfunc = "t*(t+t)"; break;
31558                         case details::e_sub : specfunc = "t*(t-t)"; break;
31559                         default             : return error_node();
31560                      }
31561
31562                      const bool synthesis_result =
31563                         synthesize_sf3ext_expression::
31564                            template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result);
31565
31566                      exprtk_debug(("(c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n"));
31567
31568                      return (synthesis_result) ? result : error_node();
31569                   }
31570                }
31571
31572                const bool synthesis_result =
31573                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
31574                      (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
31575
31576                if (synthesis_result)
31577                   return result;
31578                else if (!expr_gen.valid_operator(o0,f0))
31579                   return error_node();
31580                else if (!expr_gen.valid_operator(o1,f1))
31581                   return error_node();
31582                else if (!expr_gen.valid_operator(o2,f2))
31583                   return error_node();
31584                else
31585                   return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
31586             }
31587
31588             static inline std::string id(expression_generator<Type>& expr_gen,
31589                                          const details::operator_type o0,
31590                                          const details::operator_type o1,
31591                                          const details::operator_type o2)
31592             {
31593                return details::build_string()
31594                          << "(t" << expr_gen.to_str(o0)
31595                          << "t)" << expr_gen.to_str(o1)
31596                          << "(t" << expr_gen.to_str(o2)
31597                          << "t)";
31598             }
31599          };
31600
31601          struct synthesize_vocovoc_expression0
31602          {
31603             typedef typename vocovoc_t::type0 node_type;
31604             typedef typename vocovoc_t::sf4_type sf4_type;
31605             typedef typename node_type::T0 T0;
31606             typedef typename node_type::T1 T1;
31607             typedef typename node_type::T2 T2;
31608             typedef typename node_type::T3 T3;
31609
31610             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
31611                                                       const details::operator_type& operation,
31612                                                       expression_node_ptr (&branch)[2])
31613             {
31614                // (v0 o0 c0) o1 (v1 o2 c1)
31615                const details::voc_base_node<Type>* voc0 = static_cast<details::voc_base_node<Type>*>(branch[0]);
31616                const details::voc_base_node<Type>* voc1 = static_cast<details::voc_base_node<Type>*>(branch[1]);
31617                const Type  c0 = voc0->c();
31618                const Type& v0 = voc0->v();
31619                const Type  c1 = voc1->c();
31620                const Type& v1 = voc1->v();
31621                const details::operator_type o0 = voc0->operation();
31622                const details::operator_type o1 = operation;
31623                const details::operator_type o2 = voc1->operation();
31624
31625                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31626                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31627                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
31628
31629                details::free_node(*(expr_gen.node_allocator_),branch[0]);
31630                details::free_node(*(expr_gen.node_allocator_),branch[1]);
31631
31632                expression_node_ptr result = error_node();
31633
31634                if (expr_gen.parser_->settings_.strength_reduction_enabled())
31635                {
31636                   // (v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1
31637                   if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
31638                   {
31639                      const bool synthesis_result =
31640                         synthesize_sf3ext_expression::
31641                            template compile<ctype,vtype,vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
31642
31643                      exprtk_debug(("(v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n"));
31644
31645                      return (synthesis_result) ? result : error_node();
31646                   }
31647                   // (v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1
31648                   else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
31649                   {
31650                      const bool synthesis_result =
31651                         synthesize_sf3ext_expression::
31652                            template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
31653
31654                      exprtk_debug(("(v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n"));
31655
31656                      return (synthesis_result) ? result : error_node();
31657                   }
31658                   // (v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1
31659                   else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
31660                   {
31661                      const bool synthesis_result =
31662                         synthesize_sf3ext_expression::
31663                            template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c1 - c0), v0, v1, result);
31664
31665                      exprtk_debug(("(v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1\n"));
31666
31667                      return (synthesis_result) ? result : error_node();
31668                   }
31669                   // (v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1
31670                   else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
31671                   {
31672                      const bool synthesis_result =
31673                         synthesize_sf3ext_expression::
31674                            template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
31675
31676                      exprtk_debug(("(v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n"));
31677
31678                      return (synthesis_result) ? result : error_node();
31679                   }
31680                   // (v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)
31681                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
31682                   {
31683                      const bool synthesis_result =
31684                         synthesize_sf3ext_expression::
31685                            template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
31686
31687                      exprtk_debug(("(v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
31688
31689                      return (synthesis_result) ? result : error_node();
31690                   }
31691                   // (v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1
31692                   else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
31693                   {
31694                      const bool synthesis_result =
31695                         synthesize_sf3ext_expression::
31696                            template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", Type(1) / (c0 * c1), v0, v1, result);
31697
31698                      exprtk_debug(("(v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1\n"));
31699
31700                      return (synthesis_result) ? result : error_node();
31701                   }
31702                   // (v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1
31703                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
31704                   {
31705                      const bool synthesis_result =
31706                         synthesize_sf3ext_expression::
31707                            template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result);
31708
31709                      exprtk_debug(("(v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1\n"));
31710
31711                      return (synthesis_result) ? result : error_node();
31712                   }
31713                   // (v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)
31714                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
31715                   {
31716                      const bool synthesis_result =
31717                         synthesize_sf3ext_expression::
31718                            template compile<ctype,vtype,vtype>(expr_gen, "t*(t/t)", (c0 * c1), v0, v1, result);
31719
31720                      exprtk_debug(("(v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n"));
31721
31722                      return (synthesis_result) ? result : error_node();
31723                   }
31724                   // (v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1
31725                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
31726                   {
31727                      const bool synthesis_result =
31728                         synthesize_sf3ext_expression::
31729                            template compile<ctype,vtype,vtype>(expr_gen, "t*(t/t)", Type(1) / (c0 * c1), v0, v1, result);
31730
31731                      exprtk_debug(("(v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1\n"));
31732
31733                      return (synthesis_result) ? result : error_node();
31734                   }
31735                   // (v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1)
31736                   else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_add == o2))
31737                   {
31738                      const bool synthesis_result =
31739                         synthesize_sf4ext_expression::
31740                            template compile<vtype,ctype,vtype,ctype>(expr_gen, "(t*t)*(t+t)", v0, T(1) / c0, v1, c1, result);
31741
31742                      exprtk_debug(("(v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1)\n"));
31743
31744                      return (synthesis_result) ? result : error_node();
31745                   }
31746                   // (v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1)
31747                   else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_sub == o2))
31748                   {
31749                      const bool synthesis_result =
31750                         synthesize_sf4ext_expression::
31751                            template compile<vtype,ctype,vtype,ctype>(expr_gen, "(t*t)*(t-t)", v0, T(1) / c0, v1, c1, result);
31752
31753                      exprtk_debug(("(v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1)\n"));
31754
31755                      return (synthesis_result) ? result : error_node();
31756                   }
31757                   // (v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)
31758                   else if (
31759                             (std::equal_to<T>()(c0,c1)) &&
31760                             (details::e_mul == o0)      &&
31761                             (details::e_mul == o2)      &&
31762                             (
31763                               (details::e_add == o1) ||
31764                               (details::e_sub == o1)
31765                             )
31766                           )
31767                   {
31768                      std::string specfunc;
31769
31770                      switch (o1)
31771                      {
31772                         case details::e_add : specfunc = "t*(t+t)"; break;
31773                         case details::e_sub : specfunc = "t*(t-t)"; break;
31774                         default             : return error_node();
31775                      }
31776
31777                      const bool synthesis_result =
31778                         synthesize_sf3ext_expression::
31779                            template compile<ctype,vtype,vtype>(expr_gen, specfunc, c0, v0, v1, result);
31780
31781                      exprtk_debug(("(v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n"));
31782
31783                      return (synthesis_result) ? result : error_node();
31784                   }
31785                   // (v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c
31786                   else if (
31787                             (std::equal_to<T>()(c0,c1)) &&
31788                             (details::e_div == o0)      &&
31789                             (details::e_div == o2)      &&
31790                             (
31791                               (details::e_add == o1) ||
31792                               (details::e_sub == o1)
31793                             )
31794                           )
31795                   {
31796                      std::string specfunc;
31797
31798                      switch (o1)
31799                      {
31800                         case details::e_add : specfunc = "(t+t)/t"; break;
31801                         case details::e_sub : specfunc = "(t-t)/t"; break;
31802                         default             : return error_node();
31803                      }
31804
31805                      const bool synthesis_result =
31806                         synthesize_sf3ext_expression::
31807                            template compile<vtype,vtype,ctype>(expr_gen, specfunc, v0, v1, c0, result);
31808
31809                      exprtk_debug(("(v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c\n"));
31810
31811                      return (synthesis_result) ? result : error_node();
31812                   }
31813                }
31814
31815                const bool synthesis_result =
31816                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
31817                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
31818
31819                if (synthesis_result)
31820                   return result;
31821                else if (!expr_gen.valid_operator(o0,f0))
31822                   return error_node();
31823                else if (!expr_gen.valid_operator(o1,f1))
31824                   return error_node();
31825                else if (!expr_gen.valid_operator(o2,f2))
31826                   return error_node();
31827                else
31828                   return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
31829             }
31830
31831             static inline std::string id(expression_generator<Type>& expr_gen,
31832                                          const details::operator_type o0,
31833                                          const details::operator_type o1,
31834                                          const details::operator_type o2)
31835             {
31836                return details::build_string()
31837                          << "(t" << expr_gen.to_str(o0)
31838                          << "t)" << expr_gen.to_str(o1)
31839                          << "(t" << expr_gen.to_str(o2)
31840                          << "t)";
31841             }
31842          };
31843
31844          struct synthesize_covovoc_expression0
31845          {
31846             typedef typename covovoc_t::type0 node_type;
31847             typedef typename covovoc_t::sf4_type sf4_type;
31848             typedef typename node_type::T0 T0;
31849             typedef typename node_type::T1 T1;
31850             typedef typename node_type::T2 T2;
31851             typedef typename node_type::T3 T3;
31852
31853             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
31854                                                       const details::operator_type& operation,
31855                                                       expression_node_ptr (&branch)[2])
31856             {
31857                // (c0 o0 v0) o1 (v1 o2 c1)
31858                const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
31859                const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);
31860                const Type  c0 = cov->c();
31861                const Type& v0 = cov->v();
31862                const Type  c1 = voc->c();
31863                const Type& v1 = voc->v();
31864                const details::operator_type o0 = cov->operation();
31865                const details::operator_type o1 = operation;
31866                const details::operator_type o2 = voc->operation();
31867
31868                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31869                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31870                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
31871
31872                details::free_node(*(expr_gen.node_allocator_),branch[0]);
31873                details::free_node(*(expr_gen.node_allocator_),branch[1]);
31874
31875                expression_node_ptr result = error_node();
31876
31877                if (expr_gen.parser_->settings_.strength_reduction_enabled())
31878                {
31879                   // (c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1
31880                   if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
31881                   {
31882                      const bool synthesis_result =
31883                         synthesize_sf3ext_expression::
31884                            template compile<ctype,vtype,vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
31885
31886                      exprtk_debug(("(c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n"));
31887
31888                      return (synthesis_result) ? result : error_node();
31889                   }
31890                   // (c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1
31891                   else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
31892                   {
31893                      const bool synthesis_result =
31894                         synthesize_sf3ext_expression::
31895                            template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
31896
31897                      exprtk_debug(("(c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n"));
31898
31899                      return (synthesis_result) ? result : error_node();
31900                   }
31901                   // (c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1
31902                   else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
31903                   {
31904                      const bool synthesis_result =
31905                         synthesize_sf3ext_expression::
31906                            template compile<ctype,vtype,vtype>(expr_gen, "t-(t+t)", (c0 + c1), v0, v1, result);
31907
31908                      exprtk_debug(("(c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1\n"));
31909
31910                      return (synthesis_result) ? result : error_node();
31911                   }
31912                   // (c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1
31913                   else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
31914                   {
31915                      const bool synthesis_result =
31916                         synthesize_sf3ext_expression::
31917                            template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
31918
31919                      exprtk_debug(("(c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n"));
31920
31921                      return (synthesis_result) ? result : error_node();
31922                   }
31923                   // (c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)
31924                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
31925                   {
31926                      const bool synthesis_result =
31927                         synthesize_sf3ext_expression::
31928                            template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
31929
31930                      exprtk_debug(("(c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
31931
31932                      return (synthesis_result) ? result : error_node();
31933                   }
31934                   // (c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)
31935                   else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
31936                   {
31937                      const bool synthesis_result =
31938                         synthesize_sf3ext_expression::
31939                            template compile<ctype,vtype,vtype>(expr_gen, "t*(t/t)", (c0 / c1), v1, v0, result);
31940
31941                      exprtk_debug(("(c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)\n"));
31942
31943                      return (synthesis_result) ? result : error_node();
31944                   }
31945                   // (c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1)
31946                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
31947                   {
31948                      const bool synthesis_result =
31949                         synthesize_sf3ext_expression::
31950                            template compile<ctype,vtype,vtype>(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result);
31951
31952                      exprtk_debug(("(c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1)\n"));
31953
31954                      return (synthesis_result) ? result : error_node();
31955                   }
31956                   // (c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)
31957                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
31958                   {
31959                      const bool synthesis_result =
31960                         synthesize_sf3ext_expression::
31961                            template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 * c1), v0, v1, result);
31962
31963                      exprtk_debug(("(c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n"));
31964
31965                      return (synthesis_result) ? result : error_node();
31966                   }
31967                   // (c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)
31968                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
31969                   {
31970                      const bool synthesis_result =
31971                         synthesize_sf3ext_expression::
31972                            template compile<ctype,vtype,vtype>(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result);
31973
31974                      exprtk_debug(("(c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)\n"));
31975
31976                      return (synthesis_result) ? result : error_node();
31977                   }
31978                   // (c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)
31979                   else if (
31980                             (std::equal_to<T>()(c0,c1)) &&
31981                             (details::e_mul == o0)      &&
31982                             (details::e_mul == o2)      &&
31983                             (
31984                               (details::e_add == o1) ||
31985                               (details::e_sub == o1)
31986                             )
31987                           )
31988                   {
31989                      std::string specfunc;
31990
31991                      switch (o1)
31992                      {
31993                         case details::e_add : specfunc = "t*(t+t)"; break;
31994                         case details::e_sub : specfunc = "t*(t-t)"; break;
31995                         default             : return error_node();
31996                      }
31997
31998                      const bool synthesis_result =
31999                         synthesize_sf3ext_expression::
32000                            template compile<ctype,vtype,vtype>(expr_gen,specfunc, c0, v0, v1, result);
32001
32002                      exprtk_debug(("(c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n"));
32003
32004                      return (synthesis_result) ? result : error_node();
32005                   }
32006                }
32007
32008                const bool synthesis_result =
32009                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32010                      (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
32011
32012                if (synthesis_result)
32013                   return result;
32014                else if (!expr_gen.valid_operator(o0,f0))
32015                   return error_node();
32016                else if (!expr_gen.valid_operator(o1,f1))
32017                   return error_node();
32018                else if (!expr_gen.valid_operator(o2,f2))
32019                   return error_node();
32020                else
32021                   return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
32022             }
32023
32024             static inline std::string id(expression_generator<Type>& expr_gen,
32025                                          const details::operator_type o0,
32026                                          const details::operator_type o1,
32027                                          const details::operator_type o2)
32028             {
32029                return details::build_string()
32030                          << "(t" << expr_gen.to_str(o0)
32031                          << "t)" << expr_gen.to_str(o1)
32032                          << "(t" << expr_gen.to_str(o2)
32033                          << "t)";
32034             }
32035          };
32036
32037          struct synthesize_vococov_expression0
32038          {
32039             typedef typename vococov_t::type0 node_type;
32040             typedef typename vococov_t::sf4_type sf4_type;
32041             typedef typename node_type::T0 T0;
32042             typedef typename node_type::T1 T1;
32043             typedef typename node_type::T2 T2;
32044             typedef typename node_type::T3 T3;
32045
32046             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32047                                                       const details::operator_type& operation,
32048                                                       expression_node_ptr (&branch)[2])
32049             {
32050                // (v0 o0 c0) o1 (c1 o2 v1)
32051                const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
32052                const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
32053                const Type  c0 = voc->c();
32054                const Type& v0 = voc->v();
32055                const Type  c1 = cov->c();
32056                const Type& v1 = cov->v();
32057                const details::operator_type o0 = voc->operation();
32058                const details::operator_type o1 = operation;
32059                const details::operator_type o2 = cov->operation();
32060
32061                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32062                binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
32063                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
32064
32065                details::free_node(*(expr_gen.node_allocator_),branch[0]);
32066                details::free_node(*(expr_gen.node_allocator_),branch[1]);
32067
32068                expression_node_ptr result = error_node();
32069
32070                if (expr_gen.parser_->settings_.strength_reduction_enabled())
32071                {
32072                   // (v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1
32073                   if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
32074                   {
32075                      const bool synthesis_result =
32076                         synthesize_sf3ext_expression::
32077                            template compile<ctype,vtype,vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
32078
32079                      exprtk_debug(("(v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n"));
32080
32081                      return (synthesis_result) ? result : error_node();
32082                   }
32083                   // (v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1
32084                   else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
32085                   {
32086                      const bool synthesis_result =
32087                         synthesize_sf3ext_expression::
32088                            template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
32089
32090                      exprtk_debug(("(v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n"));
32091
32092                      return (synthesis_result) ? result : error_node();
32093                   }
32094                   // (v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)
32095                   else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
32096                   {
32097                      const bool synthesis_result =
32098                         synthesize_sf3ext_expression::
32099                            template compile<vtype,vtype,ctype>(expr_gen, "(t+t)-t", v0, v1, (c1 + c0), result);
32100
32101                      exprtk_debug(("(v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)\n"));
32102
32103                      return (synthesis_result) ? result : error_node();
32104                   }
32105                   // (v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1
32106                   else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
32107                   {
32108                      const bool synthesis_result =
32109                         synthesize_sf3ext_expression::
32110                            template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
32111
32112                      exprtk_debug(("(v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n"));
32113
32114                      return (synthesis_result) ? result : error_node();
32115                   }
32116                   // (v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)
32117                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
32118                   {
32119                      const bool synthesis_result =
32120                         synthesize_sf3ext_expression::
32121                            template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
32122
32123                      exprtk_debug(("(v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
32124
32125                      return (synthesis_result) ? result : error_node();
32126                   }
32127                   // (v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)
32128                   else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
32129                   {
32130                      const bool synthesis_result =
32131                         synthesize_sf3ext_expression::
32132                            template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result);
32133
32134                      exprtk_debug(("(v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)\n"));
32135
32136                      return (synthesis_result) ? result : error_node();
32137                   }
32138                   // (v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)
32139                   else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
32140                   {
32141                      const bool synthesis_result =
32142                         synthesize_sf3ext_expression::
32143                            template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 / c1), v0, v1, result);
32144
32145                      exprtk_debug(("(v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
32146
32147                      return (synthesis_result) ? result : error_node();
32148                   }
32149                   // (v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)
32150                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
32151                   {
32152                      const bool synthesis_result =
32153                         synthesize_sf3ext_expression::
32154                            template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", Type(1) / (c0 * c1), v0, v1, result);
32155
32156                      exprtk_debug(("(v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)\n"));
32157
32158                      return (synthesis_result) ? result : error_node();
32159                   }
32160                   // (v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1))
32161                   else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
32162                   {
32163                      const bool synthesis_result =
32164                         synthesize_sf3ext_expression::
32165                            template compile<vtype,vtype,ctype>(expr_gen, "(t*t)*t", v0, v1, Type(1) / (c0 * c1), result);
32166
32167                      exprtk_debug(("(v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1))\n"));
32168
32169                      return (synthesis_result) ? result : error_node();
32170                   }
32171                   // (v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)
32172                   else if (
32173                             (std::equal_to<T>()(c0,c1)) &&
32174                             (details::e_mul == o0)      &&
32175                             (details::e_mul == o2)      &&
32176                             (
32177                               (details::e_add == o1) || (details::e_sub == o1)
32178                             )
32179                           )
32180                   {
32181                      std::string specfunc;
32182
32183                      switch (o1)
32184                      {
32185                         case details::e_add : specfunc = "t*(t+t)"; break;
32186                         case details::e_sub : specfunc = "t*(t-t)"; break;
32187                         default             : return error_node();
32188                      }
32189
32190                      const bool synthesis_result =
32191                         synthesize_sf3ext_expression::
32192                            template compile<ctype,vtype,vtype>(expr_gen, specfunc, c0, v0, v1, result);
32193
32194                      exprtk_debug(("(v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n"));
32195
32196                      return (synthesis_result) ? result : error_node();
32197                   }
32198                }
32199
32200                const bool synthesis_result =
32201                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32202                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result);
32203
32204                if (synthesis_result)
32205                   return result;
32206                else if (!expr_gen.valid_operator(o0,f0))
32207                   return error_node();
32208                else if (!expr_gen.valid_operator(o1,f1))
32209                   return error_node();
32210                else if (!expr_gen.valid_operator(o2,f2))
32211                   return error_node();
32212                else
32213                   return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2);
32214             }
32215
32216             static inline std::string id(expression_generator<Type>& expr_gen,
32217                                          const details::operator_type o0,
32218                                          const details::operator_type o1,
32219                                          const details::operator_type o2)
32220             {
32221                return details::build_string()
32222                          << "(t" << expr_gen.to_str(o0)
32223                          << "t)" << expr_gen.to_str(o1)
32224                          << "(t" << expr_gen.to_str(o2)
32225                          << "t)";
32226             }
32227          };
32228
32229          struct synthesize_vovovov_expression1
32230          {
32231             typedef typename vovovov_t::type1 node_type;
32232             typedef typename vovovov_t::sf4_type sf4_type;
32233             typedef typename node_type::T0 T0;
32234             typedef typename node_type::T1 T1;
32235             typedef typename node_type::T2 T2;
32236             typedef typename node_type::T3 T3;
32237
32238             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32239                                                       const details::operator_type& operation,
32240                                                       expression_node_ptr (&branch)[2])
32241             {
32242                // v0 o0 (v1 o1 (v2 o2 v3))
32243                typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
32244
32245                const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
32246                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
32247                const Type& v1 = vovov->t0();
32248                const Type& v2 = vovov->t1();
32249                const Type& v3 = vovov->t2();
32250                const details::operator_type o0 = operation;
32251                const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
32252                const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
32253
32254                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32255                binary_functor_t f1 = vovov->f0();
32256                binary_functor_t f2 = vovov->f1();
32257
32258                details::free_node(*(expr_gen.node_allocator_),branch[1]);
32259
32260                expression_node_ptr result = error_node();
32261
32262                if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result))
32263                   return result;
32264                else if (!expr_gen.valid_operator(o0,f0))
32265                   return error_node();
32266
32267                exprtk_debug(("v0 o0 (v1 o1 (v2 o2 v3))\n"));
32268
32269                return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2);
32270             }
32271
32272             static inline std::string id(expression_generator<Type>& expr_gen,
32273                                          const details::operator_type o0,
32274                                          const details::operator_type o1,
32275                                          const details::operator_type o2)
32276             {
32277                return details::build_string()
32278                          << "t"  << expr_gen.to_str(o0)
32279                          << "(t" << expr_gen.to_str(o1)
32280                          << "(t" << expr_gen.to_str(o2)
32281                          << "t))";
32282             }
32283          };
32284
32285          struct synthesize_vovovoc_expression1
32286          {
32287             typedef typename vovovoc_t::type1 node_type;
32288             typedef typename vovovoc_t::sf4_type sf4_type;
32289             typedef typename node_type::T0 T0;
32290             typedef typename node_type::T1 T1;
32291             typedef typename node_type::T2 T2;
32292             typedef typename node_type::T3 T3;
32293
32294             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32295                                                       const details::operator_type& operation,
32296                                                       expression_node_ptr (&branch)[2])
32297             {
32298                // v0 o0 (v1 o1 (v2 o2 c))
32299                typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t;
32300
32301                const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
32302                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
32303                const Type& v1 = vovoc->t0();
32304                const Type& v2 = vovoc->t1();
32305                const Type   c = vovoc->t2();
32306                const details::operator_type o0 = operation;
32307                const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
32308                const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
32309
32310                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32311                binary_functor_t f1 = vovoc->f0();
32312                binary_functor_t f2 = vovoc->f1();
32313
32314                details::free_node(*(expr_gen.node_allocator_),branch[1]);
32315
32316                expression_node_ptr result = error_node();
32317
32318                const bool synthesis_result =
32319                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32320                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
32321
32322                if (synthesis_result)
32323                   return result;
32324                else if (!expr_gen.valid_operator(o0,f0))
32325                   return error_node();
32326
32327                exprtk_debug(("v0 o0 (v1 o1 (v2 o2 c))\n"));
32328
32329                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
32330             }
32331
32332             static inline std::string id(expression_generator<Type>& expr_gen,
32333                                          const details::operator_type o0,
32334                                          const details::operator_type o1,
32335                                          const details::operator_type o2)
32336             {
32337                return details::build_string()
32338                          << "t"  << expr_gen.to_str(o0)
32339                          << "(t" << expr_gen.to_str(o1)
32340                          << "(t" << expr_gen.to_str(o2)
32341                          << "t))";
32342             }
32343          };
32344
32345          struct synthesize_vovocov_expression1
32346          {
32347             typedef typename vovocov_t::type1 node_type;
32348             typedef typename vovocov_t::sf4_type sf4_type;
32349             typedef typename node_type::T0 T0;
32350             typedef typename node_type::T1 T1;
32351             typedef typename node_type::T2 T2;
32352             typedef typename node_type::T3 T3;
32353
32354             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32355                                                       const details::operator_type& operation,
32356                                                       expression_node_ptr (&branch)[2])
32357             {
32358                // v0 o0 (v1 o1 (c o2 v2))
32359                typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
32360
32361                const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
32362                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
32363                const Type& v1 = vocov->t0();
32364                const Type   c = vocov->t1();
32365                const Type& v2 = vocov->t2();
32366                const details::operator_type o0 = operation;
32367                const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
32368                const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
32369
32370                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32371                binary_functor_t f1 = vocov->f0();
32372                binary_functor_t f2 = vocov->f1();
32373
32374                details::free_node(*(expr_gen.node_allocator_),branch[1]);
32375
32376                expression_node_ptr result = error_node();
32377
32378                const bool synthesis_result =
32379                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32380                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
32381
32382                if (synthesis_result)
32383                   return result;
32384                if (!expr_gen.valid_operator(o0,f0))
32385                   return error_node();
32386
32387                exprtk_debug(("v0 o0 (v1 o1 (c o2 v2))\n"));
32388
32389                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
32390             }
32391
32392             static inline std::string id(expression_generator<Type>& expr_gen,
32393                                          const details::operator_type o0,
32394                                          const details::operator_type o1,
32395                                          const details::operator_type o2)
32396             {
32397                return details::build_string()
32398                          << "t"  << expr_gen.to_str(o0)
32399                          << "(t" << expr_gen.to_str(o1)
32400                          << "(t" << expr_gen.to_str(o2)
32401                          << "t))";
32402             }
32403          };
32404
32405          struct synthesize_vocovov_expression1
32406          {
32407             typedef typename vocovov_t::type1 node_type;
32408             typedef typename vocovov_t::sf4_type sf4_type;
32409             typedef typename node_type::T0 T0;
32410             typedef typename node_type::T1 T1;
32411             typedef typename node_type::T2 T2;
32412             typedef typename node_type::T3 T3;
32413
32414             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32415                                                       const details::operator_type& operation,
32416                                                       expression_node_ptr (&branch)[2])
32417             {
32418                // v0 o0 (c o1 (v1 o2 v2))
32419                typedef typename synthesize_covov_expression1::node_type lcl_covov_t;
32420
32421                const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]);
32422                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
32423                const Type   c = covov->t0();
32424                const Type& v1 = covov->t1();
32425                const Type& v2 = covov->t2();
32426                const details::operator_type o0 = operation;
32427                const details::operator_type o1 = expr_gen.get_operator(covov->f0());
32428                const details::operator_type o2 = expr_gen.get_operator(covov->f1());
32429
32430                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32431                binary_functor_t f1 = covov->f0();
32432                binary_functor_t f2 = covov->f1();
32433
32434                details::free_node(*(expr_gen.node_allocator_),branch[1]);
32435
32436                expression_node_ptr result = error_node();
32437
32438                const bool synthesis_result =
32439                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32440                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
32441
32442                if (synthesis_result)
32443                   return result;
32444                else if (!expr_gen.valid_operator(o0,f0))
32445                   return error_node();
32446
32447                exprtk_debug(("v0 o0 (c o1 (v1 o2 v2))\n"));
32448
32449                return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
32450             }
32451
32452             static inline std::string id(expression_generator<Type>& expr_gen,
32453                                          const details::operator_type o0,
32454                                          const details::operator_type o1,
32455                                          const details::operator_type o2)
32456             {
32457                return details::build_string()
32458                          << "t"  << expr_gen.to_str(o0)
32459                          << "(t" << expr_gen.to_str(o1)
32460                          << "(t" << expr_gen.to_str(o2)
32461                          << "t))";
32462             }
32463          };
32464
32465          struct synthesize_covovov_expression1
32466          {
32467             typedef typename covovov_t::type1 node_type;
32468             typedef typename covovov_t::sf4_type sf4_type;
32469             typedef typename node_type::T0 T0;
32470             typedef typename node_type::T1 T1;
32471             typedef typename node_type::T2 T2;
32472             typedef typename node_type::T3 T3;
32473
32474             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32475                                                       const details::operator_type& operation,
32476                                                       expression_node_ptr (&branch)[2])
32477             {
32478                // c o0 (v0 o1 (v1 o2 v2))
32479                typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
32480
32481                const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
32482                const Type   c = static_cast<details::literal_node<Type>*>(branch[0])->value();
32483                const Type& v0 = vovov->t0();
32484                const Type& v1 = vovov->t1();
32485                const Type& v2 = vovov->t2();
32486                const details::operator_type o0 = operation;
32487                const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
32488                const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
32489
32490                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32491                binary_functor_t f1 = vovov->f0();
32492                binary_functor_t f2 = vovov->f1();
32493
32494                details::free_node(*(expr_gen.node_allocator_),branch[0]);
32495                details::free_node(*(expr_gen.node_allocator_),branch[1]);
32496
32497                expression_node_ptr result = error_node();
32498
32499                const bool synthesis_result =
32500                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32501                      (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
32502
32503                if (synthesis_result)
32504                   return result;
32505                if (!expr_gen.valid_operator(o0,f0))
32506                   return error_node();
32507
32508                exprtk_debug(("c o0 (v0 o1 (v1 o2 v2))\n"));
32509
32510                return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
32511             }
32512
32513             static inline std::string id(expression_generator<Type>& expr_gen,
32514                                          const details::operator_type o0,
32515                                          const details::operator_type o1,
32516                                          const details::operator_type o2)
32517             {
32518                return details::build_string()
32519                          << "t"  << expr_gen.to_str(o0)
32520                          << "(t" << expr_gen.to_str(o1)
32521                          << "(t" << expr_gen.to_str(o2)
32522                          << "t))";
32523             }
32524          };
32525
32526          struct synthesize_covocov_expression1
32527          {
32528             typedef typename covocov_t::type1 node_type;
32529             typedef typename covocov_t::sf4_type sf4_type;
32530             typedef typename node_type::T0 T0;
32531             typedef typename node_type::T1 T1;
32532             typedef typename node_type::T2 T2;
32533             typedef typename node_type::T3 T3;
32534
32535             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32536                                                       const details::operator_type& operation,
32537                                                       expression_node_ptr (&branch)[2])
32538             {
32539                // c0 o0 (v0 o1 (c1 o2 v1))
32540                typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
32541
32542                const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
32543                const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
32544                const Type& v0 = vocov->t0();
32545                const Type  c1 = vocov->t1();
32546                const Type& v1 = vocov->t2();
32547                const details::operator_type o0 = operation;
32548                const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
32549                const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
32550
32551                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32552                binary_functor_t f1 = vocov->f0();
32553                binary_functor_t f2 = vocov->f1();
32554
32555                details::free_node(*(expr_gen.node_allocator_),branch[0]);
32556                details::free_node(*(expr_gen.node_allocator_),branch[1]);
32557
32558                expression_node_ptr result = error_node();
32559
32560                const bool synthesis_result =
32561                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32562                      (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
32563
32564                if (synthesis_result)
32565                   return result;
32566                else if (!expr_gen.valid_operator(o0,f0))
32567                   return error_node();
32568
32569                exprtk_debug(("c0 o0 (v0 o1 (c1 o2 v1))\n"));
32570
32571                return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
32572             }
32573
32574             static inline std::string id(expression_generator<Type>& expr_gen,
32575                                          const details::operator_type o0,
32576                                          const details::operator_type o1,
32577                                          const details::operator_type o2)
32578             {
32579                return details::build_string()
32580                          << "t"  << expr_gen.to_str(o0)
32581                          << "(t" << expr_gen.to_str(o1)
32582                          << "(t" << expr_gen.to_str(o2)
32583                          << "t))";
32584             }
32585          };
32586
32587          struct synthesize_vocovoc_expression1
32588          {
32589             typedef typename vocovoc_t::type1 node_type;
32590             typedef typename vocovoc_t::sf4_type sf4_type;
32591             typedef typename node_type::T0 T0;
32592             typedef typename node_type::T1 T1;
32593             typedef typename node_type::T2 T2;
32594             typedef typename node_type::T3 T3;
32595
32596             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32597                                                       const details::operator_type& operation,
32598                                                       expression_node_ptr (&branch)[2])
32599             {
32600                // v0 o0 (c0 o1 (v1 o2 c2))
32601                typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t;
32602
32603                const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]);
32604                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
32605                const Type  c0 = covoc->t0();
32606                const Type& v1 = covoc->t1();
32607                const Type  c1 = covoc->t2();
32608                const details::operator_type o0 = operation;
32609                const details::operator_type o1 = expr_gen.get_operator(covoc->f0());
32610                const details::operator_type o2 = expr_gen.get_operator(covoc->f1());
32611
32612                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32613                binary_functor_t f1 = covoc->f0();
32614                binary_functor_t f2 = covoc->f1();
32615
32616                details::free_node(*(expr_gen.node_allocator_),branch[1]);
32617
32618                expression_node_ptr result = error_node();
32619
32620                const bool synthesis_result =
32621                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32622                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
32623
32624                if (synthesis_result)
32625                   return result;
32626                else if (!expr_gen.valid_operator(o0,f0))
32627                   return error_node();
32628
32629                exprtk_debug(("v0 o0 (c0 o1 (v1 o2 c2))\n"));
32630
32631                return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
32632             }
32633
32634             static inline std::string id(expression_generator<Type>& expr_gen,
32635                                          const details::operator_type o0,
32636                                          const details::operator_type o1,
32637                                          const details::operator_type o2)
32638             {
32639                return details::build_string()
32640                          << "t"  << expr_gen.to_str(o0)
32641                          << "(t" << expr_gen.to_str(o1)
32642                          << "(t" << expr_gen.to_str(o2)
32643                          << "t))";
32644             }
32645          };
32646
32647          struct synthesize_covovoc_expression1
32648          {
32649             typedef typename covovoc_t::type1 node_type;
32650             typedef typename covovoc_t::sf4_type sf4_type;
32651             typedef typename node_type::T0 T0;
32652             typedef typename node_type::T1 T1;
32653             typedef typename node_type::T2 T2;
32654             typedef typename node_type::T3 T3;
32655             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32656                                                       const details::operator_type& operation,
32657                                                       expression_node_ptr (&branch)[2])
32658             {
32659                // c0 o0 (v0 o1 (v1 o2 c1))
32660                typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t;
32661
32662                const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
32663                const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
32664                const Type& v0 = vovoc->t0();
32665                const Type& v1 = vovoc->t1();
32666                const Type  c1 = vovoc->t2();
32667                const details::operator_type o0 = operation;
32668                const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
32669                const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
32670
32671                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32672                binary_functor_t f1 = vovoc->f0();
32673                binary_functor_t f2 = vovoc->f1();
32674
32675                details::free_node(*(expr_gen.node_allocator_),branch[0]);
32676                details::free_node(*(expr_gen.node_allocator_),branch[1]);
32677
32678                expression_node_ptr result = error_node();
32679
32680                const bool synthesis_result =
32681                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32682                      (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
32683
32684                if (synthesis_result)
32685                   return result;
32686                else if (!expr_gen.valid_operator(o0,f0))
32687                   return error_node();
32688
32689                exprtk_debug(("c0 o0 (v0 o1 (v1 o2 c1))\n"));
32690
32691                return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
32692             }
32693
32694             static inline std::string id(expression_generator<Type>& expr_gen,
32695                                          const details::operator_type o0,
32696                                          const details::operator_type o1,
32697                                          const details::operator_type o2)
32698             {
32699                return details::build_string()
32700                          << "t"  << expr_gen.to_str(o0)
32701                          << "(t" << expr_gen.to_str(o1)
32702                          << "(t" << expr_gen.to_str(o2)
32703                          << "t))";
32704             }
32705          };
32706
32707          struct synthesize_vococov_expression1
32708          {
32709             typedef typename vococov_t::type1 node_type;
32710             typedef typename vococov_t::sf4_type sf4_type;
32711             typedef typename node_type::T0 T0;
32712             typedef typename node_type::T1 T1;
32713             typedef typename node_type::T2 T2;
32714             typedef typename node_type::T3 T3;
32715
32716             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32717                                                       const details::operator_type& operation,
32718                                                       expression_node_ptr (&branch)[2])
32719             {
32720                // v0 o0 (c0 o1 (c1 o2 v1))
32721                typedef typename synthesize_cocov_expression1::node_type lcl_cocov_t;
32722
32723                const lcl_cocov_t* cocov = static_cast<const lcl_cocov_t*>(branch[1]);
32724                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
32725                const Type  c0 = cocov->t0();
32726                const Type  c1 = cocov->t1();
32727                const Type& v1 = cocov->t2();
32728                const details::operator_type o0 = operation;
32729                const details::operator_type o1 = expr_gen.get_operator(cocov->f0());
32730                const details::operator_type o2 = expr_gen.get_operator(cocov->f1());
32731
32732                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32733                binary_functor_t f1 = cocov->f0();
32734                binary_functor_t f2 = cocov->f1();
32735
32736                details::free_node(*(expr_gen.node_allocator_),branch[1]);
32737
32738                expression_node_ptr result = error_node();
32739
32740                const bool synthesis_result =
32741                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32742                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result);
32743
32744                if (synthesis_result)
32745                   return result;
32746                else if (!expr_gen.valid_operator(o0,f0))
32747                   return error_node();
32748
32749                exprtk_debug(("v0 o0 (c0 o1 (c1 o2 v1))\n"));
32750
32751                return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2);
32752             }
32753
32754             static inline std::string id(expression_generator<Type>& expr_gen,
32755                                          const details::operator_type o0,
32756                                          const details::operator_type o1,
32757                                          const details::operator_type o2)
32758             {
32759                return details::build_string()
32760                          << "t"  << expr_gen.to_str(o0)
32761                          << "(t" << expr_gen.to_str(o1)
32762                          << "(t" << expr_gen.to_str(o2)
32763                          << "t))";
32764             }
32765          };
32766
32767          struct synthesize_vovovov_expression2
32768          {
32769             typedef typename vovovov_t::type2 node_type;
32770             typedef typename vovovov_t::sf4_type sf4_type;
32771             typedef typename node_type::T0 T0;
32772             typedef typename node_type::T1 T1;
32773             typedef typename node_type::T2 T2;
32774             typedef typename node_type::T3 T3;
32775
32776             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32777                                                       const details::operator_type& operation,
32778                                                       expression_node_ptr (&branch)[2])
32779             {
32780                // v0 o0 ((v1 o1 v2) o2 v3)
32781                typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
32782
32783                const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
32784                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
32785                const Type& v1 = vovov->t0();
32786                const Type& v2 = vovov->t1();
32787                const Type& v3 = vovov->t2();
32788                const details::operator_type o0 = operation;
32789                const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
32790                const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
32791
32792                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32793                binary_functor_t f1 = vovov->f0();
32794                binary_functor_t f2 = vovov->f1();
32795
32796                details::free_node(*(expr_gen.node_allocator_),branch[1]);
32797
32798                expression_node_ptr result = error_node();
32799
32800                const bool synthesis_result =
32801                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32802                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
32803
32804                if (synthesis_result)
32805                   return result;
32806                else if (!expr_gen.valid_operator(o0,f0))
32807                   return error_node();
32808
32809                exprtk_debug(("v0 o0 ((v1 o1 v2) o2 v3)\n"));
32810
32811                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
32812             }
32813
32814             static inline std::string id(expression_generator<Type>& expr_gen,
32815                                          const details::operator_type o0,
32816                                          const details::operator_type o1,
32817                                          const details::operator_type o2)
32818             {
32819                return details::build_string()
32820                          << "t"   << expr_gen.to_str(o0)
32821                          << "((t" << expr_gen.to_str(o1)
32822                          << "t)"  << expr_gen.to_str(o2)
32823                          << "t)";
32824             }
32825          };
32826
32827          struct synthesize_vovovoc_expression2
32828          {
32829             typedef typename vovovoc_t::type2 node_type;
32830             typedef typename vovovoc_t::sf4_type sf4_type;
32831             typedef typename node_type::T0 T0;
32832             typedef typename node_type::T1 T1;
32833             typedef typename node_type::T2 T2;
32834             typedef typename node_type::T3 T3;
32835
32836             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32837                                                       const details::operator_type& operation,
32838                                                       expression_node_ptr (&branch)[2])
32839             {
32840                // v0 o0 ((v1 o1 v2) o2 c)
32841                typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t;
32842
32843                const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
32844                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
32845                const Type& v1 = vovoc->t0();
32846                const Type& v2 = vovoc->t1();
32847                const Type   c = vovoc->t2();
32848                const details::operator_type o0 = operation;
32849                const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
32850                const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
32851
32852                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32853                binary_functor_t f1 = vovoc->f0();
32854                binary_functor_t f2 = vovoc->f1();
32855
32856                details::free_node(*(expr_gen.node_allocator_),branch[1]);
32857
32858                expression_node_ptr result = error_node();
32859
32860                const bool synthesis_result =
32861                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32862                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
32863
32864                if (synthesis_result)
32865                   return result;
32866                else if (!expr_gen.valid_operator(o0,f0))
32867                   return error_node();
32868
32869                exprtk_debug(("v0 o0 ((v1 o1 v2) o2 c)\n"));
32870
32871                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
32872             }
32873
32874             static inline std::string id(expression_generator<Type>& expr_gen,
32875                                          const details::operator_type o0,
32876                                          const details::operator_type o1,
32877                                          const details::operator_type o2)
32878             {
32879                return details::build_string()
32880                          << "t"   << expr_gen.to_str(o0)
32881                          << "((t" << expr_gen.to_str(o1)
32882                          << "t)"  << expr_gen.to_str(o2)
32883                          << "t)";
32884             }
32885          };
32886
32887          struct synthesize_vovocov_expression2
32888          {
32889             typedef typename vovocov_t::type2 node_type;
32890             typedef typename vovocov_t::sf4_type sf4_type;
32891             typedef typename node_type::T0 T0;
32892             typedef typename node_type::T1 T1;
32893             typedef typename node_type::T2 T2;
32894             typedef typename node_type::T3 T3;
32895
32896             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32897                                                       const details::operator_type& operation,
32898                                                       expression_node_ptr (&branch)[2])
32899             {
32900                // v0 o0 ((v1 o1 c) o2 v2)
32901                typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
32902
32903                const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
32904                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
32905                const Type& v1 = vocov->t0();
32906                const Type   c = vocov->t1();
32907                const Type& v2 = vocov->t2();
32908                const details::operator_type o0 = operation;
32909                const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
32910                const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
32911
32912                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32913                binary_functor_t f1 = vocov->f0();
32914                binary_functor_t f2 = vocov->f1();
32915
32916                details::free_node(*(expr_gen.node_allocator_),branch[1]);
32917
32918                expression_node_ptr result = error_node();
32919
32920                const bool synthesis_result =
32921                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32922                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
32923
32924                if (synthesis_result)
32925                   return result;
32926                else if (!expr_gen.valid_operator(o0,f0))
32927                   return error_node();
32928
32929                exprtk_debug(("v0 o0 ((v1 o1 c) o2 v2)\n"));
32930
32931                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
32932             }
32933
32934             static inline std::string id(expression_generator<Type>& expr_gen,
32935                                          const details::operator_type o0,
32936                                          const details::operator_type o1,
32937                                          const details::operator_type o2)
32938             {
32939                return details::build_string()
32940                          << "t"   << expr_gen.to_str(o0)
32941                          << "((t" << expr_gen.to_str(o1)
32942                          << "t)"  << expr_gen.to_str(o2)
32943                          << "t)";
32944             }
32945          };
32946
32947          struct synthesize_vocovov_expression2
32948          {
32949             typedef typename vocovov_t::type2 node_type;
32950             typedef typename vocovov_t::sf4_type sf4_type;
32951             typedef typename node_type::T0 T0;
32952             typedef typename node_type::T1 T1;
32953             typedef typename node_type::T2 T2;
32954             typedef typename node_type::T3 T3;
32955
32956             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
32957                                                       const details::operator_type& operation,
32958                                                       expression_node_ptr (&branch)[2])
32959             {
32960                // v0 o0 ((c o1 v1) o2 v2)
32961                typedef typename synthesize_covov_expression0::node_type lcl_covov_t;
32962
32963                const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]);
32964                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
32965                const Type   c = covov->t0();
32966                const Type& v1 = covov->t1();
32967                const Type& v2 = covov->t2();
32968                const details::operator_type o0 = operation;
32969                const details::operator_type o1 = expr_gen.get_operator(covov->f0());
32970                const details::operator_type o2 = expr_gen.get_operator(covov->f1());
32971
32972                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32973                binary_functor_t f1 = covov->f0();
32974                binary_functor_t f2 = covov->f1();
32975
32976                details::free_node(*(expr_gen.node_allocator_),branch[1]);
32977
32978                expression_node_ptr result = error_node();
32979
32980                const bool synthesis_result =
32981                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32982                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
32983
32984                if (synthesis_result)
32985                   return result;
32986                else if (!expr_gen.valid_operator(o0,f0))
32987                   return error_node();
32988
32989                exprtk_debug(("v0 o0 ((c o1 v1) o2 v2)\n"));
32990
32991                return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
32992             }
32993
32994             static inline std::string id(expression_generator<Type>& expr_gen,
32995                                          const details::operator_type o0,
32996                                          const details::operator_type o1,
32997                                          const details::operator_type o2)
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_covovov_expression2
33008          {
33009             typedef typename covovov_t::type2 node_type;
33010             typedef typename covovov_t::sf4_type sf4_type;
33011             typedef typename node_type::T0 T0;
33012             typedef typename node_type::T1 T1;
33013             typedef typename node_type::T2 T2;
33014             typedef typename node_type::T3 T3;
33015
33016             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                // c o0 ((v1 o1 v2) o2 v3)
33021                typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
33022
33023                const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
33024                const Type   c = static_cast<details::literal_node<Type>*>(branch[0])->value();
33025                const Type& v0 = vovov->t0();
33026                const Type& v1 = vovov->t1();
33027                const Type& v2 = vovov->t2();
33028                const details::operator_type o0 = operation;
33029                const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
33030                const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
33031
33032                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
33033                binary_functor_t f1 = vovov->f0();
33034                binary_functor_t f2 = vovov->f1();
33035
33036                details::free_node(*(expr_gen.node_allocator_),branch[0]);
33037                details::free_node(*(expr_gen.node_allocator_),branch[1]);
33038
33039                expression_node_ptr result = error_node();
33040
33041                const bool synthesis_result =
33042                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33043                      (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
33044
33045                if (synthesis_result)
33046                   return result;
33047                else if (!expr_gen.valid_operator(o0,f0))
33048                   return error_node();
33049
33050                exprtk_debug(("c o0 ((v1 o1 v2) o2 v3)\n"));
33051
33052                return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
33053             }
33054
33055             static inline std::string id(expression_generator<Type>& expr_gen,
33056                                          const details::operator_type o0,
33057                                          const details::operator_type o1,
33058                                          const details::operator_type o2)
33059             {
33060                return details::build_string()
33061                          << "t"   << expr_gen.to_str(o0)
33062                          << "((t" << expr_gen.to_str(o1)
33063                          << "t)"  << expr_gen.to_str(o2)
33064                          << "t)";
33065             }
33066         };
33067
33068          struct synthesize_covocov_expression2
33069          {
33070             typedef typename covocov_t::type2 node_type;
33071             typedef typename covocov_t::sf4_type sf4_type;
33072             typedef typename node_type::T0 T0;
33073             typedef typename node_type::T1 T1;
33074             typedef typename node_type::T2 T2;
33075             typedef typename node_type::T3 T3;
33076
33077             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33078                                                       const details::operator_type& operation,
33079                                                       expression_node_ptr (&branch)[2])
33080             {
33081                // c0 o0 ((v0 o1 c1) o2 v1)
33082                typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
33083
33084                const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
33085                const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
33086                const Type& v0 = vocov->t0();
33087                const Type  c1 = vocov->t1();
33088                const Type& v1 = vocov->t2();
33089                const details::operator_type o0 = operation;
33090                const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
33091                const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
33092
33093                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
33094                binary_functor_t f1 = vocov->f0();
33095                binary_functor_t f2 = vocov->f1();
33096
33097                details::free_node(*(expr_gen.node_allocator_),branch[0]);
33098                details::free_node(*(expr_gen.node_allocator_),branch[1]);
33099
33100                expression_node_ptr result = error_node();
33101
33102                const bool synthesis_result =
33103                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33104                      (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
33105
33106                if (synthesis_result)
33107                   return result;
33108                else if (!expr_gen.valid_operator(o0,f0))
33109                   return error_node();
33110
33111                exprtk_debug(("c0 o0 ((v0 o1 c1) o2 v1)\n"));
33112
33113                return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
33114             }
33115
33116             static inline std::string id(expression_generator<Type>& expr_gen,
33117                                          const details::operator_type o0,
33118                                          const details::operator_type o1,
33119                                          const details::operator_type o2)
33120             {
33121                return details::build_string()
33122                          << "t"   << expr_gen.to_str(o0)
33123                          << "((t" << expr_gen.to_str(o1)
33124                          << "t)"  << expr_gen.to_str(o2)
33125                          << "t)";
33126             }
33127          };
33128
33129          struct synthesize_vocovoc_expression2
33130          {
33131             typedef typename vocovoc_t::type2 node_type;
33132             typedef typename vocovoc_t::sf4_type sf4_type;
33133             typedef typename node_type::T0 T0;
33134             typedef typename node_type::T1 T1;
33135             typedef typename node_type::T2 T2;
33136             typedef typename node_type::T3 T3;
33137
33138             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33139                                                       const details::operator_type& operation,
33140                                                       expression_node_ptr (&branch)[2])
33141             {
33142                // v0 o0 ((c0 o1 v1) o2 c1)
33143                typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t;
33144
33145                const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]);
33146                const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
33147                const Type  c0 = covoc->t0();
33148                const Type& v1 = covoc->t1();
33149                const Type  c1 = covoc->t2();
33150                const details::operator_type o0 = operation;
33151                const details::operator_type o1 = expr_gen.get_operator(covoc->f0());
33152                const details::operator_type o2 = expr_gen.get_operator(covoc->f1());
33153
33154                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
33155                binary_functor_t f1 = covoc->f0();
33156                binary_functor_t f2 = covoc->f1();
33157
33158                details::free_node(*(expr_gen.node_allocator_),branch[1]);
33159
33160                expression_node_ptr result = error_node();
33161
33162                const bool synthesis_result =
33163                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33164                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
33165
33166                if (synthesis_result)
33167                   return result;
33168                else if (!expr_gen.valid_operator(o0,f0))
33169                   return error_node();
33170
33171                exprtk_debug(("v0 o0 ((c0 o1 v1) o2 c1)\n"));
33172
33173                return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
33174             }
33175
33176             static inline std::string id(expression_generator<Type>& expr_gen,
33177                                          const details::operator_type o0,
33178                                          const details::operator_type o1,
33179                                          const details::operator_type o2)
33180             {
33181                return details::build_string()
33182                          << "t"   << expr_gen.to_str(o0)
33183                          << "((t" << expr_gen.to_str(o1)
33184                          << "t)"  << expr_gen.to_str(o2)
33185                          << "t)";
33186             }
33187          };
33188
33189          struct synthesize_covovoc_expression2
33190          {
33191             typedef typename covovoc_t::type2 node_type;
33192             typedef typename covovoc_t::sf4_type sf4_type;
33193             typedef typename node_type::T0 T0;
33194             typedef typename node_type::T1 T1;
33195             typedef typename node_type::T2 T2;
33196             typedef typename node_type::T3 T3;
33197
33198             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33199                                                       const details::operator_type& operation,
33200                                                       expression_node_ptr (&branch)[2])
33201             {
33202                // c0 o0 ((v0 o1 v1) o2 c1)
33203                typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t;
33204
33205                const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
33206                const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
33207                const Type& v0 = vovoc->t0();
33208                const Type& v1 = vovoc->t1();
33209                const Type  c1 = vovoc->t2();
33210                const details::operator_type o0 = operation;
33211                const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
33212                const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
33213
33214                binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
33215                binary_functor_t f1 = vovoc->f0();
33216                binary_functor_t f2 = vovoc->f1();
33217
33218                details::free_node(*(expr_gen.node_allocator_),branch[0]);
33219                details::free_node(*(expr_gen.node_allocator_),branch[1]);
33220
33221                expression_node_ptr result = error_node();
33222
33223                const bool synthesis_result =
33224                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33225                      (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
33226
33227                if (synthesis_result)
33228                   return result;
33229                else if (!expr_gen.valid_operator(o0,f0))
33230                   return error_node();
33231
33232                exprtk_debug(("c0 o0 ((v0 o1 v1) o2 c1)\n"));
33233
33234                return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
33235             }
33236
33237             static inline std::string id(expression_generator<Type>& expr_gen,
33238                                          const details::operator_type o0,
33239                                          const details::operator_type o1,
33240                                          const details::operator_type o2)
33241             {
33242                return details::build_string()
33243                          << "t"   << expr_gen.to_str(o0)
33244                          << "((t" << expr_gen.to_str(o1)
33245                          << "t)"  << expr_gen.to_str(o2)
33246                          << "t)";
33247             }
33248          };
33249
33250          struct synthesize_vococov_expression2
33251          {
33252             typedef typename vococov_t::type2 node_type;
33253             static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
33254             {
33255                // v0 o0 ((c0 o1 c1) o2 v1) - Not possible
33256                exprtk_debug(("v0 o0 ((c0 o1 c1) o2 v1) - Not possible\n"));
33257                return error_node();
33258             }
33259
33260             static inline std::string id(expression_generator<Type>&,
33261                                          const details::operator_type, const details::operator_type, const details::operator_type)
33262             {
33263                return "INVALID";
33264             }
33265          };
33266
33267          struct synthesize_vovovov_expression3
33268          {
33269             typedef typename vovovov_t::type3 node_type;
33270             typedef typename vovovov_t::sf4_type sf4_type;
33271             typedef typename node_type::T0 T0;
33272             typedef typename node_type::T1 T1;
33273             typedef typename node_type::T2 T2;
33274             typedef typename node_type::T3 T3;
33275
33276             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33277                                                       const details::operator_type& operation,
33278                                                       expression_node_ptr (&branch)[2])
33279             {
33280                // ((v0 o0 v1) o1 v2) o2 v3
33281                typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
33282
33283                const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
33284                const Type& v0 = vovov->t0();
33285                const Type& v1 = vovov->t1();
33286                const Type& v2 = vovov->t2();
33287                const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
33288                const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
33289                const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
33290                const details::operator_type o2 = operation;
33291
33292                binary_functor_t f0 = vovov->f0();
33293                binary_functor_t f1 = vovov->f1();
33294                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33295
33296                details::free_node(*(expr_gen.node_allocator_),branch[0]);
33297
33298                expression_node_ptr result = error_node();
33299
33300                const bool synthesis_result =
33301                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33302                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
33303
33304                if (synthesis_result)
33305                   return result;
33306                else if (!expr_gen.valid_operator(o2,f2))
33307                   return error_node();
33308
33309                exprtk_debug(("((v0 o0 v1) o1 v2) o2 v3\n"));
33310
33311                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
33312             }
33313
33314             static inline std::string id(expression_generator<Type>& expr_gen,
33315                                          const details::operator_type o0,
33316                                          const details::operator_type o1,
33317                                          const details::operator_type o2)
33318             {
33319                return details::build_string()
33320                          << "((t" << expr_gen.to_str(o0)
33321                          << "t)"  << expr_gen.to_str(o1)
33322                          << "t)"  << expr_gen.to_str(o2)
33323                          << "t";
33324             }
33325          };
33326
33327          struct synthesize_vovovoc_expression3
33328          {
33329             typedef typename vovovoc_t::type3 node_type;
33330             typedef typename vovovoc_t::sf4_type sf4_type;
33331             typedef typename node_type::T0 T0;
33332             typedef typename node_type::T1 T1;
33333             typedef typename node_type::T2 T2;
33334             typedef typename node_type::T3 T3;
33335
33336             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33337                                                       const details::operator_type& operation,
33338                                                       expression_node_ptr (&branch)[2])
33339             {
33340                // ((v0 o0 v1) o1 v2) o2 c
33341                typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
33342
33343                const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
33344                const Type& v0 = vovov->t0();
33345                const Type& v1 = vovov->t1();
33346                const Type& v2 = vovov->t2();
33347                const Type   c = static_cast<details::literal_node<Type>*>(branch[1])->value();
33348                const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
33349                const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
33350                const details::operator_type o2 = operation;
33351
33352                binary_functor_t f0 = vovov->f0();
33353                binary_functor_t f1 = vovov->f1();
33354                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33355
33356                details::free_node(*(expr_gen.node_allocator_),branch[0]);
33357                details::free_node(*(expr_gen.node_allocator_),branch[1]);
33358
33359                expression_node_ptr result = error_node();
33360
33361                const bool synthesis_result =
33362                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33363                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
33364
33365                if (synthesis_result)
33366                   return result;
33367                else if (!expr_gen.valid_operator(o2,f2))
33368                   return error_node();
33369
33370                exprtk_debug(("((v0 o0 v1) o1 v2) o2 c\n"));
33371
33372                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
33373             }
33374
33375             static inline std::string id(expression_generator<Type>& expr_gen,
33376                                          const details::operator_type o0,
33377                                          const details::operator_type o1,
33378                                          const details::operator_type o2)
33379             {
33380                return details::build_string()
33381                          << "((t" << expr_gen.to_str(o0)
33382                          << "t)"  << expr_gen.to_str(o1)
33383                          << "t)"  << expr_gen.to_str(o2)
33384                          << "t";
33385             }
33386          };
33387
33388          struct synthesize_vovocov_expression3
33389          {
33390             typedef typename vovocov_t::type3 node_type;
33391             typedef typename vovocov_t::sf4_type sf4_type;
33392             typedef typename node_type::T0 T0;
33393             typedef typename node_type::T1 T1;
33394             typedef typename node_type::T2 T2;
33395             typedef typename node_type::T3 T3;
33396
33397             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33398                                                       const details::operator_type& operation,
33399                                                       expression_node_ptr (&branch)[2])
33400             {
33401                // ((v0 o0 v1) o1 c) o2 v2
33402                typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t;
33403
33404                const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]);
33405                const Type& v0 = vovoc->t0();
33406                const Type& v1 = vovoc->t1();
33407                const Type   c = vovoc->t2();
33408                const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
33409                const details::operator_type o0 = expr_gen.get_operator(vovoc->f0());
33410                const details::operator_type o1 = expr_gen.get_operator(vovoc->f1());
33411                const details::operator_type o2 = operation;
33412
33413                binary_functor_t f0 = vovoc->f0();
33414                binary_functor_t f1 = vovoc->f1();
33415                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33416
33417                details::free_node(*(expr_gen.node_allocator_),branch[0]);
33418
33419                expression_node_ptr result = error_node();
33420
33421                const bool synthesis_result =
33422                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33423                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
33424
33425                if (synthesis_result)
33426                   return result;
33427                else if (!expr_gen.valid_operator(o2,f2))
33428                   return error_node();
33429
33430                exprtk_debug(("((v0 o0 v1) o1 c) o2 v2\n"));
33431
33432                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
33433             }
33434
33435             static inline std::string id(expression_generator<Type>& expr_gen,
33436                                          const details::operator_type o0,
33437                                          const details::operator_type o1,
33438                                          const details::operator_type o2)
33439             {
33440                return details::build_string()
33441                          << "((t" << expr_gen.to_str(o0)
33442                          << "t)"  << expr_gen.to_str(o1)
33443                          << "t)"  << expr_gen.to_str(o2)
33444                          << "t";
33445             }
33446          };
33447
33448          struct synthesize_vocovov_expression3
33449          {
33450             typedef typename vocovov_t::type3 node_type;
33451             typedef typename vocovov_t::sf4_type sf4_type;
33452             typedef typename node_type::T0 T0;
33453             typedef typename node_type::T1 T1;
33454             typedef typename node_type::T2 T2;
33455             typedef typename node_type::T3 T3;
33456
33457             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33458                                                       const details::operator_type& operation,
33459                                                       expression_node_ptr (&branch)[2])
33460             {
33461                // ((v0 o0 c) o1 v1) o2 v2
33462                typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
33463
33464                const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
33465                const Type& v0 = vocov->t0();
33466                const Type   c = vocov->t1();
33467                const Type& v1 = vocov->t2();
33468                const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
33469                const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
33470                const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
33471                const details::operator_type o2 = operation;
33472
33473                binary_functor_t f0 = vocov->f0();
33474                binary_functor_t f1 = vocov->f1();
33475                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33476
33477                details::free_node(*(expr_gen.node_allocator_),branch[0]);
33478
33479                expression_node_ptr result = error_node();
33480
33481                const bool synthesis_result =
33482                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33483                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
33484
33485                if (synthesis_result)
33486                   return result;
33487                else if (!expr_gen.valid_operator(o2,f2))
33488                   return error_node();
33489
33490                exprtk_debug(("((v0 o0 c) o1 v1) o2 v2\n"));
33491
33492                return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
33493             }
33494
33495             static inline std::string id(expression_generator<Type>& expr_gen,
33496                                          const details::operator_type o0,
33497                                          const details::operator_type o1,
33498                                          const details::operator_type o2)
33499             {
33500                return details::build_string()
33501                          << "((t" << expr_gen.to_str(o0)
33502                          << "t)"  << expr_gen.to_str(o1)
33503                          << "t)"  << expr_gen.to_str(o2)
33504                          << "t";
33505             }
33506          };
33507
33508          struct synthesize_covovov_expression3
33509          {
33510             typedef typename covovov_t::type3 node_type;
33511             typedef typename covovov_t::sf4_type sf4_type;
33512             typedef typename node_type::T0 T0;
33513             typedef typename node_type::T1 T1;
33514             typedef typename node_type::T2 T2;
33515             typedef typename node_type::T3 T3;
33516
33517             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33518                                                       const details::operator_type& operation,
33519                                                       expression_node_ptr (&branch)[2])
33520             {
33521                // ((c o0 v0) o1 v1) o2 v2
33522                typedef typename synthesize_covov_expression0::node_type lcl_covov_t;
33523
33524                const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
33525                const Type   c = covov->t0();
33526                const Type& v0 = covov->t1();
33527                const Type& v1 = covov->t2();
33528                const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
33529                const details::operator_type o0 = expr_gen.get_operator(covov->f0());
33530                const details::operator_type o1 = expr_gen.get_operator(covov->f1());
33531                const details::operator_type o2 = operation;
33532
33533                binary_functor_t f0 = covov->f0();
33534                binary_functor_t f1 = covov->f1();
33535                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33536
33537                details::free_node(*(expr_gen.node_allocator_),branch[0]);
33538
33539                expression_node_ptr result = error_node();
33540
33541                const bool synthesis_result =
33542                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33543                      (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
33544
33545                if (synthesis_result)
33546                   return result;
33547                else if (!expr_gen.valid_operator(o2,f2))
33548                   return error_node();
33549
33550                exprtk_debug(("((c o0 v0) o1 v1) o2 v2\n"));
33551
33552                return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
33553             }
33554
33555             static inline std::string id(expression_generator<Type>& expr_gen,
33556                                          const details::operator_type o0,
33557                                          const details::operator_type o1,
33558                                          const details::operator_type o2)
33559             {
33560                return details::build_string()
33561                          << "((t" << expr_gen.to_str(o0)
33562                          << "t)"  << expr_gen.to_str(o1)
33563                          << "t)"  << expr_gen.to_str(o2)
33564                          << "t";
33565             }
33566          };
33567
33568          struct synthesize_covocov_expression3
33569          {
33570             typedef typename covocov_t::type3 node_type;
33571             typedef typename covocov_t::sf4_type sf4_type;
33572             typedef typename node_type::T0 T0;
33573             typedef typename node_type::T1 T1;
33574             typedef typename node_type::T2 T2;
33575             typedef typename node_type::T3 T3;
33576
33577             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33578                                                       const details::operator_type& operation,
33579                                                       expression_node_ptr (&branch)[2])
33580             {
33581                // ((c0 o0 v0) o1 c1) o2 v1
33582                typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t;
33583
33584                const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]);
33585                const Type  c0 = covoc->t0();
33586                const Type& v0 = covoc->t1();
33587                const Type  c1 = covoc->t2();
33588                const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
33589                const details::operator_type o0 = expr_gen.get_operator(covoc->f0());
33590                const details::operator_type o1 = expr_gen.get_operator(covoc->f1());
33591                const details::operator_type o2 = operation;
33592
33593                binary_functor_t f0 = covoc->f0();
33594                binary_functor_t f1 = covoc->f1();
33595                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33596
33597                details::free_node(*(expr_gen.node_allocator_),branch[0]);
33598
33599                expression_node_ptr result = error_node();
33600
33601                const bool synthesis_result =
33602                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33603                      (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
33604
33605                if (synthesis_result)
33606                   return result;
33607                else if (!expr_gen.valid_operator(o2,f2))
33608                   return error_node();
33609
33610                exprtk_debug(("((c0 o0 v0) o1 c1) o2 v1\n"));
33611
33612                return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
33613             }
33614
33615             static inline std::string id(expression_generator<Type>& expr_gen,
33616                                          const details::operator_type o0,
33617                                          const details::operator_type o1,
33618                                          const details::operator_type o2)
33619             {
33620                return details::build_string()
33621                          << "((t" << expr_gen.to_str(o0)
33622                          << "t)"  << expr_gen.to_str(o1)
33623                          << "t)"  << expr_gen.to_str(o2)
33624                          << "t";
33625             }
33626          };
33627
33628          struct synthesize_vocovoc_expression3
33629          {
33630             typedef typename vocovoc_t::type3 node_type;
33631             typedef typename vocovoc_t::sf4_type sf4_type;
33632             typedef typename node_type::T0 T0;
33633             typedef typename node_type::T1 T1;
33634             typedef typename node_type::T2 T2;
33635             typedef typename node_type::T3 T3;
33636
33637             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33638                                                       const details::operator_type& operation,
33639                                                       expression_node_ptr (&branch)[2])
33640             {
33641                // ((v0 o0 c0) o1 v1) o2 c1
33642                typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
33643
33644                const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
33645                const Type& v0 = vocov->t0();
33646                const Type  c0 = vocov->t1();
33647                const Type& v1 = vocov->t2();
33648                const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
33649                const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
33650                const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
33651                const details::operator_type o2 = operation;
33652
33653                binary_functor_t f0 = vocov->f0();
33654                binary_functor_t f1 = vocov->f1();
33655                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33656
33657                details::free_node(*(expr_gen.node_allocator_),branch[0]);
33658                details::free_node(*(expr_gen.node_allocator_),branch[1]);
33659
33660                expression_node_ptr result = error_node();
33661
33662                const bool synthesis_result =
33663                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33664                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
33665
33666                if (synthesis_result)
33667                   return result;
33668                else if (!expr_gen.valid_operator(o2,f2))
33669                   return error_node();
33670
33671                exprtk_debug(("((v0 o0 c0) o1 v1) o2 c1\n"));
33672
33673                return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
33674             }
33675
33676             static inline std::string id(expression_generator<Type>& expr_gen,
33677                                          const details::operator_type o0,
33678                                          const details::operator_type o1,
33679                                          const details::operator_type o2)
33680             {
33681                return details::build_string()
33682                          << "((t" << expr_gen.to_str(o0)
33683                          << "t)"  << expr_gen.to_str(o1)
33684                          << "t)"  << expr_gen.to_str(o2)
33685                          << "t";
33686             }
33687          };
33688
33689          struct synthesize_covovoc_expression3
33690          {
33691             typedef typename covovoc_t::type3 node_type;
33692             typedef typename covovoc_t::sf4_type sf4_type;
33693             typedef typename node_type::T0 T0;
33694             typedef typename node_type::T1 T1;
33695             typedef typename node_type::T2 T2;
33696             typedef typename node_type::T3 T3;
33697
33698             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33699                                                       const details::operator_type& operation,
33700                                                       expression_node_ptr (&branch)[2])
33701             {
33702                // ((c0 o0 v0) o1 v1) o2 c1
33703                typedef typename synthesize_covov_expression0::node_type lcl_covov_t;
33704
33705                const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
33706                const Type  c0 = covov->t0();
33707                const Type& v0 = covov->t1();
33708                const Type& v1 = covov->t2();
33709                const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
33710                const details::operator_type o0 = expr_gen.get_operator(covov->f0());
33711                const details::operator_type o1 = expr_gen.get_operator(covov->f1());
33712                const details::operator_type o2 = operation;
33713
33714                binary_functor_t f0 = covov->f0();
33715                binary_functor_t f1 = covov->f1();
33716                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33717
33718                details::free_node(*(expr_gen.node_allocator_),branch[0]);
33719                details::free_node(*(expr_gen.node_allocator_),branch[1]);
33720
33721                expression_node_ptr result = error_node();
33722
33723                const bool synthesis_result =
33724                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33725                      (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
33726
33727                if (synthesis_result)
33728                   return result;
33729                else if (!expr_gen.valid_operator(o2,f2))
33730                   return error_node();
33731
33732                exprtk_debug(("((c0 o0 v0) o1 v1) o2 c1\n"));
33733
33734                return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
33735             }
33736
33737             static inline std::string id(expression_generator<Type>& expr_gen,
33738                                          const details::operator_type o0,
33739                                          const details::operator_type o1,
33740                                          const details::operator_type o2)
33741             {
33742                return details::build_string()
33743                          << "((t" << expr_gen.to_str(o0)
33744                          << "t)"  << expr_gen.to_str(o1)
33745                          << "t)"  << expr_gen.to_str(o2)
33746                          << "t";
33747             }
33748          };
33749
33750          struct synthesize_vococov_expression3
33751          {
33752             typedef typename vococov_t::type3 node_type;
33753             typedef typename vococov_t::sf4_type sf4_type;
33754             typedef typename node_type::T0 T0;
33755             typedef typename node_type::T1 T1;
33756             typedef typename node_type::T2 T2;
33757             typedef typename node_type::T3 T3;
33758
33759             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33760                                                       const details::operator_type& operation,
33761                                                       expression_node_ptr (&branch)[2])
33762             {
33763                // ((v0 o0 c0) o1 c1) o2 v1
33764                typedef typename synthesize_vococ_expression0::node_type lcl_vococ_t;
33765
33766                const lcl_vococ_t* vococ = static_cast<const lcl_vococ_t*>(branch[0]);
33767                const Type& v0 = vococ->t0();
33768                const Type  c0 = vococ->t1();
33769                const Type  c1 = vococ->t2();
33770                const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
33771                const details::operator_type o0 = expr_gen.get_operator(vococ->f0());
33772                const details::operator_type o1 = expr_gen.get_operator(vococ->f1());
33773                const details::operator_type o2 = operation;
33774
33775                binary_functor_t f0 = vococ->f0();
33776                binary_functor_t f1 = vococ->f1();
33777                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33778
33779                details::free_node(*(expr_gen.node_allocator_),branch[0]);
33780
33781                expression_node_ptr result = error_node();
33782
33783                const bool synthesis_result =
33784                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33785                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result);
33786
33787                if (synthesis_result)
33788                   return result;
33789                else if (!expr_gen.valid_operator(o2,f2))
33790                   return error_node();
33791
33792                exprtk_debug(("((v0 o0 c0) o1 c1) o2 v1\n"));
33793
33794                return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2);
33795             }
33796
33797             static inline std::string id(expression_generator<Type>& expr_gen,
33798                                          const details::operator_type o0,
33799                                          const details::operator_type o1,
33800                                          const details::operator_type o2)
33801             {
33802                return details::build_string()
33803                          << "((t" << expr_gen.to_str(o0)
33804                          << "t)"  << expr_gen.to_str(o1)
33805                          << "t)"  << expr_gen.to_str(o2)
33806                          << "t";
33807             }
33808          };
33809
33810          struct synthesize_vovovov_expression4
33811          {
33812             typedef typename vovovov_t::type4 node_type;
33813             typedef typename vovovov_t::sf4_type sf4_type;
33814             typedef typename node_type::T0 T0;
33815             typedef typename node_type::T1 T1;
33816             typedef typename node_type::T2 T2;
33817             typedef typename node_type::T3 T3;
33818
33819             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33820                                                       const details::operator_type& operation,
33821                                                       expression_node_ptr (&branch)[2])
33822             {
33823                // (v0 o0 (v1 o1 v2)) o2 v3
33824                typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
33825
33826                const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
33827                const Type& v0 = vovov->t0();
33828                const Type& v1 = vovov->t1();
33829                const Type& v2 = vovov->t2();
33830                const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
33831                const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
33832                const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
33833                const details::operator_type o2 = operation;
33834
33835                binary_functor_t f0 = vovov->f0();
33836                binary_functor_t f1 = vovov->f1();
33837                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33838
33839                details::free_node(*(expr_gen.node_allocator_),branch[0]);
33840
33841                expression_node_ptr result = error_node();
33842
33843                const bool synthesis_result =
33844                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33845                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
33846
33847                if (synthesis_result)
33848                   return result;
33849                else if (!expr_gen.valid_operator(o2,f2))
33850                   return error_node();
33851
33852                exprtk_debug(("(v0 o0 (v1 o1 v2)) o2 v3\n"));
33853
33854                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
33855             }
33856
33857             static inline std::string id(expression_generator<Type>& expr_gen,
33858                                          const details::operator_type o0,
33859                                          const details::operator_type o1,
33860                                          const details::operator_type o2)
33861             {
33862                return details::build_string()
33863                          << "(t" << expr_gen.to_str(o0)
33864                          << "(t" << expr_gen.to_str(o1)
33865                          << "t)" << expr_gen.to_str(o2)
33866                          << "t";
33867             }
33868          };
33869
33870          struct synthesize_vovovoc_expression4
33871          {
33872             typedef typename vovovoc_t::type4 node_type;
33873             typedef typename vovovoc_t::sf4_type sf4_type;
33874             typedef typename node_type::T0 T0;
33875             typedef typename node_type::T1 T1;
33876             typedef typename node_type::T2 T2;
33877             typedef typename node_type::T3 T3;
33878
33879             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33880                                                       const details::operator_type& operation,
33881                                                       expression_node_ptr (&branch)[2])
33882             {
33883                // ((v0 o0 (v1 o1 v2)) o2 c)
33884                typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
33885
33886                const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
33887                const Type& v0 = vovov->t0();
33888                const Type& v1 = vovov->t1();
33889                const Type& v2 = vovov->t2();
33890                const Type   c = static_cast<details::literal_node<Type>*>(branch[1])->value();
33891                const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
33892                const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
33893                const details::operator_type o2 = operation;
33894
33895                binary_functor_t f0 = vovov->f0();
33896                binary_functor_t f1 = vovov->f1();
33897                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33898
33899                details::free_node(*(expr_gen.node_allocator_),branch[0]);
33900                details::free_node(*(expr_gen.node_allocator_),branch[1]);
33901
33902                expression_node_ptr result = error_node();
33903
33904                const bool synthesis_result =
33905                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33906                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
33907
33908                if (synthesis_result)
33909                   return result;
33910                else if (!expr_gen.valid_operator(o2,f2))
33911                   return error_node();
33912
33913                exprtk_debug(("((v0 o0 (v1 o1 v2)) o2 c)\n"));
33914
33915                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
33916             }
33917
33918             static inline std::string id(expression_generator<Type>& expr_gen,
33919                                          const details::operator_type o0,
33920                                          const details::operator_type o1,
33921                                          const details::operator_type o2)
33922             {
33923                return details::build_string()
33924                          << "(t" << expr_gen.to_str(o0)
33925                          << "(t" << expr_gen.to_str(o1)
33926                          << "t)" << expr_gen.to_str(o2)
33927                          << "t";
33928             }
33929          };
33930
33931          struct synthesize_vovocov_expression4
33932          {
33933             typedef typename vovocov_t::type4 node_type;
33934             typedef typename vovocov_t::sf4_type sf4_type;
33935             typedef typename node_type::T0 T0;
33936             typedef typename node_type::T1 T1;
33937             typedef typename node_type::T2 T2;
33938             typedef typename node_type::T3 T3;
33939
33940             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
33941                                                       const details::operator_type& operation,
33942                                                       expression_node_ptr (&branch)[2])
33943             {
33944                // ((v0 o0 (v1 o1 c)) o2 v1)
33945                typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t;
33946
33947                const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]);
33948                const Type& v0 = vovoc->t0();
33949                const Type& v1 = vovoc->t1();
33950                const Type   c = vovoc->t2();
33951                const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
33952                const details::operator_type o0 = expr_gen.get_operator(vovoc->f0());
33953                const details::operator_type o1 = expr_gen.get_operator(vovoc->f1());
33954                const details::operator_type o2 = operation;
33955
33956                binary_functor_t f0 = vovoc->f0();
33957                binary_functor_t f1 = vovoc->f1();
33958                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33959
33960                details::free_node(*(expr_gen.node_allocator_),branch[0]);
33961
33962                expression_node_ptr result = error_node();
33963
33964                const bool synthesis_result =
33965                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33966                      (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
33967
33968                if (synthesis_result)
33969                   return result;
33970                else if (!expr_gen.valid_operator(o2,f2))
33971                   return error_node();
33972
33973                exprtk_debug(("((v0 o0 (v1 o1 c)) o2 v1)\n"));
33974
33975                return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
33976             }
33977
33978             static inline std::string id(expression_generator<Type>& expr_gen,
33979                                          const details::operator_type o0,
33980                                          const details::operator_type o1,
33981                                          const details::operator_type o2)
33982             {
33983                return details::build_string()
33984                          << "(t" << expr_gen.to_str(o0)
33985                          << "(t" << expr_gen.to_str(o1)
33986                          << "t)" << expr_gen.to_str(o2)
33987                          << "t";
33988             }
33989          };
33990
33991          struct synthesize_vocovov_expression4
33992          {
33993             typedef typename vocovov_t::type4 node_type;
33994             typedef typename vocovov_t::sf4_type sf4_type;
33995             typedef typename node_type::T0 T0;
33996             typedef typename node_type::T1 T1;
33997             typedef typename node_type::T2 T2;
33998             typedef typename node_type::T3 T3;
33999
34000             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34001                                                       const details::operator_type& operation,
34002                                                       expression_node_ptr (&branch)[2])
34003             {
34004                // ((v0 o0 (c o1 v1)) o2 v2)
34005                typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
34006
34007                const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
34008                const Type& v0 = vocov->t0();
34009                const Type   c = vocov->t1();
34010                const Type& v1 = vocov->t2();
34011                const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
34012                const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
34013                const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
34014                const details::operator_type o2 = operation;
34015
34016                binary_functor_t f0 = vocov->f0();
34017                binary_functor_t f1 = vocov->f1();
34018                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34019
34020                details::free_node(*(expr_gen.node_allocator_),branch[0]);
34021                expression_node_ptr result = error_node();
34022
34023                const bool synthesis_result =
34024                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34025                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
34026
34027                if (synthesis_result)
34028                   return result;
34029                else if (!expr_gen.valid_operator(o2,f2))
34030                   return error_node();
34031
34032                exprtk_debug(("((v0 o0 (c o1 v1)) o2 v2)\n"));
34033
34034                return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
34035             }
34036
34037             static inline std::string id(expression_generator<Type>& expr_gen,
34038                                          const details::operator_type o0,
34039                                          const details::operator_type o1,
34040                                          const details::operator_type o2)
34041             {
34042                return details::build_string()
34043                          << "(t" << expr_gen.to_str(o0)
34044                          << "(t" << expr_gen.to_str(o1)
34045                          << "t)" << expr_gen.to_str(o2)
34046                          << "t";
34047             }
34048          };
34049
34050          struct synthesize_covovov_expression4
34051          {
34052             typedef typename covovov_t::type4 node_type;
34053             typedef typename covovov_t::sf4_type sf4_type;
34054             typedef typename node_type::T0 T0;
34055             typedef typename node_type::T1 T1;
34056             typedef typename node_type::T2 T2;
34057             typedef typename node_type::T3 T3;
34058
34059             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34060                                                       const details::operator_type& operation,
34061                                                       expression_node_ptr (&branch)[2])
34062             {
34063                // ((c o0 (v0 o1 v1)) o2 v2)
34064                typedef typename synthesize_covov_expression1::node_type lcl_covov_t;
34065
34066                const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
34067                const Type   c = covov->t0();
34068                const Type& v0 = covov->t1();
34069                const Type& v1 = covov->t2();
34070                const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
34071                const details::operator_type o0 = expr_gen.get_operator(covov->f0());
34072                const details::operator_type o1 = expr_gen.get_operator(covov->f1());
34073                const details::operator_type o2 = operation;
34074
34075                binary_functor_t f0 = covov->f0();
34076                binary_functor_t f1 = covov->f1();
34077                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34078
34079                details::free_node(*(expr_gen.node_allocator_),branch[0]);
34080
34081                expression_node_ptr result = error_node();
34082
34083                const bool synthesis_result =
34084                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34085                      (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
34086
34087                if (synthesis_result)
34088                   return result;
34089                else if (!expr_gen.valid_operator(o2,f2))
34090                   return error_node();
34091
34092                exprtk_debug(("((c o0 (v0 o1 v1)) o2 v2)\n"));
34093
34094                return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
34095             }
34096
34097             static inline std::string id(expression_generator<Type>& expr_gen,
34098                                          const details::operator_type o0,
34099                                          const details::operator_type o1,
34100                                          const details::operator_type o2)
34101             {
34102                return details::build_string()
34103                          << "(t" << expr_gen.to_str(o0)
34104                          << "(t" << expr_gen.to_str(o1)
34105                          << "t)" << expr_gen.to_str(o2)
34106                          << "t";
34107             }
34108          };
34109
34110          struct synthesize_covocov_expression4
34111          {
34112             typedef typename covocov_t::type4 node_type;
34113             typedef typename covocov_t::sf4_type sf4_type;
34114             typedef typename node_type::T0 T0;
34115             typedef typename node_type::T1 T1;
34116             typedef typename node_type::T2 T2;
34117             typedef typename node_type::T3 T3;
34118
34119             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34120                                                       const details::operator_type& operation,
34121                                                       expression_node_ptr (&branch)[2])
34122             {
34123                // ((c0 o0 (v0 o1 c1)) o2 v1)
34124                typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t;
34125
34126                const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]);
34127                const Type  c0 = covoc->t0();
34128                const Type& v0 = covoc->t1();
34129                const Type  c1 = covoc->t2();
34130                const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
34131                const details::operator_type o0 = expr_gen.get_operator(covoc->f0());
34132                const details::operator_type o1 = expr_gen.get_operator(covoc->f1());
34133                const details::operator_type o2 = operation;
34134
34135                binary_functor_t f0 = covoc->f0();
34136                binary_functor_t f1 = covoc->f1();
34137                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34138
34139                details::free_node(*(expr_gen.node_allocator_),branch[0]);
34140
34141                expression_node_ptr result = error_node();
34142
34143                const bool synthesis_result =
34144                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34145                      (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
34146
34147                if (synthesis_result)
34148                   return result;
34149                else if (!expr_gen.valid_operator(o2,f2))
34150                   return error_node();
34151
34152                exprtk_debug(("((c0 o0 (v0 o1 c1)) o2 v1)\n"));
34153
34154                return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
34155             }
34156
34157             static inline std::string id(expression_generator<Type>& expr_gen,
34158                                          const details::operator_type o0,
34159                                          const details::operator_type o1,
34160                                          const details::operator_type o2)
34161             {
34162                return details::build_string()
34163                          << "(t" << expr_gen.to_str(o0)
34164                          << "(t" << expr_gen.to_str(o1)
34165                          << "t)" << expr_gen.to_str(o2)
34166                          << "t";
34167             }
34168          };
34169
34170          struct synthesize_vocovoc_expression4
34171          {
34172             typedef typename vocovoc_t::type4 node_type;
34173             typedef typename vocovoc_t::sf4_type sf4_type;
34174             typedef typename node_type::T0 T0;
34175             typedef typename node_type::T1 T1;
34176             typedef typename node_type::T2 T2;
34177             typedef typename node_type::T3 T3;
34178
34179             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34180                                                       const details::operator_type& operation,
34181                                                       expression_node_ptr (&branch)[2])
34182             {
34183                // ((v0 o0 (c0 o1 v1)) o2 c1)
34184                typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
34185
34186                const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
34187                const Type& v0 = vocov->t0();
34188                const Type  c0 = vocov->t1();
34189                const Type& v1 = vocov->t2();
34190                const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
34191                const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
34192                const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
34193                const details::operator_type o2 = operation;
34194
34195                binary_functor_t f0 = vocov->f0();
34196                binary_functor_t f1 = vocov->f1();
34197                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34198
34199                details::free_node(*(expr_gen.node_allocator_),branch[0]);
34200                details::free_node(*(expr_gen.node_allocator_),branch[1]);
34201
34202                expression_node_ptr result = error_node();
34203
34204                const bool synthesis_result =
34205                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34206                      (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
34207
34208                if (synthesis_result)
34209                   return result;
34210                else if (!expr_gen.valid_operator(o2,f2))
34211                   return error_node();
34212
34213                exprtk_debug(("((v0 o0 (c0 o1 v1)) o2 c1)\n"));
34214
34215                return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
34216             }
34217
34218             static inline std::string id(expression_generator<Type>& expr_gen,
34219                                          const details::operator_type o0,
34220                                          const details::operator_type o1,
34221                                          const details::operator_type o2)
34222             {
34223                return details::build_string()
34224                          << "(t" << expr_gen.to_str(o0)
34225                          << "(t" << expr_gen.to_str(o1)
34226                          << "t)" << expr_gen.to_str(o2)
34227                          << "t";
34228             }
34229          };
34230
34231          struct synthesize_covovoc_expression4
34232          {
34233             typedef typename covovoc_t::type4 node_type;
34234             typedef typename covovoc_t::sf4_type sf4_type;
34235             typedef typename node_type::T0 T0;
34236             typedef typename node_type::T1 T1;
34237             typedef typename node_type::T2 T2;
34238             typedef typename node_type::T3 T3;
34239
34240             static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
34241                                                       const details::operator_type& operation,
34242                                                       expression_node_ptr (&branch)[2])
34243             {
34244                // ((c0 o0 (v0 o1 v1)) o2 c1)
34245                typedef typename synthesize_covov_expression1::node_type lcl_covov_t;
34246
34247                const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
34248                const Type  c0 = covov->t0();
34249                const Type& v0 = covov->t1();
34250                const Type& v1 = covov->t2();
34251                const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
34252                const details::operator_type o0 = expr_gen.get_operator(covov->f0());
34253                const details::operator_type o1 = expr_gen.get_operator(covov->f1());
34254                const details::operator_type o2 = operation;
34255
34256                binary_functor_t f0 = covov->f0();
34257                binary_functor_t f1 = covov->f1();
34258                binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34259
34260                details::free_node(*(expr_gen.node_allocator_),branch[0]);
34261                details::free_node(*(expr_gen.node_allocator_),branch[1]);
34262
34263                expression_node_ptr result = error_node();
34264
34265                const bool synthesis_result =
34266                   synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34267                      (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
34268
34269                if (synthesis_result)
34270                   return result;
34271                else if (!expr_gen.valid_operator(o2,f2))
34272                   return error_node();
34273
34274                exprtk_debug(("((c0 o0 (v0 o1 v1)) o2 c1)\n"));
34275
34276                return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
34277             }
34278
34279             static inline std::string id(expression_generator<Type>& expr_gen,
34280                                          const details::operator_type o0,
34281                                          const details::operator_type o1,
34282                                          const details::operator_type o2)
34283             {
34284                return details::build_string()
34285                          << "(t" << expr_gen.to_str(o0)
34286                          << "(t" << expr_gen.to_str(o1)
34287                          << "t)" << expr_gen.to_str(o2)
34288                          << "t";
34289             }
34290          };
34291
34292          struct synthesize_vococov_expression4
34293          {
34294             typedef typename vococov_t::type4 node_type;
34295             static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
34296             {
34297                // ((v0 o0 (c0 o1 c1)) o2 v1) - Not possible
34298                exprtk_debug(("((v0 o0 (c0 o1 c1)) o2 v1) - Not possible\n"));
34299                return error_node();
34300             }
34301
34302             static inline std::string id(expression_generator<Type>&,
34303                                          const details::operator_type, const details::operator_type, const details::operator_type)
34304             {
34305                return "INVALID";
34306             }
34307          };
34308          #endif
34309
34310          inline expression_node_ptr synthesize_uvouv_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
34311          {
34312             // Definition: uv o uv
34313             details::operator_type o0 = static_cast<details::uv_base_node<Type>*>(branch[0])->operation();
34314             details::operator_type o1 = static_cast<details::uv_base_node<Type>*>(branch[1])->operation();
34315             const Type& v0 = static_cast<details::uv_base_node<Type>*>(branch[0])->v();
34316             const Type& v1 = static_cast<details::uv_base_node<Type>*>(branch[1])->v();
34317             unary_functor_t u0 = reinterpret_cast<unary_functor_t> (0);
34318             unary_functor_t u1 = reinterpret_cast<unary_functor_t> (0);
34319             binary_functor_t f = reinterpret_cast<binary_functor_t>(0);
34320
34321             if (!valid_operator(o0,u0))
34322                return error_node();
34323             else if (!valid_operator(o1,u1))
34324                return error_node();
34325             else if (!valid_operator(operation,f))
34326                return error_node();
34327
34328             expression_node_ptr result = error_node();
34329
34330             if (
34331                  (details::e_neg == o0) &&
34332                  (details::e_neg == o1)
34333                )
34334             {
34335                switch (operation)
34336                {
34337                   // (-v0 + -v1) --> -(v0 + v1)
34338                   case details::e_add : result = (*this)(details::e_neg,
34339                                                     node_allocator_->
34340                                                        allocate_rr<typename details::
34341                                                           vov_node<Type,details::add_op<Type> > >(v0, v1));
34342                                         exprtk_debug(("(-v0 + -v1) --> -(v0 + v1)\n"));
34343                                         break;
34344
34345                   // (-v0 - -v1) --> (v1 - v0)
34346                   case details::e_sub : result = node_allocator_->
34347                                                     allocate_rr<typename details::
34348                                                        vov_node<Type,details::sub_op<Type> > >(v1, v0);
34349                                         exprtk_debug(("(-v0 - -v1) --> (v1 - v0)\n"));
34350                                         break;
34351
34352                   // (-v0 * -v1) --> (v0 * v1)
34353                   case details::e_mul : result = node_allocator_->
34354                                                     allocate_rr<typename details::
34355                                                        vov_node<Type,details::mul_op<Type> > >(v0, v1);
34356                                         exprtk_debug(("(-v0 * -v1) --> (v0 * v1)\n"));
34357                                         break;
34358
34359                   // (-v0 / -v1) --> (v0 / v1)
34360                   case details::e_div : result = node_allocator_->
34361                                                     allocate_rr<typename details::
34362                                                        vov_node<Type,details::div_op<Type> > >(v0, v1);
34363                                         exprtk_debug(("(-v0 / -v1) --> (v0 / v1)\n"));
34364                                         break;
34365
34366                   default             : break;
34367                }
34368             }
34369
34370             if (0 == result)
34371             {
34372                result = node_allocator_->
34373                             allocate_rrrrr<typename details::uvouv_node<Type> >(v0, v1, u0, u1, f);
34374             }
34375
34376             details::free_all_nodes(*node_allocator_,branch);
34377             return result;
34378          }
34379
34380          #undef basic_opr_switch_statements
34381          #undef extended_opr_switch_statements
34382          #undef unary_opr_switch_statements
34383
34384          #ifndef exprtk_disable_string_capabilities
34385
34386          #define string_opr_switch_statements          \
34387          case_stmt(details::  e_lt ,details::   lt_op) \
34388          case_stmt(details:: e_lte ,details::  lte_op) \
34389          case_stmt(details::  e_gt ,details::   gt_op) \
34390          case_stmt(details:: e_gte ,details::  gte_op) \
34391          case_stmt(details::  e_eq ,details::   eq_op) \
34392          case_stmt(details::  e_ne ,details::   ne_op) \
34393          case_stmt(details::e_in   ,details::   in_op) \
34394          case_stmt(details::e_like ,details:: like_op) \
34395          case_stmt(details::e_ilike,details::ilike_op) \
34396
34397          template <typename T0, typename T1>
34398          inline expression_node_ptr synthesize_str_xrox_expression_impl(const details::operator_type& opr,
34399                                                                         T0 s0, T1 s1,
34400                                                                         range_t rp0)
34401          {
34402             switch (opr)
34403             {
34404                #define case_stmt(op0,op1)                                                                       \
34405                case op0 : return node_allocator_->                                                              \
34406                              allocate_ttt<typename details::str_xrox_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \
34407                                 (s0, s1, rp0);                                                                  \
34408
34409                string_opr_switch_statements
34410                #undef case_stmt
34411                default : return error_node();
34412             }
34413          }
34414
34415          template <typename T0, typename T1>
34416          inline expression_node_ptr synthesize_str_xoxr_expression_impl(const details::operator_type& opr,
34417                                                                         T0 s0, T1 s1,
34418                                                                         range_t rp1)
34419          {
34420             switch (opr)
34421             {
34422                #define case_stmt(op0,op1)                                                                       \
34423                case op0 : return node_allocator_->                                                              \
34424                              allocate_ttt<typename details::str_xoxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \
34425                                 (s0, s1, rp1);                                                                  \
34426
34427                string_opr_switch_statements
34428                #undef case_stmt
34429                default : return error_node();
34430             }
34431          }
34432
34433          template <typename T0, typename T1>
34434          inline expression_node_ptr synthesize_str_xroxr_expression_impl(const details::operator_type& opr,
34435                                                                          T0 s0, T1 s1,
34436                                                                          range_t rp0, range_t rp1)
34437          {
34438             switch (opr)
34439             {
34440                #define case_stmt(op0,op1)                                                                         \
34441                case op0 : return node_allocator_->                                                                \
34442                              allocate_tttt<typename details::str_xroxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \
34443                                 (s0, s1, rp0, rp1);                                                               \
34444
34445                string_opr_switch_statements
34446                #undef case_stmt
34447                default : return error_node();
34448             }
34449          }
34450
34451          template <typename T0, typename T1>
34452          inline expression_node_ptr synthesize_sos_expression_impl(const details::operator_type& opr, T0 s0, T1 s1)
34453          {
34454             switch (opr)
34455             {
34456                #define case_stmt(op0,op1)                                                                  \
34457                case op0 : return node_allocator_->                                                         \
34458                              allocate_tt<typename details::sos_node<Type,T0,T1,op1<Type> >,T0,T1>(s0, s1); \
34459
34460                string_opr_switch_statements
34461                #undef case_stmt
34462                default : return error_node();
34463             }
34464          }
34465
34466          inline expression_node_ptr synthesize_sos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34467          {
34468             std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref();
34469             std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref();
34470
34471             return synthesize_sos_expression_impl<std::string&,std::string&>(opr, s0, s1);
34472          }
34473
34474          inline expression_node_ptr synthesize_sros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34475          {
34476             std::string&  s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref  ();
34477             std::string&  s1 = static_cast<details::stringvar_node<Type>*>   (branch[1])->ref  ();
34478             range_t      rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range();
34479
34480             static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();
34481
34482             free_node(*node_allocator_,branch[0]);
34483
34484             return synthesize_str_xrox_expression_impl<std::string&,std::string&>(opr, s0, s1, rp0);
34485          }
34486
34487          inline expression_node_ptr synthesize_sosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34488          {
34489             std::string&  s0 = static_cast<details::stringvar_node<Type>*>   (branch[0])->ref  ();
34490             std::string&  s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref  ();
34491             range_t      rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range();
34492
34493             static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();
34494
34495             free_node(*node_allocator_,branch[1]);
34496
34497             return synthesize_str_xoxr_expression_impl<std::string&,std::string&>(opr, s0, s1, rp1);
34498          }
34499
34500          inline expression_node_ptr synthesize_socsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34501          {
34502             std::string&  s0 = static_cast<details::stringvar_node<Type>*>         (branch[0])->ref  ();
34503             std::string   s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str  ();
34504             range_t      rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
34505
34506             static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
34507
34508             free_node(*node_allocator_,branch[1]);
34509
34510             return synthesize_str_xoxr_expression_impl<std::string&, const std::string>(opr, s0, s1, rp1);
34511          }
34512
34513          inline expression_node_ptr synthesize_srosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34514          {
34515             std::string&  s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref  ();
34516             std::string&  s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref  ();
34517             range_t      rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range();
34518             range_t      rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range();
34519
34520             static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();
34521             static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();
34522
34523             details::free_node(*node_allocator_,branch[0]);
34524             details::free_node(*node_allocator_,branch[1]);
34525
34526             return synthesize_str_xroxr_expression_impl<std::string&,std::string&>(opr, s0, s1, rp0, rp1);
34527          }
34528
34529          inline expression_node_ptr synthesize_socs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34530          {
34531             std::string& s0 = static_cast<     details::stringvar_node<Type>*>(branch[0])->ref();
34532             std::string  s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
34533
34534             details::free_node(*node_allocator_,branch[1]);
34535
34536             return synthesize_sos_expression_impl<std::string&, const std::string>(opr, s0, s1);
34537          }
34538
34539          inline expression_node_ptr synthesize_csos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34540          {
34541             std::string  s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
34542             std::string& s1 = static_cast<     details::stringvar_node<Type>*>(branch[1])->ref();
34543
34544             details::free_node(*node_allocator_,branch[0]);
34545
34546             return synthesize_sos_expression_impl<const std::string,std::string&>(opr, s0, s1);
34547          }
34548
34549          inline expression_node_ptr synthesize_csosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34550          {
34551             std::string   s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str  ();
34552             std::string&  s1 = static_cast<details::string_range_node<Type>*>  (branch[1])->ref  ();
34553             range_t      rp1 = static_cast<details::string_range_node<Type>*>  (branch[1])->range();
34554
34555             static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();
34556
34557             details::free_node(*node_allocator_,branch[0]);
34558             details::free_node(*node_allocator_,branch[1]);
34559
34560             return synthesize_str_xoxr_expression_impl<const std::string,std::string&>(opr, s0, s1, rp1);
34561          }
34562
34563          inline expression_node_ptr synthesize_srocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34564          {
34565             std::string&  s0 = static_cast<details::string_range_node<Type>*>  (branch[0])->ref  ();
34566             std::string   s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str  ();
34567             range_t      rp0 = static_cast<details::string_range_node<Type>*>  (branch[0])->range();
34568
34569             static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();
34570
34571             details::free_node(*node_allocator_,branch[0]);
34572             details::free_node(*node_allocator_,branch[1]);
34573
34574             return synthesize_str_xrox_expression_impl<std::string&, const std::string>(opr, s0, s1, rp0);
34575          }
34576
34577          inline expression_node_ptr synthesize_srocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34578          {
34579             std::string&  s0 = static_cast<details::string_range_node<Type>*>      (branch[0])->ref  ();
34580             std::string   s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str  ();
34581             range_t      rp0 = static_cast<details::string_range_node<Type>*>      (branch[0])->range();
34582             range_t      rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
34583
34584             static_cast<details::string_range_node<Type>*>      (branch[0])->range_ref().clear();
34585             static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
34586
34587             details::free_node(*node_allocator_,branch[0]);
34588             details::free_node(*node_allocator_,branch[1]);
34589
34590             return synthesize_str_xroxr_expression_impl<std::string&, const std::string>(opr, s0, s1, rp0, rp1);
34591          }
34592
34593          inline expression_node_ptr synthesize_csocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34594          {
34595             const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
34596             const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
34597
34598             expression_node_ptr result = error_node();
34599
34600             if (details::e_add == opr)
34601                result = node_allocator_->allocate_c<details::string_literal_node<Type> >(s0 + s1);
34602             else if (details::e_in == opr)
34603                result = node_allocator_->allocate_c<details::literal_node<Type> >(details::in_op   <Type>::process(s0,s1));
34604             else if (details::e_like == opr)
34605                result = node_allocator_->allocate_c<details::literal_node<Type> >(details::like_op <Type>::process(s0,s1));
34606             else if (details::e_ilike == opr)
34607                result = node_allocator_->allocate_c<details::literal_node<Type> >(details::ilike_op<Type>::process(s0,s1));
34608             else
34609             {
34610                expression_node_ptr temp = synthesize_sos_expression_impl<const std::string, const std::string>(opr, s0, s1);
34611
34612                const Type v = temp->value();
34613
34614                details::free_node(*node_allocator_,temp);
34615
34616                result = node_allocator_->allocate<literal_node_t>(v);
34617             }
34618
34619             details::free_all_nodes(*node_allocator_,branch);
34620
34621             return result;
34622          }
34623
34624          inline expression_node_ptr synthesize_csocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34625          {
34626             const std::string s0 = static_cast<details::string_literal_node<Type>*>    (branch[0])->str  ();
34627                   std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str  ();
34628             range_t          rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
34629
34630             static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
34631
34632             free_node(*node_allocator_,branch[0]);
34633             free_node(*node_allocator_,branch[1]);
34634
34635             return synthesize_str_xoxr_expression_impl<const std::string, const std::string>(opr, s0, s1, rp1);
34636          }
34637
34638          inline expression_node_ptr synthesize_csros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34639          {
34640             std::string   s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str  ();
34641             std::string&  s1 = static_cast<details::stringvar_node<Type>*>         (branch[1])->ref  ();
34642             range_t      rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
34643
34644             static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
34645
34646             free_node(*node_allocator_,branch[0]);
34647
34648             return synthesize_str_xrox_expression_impl<const std::string,std::string&>(opr, s0, s1, rp0);
34649          }
34650
34651          inline expression_node_ptr synthesize_csrosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34652          {
34653             const std::string  s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str  ();
34654                   std::string& s1 = static_cast<details::string_range_node<Type>*>      (branch[1])->ref  ();
34655             const range_t     rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
34656             const range_t     rp1 = static_cast<details::string_range_node<Type>*>      (branch[1])->range();
34657
34658             static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
34659             static_cast<details::string_range_node<Type>*>      (branch[1])->range_ref().clear();
34660
34661             free_node(*node_allocator_,branch[0]);
34662             free_node(*node_allocator_,branch[1]);
34663
34664             return synthesize_str_xroxr_expression_impl<const std::string,std::string&>(opr, s0, s1, rp0, rp1);
34665          }
34666
34667          inline expression_node_ptr synthesize_csrocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34668          {
34669             const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str  ();
34670             const std::string s1 = static_cast<details::string_literal_node<Type>*>    (branch[1])->str  ();
34671             const range_t    rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
34672
34673             static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
34674
34675             details::free_all_nodes(*node_allocator_,branch);
34676
34677             return synthesize_str_xrox_expression_impl<const std::string,std::string>(opr, s0, s1, rp0);
34678          }
34679
34680          inline expression_node_ptr synthesize_csrocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34681          {
34682             const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str  ();
34683             const std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str  ();
34684             const range_t    rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
34685             const range_t    rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
34686
34687             static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
34688             static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
34689
34690             details::free_all_nodes(*node_allocator_,branch);
34691
34692             return synthesize_str_xroxr_expression_impl<const std::string, const std::string>(opr, s0, s1, rp0, rp1);
34693          }
34694
34695          inline expression_node_ptr synthesize_strogen_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34696          {
34697             switch (opr)
34698             {
34699                #define case_stmt(op0,op1)                                                       \
34700                case op0 : return node_allocator_->                                              \
34701                              allocate_ttt<typename details::str_sogens_node<Type,op1<Type> > >  \
34702                                 (opr, branch[0], branch[1]);                                    \
34703
34704                string_opr_switch_statements
34705                #undef case_stmt
34706                default : return error_node();
34707             }
34708          }
34709          #endif
34710
34711          #ifndef exprtk_disable_string_capabilities
34712          inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
34713          {
34714             if ((0 == branch[0]) || (0 == branch[1]))
34715             {
34716                details::free_all_nodes(*node_allocator_,branch);
34717
34718                return error_node();
34719             }
34720
34721             const bool b0_is_s   = details::is_string_node            (branch[0]);
34722             const bool b0_is_cs  = details::is_const_string_node      (branch[0]);
34723             const bool b0_is_sr  = details::is_string_range_node      (branch[0]);
34724             const bool b0_is_csr = details::is_const_string_range_node(branch[0]);
34725
34726             const bool b1_is_s   = details::is_string_node            (branch[1]);
34727             const bool b1_is_cs  = details::is_const_string_node      (branch[1]);
34728             const bool b1_is_sr  = details::is_string_range_node      (branch[1]);
34729             const bool b1_is_csr = details::is_const_string_range_node(branch[1]);
34730
34731             const bool b0_is_gen = details::is_string_assignment_node (branch[0]) ||
34732                                    details::is_genricstring_range_node(branch[0]) ||
34733                                    details::is_string_concat_node     (branch[0]) ||
34734                                    details::is_string_function_node   (branch[0]) ||
34735                                    details::is_string_condition_node  (branch[0]) ||
34736                                    details::is_string_ccondition_node (branch[0]) ||
34737                                    details::is_string_vararg_node     (branch[0]) ;
34738
34739             const bool b1_is_gen = details::is_string_assignment_node (branch[1]) ||
34740                                    details::is_genricstring_range_node(branch[1]) ||
34741                                    details::is_string_concat_node     (branch[1]) ||
34742                                    details::is_string_function_node   (branch[1]) ||
34743                                    details::is_string_condition_node  (branch[1]) ||
34744                                    details::is_string_ccondition_node (branch[1]) ||
34745                                    details::is_string_vararg_node     (branch[1]) ;
34746
34747             if (details::e_add == opr)
34748             {
34749                if (!b0_is_cs || !b1_is_cs)
34750                {
34751                   return synthesize_expression<string_concat_node_t,2>(opr,branch);
34752                }
34753             }
34754
34755             if (b0_is_gen || b1_is_gen)
34756             {
34757                return synthesize_strogen_expression(opr,branch);
34758             }
34759             else if (b0_is_s)
34760             {
34761                     if (b1_is_s  ) return synthesize_sos_expression   (opr,branch);
34762                else if (b1_is_cs ) return synthesize_socs_expression  (opr,branch);
34763                else if (b1_is_sr ) return synthesize_sosr_expression  (opr,branch);
34764                else if (b1_is_csr) return synthesize_socsr_expression (opr,branch);
34765             }
34766             else if (b0_is_cs)
34767             {
34768                     if (b1_is_s  ) return synthesize_csos_expression  (opr,branch);
34769                else if (b1_is_cs ) return synthesize_csocs_expression (opr,branch);
34770                else if (b1_is_sr ) return synthesize_csosr_expression (opr,branch);
34771                else if (b1_is_csr) return synthesize_csocsr_expression(opr,branch);
34772             }
34773             else if (b0_is_sr)
34774             {
34775                     if (b1_is_s  ) return synthesize_sros_expression  (opr,branch);
34776                else if (b1_is_sr ) return synthesize_srosr_expression (opr,branch);
34777                else if (b1_is_cs ) return synthesize_srocs_expression (opr,branch);
34778                else if (b1_is_csr) return synthesize_srocsr_expression(opr,branch);
34779             }
34780             else if (b0_is_csr)
34781             {
34782                     if (b1_is_s  ) return synthesize_csros_expression  (opr,branch);
34783                else if (b1_is_sr ) return synthesize_csrosr_expression (opr,branch);
34784                else if (b1_is_cs ) return synthesize_csrocs_expression (opr,branch);
34785                else if (b1_is_csr) return synthesize_csrocsr_expression(opr,branch);
34786             }
34787
34788             return error_node();
34789          }
34790          #else
34791          inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[2])
34792          {
34793             details::free_all_nodes(*node_allocator_,branch);
34794             return error_node();
34795          }
34796          #endif
34797
34798          #ifndef exprtk_disable_string_capabilities
34799          inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[3])
34800          {
34801             if (details::e_inrange != opr)
34802                return error_node();
34803             else if ((0 == branch[0]) || (0 == branch[1]) || (0 == branch[2]))
34804             {
34805                details::free_all_nodes(*node_allocator_,branch);
34806
34807                return error_node();
34808             }
34809             else if (
34810                       details::is_const_string_node(branch[0]) &&
34811                       details::is_const_string_node(branch[1]) &&
34812                       details::is_const_string_node(branch[2])
34813                     )
34814             {
34815                const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
34816                const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
34817                const std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();
34818
34819                const Type v = (((s0 <= s1) && (s1 <= s2)) ? Type(1) : Type(0));
34820
34821                details::free_all_nodes(*node_allocator_,branch);
34822
34823                return node_allocator_->allocate_c<details::literal_node<Type> >(v);
34824             }
34825             else if (
34826                       details::is_string_node(branch[0]) &&
34827                       details::is_string_node(branch[1]) &&
34828                       details::is_string_node(branch[2])
34829                     )
34830             {
34831                std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref();
34832                std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref();
34833                std::string& s2 = static_cast<details::stringvar_node<Type>*>(branch[2])->ref();
34834
34835                typedef typename details::sosos_node<Type, std::string&, std::string&, std::string&, details::inrange_op<Type> > inrange_t;
34836
34837                return node_allocator_->allocate_type<inrange_t, std::string&, std::string&, std::string&>(s0, s1, s2);
34838             }
34839             else if (
34840                       details::is_const_string_node(branch[0]) &&
34841                             details::is_string_node(branch[1]) &&
34842                       details::is_const_string_node(branch[2])
34843                     )
34844             {
34845                std::string  s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
34846                std::string& s1 = static_cast<     details::stringvar_node<Type>*>(branch[1])->ref();
34847                std::string  s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();
34848
34849                typedef typename details::sosos_node<Type, std::string, std::string&, std::string, details::inrange_op<Type> > inrange_t;
34850
34851                details::free_node(*node_allocator_,branch[0]);
34852                details::free_node(*node_allocator_,branch[2]);
34853
34854                return node_allocator_->allocate_type<inrange_t, std::string, std::string&, std::string>(s0, s1, s2);
34855             }
34856             else if (
34857                             details::is_string_node(branch[0]) &&
34858                       details::is_const_string_node(branch[1]) &&
34859                             details::is_string_node(branch[2])
34860                     )
34861             {
34862                std::string&  s0 = static_cast<     details::stringvar_node<Type>*>(branch[0])->ref();
34863                std::string   s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
34864                std::string&  s2 = static_cast<     details::stringvar_node<Type>*>(branch[2])->ref();
34865
34866                typedef typename details::sosos_node<Type, std::string&, std::string, std::string&, details::inrange_op<Type> > inrange_t;
34867
34868                details::free_node(*node_allocator_,branch[1]);
34869
34870                return node_allocator_->allocate_type<inrange_t, std::string&, std::string, std::string&>(s0, s1, s2);
34871             }
34872             else if (
34873                       details::is_string_node(branch[0]) &&
34874                       details::is_string_node(branch[1]) &&
34875                       details::is_const_string_node(branch[2])
34876                     )
34877             {
34878                std::string& s0 = static_cast<     details::stringvar_node<Type>*>(branch[0])->ref();
34879                std::string& s1 = static_cast<     details::stringvar_node<Type>*>(branch[1])->ref();
34880                std::string  s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();
34881
34882                typedef typename details::sosos_node<Type, std::string&, std::string&, std::string, details::inrange_op<Type> > inrange_t;
34883
34884                details::free_node(*node_allocator_,branch[2]);
34885
34886                return node_allocator_->allocate_type<inrange_t, std::string&, std::string&, std::string>(s0, s1, s2);
34887             }
34888             else if (
34889                       details::is_const_string_node(branch[0]) &&
34890                       details::      is_string_node(branch[1]) &&
34891                       details::      is_string_node(branch[2])
34892                     )
34893             {
34894                std::string  s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
34895                std::string& s1 = static_cast<     details::stringvar_node<Type>*>(branch[1])->ref();
34896                std::string& s2 = static_cast<     details::stringvar_node<Type>*>(branch[2])->ref();
34897
34898                typedef typename details::sosos_node<Type, std::string, std::string&, std::string&, details::inrange_op<Type> > inrange_t;
34899
34900                details::free_node(*node_allocator_,branch[0]);
34901
34902                return node_allocator_->allocate_type<inrange_t, std::string, std::string&, std::string&>(s0, s1, s2);
34903             }
34904             else
34905                return error_node();
34906          }
34907          #else
34908          inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[3])
34909          {
34910             details::free_all_nodes(*node_allocator_,branch);
34911             return error_node();
34912          }
34913          #endif
34914
34915          inline expression_node_ptr synthesize_null_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
34916          {
34917             /*
34918              Note: The following are the type promotion rules
34919              that relate to operations that include 'null':
34920              0. null ==/!=     null --> true false
34921              1. null operation null --> null
34922              2. x    ==/!=     null --> true/false
34923              3. null ==/!=     x    --> true/false
34924              4. x   operation  null --> x
34925              5. null operation x    --> x
34926             */
34927
34928             typedef typename details::null_eq_node<T> nulleq_node_t;
34929
34930             const bool b0_null = details::is_null_node(branch[0]);
34931             const bool b1_null = details::is_null_node(branch[1]);
34932
34933             if (b0_null && b1_null)
34934             {
34935                expression_node_ptr result = error_node();
34936
34937                if (details::e_eq == operation)
34938                   result = node_allocator_->allocate_c<literal_node_t>(T(1));
34939                else if (details::e_ne == operation)
34940                   result = node_allocator_->allocate_c<literal_node_t>(T(0));
34941
34942                if (result)
34943                {
34944                   details::free_node(*node_allocator_,branch[0]);
34945                   details::free_node(*node_allocator_,branch[1]);
34946
34947                   return result;
34948                }
34949
34950                details::free_node(*node_allocator_,branch[1]);
34951
34952                return branch[0];
34953             }
34954             else if (details::e_eq == operation)
34955             {
34956                expression_node_ptr result = node_allocator_->
34957                                                 allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],true);
34958
34959                details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]);
34960
34961                return result;
34962             }
34963             else if (details::e_ne == operation)
34964             {
34965                expression_node_ptr result = node_allocator_->
34966                                                 allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],false);
34967
34968                details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]);
34969
34970                return result;
34971             }
34972             else if (b0_null)
34973             {
34974                details::free_node(*node_allocator_,branch[0]);
34975                branch[0] = branch[1];
34976                branch[1] = error_node();
34977             }
34978             else if (b1_null)
34979             {
34980                details::free_node(*node_allocator_,branch[1]);
34981                branch[1] = error_node();
34982             }
34983
34984             if (
34985                  (details::e_add == operation) || (details::e_sub == operation) ||
34986                  (details::e_mul == operation) || (details::e_div == operation) ||
34987                  (details::e_mod == operation) || (details::e_pow == operation)
34988                )
34989             {
34990                return branch[0];
34991             }
34992             else if (
34993                       (details::e_lt    == operation) || (details::e_lte  == operation) ||
34994                       (details::e_gt    == operation) || (details::e_gte  == operation) ||
34995                       (details::e_and   == operation) || (details::e_nand == operation) ||
34996                       (details::e_or    == operation) || (details::e_nor  == operation) ||
34997                       (details::e_xor   == operation) || (details::e_xnor == operation) ||
34998                       (details::e_in    == operation) || (details::e_like == operation) ||
34999                       (details::e_ilike == operation)
35000                     )
35001             {
35002                return node_allocator_->allocate_c<literal_node_t>(T(0));
35003             }
35004
35005             details::free_node(*node_allocator_,branch[0]);
35006
35007             return node_allocator_->allocate<details::null_node<Type> >();
35008          }
35009
35010          template <typename NodeType, std::size_t N>
35011          inline expression_node_ptr synthesize_expression(const details::operator_type& operation, expression_node_ptr (&branch)[N])
35012          {
35013             if (
35014                  (details::e_in    == operation) ||
35015                  (details::e_like  == operation) ||
35016                  (details::e_ilike == operation)
35017                )
35018             {
35019                free_all_nodes(*node_allocator_,branch);
35020
35021                return error_node();
35022             }
35023             else if (!details::all_nodes_valid<N>(branch))
35024             {
35025                free_all_nodes(*node_allocator_,branch);
35026
35027                return error_node();
35028             }
35029             else if ((details::e_default != operation))
35030             {
35031                // Attempt simple constant folding optimisation.
35032                expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(operation,branch);
35033
35034                if (is_constant_foldable<N>(branch))
35035                {
35036                   const Type v = expression_point->value();
35037                   details::free_node(*node_allocator_,expression_point);
35038
35039                   return node_allocator_->allocate<literal_node_t>(v);
35040                }
35041                else
35042                   return expression_point;
35043             }
35044             else
35045                return error_node();
35046          }
35047
35048          template <typename NodeType, std::size_t N>
35049          inline expression_node_ptr synthesize_expression(F* f, expression_node_ptr (&branch)[N])
35050          {
35051             if (!details::all_nodes_valid<N>(branch))
35052             {
35053                free_all_nodes(*node_allocator_,branch);
35054
35055                return error_node();
35056             }
35057
35058             typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t;
35059
35060             // Attempt simple constant folding optimisation.
35061
35062             expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(f);
35063             function_N_node_t* func_node_ptr = dynamic_cast<function_N_node_t*>(expression_point);
35064
35065             if (0 == func_node_ptr)
35066             {
35067                free_all_nodes(*node_allocator_,branch);
35068
35069                return error_node();
35070             }
35071             else
35072                func_node_ptr->init_branches(branch);
35073
35074             if (is_constant_foldable<N>(branch) && !f->has_side_effects())
35075             {
35076                Type v = expression_point->value();
35077                details::free_node(*node_allocator_,expression_point);
35078
35079                return node_allocator_->allocate<literal_node_t>(v);
35080             }
35081
35082             parser_->state_.activate_side_effect("synthesize_expression(function<NT,N>)");
35083
35084             return expression_point;
35085          }
35086
35087          bool                     strength_reduction_enabled_;
35088          details::node_allocator* node_allocator_;
35089          synthesize_map_t         synthesize_map_;
35090          unary_op_map_t*          unary_op_map_;
35091          binary_op_map_t*         binary_op_map_;
35092          inv_binary_op_map_t*     inv_binary_op_map_;
35093          sf3_map_t*               sf3_map_;
35094          sf4_map_t*               sf4_map_;
35095          parser_t*                parser_;
35096       };
35097
35098       inline void set_error(const parser_error::type& error_type)
35099       {
35100          error_list_.push_back(error_type);
35101       }
35102
35103       inline void remove_last_error()
35104       {
35105          if (!error_list_.empty())
35106          {
35107             error_list_.pop_back();
35108          }
35109       }
35110
35111       inline void set_synthesis_error(const std::string& synthesis_error_message)
35112       {
35113          if (synthesis_error_.empty())
35114          {
35115             synthesis_error_ = synthesis_error_message;
35116          }
35117       }
35118
35119       inline void register_local_vars(expression<T>& e)
35120       {
35121          for (std::size_t i = 0; i < sem_.size(); ++i)
35122          {
35123             scope_element& se = sem_.get_element(i);
35124
35125             if (
35126                  (scope_element::e_variable == se.type) ||
35127                  (scope_element::e_vecelem  == se.type)
35128                )
35129             {
35130                if (se.var_node)
35131                {
35132                   e.register_local_var(se.var_node);
35133                }
35134
35135                if (se.data)
35136                {
35137                   e.register_local_data(se.data, 1, 0);
35138                }
35139             }
35140             else if (scope_element::e_vector == se.type)
35141             {
35142                if (se.vec_node)
35143                {
35144                   e.register_local_var(se.vec_node);
35145                }
35146
35147                if (se.data)
35148                {
35149                   e.register_local_data(se.data, se.size, 1);
35150                }
35151             }
35152             #ifndef exprtk_disable_string_capabilities
35153             else if (scope_element::e_string == se.type)
35154             {
35155                if (se.str_node)
35156                {
35157                   e.register_local_var(se.str_node);
35158                }
35159
35160                if (se.data)
35161                {
35162                   e.register_local_data(se.data, se.size, 2);
35163                }
35164             }
35165             #endif
35166
35167             se.var_node  = 0;
35168             se.vec_node  = 0;
35169             #ifndef exprtk_disable_string_capabilities
35170             se.str_node  = 0;
35171             #endif
35172             se.data      = 0;
35173             se.ref_count = 0;
35174             se.active    = false;
35175          }
35176       }
35177
35178       inline void register_return_results(expression<T>& e)
35179       {
35180          e.register_return_results(results_context_);
35181          results_context_ = 0;
35182       }
35183
35184       inline void load_unary_operations_map(unary_op_map_t& m)
35185       {
35186          #define register_unary_op(Op,UnaryFunctor)             \
35187          m.insert(std::make_pair(Op,UnaryFunctor<T>::process)); \
35188
35189          register_unary_op(details::  e_abs, details::  abs_op)
35190          register_unary_op(details:: e_acos, details:: acos_op)
35191          register_unary_op(details::e_acosh, details::acosh_op)
35192          register_unary_op(details:: e_asin, details:: asin_op)
35193          register_unary_op(details::e_asinh, details::asinh_op)
35194          register_unary_op(details::e_atanh, details::atanh_op)
35195          register_unary_op(details:: e_ceil, details:: ceil_op)
35196          register_unary_op(details::  e_cos, details::  cos_op)
35197          register_unary_op(details:: e_cosh, details:: cosh_op)
35198          register_unary_op(details::  e_exp, details::  exp_op)
35199          register_unary_op(details::e_expm1, details::expm1_op)
35200          register_unary_op(details::e_floor, details::floor_op)
35201          register_unary_op(details::  e_log, details::  log_op)
35202          register_unary_op(details::e_log10, details::log10_op)
35203          register_unary_op(details:: e_log2, details:: log2_op)
35204          register_unary_op(details::e_log1p, details::log1p_op)
35205          register_unary_op(details::  e_neg, details::  neg_op)
35206          register_unary_op(details::  e_pos, details::  pos_op)
35207          register_unary_op(details::e_round, details::round_op)
35208          register_unary_op(details::  e_sin, details::  sin_op)
35209          register_unary_op(details:: e_sinc, details:: sinc_op)
35210          register_unary_op(details:: e_sinh, details:: sinh_op)
35211          register_unary_op(details:: e_sqrt, details:: sqrt_op)
35212          register_unary_op(details::  e_tan, details::  tan_op)
35213          register_unary_op(details:: e_tanh, details:: tanh_op)
35214          register_unary_op(details::  e_cot, details::  cot_op)
35215          register_unary_op(details::  e_sec, details::  sec_op)
35216          register_unary_op(details::  e_csc, details::  csc_op)
35217          register_unary_op(details::  e_r2d, details::  r2d_op)
35218          register_unary_op(details::  e_d2r, details::  d2r_op)
35219          register_unary_op(details::  e_d2g, details::  d2g_op)
35220          register_unary_op(details::  e_g2d, details::  g2d_op)
35221          register_unary_op(details:: e_notl, details:: notl_op)
35222          register_unary_op(details::  e_sgn, details::  sgn_op)
35223          register_unary_op(details::  e_erf, details::  erf_op)
35224          register_unary_op(details:: e_erfc, details:: erfc_op)
35225          register_unary_op(details:: e_ncdf, details:: ncdf_op)
35226          register_unary_op(details:: e_frac, details:: frac_op)
35227          register_unary_op(details::e_trunc, details::trunc_op)
35228          #undef register_unary_op
35229       }
35230
35231       inline void load_binary_operations_map(binary_op_map_t& m)
35232       {
35233          typedef typename binary_op_map_t::value_type value_type;
35234
35235          #define register_binary_op(Op,BinaryFunctor)        \
35236          m.insert(value_type(Op,BinaryFunctor<T>::process)); \
35237
35238          register_binary_op(details:: e_add, details:: add_op)
35239          register_binary_op(details:: e_sub, details:: sub_op)
35240          register_binary_op(details:: e_mul, details:: mul_op)
35241          register_binary_op(details:: e_div, details:: div_op)
35242          register_binary_op(details:: e_mod, details:: mod_op)
35243          register_binary_op(details:: e_pow, details:: pow_op)
35244          register_binary_op(details::  e_lt, details::  lt_op)
35245          register_binary_op(details:: e_lte, details:: lte_op)
35246          register_binary_op(details::  e_gt, details::  gt_op)
35247          register_binary_op(details:: e_gte, details:: gte_op)
35248          register_binary_op(details::  e_eq, details::  eq_op)
35249          register_binary_op(details::  e_ne, details::  ne_op)
35250          register_binary_op(details:: e_and, details:: and_op)
35251          register_binary_op(details::e_nand, details::nand_op)
35252          register_binary_op(details::  e_or, details::  or_op)
35253          register_binary_op(details:: e_nor, details:: nor_op)
35254          register_binary_op(details:: e_xor, details:: xor_op)
35255          register_binary_op(details::e_xnor, details::xnor_op)
35256          #undef register_binary_op
35257       }
35258
35259       inline void load_inv_binary_operations_map(inv_binary_op_map_t& m)
35260       {
35261          typedef typename inv_binary_op_map_t::value_type value_type;
35262
35263          #define register_binary_op(Op,BinaryFunctor)        \
35264          m.insert(value_type(BinaryFunctor<T>::process,Op)); \
35265
35266          register_binary_op(details:: e_add, details:: add_op)
35267          register_binary_op(details:: e_sub, details:: sub_op)
35268          register_binary_op(details:: e_mul, details:: mul_op)
35269          register_binary_op(details:: e_div, details:: div_op)
35270          register_binary_op(details:: e_mod, details:: mod_op)
35271          register_binary_op(details:: e_pow, details:: pow_op)
35272          register_binary_op(details::  e_lt, details::  lt_op)
35273          register_binary_op(details:: e_lte, details:: lte_op)
35274          register_binary_op(details::  e_gt, details::  gt_op)
35275          register_binary_op(details:: e_gte, details:: gte_op)
35276          register_binary_op(details::  e_eq, details::  eq_op)
35277          register_binary_op(details::  e_ne, details::  ne_op)
35278          register_binary_op(details:: e_and, details:: and_op)
35279          register_binary_op(details::e_nand, details::nand_op)
35280          register_binary_op(details::  e_or, details::  or_op)
35281          register_binary_op(details:: e_nor, details:: nor_op)
35282          register_binary_op(details:: e_xor, details:: xor_op)
35283          register_binary_op(details::e_xnor, details::xnor_op)
35284          #undef register_binary_op
35285       }
35286
35287       inline void load_sf3_map(sf3_map_t& sf3_map)
35288       {
35289          typedef std::pair<trinary_functor_t,details::operator_type> pair_t;
35290
35291          #define register_sf3(Op)                                                                             \
35292          sf3_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \
35293
35294          register_sf3(00) register_sf3(01) register_sf3(02) register_sf3(03)
35295          register_sf3(04) register_sf3(05) register_sf3(06) register_sf3(07)
35296          register_sf3(08) register_sf3(09) register_sf3(10) register_sf3(11)
35297          register_sf3(12) register_sf3(13) register_sf3(14) register_sf3(15)
35298          register_sf3(16) register_sf3(17) register_sf3(18) register_sf3(19)
35299          register_sf3(20) register_sf3(21) register_sf3(22) register_sf3(23)
35300          register_sf3(24) register_sf3(25) register_sf3(26) register_sf3(27)
35301          register_sf3(28) register_sf3(29) register_sf3(30)
35302          #undef register_sf3
35303
35304          #define register_sf3_extid(Id, Op)                                        \
35305          sf3_map[Id] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \
35306
35307          register_sf3_extid("(t-t)-t",23)  // (t-t)-t --> t-(t+t)
35308          #undef register_sf3_extid
35309       }
35310
35311       inline void load_sf4_map(sf4_map_t& sf4_map)
35312       {
35313          typedef std::pair<quaternary_functor_t,details::operator_type> pair_t;
35314
35315          #define register_sf4(Op)                                                                             \
35316          sf4_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \
35317
35318          register_sf4(48) register_sf4(49) register_sf4(50) register_sf4(51)
35319          register_sf4(52) register_sf4(53) register_sf4(54) register_sf4(55)
35320          register_sf4(56) register_sf4(57) register_sf4(58) register_sf4(59)
35321          register_sf4(60) register_sf4(61) register_sf4(62) register_sf4(63)
35322          register_sf4(64) register_sf4(65) register_sf4(66) register_sf4(67)
35323          register_sf4(68) register_sf4(69) register_sf4(70) register_sf4(71)
35324          register_sf4(72) register_sf4(73) register_sf4(74) register_sf4(75)
35325          register_sf4(76) register_sf4(77) register_sf4(78) register_sf4(79)
35326          register_sf4(80) register_sf4(81) register_sf4(82) register_sf4(83)
35327          #undef register_sf4
35328
35329          #define register_sf4ext(Op)                                                                                    \
35330          sf4_map[details::sfext##Op##_op<T>::id()] = pair_t(details::sfext##Op##_op<T>::process,details::e_sf4ext##Op); \
35331
35332          register_sf4ext(00) register_sf4ext(01) register_sf4ext(02) register_sf4ext(03)
35333          register_sf4ext(04) register_sf4ext(05) register_sf4ext(06) register_sf4ext(07)
35334          register_sf4ext(08) register_sf4ext(09) register_sf4ext(10) register_sf4ext(11)
35335          register_sf4ext(12) register_sf4ext(13) register_sf4ext(14) register_sf4ext(15)
35336          register_sf4ext(16) register_sf4ext(17) register_sf4ext(18) register_sf4ext(19)
35337          register_sf4ext(20) register_sf4ext(21) register_sf4ext(22) register_sf4ext(23)
35338          register_sf4ext(24) register_sf4ext(25) register_sf4ext(26) register_sf4ext(27)
35339          register_sf4ext(28) register_sf4ext(29) register_sf4ext(30) register_sf4ext(31)
35340          register_sf4ext(32) register_sf4ext(33) register_sf4ext(34) register_sf4ext(35)
35341          register_sf4ext(36) register_sf4ext(36) register_sf4ext(38) register_sf4ext(39)
35342          register_sf4ext(40) register_sf4ext(41) register_sf4ext(42) register_sf4ext(43)
35343          register_sf4ext(44) register_sf4ext(45) register_sf4ext(46) register_sf4ext(47)
35344          register_sf4ext(48) register_sf4ext(49) register_sf4ext(50) register_sf4ext(51)
35345          register_sf4ext(52) register_sf4ext(53) register_sf4ext(54) register_sf4ext(55)
35346          register_sf4ext(56) register_sf4ext(57) register_sf4ext(58) register_sf4ext(59)
35347          register_sf4ext(60) register_sf4ext(61)
35348          #undef register_sf4ext
35349       }
35350
35351       inline results_context_t& results_ctx()
35352       {
35353          if (0 == results_context_)
35354          {
35355             results_context_ = new results_context_t();
35356          }
35357
35358          return (*results_context_);
35359       }
35360
35361       inline void return_cleanup()
35362       {
35363          #ifndef exprtk_disable_return_statement
35364          if (results_context_)
35365          {
35366             delete results_context_;
35367             results_context_ = 0;
35368          }
35369
35370          state_.return_stmt_present = false;
35371          #endif
35372       }
35373
35374    private:
35375
35376       parser(const parser<T>&);
35377       parser<T>& operator=(const parser<T>&);
35378
35379       settings_store settings_;
35380       expression_generator<T> expression_generator_;
35381       details::node_allocator node_allocator_;
35382       symtab_store symtab_store_;
35383       dependent_entity_collector dec_;
35384       std::deque<parser_error::type> error_list_;
35385       std::deque<bool> brkcnt_list_;
35386       parser_state state_;
35387       bool resolve_unknown_symbol_;
35388       results_context_t* results_context_;
35389       unknown_symbol_resolver* unknown_symbol_resolver_;
35390       unknown_symbol_resolver default_usr_;
35391       base_ops_map_t base_ops_map_;
35392       unary_op_map_t unary_op_map_;
35393       binary_op_map_t binary_op_map_;
35394       inv_binary_op_map_t inv_binary_op_map_;
35395       sf3_map_t sf3_map_;
35396       sf4_map_t sf4_map_;
35397       std::string synthesis_error_;
35398       scope_element_manager sem_;
35399
35400       lexer::helper::helper_assembly helper_assembly_;
35401
35402       lexer::helper::commutative_inserter       commutative_inserter_;
35403       lexer::helper::operator_joiner            operator_joiner_2_;
35404       lexer::helper::operator_joiner            operator_joiner_3_;
35405       lexer::helper::symbol_replacer            symbol_replacer_;
35406       lexer::helper::bracket_checker            bracket_checker_;
35407       lexer::helper::numeric_checker            numeric_checker_;
35408       lexer::helper::sequence_validator         sequence_validator_;
35409       lexer::helper::sequence_validator_3tokens sequence_validator_3tkns_;
35410
35411       template <typename ParserType>
35412       friend void details::disable_type_checking(ParserType& p);
35413    };
35414
35415    namespace details
35416    {
35417       template <typename T>
35418       struct collector_helper
35419       {
35420          typedef exprtk::symbol_table<T> symbol_table_t;
35421          typedef exprtk::expression<T>     expression_t;
35422          typedef exprtk::parser<T>             parser_t;
35423          typedef typename parser_t::dependent_entity_collector::symbol_t symbol_t;
35424          typedef typename parser_t::unknown_symbol_resolver usr_t;
35425
35426          struct resolve_as_vector : public parser_t::unknown_symbol_resolver
35427          {
35428             typedef exprtk::parser<T> parser_t;
35429
35430             resolve_as_vector()
35431             : usr_t(usr_t::e_usrmode_extended)
35432             {}
35433
35434             virtual bool process(const std::string& unknown_symbol,
35435                                  symbol_table_t& symbol_table,
35436                                  std::string&)
35437             {
35438                static T v[1];
35439                symbol_table.add_vector(unknown_symbol,v);
35440                return true;
35441             }
35442          };
35443
35444          static inline bool collection_pass(const std::string& expression_string,
35445                                             std::set<std::string>& symbol_set,
35446                                             const bool collect_variables,
35447                                             const bool collect_functions,
35448                                             const bool vector_pass,
35449                                             symbol_table_t& ext_symbol_table)
35450          {
35451             symbol_table_t symbol_table;
35452             expression_t   expression;
35453             parser_t       parser;
35454
35455             resolve_as_vector vect_resolver;
35456
35457             expression.register_symbol_table(symbol_table    );
35458             expression.register_symbol_table(ext_symbol_table);
35459
35460             if (vector_pass)
35461                parser.enable_unknown_symbol_resolver(&vect_resolver);
35462             else
35463                parser.enable_unknown_symbol_resolver();
35464
35465             if (collect_variables)
35466                parser.dec().collect_variables() = true;
35467
35468             if (collect_functions)
35469                parser.dec().collect_functions() = true;
35470
35471             bool pass_result = false;
35472
35473             details::disable_type_checking(parser);
35474
35475             if (parser.compile(expression_string, expression))
35476             {
35477                pass_result = true;
35478
35479                std::deque<symbol_t> symb_list;
35480                parser.dec().symbols(symb_list);
35481
35482                for (std::size_t i = 0; i < symb_list.size(); ++i)
35483                {
35484                   symbol_set.insert(symb_list[i].first);
35485                }
35486             }
35487
35488             return pass_result;
35489          }
35490       };
35491    }
35492
35493    template <typename Allocator,
35494              template <typename, typename> class Sequence>
35495    inline bool collect_variables(const std::string& expression,
35496                                  Sequence<std::string, Allocator>& symbol_list)
35497    {
35498       typedef double T;
35499       typedef details::collector_helper<T> collect_t;
35500
35501       collect_t::symbol_table_t null_symbol_table;
35502
35503       std::set<std::string> symbol_set;
35504
35505       const bool variable_pass = collect_t::collection_pass
35506                                     (expression, symbol_set, true, false, false, null_symbol_table);
35507       const bool vector_pass   = collect_t::collection_pass
35508                                     (expression, symbol_set, true, false,  true, null_symbol_table);
35509
35510       if (!variable_pass && !vector_pass)
35511          return false;
35512
35513       std::set<std::string>::iterator itr = symbol_set.begin();
35514
35515       while (symbol_set.end() != itr)
35516       {
35517          symbol_list.push_back(*itr);
35518          ++itr;
35519       }
35520
35521       return true;
35522    }
35523
35524    template <typename T,
35525              typename Allocator,
35526              template <typename, typename> class Sequence>
35527    inline bool collect_variables(const std::string& expression,
35528                                  exprtk::symbol_table<T>& extrnl_symbol_table,
35529                                  Sequence<std::string, Allocator>& symbol_list)
35530    {
35531       typedef details::collector_helper<T> collect_t;
35532
35533       std::set<std::string> symbol_set;
35534
35535       const bool variable_pass = collect_t::collection_pass
35536                                     (expression, symbol_set, true, false, false, extrnl_symbol_table);
35537       const bool vector_pass   = collect_t::collection_pass
35538                                     (expression, symbol_set, true, false,  true, extrnl_symbol_table);
35539
35540       if (!variable_pass && !vector_pass)
35541          return false;
35542
35543       std::set<std::string>::iterator itr = symbol_set.begin();
35544
35545       while (symbol_set.end() != itr)
35546       {
35547          symbol_list.push_back(*itr);
35548          ++itr;
35549       }
35550
35551       return true;
35552    }
35553
35554    template <typename Allocator,
35555              template <typename, typename> class Sequence>
35556    inline bool collect_functions(const std::string& expression,
35557                                  Sequence<std::string, Allocator>& symbol_list)
35558    {
35559       typedef double T;
35560       typedef details::collector_helper<T> collect_t;
35561
35562       collect_t::symbol_table_t null_symbol_table;
35563
35564       std::set<std::string> symbol_set;
35565
35566       const bool variable_pass = collect_t::collection_pass
35567                                     (expression, symbol_set, false, true, false, null_symbol_table);
35568       const bool vector_pass   = collect_t::collection_pass
35569                                     (expression, symbol_set, false, true,  true, null_symbol_table);
35570
35571       if (!variable_pass && !vector_pass)
35572          return false;
35573
35574       std::set<std::string>::iterator itr = symbol_set.begin();
35575
35576       while (symbol_set.end() != itr)
35577       {
35578          symbol_list.push_back(*itr);
35579          ++itr;
35580       }
35581
35582       return true;
35583    }
35584
35585    template <typename T,
35586              typename Allocator,
35587              template <typename, typename> class Sequence>
35588    inline bool collect_functions(const std::string& expression,
35589                                  exprtk::symbol_table<T>& extrnl_symbol_table,
35590                                  Sequence<std::string, Allocator>& symbol_list)
35591    {
35592       typedef details::collector_helper<T> collect_t;
35593
35594       std::set<std::string> symbol_set;
35595
35596       const bool variable_pass = collect_t::collection_pass
35597                                     (expression, symbol_set, false, true, false, extrnl_symbol_table);
35598       const bool vector_pass   = collect_t::collection_pass
35599                                     (expression, symbol_set, false, true,  true, extrnl_symbol_table);
35600
35601       if (!variable_pass && !vector_pass)
35602          return false;
35603
35604       std::set<std::string>::iterator itr = symbol_set.begin();
35605
35606       while (symbol_set.end() != itr)
35607       {
35608          symbol_list.push_back(*itr);
35609          ++itr;
35610       }
35611
35612       return true;
35613    }
35614
35615    template <typename T>
35616    inline T integrate(const expression<T>& e,
35617                       T& x,
35618                       const T& r0, const T& r1,
35619                       const std::size_t number_of_intervals = 1000000)
35620    {
35621       if (r0 > r1)
35622          return T(0);
35623
35624       const T h = (r1 - r0) / (T(2) * number_of_intervals);
35625       T total_area = T(0);
35626
35627       for (std::size_t i = 0; i < number_of_intervals; ++i)
35628       {
35629          x = r0 + T(2) * i * h;
35630          const T y0 = e.value(); x += h;
35631          const T y1 = e.value(); x += h;
35632          const T y2 = e.value(); x += h;
35633          total_area += h * (y0 + T(4) * y1 + y2) / T(3);
35634       }
35635
35636       return total_area;
35637    }
35638
35639    template <typename T>
35640    inline T integrate(const expression<T>& e,
35641                       const std::string& variable_name,
35642                       const T& r0, const T& r1,
35643                       const std::size_t number_of_intervals = 1000000)
35644    {
35645       const symbol_table<T>& sym_table = e.get_symbol_table();
35646
35647       if (!sym_table.valid())
35648          return std::numeric_limits<T>::quiet_NaN();
35649
35650       details::variable_node<T>* var = sym_table.get_variable(variable_name);
35651
35652       if (var)
35653       {
35654          T& x = var->ref();
35655          T  x_original = x;
35656          T result = integrate(e, x, r0, r1, number_of_intervals);
35657          x = x_original;
35658
35659          return result;
35660       }
35661       else
35662          return std::numeric_limits<T>::quiet_NaN();
35663    }
35664
35665    template <typename T>
35666    inline T derivative(const expression<T>& e,
35667                        T& x,
35668                        const T& h = T(0.00000001))
35669    {
35670       const T x_init = x;
35671       const T _2h    = T(2) * h;
35672
35673       x = x_init + _2h;
35674       const T y0 = e.value();
35675       x = x_init +   h;
35676       const T y1 = e.value();
35677       x = x_init -   h;
35678       const T y2 = e.value();
35679       x = x_init - _2h;
35680       const T y3 = e.value();
35681       x = x_init;
35682
35683       return (-y0 + T(8) * (y1 - y2) + y3) / (T(12) * h);
35684    }
35685
35686    template <typename T>
35687    inline T second_derivative(const expression<T>& e,
35688                               T& x,
35689                               const T& h = T(0.00001))
35690    {
35691       const T x_init = x;
35692       const T _2h    = T(2) * h;
35693
35694       const T y = e.value();
35695       x = x_init + _2h;
35696       const T y0 = e.value();
35697       x = x_init +   h;
35698       const T y1 = e.value();
35699       x = x_init -   h;
35700       const T y2 = e.value();
35701       x = x_init - _2h;
35702       const T y3 = e.value();
35703       x = x_init;
35704
35705       return (-y0 + T(16) * (y1 + y2) - T(30) * y - y3) / (T(12) * h * h);
35706    }
35707
35708    template <typename T>
35709    inline T third_derivative(const expression<T>& e,
35710                              T& x,
35711                              const T& h = T(0.0001))
35712    {
35713       const T x_init = x;
35714       const T _2h    = T(2) * h;
35715
35716       x = x_init + _2h;
35717       const T y0 = e.value();
35718       x = x_init +   h;
35719       const T y1 = e.value();
35720       x = x_init -   h;
35721       const T y2 = e.value();
35722       x = x_init - _2h;
35723       const T y3 = e.value();
35724       x = x_init;
35725
35726       return (y0 + T(2) * (y2 - y1) - y3) / (T(2) * h * h * h);
35727    }
35728
35729    template <typename T>
35730    inline T derivative(const expression<T>& e,
35731                        const std::string& variable_name,
35732                        const T& h = T(0.00000001))
35733    {
35734       const symbol_table<T>& sym_table = e.get_symbol_table();
35735
35736       if (!sym_table.valid())
35737       {
35738          return std::numeric_limits<T>::quiet_NaN();
35739       }
35740
35741       details::variable_node<T>* var = sym_table.get_variable(variable_name);
35742
35743       if (var)
35744       {
35745          T& x = var->ref();
35746          T x_original = x;
35747          T result = derivative(e, x, h);
35748          x = x_original;
35749
35750          return result;
35751       }
35752       else
35753          return std::numeric_limits<T>::quiet_NaN();
35754    }
35755
35756    template <typename T>
35757    inline T second_derivative(const expression<T>& e,
35758                               const std::string& variable_name,
35759                               const T& h = T(0.00001))
35760    {
35761       const symbol_table<T>& sym_table = e.get_symbol_table();
35762
35763       if (!sym_table.valid())
35764       {
35765          return std::numeric_limits<T>::quiet_NaN();
35766       }
35767
35768       details::variable_node<T>* var = sym_table.get_variable(variable_name);
35769
35770       if (var)
35771       {
35772          T& x = var->ref();
35773          const T x_original = x;
35774          const T result = second_derivative(e, x, h);
35775          x = x_original;
35776
35777          return result;
35778       }
35779       else
35780          return std::numeric_limits<T>::quiet_NaN();
35781    }
35782
35783    template <typename T>
35784    inline T third_derivative(const expression<T>& e,
35785                              const std::string& variable_name,
35786                              const T& h = T(0.0001))
35787    {
35788       const symbol_table<T>& sym_table = e.get_symbol_table();
35789
35790       if (!sym_table.valid())
35791       {
35792          return std::numeric_limits<T>::quiet_NaN();
35793       }
35794
35795       details::variable_node<T>* var = sym_table.get_variable(variable_name);
35796
35797       if (var)
35798       {
35799          T& x = var->ref();
35800          const T x_original = x;
35801          const T result = third_derivative(e, x, h);
35802          x = x_original;
35803
35804          return result;
35805       }
35806       else
35807          return std::numeric_limits<T>::quiet_NaN();
35808    }
35809
35810    /*
35811       Note: The following 'compute' routines are simple helpers,
35812       for quickly setting up the required pieces of code in order
35813       to evaluate an expression. By virtue of how they operate
35814       there will be an overhead with regards to their setup and
35815       teardown and hence should not be used in time critical
35816       sections of code.
35817       Furthermore they only assume a small sub set of variables,
35818       no string variables or user defined functions.
35819    */
35820    template <typename T>
35821    inline bool compute(const std::string& expression_string, T& result)
35822    {
35823       // No variables
35824       symbol_table<T> symbol_table;
35825       symbol_table.add_constants();
35826
35827       expression<T> expression;
35828       expression.register_symbol_table(symbol_table);
35829
35830       parser<T> parser;
35831
35832       if (parser.compile(expression_string,expression))
35833       {
35834          result = expression.value();
35835
35836          return true;
35837       }
35838       else
35839          return false;
35840    }
35841
35842    template <typename T>
35843    inline bool compute(const std::string& expression_string,
35844                        const T& x,
35845                        T& result)
35846    {
35847       // Only 'x'
35848       static const std::string x_var("x");
35849
35850       symbol_table<T> symbol_table;
35851       symbol_table.add_constants();
35852       symbol_table.add_constant(x_var,x);
35853
35854       expression<T> expression;
35855       expression.register_symbol_table(symbol_table);
35856
35857       parser<T> parser;
35858
35859       if (parser.compile(expression_string,expression))
35860       {
35861          result = expression.value();
35862
35863          return true;
35864       }
35865       else
35866          return false;
35867    }
35868
35869    template <typename T>
35870    inline bool compute(const std::string& expression_string,
35871                        const T&x, const T& y,
35872                        T& result)
35873    {
35874       // Only 'x' and 'y'
35875       static const std::string x_var("x");
35876       static const std::string y_var("y");
35877
35878       symbol_table<T> symbol_table;
35879       symbol_table.add_constants();
35880       symbol_table.add_constant(x_var,x);
35881       symbol_table.add_constant(y_var,y);
35882
35883       expression<T> expression;
35884       expression.register_symbol_table(symbol_table);
35885
35886       parser<T> parser;
35887
35888       if (parser.compile(expression_string,expression))
35889       {
35890          result = expression.value();
35891
35892          return true;
35893       }
35894       else
35895          return false;
35896    }
35897
35898    template <typename T>
35899    inline bool compute(const std::string& expression_string,
35900                        const T& x, const T& y, const T& z,
35901                        T& result)
35902    {
35903       // Only 'x', 'y' or 'z'
35904       static const std::string x_var("x");
35905       static const std::string y_var("y");
35906       static const std::string z_var("z");
35907
35908       symbol_table<T> symbol_table;
35909       symbol_table.add_constants();
35910       symbol_table.add_constant(x_var,x);
35911       symbol_table.add_constant(y_var,y);
35912       symbol_table.add_constant(z_var,z);
35913
35914       expression<T> expression;
35915       expression.register_symbol_table(symbol_table);
35916
35917       parser<T> parser;
35918
35919       if (parser.compile(expression_string,expression))
35920       {
35921          result = expression.value();
35922
35923          return true;
35924       }
35925       else
35926          return false;
35927    }
35928
35929    template <typename T, std::size_t N>
35930    class polynomial : public ifunction<T>
35931    {
35932    private:
35933
35934       template <typename Type, std::size_t NumberOfCoefficients>
35935       struct poly_impl { };
35936
35937       template <typename Type>
35938       struct poly_impl <Type,12>
35939       {
35940          static inline T evaluate(const Type x,
35941                                   const Type c12, const Type c11, const Type c10, const Type c9, const Type c8,
35942                                   const Type  c7, const Type  c6, const Type  c5, const Type c4, const Type c3,
35943                                   const Type  c2, const Type  c1, const Type  c0)
35944          {
35945             // p(x) = c_12x^12 + c_11x^11 + c_10x^10 + c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
35946             return ((((((((((((c12 * x + c11) * x + c10) * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
35947          }
35948       };
35949
35950       template <typename Type>
35951       struct poly_impl <Type,11>
35952       {
35953          static inline T evaluate(const Type x,
35954                                   const Type c11, const Type c10, const Type c9, const Type c8, const Type c7,
35955                                   const Type c6,  const Type  c5, const Type c4, const Type c3, const Type c2,
35956                                   const Type c1,  const Type  c0)
35957          {
35958             // p(x) = c_11x^11 + c_10x^10 + c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
35959             return (((((((((((c11 * x + c10) * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
35960          }
35961       };
35962
35963       template <typename Type>
35964       struct poly_impl <Type,10>
35965       {
35966          static inline T evaluate(const Type x,
35967                                   const Type c10, const Type c9, const Type c8, const Type c7, const Type c6,
35968                                   const Type c5,  const Type c4, const Type c3, const Type c2, const Type c1,
35969                                   const Type c0)
35970          {
35971             // p(x) = c_10x^10 + c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
35972             return ((((((((((c10 * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
35973          }
35974       };
35975
35976       template <typename Type>
35977       struct poly_impl <Type,9>
35978       {
35979          static inline T evaluate(const Type x,
35980                                   const Type c9, const Type c8, const Type c7, const Type c6, const Type c5,
35981                                   const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
35982          {
35983             // p(x) = c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
35984             return (((((((((c9 * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
35985          }
35986       };
35987
35988       template <typename Type>
35989       struct poly_impl <Type,8>
35990       {
35991          static inline T evaluate(const Type x,
35992                                   const Type c8, const Type c7, const Type c6, const Type c5, const Type c4,
35993                                   const Type c3, const Type c2, const Type c1, const Type c0)
35994          {
35995             // p(x) = c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
35996             return ((((((((c8 * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
35997          }
35998       };
35999
36000       template <typename Type>
36001       struct poly_impl <Type,7>
36002       {
36003          static inline T evaluate(const Type x,
36004                                   const Type c7, const Type c6, const Type c5, const Type c4, const Type c3,
36005                                   const Type c2, const Type c1, const Type c0)
36006          {
36007             // p(x) = c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
36008             return (((((((c7 * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
36009          }
36010       };
36011
36012       template <typename Type>
36013       struct poly_impl <Type,6>
36014       {
36015          static inline T evaluate(const Type x,
36016                                   const Type c6, const Type c5, const Type c4, const Type c3, const Type c2,
36017                                   const Type c1, const Type c0)
36018          {
36019             // p(x) = c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
36020             return ((((((c6 * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
36021          }
36022       };
36023
36024       template <typename Type>
36025       struct poly_impl <Type,5>
36026       {
36027          static inline T evaluate(const Type x,
36028                                   const Type c5, const Type c4, const Type c3, const Type c2,
36029                                   const Type c1, const Type c0)
36030          {
36031             // p(x) = c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
36032             return (((((c5 * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
36033          }
36034       };
36035
36036       template <typename Type>
36037       struct poly_impl <Type,4>
36038       {
36039          static inline T evaluate(const Type x, const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
36040          {
36041             // p(x) = c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
36042             return ((((c4 * x + c3) * x + c2) * x + c1) * x + c0);
36043          }
36044       };
36045
36046       template <typename Type>
36047       struct poly_impl <Type,3>
36048       {
36049          static inline T evaluate(const Type x, const Type c3, const Type c2, const Type c1, const Type c0)
36050          {
36051             // p(x) = c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
36052             return (((c3 * x + c2) * x + c1) * x + c0);
36053          }
36054       };
36055
36056       template <typename Type>
36057       struct poly_impl <Type,2>
36058       {
36059          static inline T evaluate(const Type x, const Type c2, const Type c1, const Type c0)
36060          {
36061             // p(x) = c_2x^2 + c_1x^1 + c_0x^0
36062             return ((c2 * x + c1) * x + c0);
36063          }
36064       };
36065
36066       template <typename Type>
36067       struct poly_impl <Type,1>
36068       {
36069          static inline T evaluate(const Type x, const Type c1, const Type c0)
36070          {
36071             // p(x) = c_1x^1 + c_0x^0
36072             return (c1 * x + c0);
36073          }
36074       };
36075
36076    public:
36077
36078       using ifunction<T>::operator();
36079
36080       polynomial()
36081       : ifunction<T>((N+2 <= 20) ? (N + 2) : std::numeric_limits<std::size_t>::max())
36082       {
36083          disable_has_side_effects(*this);
36084       }
36085
36086       virtual ~polynomial()
36087       {}
36088
36089       #define poly_rtrn(NN) \
36090       return (NN != N) ? std::numeric_limits<T>::quiet_NaN() :
36091
36092       inline virtual T operator() (const T& x, const T& c1, const T& c0)
36093       {
36094          poly_rtrn(1) poly_impl<T,1>::evaluate(x, c1, c0);
36095       }
36096
36097       inline virtual T operator() (const T& x, const T& c2, const T& c1, const T& c0)
36098       {
36099          poly_rtrn(2) poly_impl<T,2>::evaluate(x, c2, c1, c0);
36100       }
36101
36102       inline virtual T operator() (const T& x, const T& c3, const T& c2, const T& c1, const T& c0)
36103       {
36104          poly_rtrn(3) poly_impl<T,3>::evaluate(x, c3, c2, c1, c0);
36105       }
36106
36107       inline virtual T operator() (const T& x, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
36108       {
36109          poly_rtrn(4) poly_impl<T,4>::evaluate(x, c4, c3, c2, c1, c0);
36110       }
36111
36112       inline virtual T operator() (const T& x, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
36113       {
36114          poly_rtrn(5) poly_impl<T,5>::evaluate(x, c5, c4, c3, c2, c1, c0);
36115       }
36116
36117       inline virtual T operator() (const T& x, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
36118       {
36119          poly_rtrn(6) poly_impl<T,6>::evaluate(x, c6, c5, c4, c3, c2, c1, c0);
36120       }
36121
36122       inline virtual T operator() (const T& x, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
36123       {
36124          poly_rtrn(7) poly_impl<T,7>::evaluate(x, c7, c6, c5, c4, c3, c2, c1, c0);
36125       }
36126
36127       inline virtual T operator() (const T& x, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
36128       {
36129          poly_rtrn(8) poly_impl<T,8>::evaluate(x, c8, c7, c6, c5, c4, c3, c2, c1, c0);
36130       }
36131
36132       inline virtual T operator() (const T& x, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
36133       {
36134          poly_rtrn(9) poly_impl<T,9>::evaluate(x, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0);
36135       }
36136
36137       inline virtual T operator() (const T& x, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
36138       {
36139          poly_rtrn(10) poly_impl<T,10>::evaluate(x, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0);
36140       }
36141
36142       inline virtual T operator() (const T& x, const T& c11, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
36143       {
36144          poly_rtrn(11) poly_impl<T,11>::evaluate(x, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0);
36145       }
36146
36147       inline virtual T operator() (const T& x, const T& c12, const T& c11, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
36148       {
36149          poly_rtrn(12) poly_impl<T,12>::evaluate(x, c12, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0);
36150       }
36151
36152       #undef poly_rtrn
36153
36154       inline virtual T operator() ()
36155       {
36156          return std::numeric_limits<T>::quiet_NaN();
36157       }
36158
36159       inline virtual T operator() (const T&)
36160       {
36161          return std::numeric_limits<T>::quiet_NaN();
36162       }
36163
36164       inline virtual T operator() (const T&, const T&)
36165       {
36166          return std::numeric_limits<T>::quiet_NaN();
36167       }
36168    };
36169
36170    template <typename T>
36171    class function_compositor
36172    {
36173    public:
36174
36175       typedef exprtk::expression<T>             expression_t;
36176       typedef exprtk::symbol_table<T>           symbol_table_t;
36177       typedef exprtk::parser<T>                 parser_t;
36178       typedef typename parser_t::settings_store settings_t;
36179
36180       struct function
36181       {
36182          function()
36183          {}
36184
36185          function(const std::string& n)
36186          : name_(n)
36187          {}
36188
36189          function(const std::string& name,
36190                   const std::string& expression)
36191          : name_(name),
36192            expression_(expression)
36193          {}
36194
36195          function(const std::string& name,
36196                   const std::string& expression,
36197                   const std::string& v0)
36198          : name_(name),
36199            expression_(expression)
36200          {
36201             v_.push_back(v0);
36202          }
36203
36204          function(const std::string& name,
36205                   const std::string& expression,
36206                   const std::string& v0, const std::string& v1)
36207          : name_(name),
36208            expression_(expression)
36209          {
36210             v_.push_back(v0); v_.push_back(v1);
36211          }
36212
36213          function(const std::string& name,
36214                   const std::string& expression,
36215                   const std::string& v0, const std::string& v1,
36216                   const std::string& v2)
36217          : name_(name),
36218            expression_(expression)
36219          {
36220             v_.push_back(v0); v_.push_back(v1);
36221             v_.push_back(v2);
36222          }
36223
36224          function(const std::string& name,
36225                   const std::string& expression,
36226                   const std::string& v0, const std::string& v1,
36227                   const std::string& v2, const std::string& v3)
36228          : name_(name),
36229            expression_(expression)
36230          {
36231             v_.push_back(v0); v_.push_back(v1);
36232             v_.push_back(v2); v_.push_back(v3);
36233          }
36234
36235          function(const std::string& name,
36236                   const std::string& expression,
36237                   const std::string& v0, const std::string& v1,
36238                   const std::string& v2, const std::string& v3,
36239                   const std::string& v4)
36240          : name_(name),
36241            expression_(expression)
36242          {
36243             v_.push_back(v0); v_.push_back(v1);
36244             v_.push_back(v2); v_.push_back(v3);
36245             v_.push_back(v4);
36246          }
36247
36248          inline function& name(const std::string& n)
36249          {
36250             name_ = n;
36251             return (*this);
36252          }
36253
36254          inline function& expression(const std::string& e)
36255          {
36256             expression_ = e;
36257             return (*this);
36258          }
36259
36260          inline function& var(const std::string& v)
36261          {
36262             v_.push_back(v);
36263             return (*this);
36264          }
36265
36266          std::string name_;
36267          std::string expression_;
36268          std::deque<std::string> v_;
36269       };
36270
36271    private:
36272
36273       struct base_func : public exprtk::ifunction<T>
36274       {
36275          typedef const T&                       type;
36276          typedef exprtk::ifunction<T>     function_t;
36277          typedef std::vector<T*>            varref_t;
36278          typedef std::vector<T>                var_t;
36279          typedef std::pair<T*,std::size_t> lvarref_t;
36280          typedef std::vector<lvarref_t>    lvr_vec_t;
36281
36282          using exprtk::ifunction<T>::operator();
36283
36284          base_func(const std::size_t& pc = 0)
36285          : exprtk::ifunction<T>(pc),
36286            local_var_stack_size(0),
36287            stack_depth(0)
36288          {
36289             v.resize(pc);
36290          }
36291
36292          virtual ~base_func()
36293          {}
36294
36295          inline void update(const T& v0)
36296          {
36297             (*v[0]) = v0;
36298          }
36299
36300          inline void update(const T& v0, const T& v1)
36301          {
36302             (*v[0]) = v0; (*v[1]) = v1;
36303          }
36304
36305          inline void update(const T& v0, const T& v1, const T& v2)
36306          {
36307             (*v[0]) = v0; (*v[1]) = v1;
36308             (*v[2]) = v2;
36309          }
36310
36311          inline void update(const T& v0, const T& v1, const T& v2, const T& v3)
36312          {
36313             (*v[0]) = v0; (*v[1]) = v1;
36314             (*v[2]) = v2; (*v[3]) = v3;
36315          }
36316
36317          inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4)
36318          {
36319             (*v[0]) = v0; (*v[1]) = v1;
36320             (*v[2]) = v2; (*v[3]) = v3;
36321             (*v[4]) = v4;
36322          }
36323
36324          inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5)
36325          {
36326             (*v[0]) = v0; (*v[1]) = v1;
36327             (*v[2]) = v2; (*v[3]) = v3;
36328             (*v[4]) = v4; (*v[5]) = v5;
36329          }
36330
36331          inline function_t& setup(expression_t& expr)
36332          {
36333             expression = expr;
36334
36335             typedef typename expression_t::control_block::local_data_list_t ldl_t;
36336
36337             ldl_t ldl = expr.local_data_list();
36338
36339             std::vector<std::size_t> index_list;
36340
36341             for (std::size_t i = 0; i < ldl.size(); ++i)
36342             {
36343                if (ldl[i].size)
36344                {
36345                   index_list.push_back(i);
36346                }
36347             }
36348
36349             std::size_t input_param_count = 0;
36350
36351             for (std::size_t i = 0; i < index_list.size(); ++i)
36352             {
36353                const std::size_t index = index_list[i];
36354
36355                if (i < (index_list.size() - v.size()))
36356                {
36357                   lv.push_back(
36358                         std::make_pair(
36359                            reinterpret_cast<T*>(ldl[index].pointer),
36360                            ldl[index].size));
36361
36362                   local_var_stack_size += ldl[index].size;
36363                }
36364                else
36365                   v[input_param_count++] = reinterpret_cast<T*>(ldl[index].pointer);
36366             }
36367
36368             clear_stack();
36369
36370             return (*this);
36371          }
36372
36373          inline void pre()
36374          {
36375             if (stack_depth++)
36376             {
36377                if (!v.empty())
36378                {
36379                   var_t var_stack(v.size(),T(0));
36380                   copy(v,var_stack);
36381                   param_stack.push_back(var_stack);
36382                }
36383
36384                if (!lv.empty())
36385                {
36386                   var_t local_var_stack(local_var_stack_size,T(0));
36387                   copy(lv,local_var_stack);
36388                   local_stack.push_back(local_var_stack);
36389                }
36390             }
36391          }
36392
36393          inline void post()
36394          {
36395             if (--stack_depth)
36396             {
36397                if (!v.empty())
36398                {
36399                   copy(param_stack.back(),v);
36400                   param_stack.pop_back();
36401                }
36402
36403                if (!lv.empty())
36404                {
36405                   copy(local_stack.back(),lv);
36406                   local_stack.pop_back();
36407                }
36408             }
36409          }
36410
36411          void copy(const varref_t& src_v, var_t& dest_v)
36412          {
36413             for (std::size_t i = 0; i < src_v.size(); ++i)
36414             {
36415                dest_v[i] = (*src_v[i]);
36416             }
36417          }
36418
36419          void copy(const var_t& src_v, varref_t& dest_v)
36420          {
36421             for (std::size_t i = 0; i < src_v.size(); ++i)
36422             {
36423                (*dest_v[i]) = src_v[i];
36424             }
36425          }
36426
36427          void copy(const lvr_vec_t& src_v, var_t& dest_v)
36428          {
36429             typename var_t::iterator itr = dest_v.begin();
36430             typedef  typename std::iterator_traits<typename var_t::iterator>::difference_type diff_t;
36431
36432             for (std::size_t i = 0; i < src_v.size(); ++i)
36433             {
36434                lvarref_t vr = src_v[i];
36435
36436                if (1 == vr.second)
36437                   *itr++ = (*vr.first);
36438                else
36439                {
36440                   std::copy(vr.first, vr.first + vr.second, itr);
36441                   itr += static_cast<diff_t>(vr.second);
36442                }
36443             }
36444          }
36445
36446          void copy(const var_t& src_v, lvr_vec_t& dest_v)
36447          {
36448             typename var_t::const_iterator itr = src_v.begin();
36449             typedef  typename std::iterator_traits<typename var_t::iterator>::difference_type diff_t;
36450
36451             for (std::size_t i = 0; i < src_v.size(); ++i)
36452             {
36453                lvarref_t vr = dest_v[i];
36454
36455                if (1 == vr.second)
36456                   (*vr.first) = *itr++;
36457                else
36458                {
36459                   std::copy(itr, itr + static_cast<diff_t>(vr.second), vr.first);
36460                   itr += static_cast<diff_t>(vr.second);
36461                }
36462             }
36463          }
36464
36465          inline void clear_stack()
36466          {
36467             for (std::size_t i = 0; i < v.size(); ++i)
36468             {
36469                (*v[i]) = 0;
36470             }
36471          }
36472
36473          inline virtual T value(expression_t& e)
36474          {
36475             return e.value();
36476          }
36477
36478          expression_t expression;
36479          varref_t v;
36480          lvr_vec_t lv;
36481          std::size_t local_var_stack_size;
36482          std::size_t stack_depth;
36483          std::deque<var_t> param_stack;
36484          std::deque<var_t> local_stack;
36485       };
36486
36487       typedef std::map<std::string,base_func*> funcparam_t;
36488
36489       struct func_0param : public base_func
36490       {
36491          using exprtk::ifunction<T>::operator();
36492
36493          func_0param() : base_func(0) {}
36494
36495          inline T operator() ()
36496          {
36497             return this->value(base_func::expression);
36498          }
36499       };
36500
36501       typedef const T& type;
36502
36503       template <typename BaseFuncType>
36504       struct scoped_bft
36505       {
36506          scoped_bft(BaseFuncType& bft) : bft_(bft) { bft_.pre (); }
36507         ~scoped_bft()                              { bft_.post(); }
36508
36509          BaseFuncType& bft_;
36510
36511       private:
36512
36513          scoped_bft(scoped_bft&);
36514          scoped_bft& operator=(scoped_bft&);
36515       };
36516
36517       struct func_1param : public base_func
36518       {
36519          using exprtk::ifunction<T>::operator();
36520
36521          func_1param() : base_func(1) {}
36522
36523          inline T operator() (type v0)
36524          {
36525             scoped_bft<func_1param> sb(*this);
36526             base_func::update(v0);
36527             return this->value(base_func::expression);
36528          }
36529       };
36530
36531       struct func_2param : public base_func
36532       {
36533          using exprtk::ifunction<T>::operator();
36534
36535          func_2param() : base_func(2) {}
36536
36537          inline T operator() (type v0, type v1)
36538          {
36539             scoped_bft<func_2param> sb(*this);
36540             base_func::update(v0, v1);
36541             return this->value(base_func::expression);
36542          }
36543       };
36544
36545       struct func_3param : public base_func
36546       {
36547          using exprtk::ifunction<T>::operator();
36548
36549          func_3param() : base_func(3) {}
36550
36551          inline T operator() (type v0, type v1, type v2)
36552          {
36553             scoped_bft<func_3param> sb(*this);
36554             base_func::update(v0, v1, v2);
36555             return this->value(base_func::expression);
36556          }
36557       };
36558
36559       struct func_4param : public base_func
36560       {
36561          using exprtk::ifunction<T>::operator();
36562
36563          func_4param() : base_func(4) {}
36564
36565          inline T operator() (type v0, type v1, type v2, type v3)
36566          {
36567             scoped_bft<func_4param> sb(*this);
36568             base_func::update(v0, v1, v2, v3);
36569             return this->value(base_func::expression);
36570          }
36571       };
36572
36573       struct func_5param : public base_func
36574       {
36575          using exprtk::ifunction<T>::operator();
36576
36577          func_5param() : base_func(5) {}
36578
36579          inline T operator() (type v0, type v1, type v2, type v3, type v4)
36580          {
36581             scoped_bft<func_5param> sb(*this);
36582             base_func::update(v0, v1, v2, v3, v4);
36583             return this->value(base_func::expression);
36584          }
36585       };
36586
36587       struct func_6param : public base_func
36588       {
36589          using exprtk::ifunction<T>::operator();
36590
36591          func_6param() : base_func(6) {}
36592
36593          inline T operator() (type v0, type v1, type v2, type v3, type v4, type v5)
36594          {
36595             scoped_bft<func_6param> sb(*this);
36596             base_func::update(v0, v1, v2, v3, v4, v5);
36597             return this->value(base_func::expression);
36598          }
36599       };
36600
36601       static T return_value(expression_t& e)
36602       {
36603          typedef exprtk::results_context<T> results_context_t;
36604          typedef typename results_context_t::type_store_t type_t;
36605          typedef typename type_t::scalar_view scalar_t;
36606
36607          T result = e.value();
36608
36609          if (e.return_invoked())
36610          {
36611             // Due to the post compilation checks, it can be safely
36612             // assumed that there will be at least one parameter
36613             // and that the first parameter will always be scalar.
36614             return scalar_t(e.results()[0])();
36615          }
36616
36617          return result;
36618       }
36619
36620       #define def_fp_retval(N)                               \
36621       struct func_##N##param_retval : public func_##N##param \
36622       {                                                      \
36623          inline T value(expression_t& e)                     \
36624          {                                                   \
36625             return return_value(e);                          \
36626          }                                                   \
36627       };                                                     \
36628
36629       def_fp_retval(0)
36630       def_fp_retval(1)
36631       def_fp_retval(2)
36632       def_fp_retval(3)
36633       def_fp_retval(4)
36634       def_fp_retval(5)
36635       def_fp_retval(6)
36636
36637       template <typename Allocator,
36638                 template <typename, typename> class Sequence>
36639       inline bool add(const std::string& name,
36640                       const std::string& expression,
36641                       const Sequence<std::string,Allocator>& var_list,
36642                       const bool override = false)
36643       {
36644          const typename std::map<std::string,expression_t>::iterator itr = expr_map_.find(name);
36645
36646          if (expr_map_.end() != itr)
36647          {
36648             if (!override)
36649             {
36650                exprtk_debug(("Compositor error(add): function '%s' already defined\n",
36651                              name.c_str()));
36652
36653                return false;
36654             }
36655
36656             remove(name, var_list.size());
36657          }
36658
36659          if (compile_expression(name,expression,var_list))
36660          {
36661             const std::size_t n = var_list.size();
36662
36663             fp_map_[n][name]->setup(expr_map_[name]);
36664
36665             return true;
36666          }
36667          else
36668          {
36669             exprtk_debug(("Compositor error(add): Failed to compile function '%s'\n",
36670                           name.c_str()));
36671
36672             return false;
36673          }
36674       }
36675
36676    public:
36677
36678       function_compositor()
36679       : parser_(settings_t::compile_all_opts +
36680                 settings_t::e_disable_zero_return),
36681         fp_map_(7)
36682       {}
36683
36684       function_compositor(const symbol_table_t& st)
36685       : symbol_table_(st),
36686         parser_(settings_t::compile_all_opts +
36687                 settings_t::e_disable_zero_return),
36688         fp_map_(7)
36689       {}
36690
36691      ~function_compositor()
36692       {
36693          clear();
36694       }
36695
36696       inline symbol_table_t& symbol_table()
36697       {
36698          return symbol_table_;
36699       }
36700
36701       inline void add_auxiliary_symtab(symbol_table_t& symtab)
36702       {
36703          auxiliary_symtab_list_.push_back(&symtab);
36704       }
36705
36706       void clear()
36707       {
36708          symbol_table_.clear();
36709          expr_map_    .clear();
36710
36711          for (std::size_t i = 0; i < fp_map_.size(); ++i)
36712          {
36713             typename funcparam_t::iterator itr = fp_map_[i].begin();
36714             typename funcparam_t::iterator end = fp_map_[i].end  ();
36715
36716             while (itr != end)
36717             {
36718                delete itr->second;
36719                ++itr;
36720             }
36721
36722             fp_map_[i].clear();
36723          }
36724       }
36725
36726       inline bool add(const function& f, const bool override = false)
36727       {
36728          return add(f.name_, f.expression_, f.v_,override);
36729       }
36730
36731    private:
36732
36733       template <typename Allocator,
36734                 template <typename, typename> class Sequence>
36735       bool compile_expression(const std::string& name,
36736                               const std::string& expression,
36737                               const Sequence<std::string,Allocator>& input_var_list,
36738                               bool  return_present = false)
36739       {
36740          expression_t compiled_expression;
36741          symbol_table_t local_symbol_table;
36742
36743          local_symbol_table.load_from(symbol_table_);
36744          local_symbol_table.add_constants();
36745
36746          if (!valid(name,input_var_list.size()))
36747             return false;
36748
36749          if (!forward(name,
36750                       input_var_list.size(),
36751                       local_symbol_table,
36752                       return_present))
36753             return false;
36754
36755          compiled_expression.register_symbol_table(local_symbol_table);
36756
36757          for (std::size_t i = 0; i < auxiliary_symtab_list_.size(); ++i)
36758          {
36759             compiled_expression.register_symbol_table((*auxiliary_symtab_list_[i]));
36760          }
36761
36762          std::string mod_expression;
36763
36764          for (std::size_t i = 0; i < input_var_list.size(); ++i)
36765          {
36766             mod_expression += " var " + input_var_list[i] + "{};\n";
36767          }
36768
36769          if (
36770               ('{' == details::front(expression)) &&
36771               ('}' == details::back (expression))
36772             )
36773             mod_expression += "~" + expression + ";";
36774          else
36775             mod_expression += "~{" + expression + "};";
36776
36777          if (!parser_.compile(mod_expression,compiled_expression))
36778          {
36779             exprtk_debug(("Compositor Error: %s\n",parser_.error().c_str()));
36780             exprtk_debug(("Compositor modified expression: \n%s\n",mod_expression.c_str()));
36781
36782             remove(name,input_var_list.size());
36783
36784             return false;
36785          }
36786
36787          if (!return_present && parser_.dec().return_present())
36788          {
36789             remove(name,input_var_list.size());
36790
36791             return compile_expression(name, expression, input_var_list, true);
36792          }
36793
36794          // Make sure every return point has a scalar as its first parameter
36795          if (parser_.dec().return_present())
36796          {
36797             typedef std::vector<std::string> str_list_t;
36798
36799             str_list_t ret_param_list = parser_.dec().return_param_type_list();
36800
36801             for (std::size_t i = 0; i < ret_param_list.size(); ++i)
36802             {
36803                const std::string& params = ret_param_list[i];
36804
36805                if (params.empty() || ('T' != params[0]))
36806                {
36807                   exprtk_debug(("Compositor Error: Return statement in function '%s' is invalid\n",
36808                                 name.c_str()));
36809
36810                   remove(name,input_var_list.size());
36811
36812                   return false;
36813                }
36814             }
36815          }
36816
36817          expr_map_[name] = compiled_expression;
36818
36819          exprtk::ifunction<T>& ifunc = (*(fp_map_[input_var_list.size()])[name]);
36820
36821          if (symbol_table_.add_function(name,ifunc))
36822             return true;
36823          else
36824          {
36825             exprtk_debug(("Compositor Error: Failed to add function '%s' to symbol table\n",
36826                           name.c_str()));
36827             return false;
36828          }
36829       }
36830
36831       inline bool symbol_used(const std::string& symbol) const
36832       {
36833          return (
36834                   symbol_table_.is_variable       (symbol) ||
36835                   symbol_table_.is_stringvar      (symbol) ||
36836                   symbol_table_.is_function       (symbol) ||
36837                   symbol_table_.is_vector         (symbol) ||
36838                   symbol_table_.is_vararg_function(symbol)
36839                 );
36840       }
36841
36842       inline bool valid(const std::string& name,
36843                         const std::size_t& arg_count) const
36844       {
36845          if (arg_count > 6)
36846             return false;
36847          else if (symbol_used(name))
36848             return false;
36849          else if (fp_map_[arg_count].end() != fp_map_[arg_count].find(name))
36850             return false;
36851          else
36852             return true;
36853       }
36854
36855       inline bool forward(const std::string& name,
36856                           const std::size_t& arg_count,
36857                           symbol_table_t& sym_table,
36858                           const bool ret_present = false)
36859       {
36860          switch (arg_count)
36861          {
36862             #define case_stmt(N)                                     \
36863             case N : (fp_map_[arg_count])[name] =                    \
36864                      (!ret_present) ? static_cast<base_func*>        \
36865                                       (new func_##N##param) :        \
36866                                       static_cast<base_func*>        \
36867                                       (new func_##N##param_retval) ; \
36868                      break;                                          \
36869
36870             case_stmt(0) case_stmt(1) case_stmt(2)
36871             case_stmt(3) case_stmt(4) case_stmt(5)
36872             case_stmt(6)
36873             #undef case_stmt
36874          }
36875
36876          exprtk::ifunction<T>& ifunc = (*(fp_map_[arg_count])[name]);
36877
36878          return sym_table.add_function(name,ifunc);
36879       }
36880
36881       inline void remove(const std::string& name, const std::size_t& arg_count)
36882       {
36883          if (arg_count > 6)
36884             return;
36885
36886          const typename std::map<std::string,expression_t>::iterator em_itr = expr_map_.find(name);
36887
36888          if (expr_map_.end() != em_itr)
36889          {
36890             expr_map_.erase(em_itr);
36891          }
36892
36893          const typename funcparam_t::iterator fp_itr = fp_map_[arg_count].find(name);
36894
36895          if (fp_map_[arg_count].end() != fp_itr)
36896          {
36897             delete fp_itr->second;
36898             fp_map_[arg_count].erase(fp_itr);
36899          }
36900
36901          symbol_table_.remove_function(name);
36902       }
36903
36904    private:
36905
36906       symbol_table_t symbol_table_;
36907       parser_t parser_;
36908       std::map<std::string,expression_t> expr_map_;
36909       std::vector<funcparam_t> fp_map_;
36910       std::vector<symbol_table_t*> auxiliary_symtab_list_;
36911    };
36912
36913    template <typename T>
36914    inline bool pgo_primer()
36915    {
36916       static const std::string expression_list[] =
36917              {
36918                 "(y + x)",
36919                 "2 * (y + x)",
36920                 "(2 * y + 2 * x)",
36921                 "(y + x / y) * (x - y / x)",
36922                 "x / ((x + y) * (x - y)) / y",
36923                 "1 - ((x * y) + (y / x)) - 3",
36924                 "sin(2 * x) + cos(pi / y)",
36925                 "1 - sin(2 * x) + cos(pi / y)",
36926                 "sqrt(1 - sin(2 * x) + cos(pi / y) / 3)",
36927                 "(x^2 / sin(2 * pi / y)) -x / 2",
36928                 "x + (cos(y - sin(2 / x * pi)) - sin(x - cos(2 * y / pi))) - y",
36929                 "clamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)",
36930                 "iclamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)",
36931                 "max(3.33, min(sqrt(1 - sin(2 * x) + cos(pi / y) / 3), 1.11))",
36932                 "if(avg(x,y) <= x + y, x - y, x * y) + 2 * pi / x",
36933                 "1.1x^1 + 2.2y^2 - 3.3x^3 + 4.4y^4 - 5.5x^5 + 6.6y^6 - 7.7x^27 + 8.8y^55",
36934                 "(yy + xx)",
36935                 "2 * (yy + xx)",
36936                 "(2 * yy + 2 * xx)",
36937                 "(yy + xx / yy) * (xx - yy / xx)",
36938                 "xx / ((xx + yy) * (xx - yy)) / yy",
36939                 "1 - ((xx * yy) + (yy / xx)) - 3",
36940                 "sin(2 * xx) + cos(pi / yy)",
36941                 "1 - sin(2 * xx) + cos(pi / yy)",
36942                 "sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3)",
36943                 "(xx^2 / sin(2 * pi / yy)) -xx / 2",
36944                 "xx + (cos(yy - sin(2 / xx * pi)) - sin(xx - cos(2 * yy / pi))) - yy",
36945                 "clamp(-1.0, sin(2 * pi * xx) + cos(yy / 2 * pi), +1.0)",
36946                 "max(3.33, min(sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3), 1.11))",
36947                 "if(avg(xx,yy) <= xx + yy, xx - yy, xx * yy) + 2 * pi / xx",
36948                 "1.1xx^1 + 2.2yy^2 - 3.3xx^3 + 4.4yy^4 - 5.5xx^5 + 6.6yy^6 - 7.7xx^27 + 8.8yy^55",
36949                 "(1.1*(2.2*(3.3*(4.4*(5.5*(6.6*(7.7*(8.8*(9.9+x)))))))))",
36950                 "(((((((((x+9.9)*8.8)*7.7)*6.6)*5.5)*4.4)*3.3)*2.2)*1.1)",
36951                 "(x + y) * z", "x + (y * z)", "(x + y) * 7", "x + (y * 7)",
36952                 "(x + 7) * y", "x + (7 * y)", "(7 + x) * y", "7 + (x * y)",
36953                 "(2 + x) * 3", "2 + (x * 3)", "(2 + 3) * x", "2 + (3 * x)",
36954                 "(x + 2) * 3", "x + (2 * 3)",
36955                 "(x + y) * (z / w)", "(x + y) * (z / 7)", "(x + y) * (7 / z)", "(x + 7) * (y / z)",
36956                 "(7 + x) * (y / z)", "(2 + x) * (y / z)", "(x + 2) * (y / 3)", "(2 + x) * (y / 3)",
36957                 "(x + 2) * (3 / y)", "x + (y * (z / w))", "x + (y * (z / 7))", "x + (y * (7 / z))",
36958                 "x + (7 * (y / z))", "7 + (x * (y / z))", "2 + (x * (3 / y))", "x + (2 * (y / 4))",
36959                 "2 + (x * (y / 3))", "x + (2 * (3 / y))",
36960                 "x + ((y * z) / w)", "x + ((y * z) / 7)", "x + ((y * 7) / z)", "x + ((7 * y) / z)",
36961                 "7 + ((y * z) / w)", "2 + ((x * 3) / y)", "x + ((2 * y) / 3)", "2 + ((x * y) / 3)",
36962                 "x + ((2 * 3) / y)", "(((x + y) * z) / w)",
36963                 "(((x + y) * z) / 7)", "(((x + y) * 7) / z)", "(((x + 7) * y) / z)", "(((7 + x) * y) / z)",
36964                 "(((2 + x) * 3) / y)", "(((x + 2) * y) / 3)", "(((2 + x) * y) / 3)", "(((x + 2) * 3) / y)",
36965                 "((x + (y * z)) / w)", "((x + (y * z)) / 7)", "((x + (y * 7)) / y)", "((x + (7 * y)) / z)",
36966                 "((7 + (x * y)) / z)", "((2 + (x * 3)) / y)", "((x + (2 * y)) / 3)", "((2 + (x * y)) / 3)",
36967                 "((x + (2 * 3)) / y)",
36968                 "(xx + yy) * zz", "xx + (yy * zz)",
36969                 "(xx + yy) * 7", "xx + (yy * 7)",
36970                 "(xx + 7) * yy", "xx + (7 * yy)",
36971                 "(7 + xx) * yy", "7 + (xx * yy)",
36972                 "(2 + x) * 3", "2 + (x * 3)",
36973                 "(2 + 3) * x", "2 + (3 * x)",
36974                 "(x + 2) * 3", "x + (2 * 3)",
36975                 "(xx + yy) * (zz / ww)", "(xx + yy) * (zz / 7)",
36976                 "(xx + yy) * (7 / zz)", "(xx + 7) * (yy / zz)",
36977                 "(7 + xx) * (yy / zz)", "(2 + xx) * (yy / zz)",
36978                 "(xx + 2) * (yy / 3)", "(2 + xx) * (yy / 3)",
36979                 "(xx + 2) * (3 / yy)", "xx + (yy * (zz / ww))",
36980                 "xx + (yy * (zz / 7))", "xx + (yy * (7 / zz))",
36981                 "xx + (7 * (yy / zz))", "7 + (xx * (yy / zz))",
36982                 "2 + (xx * (3 / yy))", "xx + (2 * (yy / 4))",
36983                 "2 + (xx * (yy / 3))", "xx + (2 * (3 / yy))",
36984                 "xx + ((yy * zz) / ww)", "xx + ((yy * zz) / 7)",
36985                 "xx + ((yy * 7) / zz)", "xx + ((7 * yy) / zz)",
36986                 "7 + ((yy * zz) / ww)", "2 + ((xx * 3) / yy)",
36987                 "xx + ((2 * yy) / 3)", "2 + ((xx * yy) / 3)",
36988                 "xx + ((2 * 3) / yy)", "(((xx + yy) * zz) / ww)",
36989                 "(((xx + yy) * zz) / 7)", "(((xx + yy) * 7) / zz)",
36990                 "(((xx + 7) * yy) / zz)", "(((7 + xx) * yy) / zz)",
36991                 "(((2 + xx) * 3) / yy)", "(((xx + 2) * yy) / 3)",
36992                 "(((2 + xx) * yy) / 3)", "(((xx + 2) * 3) / yy)",
36993                 "((xx + (yy * zz)) / ww)", "((xx + (yy * zz)) / 7)",
36994                 "((xx + (yy * 7)) / yy)", "((xx + (7 * yy)) / zz)",
36995                 "((7 + (xx * yy)) / zz)", "((2 + (xx * 3)) / yy)",
36996                 "((xx + (2 * yy)) / 3)", "((2 + (xx * yy)) / 3)",
36997                 "((xx + (2 * 3)) / yy)"
36998              };
36999
37000       static const std::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string);
37001
37002       T  x = T(0);
37003       T  y = T(0);
37004       T  z = T(0);
37005       T  w = T(0);
37006       T xx = T(0);
37007       T yy = T(0);
37008       T zz = T(0);
37009       T ww = T(0);
37010
37011       exprtk::symbol_table<T> symbol_table;
37012       symbol_table.add_constants();
37013       symbol_table.add_variable( "x", x);
37014       symbol_table.add_variable( "y", y);
37015       symbol_table.add_variable( "z", z);
37016       symbol_table.add_variable( "w", w);
37017       symbol_table.add_variable("xx",xx);
37018       symbol_table.add_variable("yy",yy);
37019       symbol_table.add_variable("zz",zz);
37020       symbol_table.add_variable("ww",ww);
37021
37022       typedef typename std::deque<exprtk::expression<T> > expr_list_t;
37023       expr_list_t expr_list;
37024
37025       const std::size_t rounds = 50;
37026
37027       {
37028          for (std::size_t r = 0; r < rounds; ++r)
37029          {
37030             expr_list.clear();
37031             exprtk::parser<T> parser;
37032
37033             for (std::size_t i = 0; i < expression_list_size; ++i)
37034             {
37035                exprtk::expression<T> expression;
37036                expression.register_symbol_table(symbol_table);
37037
37038                if (!parser.compile(expression_list[i],expression))
37039                {
37040                   return false;
37041                }
37042
37043                expr_list.push_back(expression);
37044             }
37045          }
37046       }
37047
37048       struct execute
37049       {
37050          static inline T process(T& x, T& y, expression<T>& expression)
37051          {
37052             static const T lower_bound = T(-20);
37053             static const T upper_bound = T(+20);
37054             static const T delta       = T(0.1);
37055
37056             T total = T(0);
37057
37058             for (x = lower_bound; x <= upper_bound; x += delta)
37059             {
37060                for (y = lower_bound; y <= upper_bound; y += delta)
37061                {
37062                   total += expression.value();
37063                }
37064             }
37065
37066             return total;
37067          }
37068       };
37069
37070       for (std::size_t i = 0; i < expr_list.size(); ++i)
37071       {
37072          execute::process( x,  y, expr_list[i]);
37073          execute::process(xx, yy, expr_list[i]);
37074       }
37075
37076       {
37077          for (std::size_t i = 0; i < 10000; ++i)
37078          {
37079             const T v = T(123.456 + i);
37080
37081             if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 1>::result(v),details::numeric::pow(v,T( 1)))))
37082                return false;
37083
37084             #define else_stmt(N)                                                                                                           \
37085             else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,N>::result(v),details::numeric::pow(v,T(N))))) \
37086                return false;                                                                                                               \
37087
37088             else_stmt( 2) else_stmt( 3) else_stmt( 4) else_stmt( 5)
37089             else_stmt( 6) else_stmt( 7) else_stmt( 8) else_stmt( 9)
37090             else_stmt(10) else_stmt(11) else_stmt(12) else_stmt(13)
37091             else_stmt(14) else_stmt(15) else_stmt(16) else_stmt(17)
37092             else_stmt(18) else_stmt(19) else_stmt(20) else_stmt(21)
37093             else_stmt(22) else_stmt(23) else_stmt(24) else_stmt(25)
37094             else_stmt(26) else_stmt(27) else_stmt(28) else_stmt(29)
37095             else_stmt(30) else_stmt(31) else_stmt(32) else_stmt(33)
37096             else_stmt(34) else_stmt(35) else_stmt(36) else_stmt(37)
37097             else_stmt(38) else_stmt(39) else_stmt(40) else_stmt(41)
37098             else_stmt(42) else_stmt(43) else_stmt(44) else_stmt(45)
37099             else_stmt(46) else_stmt(47) else_stmt(48) else_stmt(49)
37100             else_stmt(50) else_stmt(51) else_stmt(52) else_stmt(53)
37101             else_stmt(54) else_stmt(55) else_stmt(56) else_stmt(57)
37102             else_stmt(58) else_stmt(59) else_stmt(60) else_stmt(61)
37103          }
37104       }
37105
37106       return true;
37107    }
37108 }
37109
37110 #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
37111 #   ifndef NOMINMAX
37112 #      define NOMINMAX
37113 #   endif
37114 #   ifndef WIN32_LEAN_AND_MEAN
37115 #      define WIN32_LEAN_AND_MEAN
37116 #   endif
37117 #   include <windows.h>
37118 #   include <ctime>
37119 #else
37120 #   include <ctime>
37121 #   include <sys/time.h>
37122 #   include <sys/types.h>
37123 #endif
37124
37125 namespace exprtk
37126 {
37127    class timer
37128    {
37129    public:
37130
37131       #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
37132       timer()
37133       : in_use_(false)
37134       {
37135          QueryPerformanceFrequency(&clock_frequency_);
37136       }
37137
37138       inline void start()
37139       {
37140          in_use_ = true;
37141          QueryPerformanceCounter(&start_time_);
37142       }
37143
37144       inline void stop()
37145       {
37146          QueryPerformanceCounter(&stop_time_);
37147          in_use_ = false;
37148       }
37149
37150       inline double time() const
37151       {
37152          return (1.0 * (stop_time_.QuadPart - start_time_.QuadPart)) / (1.0 * clock_frequency_.QuadPart);
37153       }
37154
37155       #else
37156
37157       timer()
37158       : in_use_(false)
37159       {
37160          start_time_.tv_sec  = 0;
37161          start_time_.tv_usec = 0;
37162          stop_time_.tv_sec   = 0;
37163          stop_time_.tv_usec  = 0;
37164       }
37165
37166       inline void start()
37167       {
37168          in_use_ = true;
37169          gettimeofday(&start_time_,0);
37170       }
37171
37172       inline void stop()
37173       {
37174          gettimeofday(&stop_time_, 0);
37175          in_use_ = false;
37176       }
37177
37178       inline unsigned long long int usec_time() const
37179       {
37180          if (!in_use_)
37181          {
37182             if (stop_time_.tv_sec >= start_time_.tv_sec)
37183             {
37184                return 1000000LLU * static_cast<details::_uint64_t>(stop_time_.tv_sec  - start_time_.tv_sec ) +
37185                                    static_cast<details::_uint64_t>(stop_time_.tv_usec - start_time_.tv_usec) ;
37186             }
37187             else
37188                return std::numeric_limits<details::_uint64_t>::max();
37189          }
37190          else
37191             return std::numeric_limits<details::_uint64_t>::max();
37192       }
37193
37194       inline double time() const
37195       {
37196          return usec_time() * 0.000001;
37197       }
37198
37199       #endif
37200
37201       inline bool in_use() const
37202       {
37203          return in_use_;
37204       }
37205
37206    private:
37207
37208       bool in_use_;
37209
37210       #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
37211          LARGE_INTEGER start_time_;
37212          LARGE_INTEGER stop_time_;
37213          LARGE_INTEGER clock_frequency_;
37214       #else
37215          struct timeval start_time_;
37216          struct timeval stop_time_;
37217       #endif
37218    };
37219
37220 } // namespace exprtk
37221
37222 #ifndef exprtk_disable_rtl_io
37223 namespace exprtk
37224 {
37225    namespace rtl { namespace io { namespace details
37226    {
37227       template <typename T>
37228       inline void print_type(const std::string& fmt,
37229                              const T v,
37230                              exprtk::details::numeric::details::real_type_tag)
37231       {
37232          printf(fmt.c_str(),v);
37233       }
37234
37235       template <typename T>
37236       struct print_impl
37237       {
37238          typedef typename igeneric_function<T>::generic_type generic_type;
37239          typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
37240          typedef typename generic_type::scalar_view scalar_t;
37241          typedef typename generic_type::vector_view vector_t;
37242          typedef typename generic_type::string_view string_t;
37243          typedef typename exprtk::details::numeric::details::number_type<T>::type num_type;
37244
37245          static void process(const std::string& scalar_format, parameter_list_t parameters)
37246          {
37247             for (std::size_t i = 0; i < parameters.size(); ++i)
37248             {
37249                generic_type& gt = parameters[i];
37250
37251                switch (gt.type)
37252                {
37253                   case generic_type::e_scalar : print(scalar_format,scalar_t(gt));
37254                                                 break;
37255
37256                   case generic_type::e_vector : print(scalar_format,vector_t(gt));
37257                                                 break;
37258
37259                   case generic_type::e_string : print(string_t(gt));
37260                                                 break;
37261
37262                   default                     : continue;
37263                }
37264             }
37265          }
37266
37267          static inline void print(const std::string& scalar_format, const scalar_t& s)
37268          {
37269             print_type(scalar_format,s(),num_type());
37270          }
37271
37272          static inline void print(const std::string& scalar_format, const vector_t& v)
37273          {
37274             for (std::size_t i = 0; i < v.size(); ++i)
37275             {
37276                print_type(scalar_format,v[i],num_type());
37277
37278                if ((i + 1) < v.size())
37279                   printf(" ");
37280             }
37281          }
37282
37283          static inline void print(const string_t& s)
37284          {
37285             printf("%s",to_str(s).c_str());
37286          }
37287       };
37288
37289    } // namespace exprtk::rtl::io::details
37290
37291    template <typename T>
37292    struct print : public exprtk::igeneric_function<T>
37293    {
37294       typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
37295
37296       using exprtk::igeneric_function<T>::operator();
37297
37298       print(const std::string& scalar_format = "%10.5f")
37299       : scalar_format_(scalar_format)
37300       {
37301          exprtk::enable_zero_parameters(*this);
37302       }
37303
37304       inline T operator() (parameter_list_t parameters)
37305       {
37306          details::print_impl<T>::process(scalar_format_,parameters);
37307          return T(0);
37308       }
37309
37310       std::string scalar_format_;
37311    };
37312
37313    template <typename T>
37314    struct println : public exprtk::igeneric_function<T>
37315    {
37316       typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
37317
37318       using exprtk::igeneric_function<T>::operator();
37319
37320       println(const std::string& scalar_format = "%10.5f")
37321       : scalar_format_(scalar_format)
37322       {
37323          exprtk::enable_zero_parameters(*this);
37324       }
37325
37326       inline T operator() (parameter_list_t parameters)
37327       {
37328          details::print_impl<T>::process(scalar_format_,parameters);
37329          printf("\n");
37330          return T(0);
37331       }
37332
37333       std::string scalar_format_;
37334    };
37335
37336    template <typename T>
37337    struct package
37338    {
37339       print  <T> p;
37340       println<T> pl;
37341
37342       bool register_package(exprtk::symbol_table<T>& symtab)
37343       {
37344          #define exprtk_register_function(FunctionName,FunctionType)              \
37345          if (!symtab.add_function(FunctionName,FunctionType))                     \
37346          {                                                                        \
37347             exprtk_debug((                                                        \
37348               "exprtk::rtl::io::register_package - Failed to add function: %s\n", \
37349               FunctionName));                                                     \
37350             return false;                                                         \
37351          }                                                                        \
37352
37353          exprtk_register_function("print"  ,  p)
37354          exprtk_register_function("println", pl)
37355          #undef exprtk_register_function
37356
37357          return true;
37358       }
37359    };
37360
37361    } // namespace exprtk::rtl::io
37362    } // namespace exprtk::rtl
37363 }    // namespace exprtk
37364 #endif
37365
37366 #ifndef exprtk_disable_rtl_io_file
37367 #include <fstream>
37368 namespace exprtk
37369 {
37370    namespace rtl { namespace io { namespace file { namespace details
37371    {
37372       enum file_mode
37373       {
37374          e_error = 0,
37375          e_read  = 1,
37376          e_write = 2,
37377          e_rdwrt = 4
37378       };
37379
37380       struct file_descriptor
37381       {
37382          file_descriptor(const std::string& fname, const std::string& access)
37383          : stream_ptr(0),
37384            mode(get_file_mode(access)),
37385            file_name(fname)
37386          {}
37387
37388          void*       stream_ptr;
37389          file_mode   mode;
37390          std::string file_name;
37391
37392          bool open()
37393          {
37394             if (e_read == mode)
37395             {
37396                std::ifstream* stream = new std::ifstream(file_name.c_str(),std::ios::binary);
37397
37398                if (!(*stream))
37399                {
37400                   file_name.clear();
37401                   delete stream;
37402
37403                   return false;
37404                }
37405                else
37406                   stream_ptr = stream;
37407
37408                return true;
37409             }
37410             else if (e_write == mode)
37411             {
37412                std::ofstream* stream = new std::ofstream(file_name.c_str(),std::ios::binary);
37413
37414                if (!(*stream))
37415                {
37416                   file_name.clear();
37417                   delete stream;
37418
37419                   return false;
37420                }
37421                else
37422                   stream_ptr = stream;
37423
37424                return true;
37425             }
37426             else if (e_rdwrt == mode)
37427             {
37428                std::fstream* stream = new std::fstream(file_name.c_str(),std::ios::binary);
37429
37430                if (!(*stream))
37431                {
37432                   file_name.clear();
37433                   delete stream;
37434
37435                   return false;
37436                }
37437                else
37438                   stream_ptr = stream;
37439
37440                return true;
37441             }
37442             else
37443                return false;
37444          }
37445
37446          template <typename Stream, typename Ptr>
37447          void close(Ptr& p)
37448          {
37449             Stream* stream = reinterpret_cast<Stream*>(p);
37450             stream->close();
37451             delete stream;
37452             p = reinterpret_cast<Ptr>(0);
37453          }
37454
37455          bool close()
37456          {
37457             switch (mode)
37458             {
37459                case e_read  : close<std::ifstream>(stream_ptr);
37460                               break;
37461
37462                case e_write : close<std::ofstream>(stream_ptr);
37463                               break;
37464
37465                case e_rdwrt : close<std::fstream> (stream_ptr);
37466                               break;
37467
37468                default      : return false;
37469             }
37470
37471             return true;
37472          }
37473
37474          template <typename View>
37475          bool write(const View& view, const std::size_t amount, const std::size_t offset = 0)
37476          {
37477             switch (mode)
37478             {
37479                case e_write : reinterpret_cast<std::ofstream*>(stream_ptr)->
37480                                  write(reinterpret_cast<const char*>(view.begin() + offset), amount * sizeof(typename View::value_t));
37481                               break;
37482
37483                case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)->
37484                                  write(reinterpret_cast<const char*>(view.begin() + offset) , amount * sizeof(typename View::value_t));
37485                               break;
37486
37487                default      : return false;
37488             }
37489
37490             return true;
37491          }
37492
37493          template <typename View>
37494          bool read(View& view, const std::size_t amount, const std::size_t offset = 0)
37495          {
37496             switch (mode)
37497             {
37498                case e_read  : reinterpret_cast<std::ifstream*>(stream_ptr)->
37499                                  read(reinterpret_cast<char*>(view.begin() + offset), amount * sizeof(typename View::value_t));
37500                               break;
37501
37502                case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)->
37503                                  read(reinterpret_cast<char*>(view.begin() + offset) , amount * sizeof(typename View::value_t));
37504                               break;
37505
37506                default      : return false;
37507             }
37508
37509             return true;
37510          }
37511
37512          bool getline(std::string& s)
37513          {
37514             switch (mode)
37515             {
37516                case e_read  : return (!!std::getline(*reinterpret_cast<std::ifstream*>(stream_ptr),s));
37517                case e_rdwrt : return (!!std::getline(*reinterpret_cast<std::fstream* >(stream_ptr),s));
37518                default      : return false;
37519             }
37520          }
37521
37522          bool eof() const
37523          {
37524             switch (mode)
37525             {
37526                case e_read  : return reinterpret_cast<std::ifstream*>(stream_ptr)->eof();
37527                case e_write : return reinterpret_cast<std::ofstream*>(stream_ptr)->eof();
37528                case e_rdwrt : return reinterpret_cast<std::fstream* >(stream_ptr)->eof();
37529                default      : return true;
37530             }
37531          }
37532
37533          file_mode get_file_mode(const std::string& access) const
37534          {
37535             if (access.empty() || access.size() > 2)
37536                return e_error;
37537
37538             std::size_t w_cnt = 0;
37539             std::size_t r_cnt = 0;
37540
37541             for (std::size_t i = 0; i < access.size(); ++i)
37542             {
37543                switch (std::tolower(access[i]))
37544                {
37545                   case 'r' : r_cnt++; break;
37546                   case 'w' : w_cnt++; break;
37547                   default  : return e_error;
37548                }
37549             }
37550
37551             if ((0 == r_cnt) && (0 == w_cnt))
37552                return e_error;
37553             else if ((r_cnt > 1) || (w_cnt > 1))
37554                return e_error;
37555             else if ((1 == r_cnt) && (1 == w_cnt))
37556                return e_rdwrt;
37557             else if (1 == r_cnt)
37558                return e_read;
37559             else
37560                return e_write;
37561          }
37562       };
37563
37564       template <typename T>
37565       file_descriptor* make_handle(T v)
37566       {
37567          file_descriptor* fd = reinterpret_cast<file_descriptor*>(0);
37568
37569          std::memcpy(reinterpret_cast<char*>(&fd),
37570                      reinterpret_cast<const char*>(&v),
37571                      sizeof(fd));
37572          return fd;
37573       }
37574
37575       template <typename T>
37576       void perform_check()
37577       {
37578          #ifdef _MSC_VER
37579          #pragma warning(push)
37580          #pragma warning(disable: 4127)
37581          #endif
37582          if (sizeof(T) < sizeof(void*))
37583          {
37584             throw std::runtime_error("exprtk::rtl::io::file - Error - pointer size larger than holder.");
37585          }
37586          #ifdef _MSC_VER
37587          #pragma warning(pop)
37588          #endif
37589       }
37590
37591    } // namespace exprtk::rtl::io::file::details
37592
37593    template <typename T>
37594    class open : public exprtk::igeneric_function<T>
37595    {
37596    public:
37597
37598       typedef typename exprtk::igeneric_function<T> igfun_t;
37599       typedef typename igfun_t::parameter_list_t    parameter_list_t;
37600       typedef typename igfun_t::generic_type        generic_type;
37601       typedef typename generic_type::string_view    string_t;
37602
37603       using exprtk::igeneric_function<T>::operator();
37604
37605       open()
37606       : exprtk::igeneric_function<T>("S|SS")
37607       { details::perform_check<T>(); }
37608
37609       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
37610       {
37611          std::string file_name = to_str(string_t(parameters[0]));
37612          std::string access;
37613
37614          if (file_name.empty())
37615             return T(0);
37616
37617          if (0 == ps_index)
37618             access = "r";
37619          else if (0 == string_t(parameters[1]).size())
37620             return T(0);
37621          else
37622             access = to_str(string_t(parameters[1]));
37623
37624          details::file_descriptor* fd = new details::file_descriptor(file_name,access);
37625
37626          if (fd->open())
37627          {
37628             T t = T(0);
37629
37630             std::memcpy(reinterpret_cast<char*>(&t ),
37631                         reinterpret_cast<char*>(&fd),
37632                         sizeof(fd));
37633             return t;
37634          }
37635          else
37636          {
37637             delete fd;
37638             return T(0);
37639          }
37640       }
37641    };
37642
37643    template <typename T>
37644    struct close : public exprtk::ifunction<T>
37645    {
37646       using exprtk::ifunction<T>::operator();
37647
37648       close()
37649       : exprtk::ifunction<T>(1)
37650       { details::perform_check<T>(); }
37651
37652       inline T operator() (const T& v)
37653       {
37654          details::file_descriptor* fd = details::make_handle(v);
37655
37656          if (!fd->close())
37657             return T(0);
37658
37659          delete fd;
37660
37661          return T(1);
37662       }
37663    };
37664
37665    template <typename T>
37666    class write : public exprtk::igeneric_function<T>
37667    {
37668    public:
37669
37670       typedef typename exprtk::igeneric_function<T> igfun_t;
37671       typedef typename igfun_t::parameter_list_t    parameter_list_t;
37672       typedef typename igfun_t::generic_type        generic_type;
37673       typedef typename generic_type::string_view    string_t;
37674       typedef typename generic_type::scalar_view    scalar_t;
37675       typedef typename generic_type::vector_view    vector_t;
37676
37677       using exprtk::igeneric_function<T>::operator();
37678
37679       write()
37680       : igfun_t("TS|TST|TV|TVT")
37681       { details::perform_check<T>(); }
37682
37683       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
37684       {
37685          details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])());
37686
37687          std::size_t amount = 0;
37688
37689          switch (ps_index)
37690          {
37691             case 0  : {
37692                          const string_t buffer(parameters[1]);
37693                          amount = buffer.size();
37694                          return T(fd->write(buffer, amount) ? 1 : 0);
37695                       }
37696
37697             case 1  : {
37698                          const string_t buffer(parameters[1]);
37699                          amount = std::min(buffer.size(),
37700                                            static_cast<std::size_t>(scalar_t(parameters[2])()));
37701                          return T(fd->write(buffer, amount) ? 1 : 0);
37702                       }
37703
37704             case 2  : {
37705                          const vector_t vec(parameters[1]);
37706                          amount = vec.size();
37707                          return T(fd->write(vec, amount) ? 1 : 0);
37708                       }
37709
37710             case 3  : {
37711                          const vector_t vec(parameters[1]);
37712                          amount = std::min(vec.size(),
37713                                            static_cast<std::size_t>(scalar_t(parameters[2])()));
37714                          return T(fd->write(vec, amount) ? 1 : 0);
37715                       }
37716          }
37717
37718          return T(0);
37719       }
37720    };
37721
37722    template <typename T>
37723    class read : public exprtk::igeneric_function<T>
37724    {
37725    public:
37726
37727       typedef typename exprtk::igeneric_function<T> igfun_t;
37728       typedef typename igfun_t::parameter_list_t    parameter_list_t;
37729       typedef typename igfun_t::generic_type        generic_type;
37730       typedef typename generic_type::string_view    string_t;
37731       typedef typename generic_type::scalar_view    scalar_t;
37732       typedef typename generic_type::vector_view    vector_t;
37733
37734       using exprtk::igeneric_function<T>::operator();
37735
37736       read()
37737       : igfun_t("TS|TST|TV|TVT")
37738       { details::perform_check<T>(); }
37739
37740       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
37741       {
37742          details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])());
37743
37744          std::size_t amount = 0;
37745
37746          switch (ps_index)
37747          {
37748             case 0  : {
37749                          string_t buffer(parameters[1]);
37750                          amount = buffer.size();
37751                          return T(fd->read(buffer,amount) ? 1 : 0);
37752                       }
37753
37754             case 1  : {
37755                          string_t buffer(parameters[1]);
37756                          amount = std::min(buffer.size(),
37757                                            static_cast<std::size_t>(scalar_t(parameters[2])()));
37758                          return T(fd->read(buffer,amount) ? 1 : 0);
37759                       }
37760
37761             case 2  : {
37762                          vector_t vec(parameters[1]);
37763                          amount = vec.size();
37764                          return T(fd->read(vec,amount) ? 1 : 0);
37765                       }
37766
37767             case 3  : {
37768                          vector_t vec(parameters[1]);
37769                          amount = std::min(vec.size(),
37770                                            static_cast<std::size_t>(scalar_t(parameters[2])()));
37771                          return T(fd->read(vec,amount) ? 1 : 0);
37772                       }
37773          }
37774
37775          return T(0);
37776       }
37777    };
37778
37779    template <typename T>
37780    class getline : public exprtk::igeneric_function<T>
37781    {
37782    public:
37783
37784       typedef typename exprtk::igeneric_function<T> igfun_t;
37785       typedef typename igfun_t::parameter_list_t    parameter_list_t;
37786       typedef typename igfun_t::generic_type        generic_type;
37787       typedef typename generic_type::string_view    string_t;
37788       typedef typename generic_type::scalar_view    scalar_t;
37789
37790       using exprtk::igeneric_function<T>::operator();
37791
37792       getline()
37793       : igfun_t("T",igfun_t::e_rtrn_string)
37794       { details::perform_check<T>(); }
37795
37796       inline T operator() (std::string& result,
37797                            parameter_list_t parameters)
37798       {
37799          details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])());
37800          return T(fd->getline(result) ? 1 : 0);
37801       }
37802    };
37803
37804    template <typename T>
37805    struct eof : public exprtk::ifunction<T>
37806    {
37807       using exprtk::ifunction<T>::operator();
37808
37809       eof()
37810       : exprtk::ifunction<T>(1)
37811       { details::perform_check<T>(); }
37812
37813       inline T operator() (const T& v)
37814       {
37815          details::file_descriptor* fd = details::make_handle(v);
37816
37817          return (fd->eof() ? T(1) : T(0));
37818       }
37819    };
37820
37821    template <typename T>
37822    struct package
37823    {
37824       open   <T> o;
37825       close  <T> c;
37826       write  <T> w;
37827       read   <T> r;
37828       getline<T> g;
37829       eof    <T> e;
37830
37831       bool register_package(exprtk::symbol_table<T>& symtab)
37832       {
37833          #define exprtk_register_function(FunctionName,FunctionType)                    \
37834          if (!symtab.add_function(FunctionName,FunctionType))                           \
37835          {                                                                              \
37836             exprtk_debug((                                                              \
37837               "exprtk::rtl::io::file::register_package - Failed to add function: %s\n", \
37838               FunctionName));                                                           \
37839             return false;                                                               \
37840          }                                                                              \
37841
37842          exprtk_register_function("open"   ,o)
37843          exprtk_register_function("close"  ,c)
37844          exprtk_register_function("write"  ,w)
37845          exprtk_register_function("read"   ,r)
37846          exprtk_register_function("getline",g)
37847          exprtk_register_function("eof"    ,e)
37848          #undef exprtk_register_function
37849
37850          return true;
37851       }
37852    };
37853
37854    } // namespace exprtk::rtl::io::file
37855    } // namespace exprtk::rtl::io
37856    } // namespace exprtk::rtl
37857 }    // namespace exprtk
37858 #endif
37859
37860 #ifndef exprtk_disable_rtl_vecops
37861 namespace exprtk
37862 {
37863    namespace rtl { namespace vecops {
37864
37865    namespace helper
37866    {
37867       template <typename Vector>
37868       inline bool invalid_range(const Vector& v, const std::size_t r0, const std::size_t r1)
37869       {
37870          if (r0 > (v.size() - 1))
37871             return true;
37872          else if (r1 > (v.size() - 1))
37873             return true;
37874          else if (r1 < r0)
37875             return true;
37876          else
37877             return false;
37878       }
37879
37880       template <typename T>
37881       struct load_vector_range
37882       {
37883          typedef typename exprtk::igeneric_function<T> igfun_t;
37884          typedef typename igfun_t::parameter_list_t    parameter_list_t;
37885          typedef typename igfun_t::generic_type        generic_type;
37886          typedef typename generic_type::scalar_view    scalar_t;
37887          typedef typename generic_type::vector_view    vector_t;
37888
37889          static inline bool process(parameter_list_t& parameters,
37890                                     std::size_t& r0, std::size_t& r1,
37891                                     const std::size_t& r0_prmidx,
37892                                     const std::size_t& r1_prmidx,
37893                                     const std::size_t vec_idx = 0)
37894          {
37895             if (r0_prmidx >= parameters.size())
37896                return false;
37897
37898             if (r1_prmidx >= parameters.size())
37899                return false;
37900
37901             if (!scalar_t(parameters[r0_prmidx]).to_uint(r0))
37902                return false;
37903
37904             if (!scalar_t(parameters[r1_prmidx]).to_uint(r1))
37905                return false;
37906
37907             return !invalid_range(vector_t(parameters[vec_idx]), r0, r1);
37908          }
37909       };
37910    }
37911
37912    namespace details
37913    {
37914       template <typename T>
37915       inline void kahan_sum(T& sum, T& error, const T v)
37916       {
37917          const T x = v - error;
37918          const T y = sum + x;
37919          error = (y - sum) - x;
37920          sum = y;
37921       }
37922
37923    } // namespace exprtk::rtl::details
37924
37925    template <typename T>
37926    class all_true : public exprtk::igeneric_function<T>
37927    {
37928    public:
37929
37930       typedef typename exprtk::igeneric_function<T> igfun_t;
37931       typedef typename igfun_t::parameter_list_t    parameter_list_t;
37932       typedef typename igfun_t::generic_type        generic_type;
37933       typedef typename generic_type::vector_view    vector_t;
37934
37935       using exprtk::igeneric_function<T>::operator();
37936
37937       all_true()
37938       : exprtk::igeneric_function<T>("V|VTT")
37939         /*
37940            Overloads:
37941            0. V   - vector
37942            1. VTT - vector, r0, r1
37943         */
37944       {}
37945
37946       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
37947       {
37948          const vector_t vec(parameters[0]);
37949
37950          std::size_t r0 = 0;
37951          std::size_t r1 = vec.size() - 1;
37952
37953          if (
37954               (1 == ps_index) &&
37955               !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
37956             )
37957             return std::numeric_limits<T>::quiet_NaN();
37958
37959          for (std::size_t i = r0; i <= r1; ++i)
37960          {
37961             if (vec[i] == T(0))
37962             {
37963                return T(0);
37964             }
37965          }
37966
37967          return T(1);
37968       }
37969    };
37970
37971    template <typename T>
37972    class all_false : public exprtk::igeneric_function<T>
37973    {
37974    public:
37975
37976       typedef typename exprtk::igeneric_function<T> igfun_t;
37977       typedef typename igfun_t::parameter_list_t    parameter_list_t;
37978       typedef typename igfun_t::generic_type        generic_type;
37979       typedef typename generic_type::vector_view    vector_t;
37980
37981       using exprtk::igeneric_function<T>::operator();
37982
37983       all_false()
37984       : exprtk::igeneric_function<T>("V|VTT")
37985         /*
37986            Overloads:
37987            0. V   - vector
37988            1. VTT - vector, r0, r1
37989         */
37990       {}
37991
37992       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
37993       {
37994          const vector_t vec(parameters[0]);
37995
37996          std::size_t r0 = 0;
37997          std::size_t r1 = vec.size() - 1;
37998
37999          if (
38000               (1 == ps_index) &&
38001               !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
38002             )
38003             return std::numeric_limits<T>::quiet_NaN();
38004
38005          for (std::size_t i = r0; i <= r1; ++i)
38006          {
38007             if (vec[i] != T(0))
38008             {
38009                return T(0);
38010             }
38011          }
38012
38013          return T(1);
38014       }
38015    };
38016
38017    template <typename T>
38018    class any_true : public exprtk::igeneric_function<T>
38019    {
38020    public:
38021
38022       typedef typename exprtk::igeneric_function<T> igfun_t;
38023       typedef typename igfun_t::parameter_list_t    parameter_list_t;
38024       typedef typename igfun_t::generic_type        generic_type;
38025       typedef typename generic_type::vector_view    vector_t;
38026
38027       using exprtk::igeneric_function<T>::operator();
38028
38029       any_true()
38030       : exprtk::igeneric_function<T>("V|VTT")
38031         /*
38032            Overloads:
38033            0. V   - vector
38034            1. VTT - vector, r0, r1
38035         */
38036       {}
38037
38038       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38039       {
38040          const vector_t vec(parameters[0]);
38041
38042          std::size_t r0 = 0;
38043          std::size_t r1 = vec.size() - 1;
38044
38045          if (
38046               (1 == ps_index) &&
38047               !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
38048             )
38049             return std::numeric_limits<T>::quiet_NaN();
38050
38051          for (std::size_t i = r0; i <= r1; ++i)
38052          {
38053             if (vec[i] != T(0))
38054             {
38055                return T(1);
38056             }
38057          }
38058
38059          return T(0);
38060       }
38061    };
38062
38063    template <typename T>
38064    class any_false : public exprtk::igeneric_function<T>
38065    {
38066    public:
38067
38068       typedef typename exprtk::igeneric_function<T> igfun_t;
38069       typedef typename igfun_t::parameter_list_t    parameter_list_t;
38070       typedef typename igfun_t::generic_type        generic_type;
38071       typedef typename generic_type::vector_view    vector_t;
38072
38073       using exprtk::igeneric_function<T>::operator();
38074
38075       any_false()
38076       : exprtk::igeneric_function<T>("V|VTT")
38077         /*
38078            Overloads:
38079            0. V   - vector
38080            1. VTT - vector, r0, r1
38081         */
38082       {}
38083
38084       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38085       {
38086          const vector_t vec(parameters[0]);
38087
38088          std::size_t r0 = 0;
38089          std::size_t r1 = vec.size() - 1;
38090
38091          if (
38092               (1 == ps_index) &&
38093               !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
38094             )
38095             return std::numeric_limits<T>::quiet_NaN();
38096
38097          for (std::size_t i = r0; i <= r1; ++i)
38098          {
38099             if (vec[i] == T(0))
38100             {
38101                return T(1);
38102             }
38103          }
38104
38105          return T(0);
38106       }
38107    };
38108
38109    template <typename T>
38110    class count : public exprtk::igeneric_function<T>
38111    {
38112    public:
38113
38114       typedef typename exprtk::igeneric_function<T> igfun_t;
38115       typedef typename igfun_t::parameter_list_t    parameter_list_t;
38116       typedef typename igfun_t::generic_type        generic_type;
38117       typedef typename generic_type::vector_view    vector_t;
38118
38119       using exprtk::igeneric_function<T>::operator();
38120
38121       count()
38122       : exprtk::igeneric_function<T>("V|VTT")
38123         /*
38124            Overloads:
38125            0. V   - vector
38126            1. VTT - vector, r0, r1
38127         */
38128       {}
38129
38130       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38131       {
38132          const vector_t vec(parameters[0]);
38133
38134          std::size_t r0 = 0;
38135          std::size_t r1 = vec.size() - 1;
38136
38137          if (
38138               (1 == ps_index) &&
38139               !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
38140             )
38141             return std::numeric_limits<T>::quiet_NaN();
38142
38143          std::size_t cnt = 0;
38144
38145          for (std::size_t i = r0; i <= r1; ++i)
38146          {
38147             if (vec[i] != T(0)) ++cnt;
38148          }
38149
38150          return T(cnt);
38151       }
38152    };
38153
38154    template <typename T>
38155    class copy : public exprtk::igeneric_function<T>
38156    {
38157    public:
38158
38159       typedef typename exprtk::igeneric_function<T> igfun_t;
38160       typedef typename igfun_t::parameter_list_t    parameter_list_t;
38161       typedef typename igfun_t::generic_type        generic_type;
38162       typedef typename generic_type::scalar_view    scalar_t;
38163       typedef typename generic_type::vector_view    vector_t;
38164
38165       using exprtk::igeneric_function<T>::operator();
38166
38167       copy()
38168       : exprtk::igeneric_function<T>("VV|VTTVTT")
38169         /*
38170            Overloads:
38171            0. VV     - x(vector), y(vector)
38172            1. VTTVTT - x(vector), xr0, xr1, y(vector), yr0, yr1,
38173         */
38174       {}
38175
38176       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38177       {
38178          const vector_t x(parameters[0]);
38179                vector_t y(parameters[(0 == ps_index) ? 1 : 3]);
38180
38181          std::size_t xr0 = 0;
38182          std::size_t xr1 = x.size() - 1;
38183
38184          std::size_t yr0 = 0;
38185          std::size_t yr1 = y.size() - 1;
38186
38187          if (1 == ps_index)
38188          {
38189             if (
38190                  !helper::load_vector_range<T>::process(parameters, xr0, xr1, 1, 2, 0) ||
38191                  !helper::load_vector_range<T>::process(parameters, yr0, yr1, 4, 5, 3)
38192                )
38193                return T(0);
38194          }
38195
38196          const std::size_t n = std::min(xr1 - xr0 + 1, yr1 - yr0 + 1);
38197
38198          std::copy(x.begin() + xr0, x.begin() + xr0 + n, y.begin() + yr0);
38199
38200          return T(n);
38201       }
38202    };
38203
38204    template <typename T>
38205    class rol : public exprtk::igeneric_function<T>
38206    {
38207    public:
38208
38209       typedef typename exprtk::igeneric_function<T> igfun_t;
38210       typedef typename igfun_t::parameter_list_t    parameter_list_t;
38211       typedef typename igfun_t::generic_type        generic_type;
38212       typedef typename generic_type::scalar_view    scalar_t;
38213       typedef typename generic_type::vector_view    vector_t;
38214
38215       using exprtk::igeneric_function<T>::operator();
38216
38217       rol()
38218       : exprtk::igeneric_function<T>("VT|VTTT")
38219         /*
38220            Overloads:
38221            0. VT   - vector, N
38222            1. VTTT - vector, N, r0, r1
38223         */
38224       {}
38225
38226       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38227       {
38228          vector_t vec(parameters[0]);
38229
38230          std::size_t n  = 0;
38231          std::size_t r0 = 0;
38232          std::size_t r1 = vec.size() - 1;
38233
38234          if (!scalar_t(parameters[1]).to_uint(n))
38235             return T(0);
38236
38237          if (
38238               (1 == ps_index) &&
38239               !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
38240             )
38241             return T(0);
38242
38243          std::size_t dist  = r1 - r0 + 1;
38244          std::size_t shift = n % dist;
38245
38246          std::rotate(vec.begin() + r0, vec.begin() + r0 + shift, vec.begin() + r1 + 1);
38247
38248          return T(1);
38249       }
38250    };
38251
38252    template <typename T>
38253    class ror : public exprtk::igeneric_function<T>
38254    {
38255    public:
38256
38257       typedef typename exprtk::igeneric_function<T> igfun_t;
38258       typedef typename igfun_t::parameter_list_t    parameter_list_t;
38259       typedef typename igfun_t::generic_type        generic_type;
38260       typedef typename generic_type::scalar_view    scalar_t;
38261       typedef typename generic_type::vector_view    vector_t;
38262
38263       using exprtk::igeneric_function<T>::operator();
38264
38265       ror()
38266       : exprtk::igeneric_function<T>("VT|VTTT")
38267         /*
38268            Overloads:
38269            0. VT   - vector, N
38270            1. VTTT - vector, N, r0, r1
38271         */
38272       {}
38273
38274       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38275       {
38276          vector_t vec(parameters[0]);
38277
38278          std::size_t n  = 0;
38279          std::size_t r0 = 0;
38280          std::size_t r1 = vec.size() - 1;
38281
38282          if (!scalar_t(parameters[1]).to_uint(n))
38283             return T(0);
38284
38285          if (
38286               (1 == ps_index) &&
38287               !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
38288             )
38289             return T(0);
38290
38291          std::size_t dist  = r1 - r0 + 1;
38292          std::size_t shift = (dist - (n % dist)) % dist;
38293
38294          std::rotate(vec.begin() + r0, vec.begin() + r0 + shift, vec.begin() + r1 + 1);
38295
38296          return T(1);
38297       }
38298    };
38299
38300    template <typename T>
38301    class shift_left : public exprtk::igeneric_function<T>
38302    {
38303    public:
38304
38305       typedef typename exprtk::igeneric_function<T> igfun_t;
38306       typedef typename igfun_t::parameter_list_t    parameter_list_t;
38307       typedef typename igfun_t::generic_type        generic_type;
38308       typedef typename generic_type::scalar_view    scalar_t;
38309       typedef typename generic_type::vector_view    vector_t;
38310
38311       using exprtk::igeneric_function<T>::operator();
38312
38313       shift_left()
38314       : exprtk::igeneric_function<T>("VT|VTTT")
38315         /*
38316            Overloads:
38317            0. VT   - vector, N
38318            1. VTTT - vector, N, r0, r1
38319         */
38320       {}
38321
38322       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38323       {
38324          vector_t vec(parameters[0]);
38325
38326          std::size_t n  = 0;
38327          std::size_t r0 = 0;
38328          std::size_t r1 = vec.size() - 1;
38329
38330          if (!scalar_t(parameters[1]).to_uint(n))
38331             return T(0);
38332
38333          if (
38334               (1 == ps_index) &&
38335               !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
38336             )
38337             return T(0);
38338
38339          std::size_t dist  = r1 - r0 + 1;
38340
38341          if (n > dist)
38342             return T(0);
38343
38344          std::rotate(vec.begin() + r0, vec.begin() + r0 + n, vec.begin() + r1 + 1);
38345
38346          for (std::size_t i = r1 - n + 1; i <= r1; ++i)
38347          {
38348             vec[i] = T(0);
38349          }
38350
38351          return T(1);
38352       }
38353    };
38354
38355    template <typename T>
38356    class shift_right : public exprtk::igeneric_function<T>
38357    {
38358    public:
38359
38360       typedef typename exprtk::igeneric_function<T> igfun_t;
38361       typedef typename igfun_t::parameter_list_t    parameter_list_t;
38362       typedef typename igfun_t::generic_type        generic_type;
38363       typedef typename generic_type::scalar_view    scalar_t;
38364       typedef typename generic_type::vector_view    vector_t;
38365
38366       using exprtk::igeneric_function<T>::operator();
38367
38368       shift_right()
38369       : exprtk::igeneric_function<T>("VT|VTTT")
38370         /*
38371            Overloads:
38372            0. VT   - vector, N
38373            1. VTTT - vector, N, r0, r1
38374         */
38375       {}
38376
38377       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38378       {
38379          vector_t vec(parameters[0]);
38380
38381          std::size_t n  = 0;
38382          std::size_t r0 = 0;
38383          std::size_t r1 = vec.size() - 1;
38384
38385          if (!scalar_t(parameters[1]).to_uint(n))
38386             return T(0);
38387
38388          if (
38389               (1 == ps_index) &&
38390               !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
38391             )
38392             return T(0);
38393
38394          std::size_t dist  = r1 - r0 + 1;
38395
38396          if (n > dist)
38397             return T(0);
38398
38399          std::size_t shift = (dist - (n % dist)) % dist;
38400
38401          std::rotate(vec.begin() + r0, vec.begin() + r0 + shift, vec.begin() + r1 + 1);
38402
38403          for (std::size_t i = r0; i < r0 + n; ++i)
38404          {
38405             vec[i] = T(0);
38406          }
38407
38408          return T(1);
38409       }
38410    };
38411
38412    template <typename T>
38413    class sort : public exprtk::igeneric_function<T>
38414    {
38415    public:
38416
38417       typedef typename exprtk::igeneric_function<T> igfun_t;
38418       typedef typename igfun_t::parameter_list_t    parameter_list_t;
38419       typedef typename igfun_t::generic_type        generic_type;
38420       typedef typename generic_type::string_view    string_t;
38421       typedef typename generic_type::vector_view    vector_t;
38422
38423       using exprtk::igeneric_function<T>::operator();
38424
38425       sort()
38426       : exprtk::igeneric_function<T>("V|VTT|VS|VSTT")
38427         /*
38428            Overloads:
38429            0. V    - vector
38430            1. VTT  - vector, r0, r1
38431            2. VS   - vector, string
38432            3. VSTT - vector, string, r0, r1
38433         */
38434       {}
38435
38436       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38437       {
38438          vector_t vec(parameters[0]);
38439
38440          std::size_t r0 = 0;
38441          std::size_t r1 = vec.size() - 1;
38442
38443          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0))
38444             return T(0);
38445          if ((3 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
38446             return T(0);
38447
38448          bool ascending = true;
38449
38450          if ((2 == ps_index) || (3 == ps_index))
38451          {
38452             if (exprtk::details::imatch(to_str(string_t(parameters[1])),"ascending"))
38453                ascending = true;
38454             else if (exprtk::details::imatch(to_str(string_t(parameters[1])),"descending"))
38455                ascending = false;
38456             else
38457                return T(0);
38458          }
38459
38460          if (ascending)
38461             std::sort(vec.begin() + r0, vec.begin() + r1 + 1, std::less<T>   ());
38462          else
38463             std::sort(vec.begin() + r0, vec.begin() + r1 + 1, std::greater<T>());
38464
38465          return T(1);
38466       }
38467    };
38468
38469    template <typename T>
38470    class nthelement : public exprtk::igeneric_function<T>
38471    {
38472    public:
38473
38474       typedef typename exprtk::igeneric_function<T> igfun_t;
38475       typedef typename igfun_t::parameter_list_t    parameter_list_t;
38476       typedef typename igfun_t::generic_type        generic_type;
38477       typedef typename generic_type::scalar_view    scalar_t;
38478       typedef typename generic_type::vector_view    vector_t;
38479
38480       using exprtk::igeneric_function<T>::operator();
38481
38482       nthelement()
38483       : exprtk::igeneric_function<T>("VT|VTTT")
38484         /*
38485            Overloads:
38486            0. VT   - vector, nth-element
38487            1. VTTT - vector, nth-element, r0, r1
38488         */
38489       {}
38490
38491       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38492       {
38493          vector_t vec(parameters[0]);
38494
38495          std::size_t n  = 0;
38496          std::size_t r0 = 0;
38497          std::size_t r1 = vec.size() - 1;
38498
38499          if (!scalar_t(parameters[1]).to_uint(n))
38500             return T(0);
38501
38502          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
38503             return std::numeric_limits<T>::quiet_NaN();
38504
38505          std::nth_element(vec.begin() + r0, vec.begin() + r0 + n , vec.begin() + r1 + 1);
38506
38507          return T(1);
38508       }
38509    };
38510
38511    template <typename T>
38512    class iota : public exprtk::igeneric_function<T>
38513    {
38514    public:
38515
38516       typedef typename exprtk::igeneric_function<T> igfun_t;
38517       typedef typename igfun_t::parameter_list_t    parameter_list_t;
38518       typedef typename igfun_t::generic_type        generic_type;
38519       typedef typename generic_type::scalar_view    scalar_t;
38520       typedef typename generic_type::vector_view    vector_t;
38521
38522       using exprtk::igeneric_function<T>::operator();
38523
38524       iota()
38525       : exprtk::igeneric_function<T>("VT|VTT|VTTT|VTTTT")
38526         /*
38527            Overloads:
38528            0. VT    - vector, increment
38529            1. VTT   - vector, increment, base
38530            2. VTTTT - vector, increment, r0, r1
38531            3. VTTTT - vector, increment, base, r0, r1
38532         */
38533       {}
38534
38535       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38536       {
38537          vector_t vec(parameters[0]);
38538
38539          T increment = scalar_t(parameters[1])();
38540          T base      = ((1 == ps_index) || (3 == ps_index)) ? scalar_t(parameters[2])() : T(0);
38541
38542          std::size_t r0 = 0;
38543          std::size_t r1 = vec.size() - 1;
38544
38545          if ((2 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
38546             return std::numeric_limits<T>::quiet_NaN();
38547          else if ((3 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 3, 4, 0))
38548             return std::numeric_limits<T>::quiet_NaN();
38549          else
38550          {
38551             long long j = 0;
38552
38553             for (std::size_t i = r0; i <= r1; ++i, ++j)
38554             {
38555                vec[i] = base + (increment * j);
38556             }
38557          }
38558
38559          return T(1);
38560       }
38561    };
38562
38563    template <typename T>
38564    class sumk : public exprtk::igeneric_function<T>
38565    {
38566    public:
38567
38568       typedef typename exprtk::igeneric_function<T> igfun_t;
38569       typedef typename igfun_t::parameter_list_t    parameter_list_t;
38570       typedef typename igfun_t::generic_type        generic_type;
38571       typedef typename generic_type::vector_view    vector_t;
38572
38573       using exprtk::igeneric_function<T>::operator();
38574
38575       sumk()
38576       : exprtk::igeneric_function<T>("V|VTT")
38577         /*
38578            Overloads:
38579            0. V   - vector
38580            1. VTT - vector, r0, r1
38581         */
38582       {}
38583
38584       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38585       {
38586          const vector_t vec(parameters[0]);
38587
38588          std::size_t r0 = 0;
38589          std::size_t r1 = vec.size() - 1;
38590
38591          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0))
38592             return std::numeric_limits<T>::quiet_NaN();
38593
38594          T result = T(0);
38595          T error  = T(0);
38596
38597          for (std::size_t i = r0; i <= r1; ++i)
38598          {
38599             details::kahan_sum(result, error, vec[i]);
38600          }
38601
38602          return result;
38603       }
38604    };
38605
38606    template <typename T>
38607    class axpy : public exprtk::igeneric_function<T>
38608    {
38609    public:
38610
38611       typedef typename exprtk::igeneric_function<T> igfun_t;
38612       typedef typename igfun_t::parameter_list_t    parameter_list_t;
38613       typedef typename igfun_t::generic_type        generic_type;
38614       typedef typename generic_type::scalar_view    scalar_t;
38615       typedef typename generic_type::vector_view    vector_t;
38616
38617       using exprtk::igeneric_function<T>::operator();
38618
38619       axpy()
38620       : exprtk::igeneric_function<T>("TVV|TVVTT")
38621         /*
38622            y <- ax + y
38623            Overloads:
38624            0. TVV   - a, x(vector), y(vector)
38625            1. TVVTT - a, x(vector), y(vector), r0, r1
38626         */
38627       {}
38628
38629       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38630       {
38631          const vector_t x(parameters[1]);
38632                vector_t y(parameters[2]);
38633
38634          std::size_t r0 = 0;
38635          std::size_t r1 = std::min(x.size(),y.size()) - 1;
38636
38637          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 3, 4, 1))
38638             return std::numeric_limits<T>::quiet_NaN();
38639          else if (helper::invalid_range(y, r0, r1))
38640             return std::numeric_limits<T>::quiet_NaN();
38641
38642          const T a = scalar_t(parameters[0])();
38643
38644          for (std::size_t i = r0; i <= r1; ++i)
38645          {
38646             y[i] = (a * x[i]) + y[i];
38647          }
38648
38649          return T(1);
38650       }
38651    };
38652
38653    template <typename T>
38654    class axpby : public exprtk::igeneric_function<T>
38655    {
38656    public:
38657
38658       typedef typename exprtk::igeneric_function<T> igfun_t;
38659       typedef typename igfun_t::parameter_list_t    parameter_list_t;
38660       typedef typename igfun_t::generic_type        generic_type;
38661       typedef typename generic_type::scalar_view    scalar_t;
38662       typedef typename generic_type::vector_view    vector_t;
38663
38664       using exprtk::igeneric_function<T>::operator();
38665
38666       axpby()
38667       : exprtk::igeneric_function<T>("TVTV|TVTVTT")
38668         /*
38669            y <- ax + by
38670            Overloads:
38671            0. TVTV   - a, x(vector), b, y(vector)
38672            1. TVTVTT - a, x(vector), b, y(vector), r0, r1
38673         */
38674       {}
38675
38676       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38677       {
38678          const vector_t x(parameters[1]);
38679                vector_t y(parameters[3]);
38680
38681          std::size_t r0 = 0;
38682          std::size_t r1 = std::min(x.size(),y.size()) - 1;
38683
38684          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1))
38685             return std::numeric_limits<T>::quiet_NaN();
38686          else if (helper::invalid_range(y, r0, r1))
38687             return std::numeric_limits<T>::quiet_NaN();
38688
38689          const T a = scalar_t(parameters[0])();
38690          const T b = scalar_t(parameters[2])();
38691
38692          for (std::size_t i = r0; i <= r1; ++i)
38693          {
38694             y[i] = (a * x[i]) + (b * y[i]);
38695          }
38696
38697          return T(1);
38698       }
38699    };
38700
38701    template <typename T>
38702    class axpyz : public exprtk::igeneric_function<T>
38703    {
38704    public:
38705
38706       typedef typename exprtk::igeneric_function<T> igfun_t;
38707       typedef typename igfun_t::parameter_list_t    parameter_list_t;
38708       typedef typename igfun_t::generic_type        generic_type;
38709       typedef typename generic_type::scalar_view    scalar_t;
38710       typedef typename generic_type::vector_view    vector_t;
38711
38712       using exprtk::igeneric_function<T>::operator();
38713
38714       axpyz()
38715       : exprtk::igeneric_function<T>("TVVV|TVVVTT")
38716         /*
38717            z <- ax + y
38718            Overloads:
38719            0. TVVV   - a, x(vector), y(vector), z(vector)
38720            1. TVVVTT - a, x(vector), y(vector), z(vector), r0, r1
38721         */
38722       {}
38723
38724       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38725       {
38726          const vector_t x(parameters[1]);
38727          const vector_t y(parameters[2]);
38728                vector_t z(parameters[3]);
38729
38730          std::size_t r0 = 0;
38731          std::size_t r1 = std::min(x.size(),y.size()) - 1;
38732
38733          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 3, 4, 1))
38734             return std::numeric_limits<T>::quiet_NaN();
38735          else if (helper::invalid_range(y, r0, r1))
38736             return std::numeric_limits<T>::quiet_NaN();
38737          else if (helper::invalid_range(z, r0, r1))
38738             return std::numeric_limits<T>::quiet_NaN();
38739
38740          const T a = scalar_t(parameters[0])();
38741
38742          for (std::size_t i = r0; i <= r1; ++i)
38743          {
38744             z[i] = (a * x[i]) + y[i];
38745          }
38746
38747          return T(1);
38748       }
38749    };
38750
38751    template <typename T>
38752    class axpbyz : public exprtk::igeneric_function<T>
38753    {
38754    public:
38755
38756       typedef typename exprtk::igeneric_function<T> igfun_t;
38757       typedef typename igfun_t::parameter_list_t    parameter_list_t;
38758       typedef typename igfun_t::generic_type        generic_type;
38759       typedef typename generic_type::scalar_view    scalar_t;
38760       typedef typename generic_type::vector_view    vector_t;
38761
38762       using exprtk::igeneric_function<T>::operator();
38763
38764       axpbyz()
38765       : exprtk::igeneric_function<T>("TVTVV|TVTVVTT")
38766         /*
38767            z <- ax + by
38768            Overloads:
38769            0. TVTVV   - a, x(vector), b, y(vector), z(vector)
38770            1. TVTVVTT - a, x(vector), b, y(vector), z(vector), r0, r1
38771         */
38772       {}
38773
38774       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38775       {
38776          const vector_t x(parameters[1]);
38777          const vector_t y(parameters[3]);
38778                vector_t z(parameters[4]);
38779
38780          std::size_t r0 = 0;
38781          std::size_t r1 = std::min(x.size(),y.size()) - 1;
38782
38783          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1))
38784             return std::numeric_limits<T>::quiet_NaN();
38785          else if (helper::invalid_range(y, r0, r1))
38786             return std::numeric_limits<T>::quiet_NaN();
38787          else if (helper::invalid_range(z, r0, r1))
38788             return std::numeric_limits<T>::quiet_NaN();
38789
38790          const T a = scalar_t(parameters[0])();
38791          const T b = scalar_t(parameters[2])();
38792
38793          for (std::size_t i = r0; i <= r1; ++i)
38794          {
38795             z[i] = (a * x[i]) + (b * y[i]);
38796          }
38797
38798          return T(1);
38799       }
38800    };
38801
38802    template <typename T>
38803    class axpbz : public exprtk::igeneric_function<T>
38804    {
38805    public:
38806
38807       typedef typename exprtk::igeneric_function<T> igfun_t;
38808       typedef typename igfun_t::parameter_list_t    parameter_list_t;
38809       typedef typename igfun_t::generic_type        generic_type;
38810       typedef typename generic_type::scalar_view    scalar_t;
38811       typedef typename generic_type::vector_view    vector_t;
38812
38813       using exprtk::igeneric_function<T>::operator();
38814
38815       axpbz()
38816       : exprtk::igeneric_function<T>("TVTV|TVTVTT")
38817         /*
38818            z <- ax + b
38819            Overloads:
38820            0. TVTV   - a, x(vector), b, z(vector)
38821            1. TVTVTT - a, x(vector), b, z(vector), r0, r1
38822         */
38823       {}
38824
38825       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38826       {
38827          const vector_t x(parameters[1]);
38828                vector_t z(parameters[3]);
38829
38830          std::size_t r0 = 0;
38831          std::size_t r1 = x.size() - 1;
38832
38833          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1))
38834             return std::numeric_limits<T>::quiet_NaN();
38835          else if (helper::invalid_range(z, r0, r1))
38836             return std::numeric_limits<T>::quiet_NaN();
38837
38838          const T a = scalar_t(parameters[0])();
38839          const T b = scalar_t(parameters[2])();
38840
38841          for (std::size_t i = r0; i <= r1; ++i)
38842          {
38843             z[i] = (a * x[i]) + b;
38844          }
38845
38846          return T(1);
38847       }
38848    };
38849
38850    template <typename T>
38851    class dot : public exprtk::igeneric_function<T>
38852    {
38853    public:
38854
38855       typedef typename exprtk::igeneric_function<T> igfun_t;
38856       typedef typename igfun_t::parameter_list_t    parameter_list_t;
38857       typedef typename igfun_t::generic_type        generic_type;
38858       typedef typename generic_type::scalar_view    scalar_t;
38859       typedef typename generic_type::vector_view    vector_t;
38860
38861       using exprtk::igeneric_function<T>::operator();
38862
38863       dot()
38864       : exprtk::igeneric_function<T>("VV|VVTT")
38865         /*
38866            Overloads:
38867            0. VV   - x(vector), y(vector)
38868            1. VVTT - x(vector), y(vector), r0, r1
38869         */
38870       {}
38871
38872       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38873       {
38874          const vector_t x(parameters[0]);
38875          const vector_t y(parameters[1]);
38876
38877          std::size_t r0 = 0;
38878          std::size_t r1 = std::min(x.size(),y.size()) - 1;
38879
38880          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
38881             return std::numeric_limits<T>::quiet_NaN();
38882          else if (helper::invalid_range(y, r0, r1))
38883             return std::numeric_limits<T>::quiet_NaN();
38884
38885          T result = T(0);
38886
38887          for (std::size_t i = r0; i <= r1; ++i)
38888          {
38889             result += (x[i] * y[i]);
38890          }
38891
38892          return result;
38893       }
38894    };
38895
38896    template <typename T>
38897    class dotk : public exprtk::igeneric_function<T>
38898    {
38899    public:
38900
38901       typedef typename exprtk::igeneric_function<T> igfun_t;
38902       typedef typename igfun_t::parameter_list_t    parameter_list_t;
38903       typedef typename igfun_t::generic_type        generic_type;
38904       typedef typename generic_type::scalar_view    scalar_t;
38905       typedef typename generic_type::vector_view    vector_t;
38906
38907       using exprtk::igeneric_function<T>::operator();
38908
38909       dotk()
38910       : exprtk::igeneric_function<T>("VV|VVTT")
38911         /*
38912            Overloads:
38913            0. VV   - x(vector), y(vector)
38914            1. VVTT - x(vector), y(vector), r0, r1
38915         */
38916       {}
38917
38918       inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38919       {
38920          const vector_t x(parameters[0]);
38921          const vector_t y(parameters[1]);
38922
38923          std::size_t r0 = 0;
38924          std::size_t r1 = std::min(x.size(),y.size()) - 1;
38925
38926          if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
38927             return std::numeric_limits<T>::quiet_NaN();
38928          else if (helper::invalid_range(y, r0, r1))
38929             return std::numeric_limits<T>::quiet_NaN();
38930
38931          T result = T(0);
38932          T error  = T(0);
38933
38934          for (std::size_t i = r0; i <= r1; ++i)
38935          {
38936             details::kahan_sum(result, error, (x[i] * y[i]));
38937          }
38938
38939          return result;
38940       }
38941    };
38942
38943    template <typename T>
38944    struct package
38945    {
38946       all_true   <T> at;
38947       all_false  <T> af;
38948       any_true   <T> nt;
38949       any_false  <T> nf;
38950       count      <T>  c;
38951       copy       <T> cp;
38952       rol        <T> rl;
38953       ror        <T> rr;
38954       shift_left <T> sl;
38955       shift_right<T> sr;
38956       sort       <T> st;
38957       nthelement <T> ne;
38958       iota       <T> ia;
38959       sumk       <T> sk;
38960       axpy       <T> b1_axpy;
38961       axpby      <T> b1_axpby;
38962       axpyz      <T> b1_axpyz;
38963       axpbyz     <T> b1_axpbyz;
38964       axpbz      <T> b1_axpbz;
38965       dot        <T> dt;
38966       dotk       <T> dtk;
38967
38968       bool register_package(exprtk::symbol_table<T>& symtab)
38969       {
38970          #define exprtk_register_function(FunctionName,FunctionType)                  \
38971          if (!symtab.add_function(FunctionName,FunctionType))                         \
38972          {                                                                            \
38973             exprtk_debug((                                                            \
38974               "exprtk::rtl::vecops::register_package - Failed to add function: %s\n", \
38975               FunctionName));                                                         \
38976             return false;                                                             \
38977          }                                                                            \
38978
38979          exprtk_register_function("all_true"     ,at)
38980          exprtk_register_function("all_false"    ,af)
38981          exprtk_register_function("any_true"     ,nt)
38982          exprtk_register_function("any_false"    ,nf)
38983          exprtk_register_function("count"        , c)
38984          exprtk_register_function("copy"         ,cp)
38985          exprtk_register_function("rotate_left"  ,rl)
38986          exprtk_register_function("rol"          ,rl)
38987          exprtk_register_function("rotate_right" ,rr)
38988          exprtk_register_function("ror"          ,rr)
38989          exprtk_register_function("shftl"        ,sl)
38990          exprtk_register_function("shftr"        ,sr)
38991          exprtk_register_function("sort"         ,st)
38992          exprtk_register_function("nth_element"  ,ne)
38993          exprtk_register_function("iota"         ,ia)
38994          exprtk_register_function("sumk"         ,sk)
38995          exprtk_register_function("axpy"    ,b1_axpy)
38996          exprtk_register_function("axpby"  ,b1_axpby)
38997          exprtk_register_function("axpyz"  ,b1_axpyz)
38998          exprtk_register_function("axpbyz",b1_axpbyz)
38999          exprtk_register_function("axpbz"  ,b1_axpbz)
39000          exprtk_register_function("dot"          ,dt)
39001          exprtk_register_function("dotk"        ,dtk)
39002          #undef exprtk_register_function
39003
39004          return true;
39005       }
39006    };
39007
39008    } // namespace exprtk::rtl::vecops
39009    } // namespace exprtk::rtl
39010 }    // namespace exprtk
39011 #endif
39012
39013 namespace exprtk
39014 {
39015    namespace information
39016    {
39017       static const char* library = "Mathematical Expression Toolkit";
39018       static const char* version = "2.7182818284590452353602874713526624977572470936999595749"
39019                                    "669676277240766303535475945713821785251664274274663919320";
39020       static const char* date    = "20200101";
39021
39022       static inline std::string data()
39023       {
39024          static const std::string info_str = std::string(library) +
39025                                              std::string(" v") + std::string(version) +
39026                                              std::string(" (") + date + std::string(")");
39027          return info_str;
39028       }
39029
39030    } // namespace information
39031
39032    #ifdef exprtk_debug
39033    #undef exprtk_debug
39034    #endif
39035
39036    #ifdef exprtk_error_location
39037    #undef exprtk_error_location
39038    #endif
39039
39040    #ifdef exprtk_disable_fallthrough_begin
39041    #undef exprtk_disable_fallthrough_begin
39042    #endif
39043
39044    #ifdef exprtk_disable_fallthrough_end
39045    #undef exprtk_disable_fallthrough_end
39046    #endif
39047
39048 } // namespace exprtk
39049
39050 #endif